fixed GL_Scissor call in rtlight code (apparently I need to feed it a top to bottom...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Feb 2004 18:56:51 +0000 (18:56 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 22 Feb 2004 18:56:51 +0000 (18:56 +0000)
made q1bsp and q3bsp a little more alike (regarding pvs clusters), now q3bsp has all the same pvs cluster fields as q3bsp
added fake lightgrid and pvs data to q3bsp loading when map is unlit or unvised respectively, this should improve internal consistency

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3922 d7cf8633-e32d-0410-b094-e92efae38249

gl_rmain.c
gl_rsurf.c
model_brush.c
model_brush.h
model_shared.h
portals.c
r_light.c
r_shadow.c
r_shadow.h
todo

index fef43b3..c79d159 100644 (file)
@@ -559,7 +559,12 @@ void R_ShadowVolumeLighting(int visiblevolumes)
                {
                        if (d_lightstylevalue[wl->style] <= 0)
                                continue;
-                       if (VIS_CullBox(wl->mins, wl->maxs))
+                       if (R_CullBox(wl->mins, wl->maxs))
+                               continue;
+                       for (i = 0;i < wl->numclusters;i++)
+                               if (CHECKPVSBIT(r_pvsbits, wl->clusterindices[i]))
+                                       break;
+                       if (i == wl->numclusters)
                                continue;
                        if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
                                continue;
index a3ddc49..75daf71 100644 (file)
@@ -1654,7 +1654,7 @@ void R_SurfaceWorldNode (entity_render_t *ent)
 
 static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
 {
-       int c, leafstackpos, *mark, *surfacevisframes, bitnum;
+       int c, leafstackpos, *mark, *surfacevisframes;
 #if WORLDNODECULLBACKFACES
        int n;
        msurface_t *surf;
@@ -1718,8 +1718,7 @@ static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
                                {
                                        leaf->worldnodeframe = r_framecount;
                                        // FIXME: R_CullBox is absolute, should be done relative
-                                       bitnum = (leaf - ent->model->brushq1.leafs) - 1;
-                                       if ((r_pvsbits[bitnum >> 3] & (1 << (bitnum & 7))) && !R_CullBox(leaf->mins, leaf->maxs))
+                                       if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
                                                leafstack[leafstackpos++] = leaf;
                                }
                        }
@@ -1744,11 +1743,10 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
                if (viewleaf)
                {
                        surfacepvsframes = model->brushq1.surfacepvsframes;
-                       for (j = 0;j < model->brushq1.visleafs;j++)
+                       for (j = 0, leaf = model->brushq1.data_leafs;j < model->brushq1.num_leafs;j++, leaf++)
                        {
-                               if (r_pvsbits[j >> 3] & (1 << (j & 7)))
+                               if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex))
                                {
-                                       leaf = model->brushq1.leafs + j + 1;
                                        leaf->pvsframe = model->brushq1.pvsframecount;
                                        leaf->pvschain = model->brushq1.pvsleafchain;
                                        model->brushq1.pvsleafchain = leaf;
@@ -1784,7 +1782,7 @@ void R_DrawWorld(entity_render_t *ent)
 {
        if (ent->model == NULL)
                return;
-       if (!ent->model->brushq1.numleafs)
+       if (!ent->model->brushq1.num_leafs)
        {
                if (ent->model->DrawSky)
                        ent->model->DrawSky(ent);
@@ -2263,7 +2261,7 @@ void R_Q3BSP_RecursiveWorldNode(entity_render_t *ent, q3mnode_t *node, const vec
                node = node->children[1];
        }
        leaf = (q3mleaf_t *)node;
-       if (pvs[leaf->clusterindex >> 3] & (1 << (leaf->clusterindex & 7)))
+       if (CHECKPVSBIT(pvs, leaf->clusterindex))
        {
                c_leafs++;
                for (i = 0;i < leaf->numleaffaces;i++)
@@ -2281,7 +2279,7 @@ void R_Q3BSP_MarkLeafPVS(entity_render_t *ent, qbyte *pvs, int markframe)
        q3mleaf_t *leaf;
        for (j = 0, leaf = ent->model->brushq3.data_leafs;j < ent->model->brushq3.num_leafs;j++, leaf++)
        {
-               if (pvs[leaf->clusterindex >> 3] & (1 << (leaf->clusterindex & 7)))
+               if (CHECKPVSBIT(pvs, leaf->clusterindex))
                {
                        c_leafs++;
                        for (i = 0;i < leaf->numleaffaces;i++)
index cea8a34..1f03498 100644 (file)
@@ -119,8 +119,8 @@ static int Mod_Q1BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
                else
                {
                        // leaf - check cluster bit
-                       clusterindex = (mleaf_t *)node - model->brushq1.leafs - 1;
-                       if (clusterindex >= 0 && pvs[clusterindex >> 3] & (1 << (clusterindex & 7)))
+                       clusterindex = ((mleaf_t *)node)->clusterindex;
+                       if (CHECKPVSBIT(pvs, clusterindex))
                        {
                                // it is visible, return immediately with the news
                                return true;
@@ -1963,7 +1963,7 @@ static void Mod_Q1BSP_LoadNodes(lump_t *l)
                        if (p >= 0)
                                out->children[j] = loadmodel->brushq1.nodes + p;
                        else
-                               out->children[j] = (mnode_t *)(loadmodel->brushq1.leafs + (-1 - p));
+                               out->children[j] = (mnode_t *)(loadmodel->brushq1.data_leafs + (-1 - p));
                }
        }
 
@@ -1974,8 +1974,7 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
 {
        dleaf_t *in;
        mleaf_t *out;
-       int i, j, count, p, pvschainbytes;
-       qbyte *pvs;
+       int i, j, count, p;
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -1983,11 +1982,13 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
        count = l->filelen / sizeof(*in);
        out = Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
 
-       loadmodel->brushq1.leafs = out;
-       loadmodel->brushq1.numleafs = count;
+       loadmodel->brushq1.data_leafs = out;
+       loadmodel->brushq1.num_leafs = count;
        // get visleafs from the submodel data
-       pvschainbytes = (loadmodel->brushq1.submodels[0].visleafs+7)>>3;
-       loadmodel->brushq1.data_decompressedpvs = pvs = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numleafs * pvschainbytes);
+       loadmodel->brushq1.num_pvsclusters = loadmodel->brushq1.submodels[0].visleafs;
+       loadmodel->brushq1.num_pvsclusterbytes = (loadmodel->brushq1.num_pvsclusters+7)>>3;
+       loadmodel->brushq1.data_pvsclusters = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.num_pvsclusters * loadmodel->brushq1.num_pvsclusterbytes);
+       memset(loadmodel->brushq1.data_pvsclusters, 0xFF, loadmodel->brushq1.num_pvsclusters * loadmodel->brushq1.num_pvsclusterbytes);
 
        for ( i=0 ; i<count ; i++, in++, out++)
        {
@@ -2010,17 +2011,18 @@ static void Mod_Q1BSP_LoadLeafs(lump_t *l)
                        out->nummarksurfaces = 0;
                }
 
-               out->pvsdata = pvs;
-               memset(out->pvsdata, 0xFF, pvschainbytes);
-               pvs += pvschainbytes;
+               out->clusterindex = i - 1;
+               if (out->clusterindex >= loadmodel->brushq1.num_pvsclusters)
+                       out->clusterindex = -1;
 
                p = LittleLong(in->visofs);
-               if (p >= 0 && i > 0) // ignore visofs errors on leaf 0 (solid)
+               // ignore visofs errors on leaf 0 (solid)
+               if (p >= 0 && out->clusterindex >= 0)
                {
                        if (p >= loadmodel->brushq1.num_compressedpvs)
                                Con_Printf("Mod_Q1BSP_LoadLeafs: invalid visofs\n");
                        else
-                               Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, out->pvsdata, out->pvsdata + pvschainbytes);
+                               Mod_Q1BSP_DecompressVis(loadmodel->brushq1.data_compressedpvs + p, loadmodel->brushq1.data_compressedpvs + loadmodel->brushq1.num_compressedpvs, loadmodel->brushq1.data_pvsclusters + out->clusterindex * loadmodel->brushq1.num_pvsclusterbytes, loadmodel->brushq1.data_pvsclusters + (out->clusterindex + 1) * loadmodel->brushq1.num_pvsclusterbytes);
                }
 
                for (j = 0;j < 4;j++)
@@ -2269,8 +2271,8 @@ static void Mod_Q1BSP_FinalizePortals(void)
        winding_t *w;
 
        // recalculate bounding boxes for all leafs(because qbsp is very sloppy)
-       leaf = loadmodel->brushq1.leafs;
-       endleaf = leaf + loadmodel->brushq1.numleafs;
+       leaf = loadmodel->brushq1.data_leafs;
+       endleaf = leaf + loadmodel->brushq1.num_leafs;
        for (;leaf < endleaf;leaf++)
        {
                VectorSet(leaf->mins,  2000000000,  2000000000,  2000000000);
@@ -2323,8 +2325,8 @@ static void Mod_Q1BSP_FinalizePortals(void)
        loadmodel->brushq1.portalpoints = (void *)((qbyte *) loadmodel->brushq1.portals + numportals * sizeof(mportal_t));
        loadmodel->brushq1.numportalpoints = numpoints;
        // clear all leaf portal chains
-       for (i = 0;i < loadmodel->brushq1.numleafs;i++)
-               loadmodel->brushq1.leafs[i].portals = NULL;
+       for (i = 0;i < loadmodel->brushq1.num_leafs;i++)
+               loadmodel->brushq1.data_leafs[i].portals = NULL;
        // process all portals in the global portal chain, while freeing them
        portal = loadmodel->brushq1.portals;
        point = loadmodel->brushq1.portalpoints;
@@ -2729,12 +2731,9 @@ static void Mod_Q1BSP_BuildPVSTextureChains(model_t *model)
 
 static void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbytes, mnode_t *node)
 {
-       int i;
-       float d;
-
-       while (node->contents >= 0)
+       while (node->plane)
        {
-               d = PlaneDiff(org, node->plane);
+               float d = PlaneDiff(org, node->plane);
                if (d > radius)
                        node = node->children[0];
                else if (d < -radius)
@@ -2746,18 +2745,21 @@ static void Mod_Q1BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
                        node = node->children[1];
                }
        }
-       // FIXME: code!
-       // if this is a leaf, accumulate the pvs bits
-       if (/*node->contents != CONTENTS_SOLID && */((mleaf_t *)node)->pvsdata)
+       // if this leaf is in a cluster, accumulate the pvs bits
+       if (((mleaf_t *)node)->clusterindex >= 0)
+       {
+               int i;
+               qbyte *pvs = model->brushq1.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
                for (i = 0;i < pvsbytes;i++)
-                       pvsbuffer[i] |= ((mleaf_t *)node)->pvsdata[i];
+                       pvsbuffer[i] |= pvs[i];
+       }
 }
 
 //Calculates a PVS that is the inclusive or of all leafs within radius pixels
 //of the given point.
 static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
 {
-       int bytes = ((model->brushq1.numleafs - 1) + 7) >> 3;
+       int bytes = ((model->brushq1.num_leafs - 1) + 7) >> 3;
        bytes = min(bytes, pvsbufferlength);
        if (r_novis.integer)
        {
@@ -2770,17 +2772,18 @@ static int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyt
 }
 
 //Returns PVS data for a given point
-//(note: always returns valid data, never NULL)
+//(note: can return NULL)
 static qbyte *Mod_Q1BSP_GetPVS(model_t *model, const vec3_t p)
 {
        mnode_t *node;
        Mod_CheckLoaded(model);
-       // LordHavoc: modified to start at first clip node,
-       // in other words: first node of the (sub)model
-       node = model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode;
-       while (node->contents == 0)
+       node = model->brushq1.nodes;
+       while (node->plane)
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
-       return ((mleaf_t *)node)->pvsdata;
+       if (((mleaf_t *)node)->clusterindex >= 0)
+               return model->brushq1.data_pvsclusters + ((mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
+       else
+               return NULL;
 }
 
 static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
@@ -2927,6 +2930,14 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                mod->Draw = R_Model_Brush_Draw;
                mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
                mod->DrawLight = R_Model_Brush_DrawLight;
+               if (i != 0)
+               {
+                       mod->brush.GetPVS = NULL;
+                       mod->brush.FatPVS = NULL;
+                       mod->brush.BoxTouchingPVS = NULL;
+                       mod->brush.LightPoint = NULL;
+                       mod->brush.AmbientSoundLevelsForPoint = NULL;
+               }
                mod->brushq1.pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->brushq1.numtextures * sizeof(msurface_t **));
                mod->brushq1.pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool,(mod->brushq1.nummodelsurfaces + mod->brushq1.numtextures) * sizeof(msurface_t *));
                mod->brushq1.pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->brushq1.numtextures * sizeof(int));
@@ -2981,7 +2992,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
                }
                Mod_Q1BSP_BuildSurfaceNeighbors(mod->brushq1.surfaces + mod->brushq1.firstmodelsurface, mod->brushq1.nummodelsurfaces, originalloadmodel->mempool);
 
-               mod->brushq1.visleafs = bm->visleafs;
+               mod->brushq1.num_visleafs = bm->visleafs;
 
                // LordHavoc: only register submodels if it is the world
                // (prevents bsp models from replacing world submodels)
@@ -3004,7 +3015,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        //Mod_Q1BSP_ProcessLightList();
 
        if (developer.integer)
-               Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.numleafs, loadmodel->brushq1.visleafs, loadmodel->brushq1.numportals);
+               Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.num_leafs, loadmodel->brushq1.num_visleafs, loadmodel->brushq1.numportals);
 }
 
 static void Mod_Q2BSP_LoadEntities(lump_t *l)
@@ -4424,9 +4435,6 @@ static void Mod_Q3BSP_LoadLightGrid(lump_t *l)
        q3dlightgrid_t *out;
        int count;
 
-       if (l->filelen == 0)
-               return;
-
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
                Host_Error("Mod_Q3BSP_LoadLightGrid: funny lump size in %s",loadmodel->name);
@@ -4443,17 +4451,37 @@ static void Mod_Q3BSP_LoadLightGrid(lump_t *l)
        loadmodel->brushq3.num_lightgrid_isize[1] = loadmodel->brushq3.num_lightgrid_imaxs[1] - loadmodel->brushq3.num_lightgrid_imins[1] + 1;
        loadmodel->brushq3.num_lightgrid_isize[2] = loadmodel->brushq3.num_lightgrid_imaxs[2] - loadmodel->brushq3.num_lightgrid_imins[2] + 1;
        count = loadmodel->brushq3.num_lightgrid_isize[0] * loadmodel->brushq3.num_lightgrid_isize[1] * loadmodel->brushq3.num_lightgrid_isize[2];
-       if (l->filelen < count * (int)sizeof(*in))
-               Host_Error("Mod_Q3BSP_LoadLightGrid: invalid lightgrid lump size %i bytes, should be %i bytes (%ix%ix%i)\n", l->filelen, count * sizeof(*in), loadmodel->brushq3.num_lightgrid_dimensions[0], loadmodel->brushq3.num_lightgrid_dimensions[1], loadmodel->brushq3.num_lightgrid_dimensions[2]);
-       if (l->filelen != count * (int)sizeof(*in))
-               Con_Printf("Mod_Q3BSP_LoadLightGrid: Warning: calculated lightgrid size %i bytes does not match lump size %i\n", count * sizeof(*in), l->filelen);
+       if (l->filelen)
+       {
+               if (l->filelen < count * (int)sizeof(*in))
+                       Host_Error("Mod_Q3BSP_LoadLightGrid: invalid lightgrid lump size %i bytes, should be %i bytes (%ix%ix%i)\n", l->filelen, count * sizeof(*in), loadmodel->brushq3.num_lightgrid_dimensions[0], loadmodel->brushq3.num_lightgrid_dimensions[1], loadmodel->brushq3.num_lightgrid_dimensions[2]);
+               if (l->filelen != count * (int)sizeof(*in))
+                       Con_Printf("Mod_Q3BSP_LoadLightGrid: Warning: calculated lightgrid size %i bytes does not match lump size %i\n", count * sizeof(*in), l->filelen);
+       }
 
        out = Mem_Alloc(loadmodel->mempool, count * sizeof(*out));
        loadmodel->brushq3.data_lightgrid = out;
        loadmodel->brushq3.num_lightgrid = count;
 
        // no swapping or validation necessary
-       memcpy(out, in, count * (int)sizeof(*out));
+       if (l->filelen)
+               memcpy(out, in, count * (int)sizeof(*out));
+       else
+       {
+               // no data, fill with white
+               int i;
+               for (i = 0;i < count;i++)
+               {
+                       out[i].ambientrgb[0] = 128;
+                       out[i].ambientrgb[1] = 128;
+                       out[i].ambientrgb[2] = 128;
+                       out[i].diffusergb[0] = 0;
+                       out[i].diffusergb[1] = 0;
+                       out[i].diffusergb[2] = 0;
+                       out[i].diffusepitch = 0;
+                       out[i].diffuseyaw = 0;
+               }
+       }
 
        Matrix4x4_CreateScale3(&loadmodel->brushq3.num_lightgrid_indexfromworld, loadmodel->brushq3.num_lightgrid_scale[0], loadmodel->brushq3.num_lightgrid_scale[1], loadmodel->brushq3.num_lightgrid_scale[2]);
        Matrix4x4_ConcatTranslate(&loadmodel->brushq3.num_lightgrid_indexfromworld, -loadmodel->brushq3.num_lightgrid_imins[0] * loadmodel->brushq3.num_lightgrid_cellsize[0], -loadmodel->brushq3.num_lightgrid_imins[1] * loadmodel->brushq3.num_lightgrid_cellsize[1], -loadmodel->brushq3.num_lightgrid_imins[2] * loadmodel->brushq3.num_lightgrid_cellsize[2]);
@@ -4465,22 +4493,36 @@ static void Mod_Q3BSP_LoadPVS(lump_t *l)
        int totalchains;
 
        if (l->filelen == 0)
+       {
+               int i;
+               // unvised maps often have cluster indices even without pvs, so check
+               // leafs to find real number of clusters
+               loadmodel->brushq3.num_pvsclusters = 1;
+               for (i = 0;i < loadmodel->brushq3.num_leafs;i++)
+                       loadmodel->brushq3.num_pvsclusters = min(loadmodel->brushq3.num_pvsclusters, loadmodel->brushq3.data_leafs[i].clusterindex + 1);
+
+               // create clusters
+               loadmodel->brushq3.num_pvsclusterbytes = (loadmodel->brushq3.num_pvsclusters + 7) / 8;
+               totalchains = loadmodel->brushq3.num_pvsclusterbytes * loadmodel->brushq3.num_pvsclusters;
+               loadmodel->brushq3.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
+               memset(loadmodel->brushq3.data_pvsclusters, 0xFF, totalchains);
                return;
+       }
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen < 9)
                Host_Error("Mod_Q3BSP_LoadPVS: funny lump size in %s",loadmodel->name);
 
        loadmodel->brushq3.num_pvsclusters = LittleLong(in->numclusters);
-       loadmodel->brushq3.num_pvschainlength = LittleLong(in->chainlength);
-       if (loadmodel->brushq3.num_pvschainlength < ((loadmodel->brushq3.num_pvsclusters + 7) / 8))
-               Host_Error("Mod_Q3BSP_LoadPVS: (chainlength = %i) < ((numclusters = %i) + 7) / 8\n", loadmodel->brushq3.num_pvschainlength, loadmodel->brushq3.num_pvsclusters);
-       totalchains = loadmodel->brushq3.num_pvschainlength * loadmodel->brushq3.num_pvsclusters;
+       loadmodel->brushq3.num_pvsclusterbytes = LittleLong(in->chainlength);
+       if (loadmodel->brushq3.num_pvsclusterbytes < ((loadmodel->brushq3.num_pvsclusters + 7) / 8))
+               Host_Error("Mod_Q3BSP_LoadPVS: (chainlength = %i) < ((numclusters = %i) + 7) / 8\n", loadmodel->brushq3.num_pvsclusterbytes, loadmodel->brushq3.num_pvsclusters);
+       totalchains = loadmodel->brushq3.num_pvsclusterbytes * loadmodel->brushq3.num_pvsclusters;
        if (l->filelen < totalchains + (int)sizeof(*in))
-               Host_Error("Mod_Q3BSP_LoadPVS: lump too small ((numclusters = %i) * (chainlength = %i) + sizeof(q3dpvs_t) == %i bytes, lump is %i bytes)\n", loadmodel->brushq3.num_pvsclusters, loadmodel->brushq3.num_pvschainlength, totalchains + sizeof(*in), l->filelen);
+               Host_Error("Mod_Q3BSP_LoadPVS: lump too small ((numclusters = %i) * (chainlength = %i) + sizeof(q3dpvs_t) == %i bytes, lump is %i bytes)\n", loadmodel->brushq3.num_pvsclusters, loadmodel->brushq3.num_pvsclusterbytes, totalchains + sizeof(*in), l->filelen);
 
-       loadmodel->brushq3.data_pvschains = Mem_Alloc(loadmodel->mempool, totalchains);
-       memcpy(loadmodel->brushq3.data_pvschains, (qbyte *)(in + 1), totalchains);
+       loadmodel->brushq3.data_pvsclusters = Mem_Alloc(loadmodel->mempool, totalchains);
+       memcpy(loadmodel->brushq3.data_pvsclusters, (qbyte *)(in + 1), totalchains);
 }
 
 static void Mod_Q3BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3_t out, vec_t radius)
