]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
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 fef43b34fcfb7e1053f04a49844ae515cd67ce4d..c79d159577444c603f37725c376513340f98e00e 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 a3ddc491ee50b5c5ade5fe812a2cdd6e885ee18b..75daf7108ceca04c8bec0af4b5b65bf6d720df96 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 cea8a34effeefa0b40ae4519dc8399d6e54e2bd4..1f0349875080a4507d49eb54db0df65459ef3b13 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 08686dfe87d6e08d376872a7d37e3e53739768ae..f812fdb8c61cf7e89b7976b8d511fcafefe533d6 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 18462985b2118aaadd857bb29a7e102928f25f32..268873cf640347f840d2bc4b26c955c3bd762349 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 da91b8f40b774e474a629cb65fd1ffb87079ccce..bf6f27448bda6d683bb6ef017a987d9ef0abdcb3 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 af11fd06dfc926f73ab6044eaf392c08780988a1..89f36ad05328615ae200ffefe01d3fda792bcf90 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 ce3cc8dcbd1a598efd35246b746a75dcfbff56c0..f5d07e3172e2c81a3f3bffc64ba0076392f38280 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 953c883cc7f3a391a11083a41fa37bdaf6076d46..4e1349a34071fa9fa290280dfeddf20326327f61 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 bd6e06e5c0a4f15c7a6c6927b2bf34b6883c80ef..f8f0c158f1d9bf3b74e15984553c3c87c8251746 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