@@ -5146,7 +5188,7 @@ static int Mod_Q3BSP_BoxTouchingPVS(model_t *model, const qbyte *pvs, const vec3
                                return true;
                        }
 #endif
-                       if (clusterindex < 0 || (pvs[clusterindex >> 3] & (1 << (clusterindex & 7))))
+                       if (CHECKPVSBIT(pvs, clusterindex))
                        {
                                // it is visible, return immediately with the news
                                return true;
@@ -5174,20 +5216,16 @@ static qbyte *Mod_Q3BSP_GetPVS(model_t *model, const vec3_t p)
        while (node->plane)
                node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p,node->plane->normal)) < node->plane->dist];
        if (((q3mleaf_t *)node)->clusterindex >= 0)
-               return model->brushq3.data_pvschains + ((q3mleaf_t *)node)->clusterindex * model->brushq3.num_pvschainlength;
+               return model->brushq3.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brushq3.num_pvsclusterbytes;
        else
                return NULL;
 }
 
 static void Mod_Q3BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbytes, q3mnode_t *node)
 {
-       int i;
-       float d;
-       qbyte *pvs;
-
        while (node->plane)
        {
-               d = PlaneDiff(org, node->plane);
+               float d = PlaneDiff(org, node->plane);
                if (d > radius)
                        node = node->children[0];
                else if (d < -radius)
@@ -5199,23 +5237,21 @@ static void Mod_Q3BSP_FatPVS_RecursiveBSPNode(model_t *model, const vec3_t org,
                        node = node->children[1];
                }
        }
-       // if this is a leaf with a pvs, accumulate the pvs bits
+       // if this leaf is in a cluster, accumulate the pvs bits
        if (((q3mleaf_t *)node)->clusterindex >= 0)
        {
-               pvs = model->brushq3.data_pvschains + ((q3mleaf_t *)node)->clusterindex * model->brushq3.num_pvschainlength;
+               int i;
+               qbyte *pvs = model->brushq1.data_pvsclusters + ((q3mleaf_t *)node)->clusterindex * model->brushq1.num_pvsclusterbytes;
                for (i = 0;i < pvsbytes;i++)
                        pvsbuffer[i] |= pvs[i];
        }
-       else
-               memset(pvsbuffer, 0xFF, pvsbytes);
-       return;
 }
 
 //Calculates a PVS that is the inclusive or of all leafs within radius pixels
 //of the given point.
 static int Mod_Q3BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
 {
-       int bytes = model->brushq3.num_pvschainlength;
+       int bytes = model->brushq3.num_pvsclusterbytes;
        bytes = min(bytes, pvsbufferlength);
        if (r_novis.integer || !loadmodel->brushq3.num_pvsclusters)
        {
index 08686df..f812fdb 100644 (file)
@@ -275,9 +275,8 @@ typedef struct mleaf_s
        // used by polygon-through-portals visibility checker
        int portalmarkid;
 
-       // decompressed pvs bits (potentially visible set)
-       // note: never NULL, always present, may be full of 0xFF though
-       qbyte *pvsdata;
+       // -1 is not in pvs, >= 0 is pvs bit number
+       int clusterindex;
 
        int *firstmarksurface;
        int nummarksurfaces;
@@ -767,5 +766,8 @@ typedef struct
 }
 q3dpvs_t;
 
+#define CHECKPVSBIT(pvs,b) ((b) >= 0 ? ((pvs)[(b) >> 3] & (1 << ((b) & 7))) : false)
+#define SETPVSBIT(pvs,b) ((b) >= 0 ? ((pvs)[(b) >> 3] |= (1 << ((b) & 7))) : false)
+
 #endif
 
index 1846298..268873c 100644 (file)
@@ -192,10 +192,10 @@ typedef struct model_brushq1_s
        mplane_t                *planes;
 
        // number of actual leafs (including 0 which is solid)
-       int                             numleafs;
+       int                             num_leafs;
        // visible leafs, not counting 0 (solid)
-       int                             visleafs;
-       mleaf_t                 *leafs;
+       int                             num_visleafs;
+       mleaf_t                 *data_leafs;
 
        int                             numvertexes;
        mvertex_t               *vertexes;
@@ -232,7 +232,9 @@ typedef struct model_brushq1_s
 
        int                             num_compressedpvs;
        qbyte                   *data_compressedpvs;
-       qbyte                   *data_decompressedpvs;
+       int num_pvsclusters;
+       int num_pvsclusterbytes;
+       unsigned char *data_pvsclusters;
 
        int                             num_lightdata;
        qbyte                   *lightdata;
@@ -517,10 +519,10 @@ typedef struct model_brushq3_s
 
        // pvs
        int num_pvsclusters;
-       int num_pvschainlength;
-       unsigned char *data_pvschains;
+       int num_pvsclusterbytes;
+       unsigned char *data_pvsclusters;
        // example
-       //pvschain = model->brushq3.data_pvschains + mycluster * model->brushq3.num_pvschainlength;
+       //pvschain = model->brushq3.data_pvsclusters + mycluster * model->brushq3.num_pvsclusterbytes;
        //if (pvschain[thatcluster >> 3] & (1 << (thatcluster & 7)))
 }
 model_brushq3_t;
index da91b8f..bf6f274 100644 (file)
--- a/portals.c
+++ b/portals.c
@@ -402,7 +402,7 @@ void Portal_RecursiveFlow (portalrecursioninfo_t *info, mleaf_t *leaf, int first
        }
 
        if (info->leafmark)
-               info->leafmark[leaf - info->model->brushq1.leafs] = true;
+               info->leafmark[leaf - info->model->brushq1.data_leafs] = true;
 
        // mark surfaces in leaf that can be seen through portal
        if (leaf->nummarksurfaces && info->surfacemark)
index af11fd0..89f36ad 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -224,8 +224,8 @@ static void R_RecursiveMarkLights(entity_render_t *ent, vec3_t lightorigin, rdli
 
        // check if leaf is visible according to pvs
        leaf = (mleaf_t *)node;
-       i = (leaf - ent->model->brushq1.leafs) - 1;
-       if (leaf->nummarksurfaces && (i >= pvsbits || pvs[i >> 3] & (1 << (i & 7))))
+       i = leaf->clusterindex;
+       if (leaf->nummarksurfaces && (i >= pvsbits || CHECKPVSBIT(pvs, i)))
        {
                int *surfacepvsframes, d, impacts, impactt;
                float sdist, maxdist, dist2, impact[3];
@@ -285,7 +285,7 @@ void R_MarkLights(entity_render_t *ent)
        int i, bit, bitindex;
        rdlight_t *rd;
        vec3_t lightorigin;
-       if (!gl_flashblend.integer && r_dynamic.integer && ent->model && ent->model->brushq1.numleafs)
+       if (!gl_flashblend.integer && r_dynamic.integer && ent->model && ent->model->brushq1.num_leafs)
        {
                for (i = 0, rd = r_dlight;i < r_numdlights;i++, rd++)
                {
@@ -295,7 +295,7 @@ void R_MarkLights(entity_render_t *ent)
                        lightpvsbytes = 0;
                        if (r_vismarklights.integer && ent->model->brush.FatPVS)
                                lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs));
-                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.visleafs));
+                       R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.num_pvsclusters));
                }
        }
 }
index ce3cc8d..f5d07e3 100644 (file)
@@ -1153,7 +1153,7 @@ int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
        if (ix2 <= ix1 || iy2 <= iy1)
                return true;
        // set up the scissor rectangle
-       GL_Scissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
+       GL_Scissor(ix1, vid.realheight - iy2, ix2 - ix1, iy2 - iy1);
        //qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
        //qglEnable(GL_SCISSOR_TEST);
        c_rt_scissored++;
@@ -1863,6 +1863,7 @@ vec3_t r_editlights_cursorlocation;
 
 static int lightpvsbytes;
 static qbyte lightpvs[(MAX_MAP_LEAFS + 7)/ 8];
+static qbyte lightfullpvs[(MAX_MAP_LEAFS + 7)/ 8];
 
 typedef struct cubemapinfo_s
 {
@@ -2037,18 +2038,34 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
        e->meshchain_light = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, true, false, true);
        if (cl.worldmodel)
        {
+               lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightfullpvs, sizeof(lightfullpvs));
+               memset(lightpvs, 0, lightpvsbytes);
                if (cl.worldmodel->brushq3.num_leafs)
                {
                        q3mleaf_t *leaf;
                        q3mface_t *face;
-                       lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightpvs, sizeof(lightpvs));
+
+                       // make a pvs that only includes things within the box
+                       for (i = 0, leaf = cl.worldmodel->brushq3.data_leafs;i < cl.worldmodel->brushq3.num_leafs;i++, leaf++)
+                               if (CHECKPVSBIT(lightfullpvs, leaf->clusterindex) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
+                                       SETPVSBIT(lightpvs, leaf->clusterindex);
+
+                       // make a cluster list for fast visibility checking during rendering
+                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq3.num_pvsclusters;i++)
+                               if (CHECKPVSBIT(lightpvs, i))
+                                       e->numclusters++;
+                       e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
+                       for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq3.num_pvsclusters;i++)
+                               if (CHECKPVSBIT(lightpvs, i))
+                                       e->clusterindices[e->numclusters++] = i;
+
                        VectorCopy(e->origin, e->mins);
                        VectorCopy(e->origin, e->maxs);
                        for (i = 0, face = cl.worldmodel->brushq3.data_thismodel->firstface;i < cl.worldmodel->brushq3.data_thismodel->numfaces;i++, face++)
                                face->lighttemp_castshadow = false;
                        for (i = 0, leaf = cl.worldmodel->brushq3.data_leafs;i < cl.worldmodel->brushq3.num_leafs;i++, leaf++)
                        {
-                               if ((leaf->clusterindex < 0 || lightpvs[leaf->clusterindex >> 3] & (1 << (leaf->clusterindex & 7))) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
+                               if (CHECKPVSBIT(lightpvs, leaf->clusterindex) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
                                {
                                        for (k = 0;k < 3;k++)
                                        {
@@ -2081,7 +2098,7 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                }
                        }
                }
-               else if (cl.worldmodel->brushq1.numleafs)
+               else if (cl.worldmodel->brushq1.num_leafs)
                {
                        mleaf_t *leaf;
                        msurface_t *surf;
@@ -2097,15 +2114,17 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                qbyte *byteleafpvs;
                                qbyte *bytesurfacepvs;
 
-                               byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numleafs);
+                               byteleafpvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.num_leafs);
                                bytesurfacepvs = Mem_Alloc(tempmempool, cl.worldmodel->brushq1.numsurfaces);
 
                                Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, mins, maxs, e->mins, e->maxs);
 
-                               for (i = 0, leaf = cl.worldmodel->brushq1.leafs;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
+                               // make a pvs that only includes things within the box
+                               for (i = 0, leaf = cl.worldmodel->brushq1.data_leafs;i < cl.worldmodel->brushq1.num_leafs;i++, leaf++)
                                {
                                        if (byteleafpvs[i] && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
                                        {
+                                               SETPVSBIT(lightpvs, leaf->clusterindex);
                                                for (k = 0;k < 3;k++)
                                                {
                                                        if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
@@ -2113,21 +2132,31 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                }
                                        }
                                }
-
+       
                                for (i = 0, surf = cl.worldmodel->brushq1.surfaces;i < cl.worldmodel->brushq1.numsurfaces;i++, surf++)
                                        if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, mins, maxs))
                                                surf->lighttemp_castshadow = true;
 
                                Mem_Free(byteleafpvs);
                                Mem_Free(bytesurfacepvs);
+       
+                               // make a cluster list for fast visibility checking during rendering
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                                       if (CHECKPVSBIT(lightpvs, i))
+                                               e->numclusters++;
+                               e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                                       if (CHECKPVSBIT(lightpvs, i))
+                                               e->clusterindices[e->numclusters++] = i;
                        }
                        else
                        {
-                               lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightpvs, sizeof(lightpvs));
-                               for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.visleafs;i++, leaf++)
+                               for (i = 0, leaf = cl.worldmodel->brushq1.data_leafs;i < cl.worldmodel->brushq1.num_leafs;i++, leaf++)
                                {
-                                       if (lightpvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
+                                       if (CHECKPVSBIT(lightfullpvs, leaf->clusterindex) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
                                        {
+                                               // make a pvs that only includes things within the box
+                                               SETPVSBIT(lightpvs, leaf->clusterindex);
                                                for (k = 0;k < 3;k++)
                                                {
                                                        if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
@@ -2141,6 +2170,20 @@ void R_Shadow_NewWorldLight(vec3_t origin, vec3_t angles, vec3_t color, vec_t ra
                                                }
                                        }
                                }
+
+                               // make a pvs that only includes things within the box
+                               for (i = 0, leaf = cl.worldmodel->brushq1.data_leafs;i < cl.worldmodel->brushq1.num_leafs;i++, leaf++)
+                                       if (CHECKPVSBIT(lightfullpvs, leaf->clusterindex) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
+                                               SETPVSBIT(lightpvs, leaf->clusterindex);
+
+                               // make a cluster list for fast visibility checking during rendering
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                                       if (CHECKPVSBIT(lightpvs, i))
+                                               e->numclusters++;
+                               e->clusterindices = Mem_Alloc(r_shadow_mempool, e->numclusters * sizeof(int));
+                               for (i = 0, e->numclusters = 0;i < cl.worldmodel->brushq1.num_pvsclusters;i++)
+                                       if (CHECKPVSBIT(lightpvs, i))
+                                               e->clusterindices[e->numclusters++] = i;
                        }
 
                        // add surfaces to shadow casting mesh and light mesh
index 953c883..4e1349a 100644 (file)
@@ -76,6 +76,10 @@ typedef struct worldlight_s
        // premade shadow volumes and lit surfaces to render
        shadowmesh_t *meshchain_shadow;
        shadowmesh_t *meshchain_light;
+       
+       // used for visibility testing
+       int numclusters;
+       int *clusterindices;
 }
 worldlight_t;
 
diff --git a/todo b/todo
index bd6e06e..f8f0c15 100644 (file)
--- a/todo
+++ b/todo
@@ -34,6 +34,7 @@
 -n darkplaces: segfault reading memory in windows when starting a new server from menu (yummyluv)
 -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv)
 -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv)
+0 darkplaces: add procedural ripple distortion texture of some sort for use with envmap reflections (FrikaC)
 0 darkplaces: fix q3bsp fogging (Sajt)
 0 darkplaces: add fov to menu
 d darkplaces: fov limit now 1-170, was 10-170