rewrote how texture chains are handled, they are now stored outside the surfaces...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 16 Nov 2002 01:24:03 +0000 (01:24 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 16 Nov 2002 01:24:03 +0000 (01:24 +0000)
good efficiency improvement I think

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

gl_rsurf.c
model_brush.c
model_brush.h
model_shared.h

index add2b1a..db6c318 100644 (file)
@@ -747,7 +747,7 @@ static int RSurf_LightCheck(const matrix4x4_t *matrix, const int *dlightbits, co
        return false;
 }
 
-static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -784,7 +784,7 @@ static void RSurfShader_Sky(const entity_render_t *ent, const texture_t *texture
        }
        m.depthwrite = true;
        R_Mesh_State(&m);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -878,13 +878,14 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        }
 }
 
-static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Water(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
+       msurface_t **chain;
        vec3_t center;
        if (texture->rendertype != SURFRENDER_OPAQUE)
        {
-               for (surf = firstsurf;surf;surf = surf->texturechain)
+               for (chain = surfchain;(surf = *chain) != NULL;*chain++)
                {
                        if (surf->visframe == r_framecount)
                        {
@@ -894,7 +895,7 @@ static void RSurfShader_Water(const entity_render_t *ent, const texture_t *textu
                }
        }
        else
-               for (surf = firstsurf;surf;surf = surf->texturechain)
+               for (chain = surfchain;(surf = *chain) != NULL;*chain++)
                        if (surf->visframe == r_framecount)
                                RSurfShader_Water_Callback(ent, surf - ent->model->surfaces);
 }
@@ -995,7 +996,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1006,7 +1007,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
        m.tex[0] = R_GetTexture(texture->texture);
-       m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
+       m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
        m.tex[2] = R_GetTexture(texture->detailtexture);
        m.texrgbscale[0] = 1;
        m.texrgbscale[1] = 4;
@@ -1014,7 +1015,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        R_Mesh_State(&m);
        cl = (float) (1 << r_lightmapscalebit) * r_colorscale;
        GL_Color(cl, cl, cl, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1037,7 +1038,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1047,12 +1048,12 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent
        m.blendfunc1 = GL_ONE;
        m.blendfunc2 = GL_ZERO;
        m.tex[0] = R_GetTexture(texture->texture);
-       m.tex[1] = R_GetTexture(firstsurf->lightmaptexture);
+       m.tex[1] = R_GetTexture((**surfchain).lightmaptexture);
        if (gl_combine.integer)
                m.texrgbscale[1] = 4;
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1074,7 +1075,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1085,7 +1086,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent,
        m.tex[0] = R_GetTexture(texture->texture);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1100,7 +1101,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent,
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1109,12 +1110,12 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent,
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ZERO;
        m.blendfunc2 = GL_SRC_COLOR;
-       m.tex[0] = R_GetTexture(firstsurf->lightmaptexture);
+       m.tex[0] = R_GetTexture((**surfchain).lightmaptexture);
        if (gl_combine.integer)
                m.texrgbscale[0] = 4;
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1135,7 +1136,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent,
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1154,7 +1155,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const
        }
        R_Mesh_State(&m);
        GL_UseColorArray();
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount && surf->dlightframe == r_framecount)
                {
@@ -1175,7 +1176,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1187,7 +1188,7 @@ static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const te
        m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
        R_Mesh_State(&m);
        GL_UseColorArray();
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1204,7 +1205,7 @@ static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const te
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1215,7 +1216,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c
        m.tex[0] = R_GetTexture(texture->detailtexture);
        R_Mesh_State(&m);
        GL_Color(1, 1, 1, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1230,7 +1231,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1241,7 +1242,7 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t
        m.tex[0] = R_GetTexture(texture->glowtexture);
        R_Mesh_State(&m);
        GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1256,7 +1257,7 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t
        }
 }
 
-static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
        const surfmesh_t *mesh;
@@ -1270,7 +1271,7 @@ static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, c
                GL_Color(r_colorscale, r_colorscale, r_colorscale, 1);
        else
                GL_Color(0, 0, 0, 1);
-       for (surf = firstsurf;surf;surf = surf->texturechain)
+       while((surf = *surfchain++) != NULL)
        {
                if (surf->visframe == r_framecount)
                {
@@ -1315,14 +1316,15 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata
                RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha);
 }
 
-static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *firstsurf)
+static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_t *texture, msurface_t **surfchain)
 {
        const msurface_t *surf;
+       msurface_t **chain;
        vec3_t center;
        if (texture->rendertype != SURFRENDER_OPAQUE)
        {
                // transparent vertex shaded from lightmap
-               for (surf = firstsurf;surf;surf = surf->texturechain)
+               for (chain = surfchain;(surf = *chain) != NULL;chain++)
                {
                        if (surf->visframe == r_framecount)
                        {
@@ -1334,22 +1336,22 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
        else if (r_shadow_lightingmode >= 2)
        {
                // opaque base lighting
-               RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, firstsurf);
+               RSurfShader_OpaqueWall_Pass_OpaqueGlow(ent, texture, surfchain);
                if (fogenabled)
-                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain);
        }
        else if (r_vertexsurfaces.integer)
        {
                // opaque vertex shaded from lightmap
-               for (surf = firstsurf;surf;surf = surf->texturechain)
+               for (chain = surfchain;(surf = *chain) != NULL;chain++)
                        if (surf->visframe == r_framecount)
                                RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, texture->rendertype, texture->currentalpha);
                if (texture->glowtexture)
-                       for (surf = firstsurf;surf;surf = surf->texturechain)
+                       for (chain = surfchain;(surf = *chain) != NULL;chain++)
                                if (surf->visframe == r_framecount)
                                        RSurfShader_Wall_Pass_Glow(ent, surf, texture, texture->rendertype, texture->currentalpha);
                if (fogenabled)
-                       for (surf = firstsurf;surf;surf = surf->texturechain)
+                       for (chain = surfchain;(surf = *chain) != NULL;chain++)
                                if (surf->visframe == r_framecount)
                                        RSurfShader_Wall_Pass_Fog(ent, surf, texture, texture->rendertype, texture->currentalpha);
        }
@@ -1359,27 +1361,27 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_
                if (r_textureunits.integer >= 2)
                {
                        if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, firstsurf);
+                               RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(ent, texture, surfchain);
                        else
                        {
-                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, firstsurf);
+                               RSurfShader_OpaqueWall_Pass_BaseDoubleTex(ent, texture, surfchain);
                                if (r_detailtextures.integer)
-                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+                                       RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain);
                        }
                }
                else
                {
-                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, firstsurf);
-                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_BaseTexture(ent, texture, surfchain);
+                       RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, texture, surfchain);
                        if (r_detailtextures.integer)
-                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, firstsurf);
+                               RSurfShader_OpaqueWall_Pass_BaseDetail(ent, texture, surfchain);
                }
                if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT))
-                       RSurfShader_OpaqueWall_Pass_Light(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_Light(ent, texture, surfchain);
                if (texture->glowtexture)
-                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain);
                if (fogenabled)
-                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, firstsurf);
+                       RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain);
        }
 }
 
@@ -1488,14 +1490,14 @@ void R_PrepareSurfaces(entity_render_t *ent)
        }
 }
 
-void R_DrawSurfaces(entity_render_t *ent, int type)
+void R_DrawSurfaces(entity_render_t *ent, int type, msurface_t ***chains)
 {
        int i;
        texture_t *t;
        R_Mesh_Matrix(&ent->matrix);
        for (i = 0, t = ent->model->textures;i < ent->model->numtextures;i++, t++)
-               if (t->shader->shaderfunc[type] && t->currentframe && ent->model->texturesurfacechains[i])
-                       t->shader->shaderfunc[type](ent, t->currentframe, ent->model->texturesurfacechains[i]);
+               if (t->shader->shaderfunc[type] && t->currentframe && chains[i] != NULL)
+                       t->shader->shaderfunc[type](ent, t->currentframe, chains[i]);
 }
 
 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
@@ -1532,24 +1534,17 @@ static void R_DrawPortals(entity_render_t *ent)
        int i;
        mportal_t *portal, *endportal;
        float temp[3], center[3], f;
-
-       if (r_drawportals.integer < 1)
-               return;
-
        for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
        {
-               if (portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount)
+               if ((portal->here->pvsframe == ent->model->pvsframecount || portal->past->pvsframe == ent->model->pvsframecount) && portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
                {
-                       if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
-                       {
-                               VectorClear(temp);
-                               for (i = 0;i < portal->numpoints;i++)
-                                       VectorAdd(temp, portal->points[i].position, temp);
-                               f = ixtable[portal->numpoints];
-                               VectorScale(temp, f, temp);
-                               Matrix4x4_Transform(&ent->matrix, temp, center);
-                               R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
-                       }
+                       VectorClear(temp);
+                       for (i = 0;i < portal->numpoints;i++)
+                               VectorAdd(temp, portal->points[i].position, temp);
+                       f = ixtable[portal->numpoints];
+                       VectorScale(temp, f, temp);
+                       Matrix4x4_Transform(&ent->matrix, temp, center);
+                       R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
                }
        }
 }
@@ -1580,22 +1575,12 @@ void R_PrepareBrushModel(entity_render_t *ent)
                if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
                {
                        if ((surf->flags & SURF_PLANEBACK))
-                       {
                                surfacevisframes[i] = r_framecount;
-                               surfacepvsframes[i] = model->pvsframecount;
-                       }
-               }
-               else
-               {
-                       if (!(surf->flags & SURF_PLANEBACK))
-                       {
-                               surfacevisframes[i] = r_framecount;
-                               surfacepvsframes[i] = model->pvsframecount;
-                       }
                }
+               else if (!(surf->flags & SURF_PLANEBACK))
+                       surfacevisframes[i] = r_framecount;
 #else
                surfacevisframes[i] = r_framecount;
-               surfacepvsframes[i] = model->pvsframecount;
 #endif
                surf->dlightframe = -1;
        }
@@ -1757,20 +1742,12 @@ void R_PVSUpdate (entity_render_t *ent, mleaf_t *viewleaf)
                                                        leaf->pvsframe = model->pvsframecount;
                                                        // mark surfaces bounding this leaf as visible
                                                        for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--, mark++)
-                                                       {
-                                                               //if (surfacepvsframes[*mark] != model->pvsframecount)
-                                                               //{
-                                                                       surfacepvsframes[*mark] = model->pvsframecount;
-                                                               //      model->pvssurflist[model->pvssurflistlength++] = *mark;
-                                                               //}
-                                                       }
+                                                               surfacepvsframes[*mark] = model->pvsframecount;
                                                }
                                        }
                                }
                        }
-                       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
-                               if (model->surfacepvsframes[j] == model->pvsframecount)
-                                       model->pvssurflist[model->pvssurflistlength++] = j;
+                       Mod_BuildPVSTextureChains(model);
                }
        }
 }
@@ -1796,15 +1773,15 @@ void R_WorldVisibility (entity_render_t *ent)
 void R_DrawWorld (entity_render_t *ent)
 {
        R_PrepareSurfaces(ent);
-       R_DrawSurfaces(ent, SHADERSTAGE_SKY);
-       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
+       R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->pvstexturechains);
+       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_DrawSky (entity_render_t *ent)
 {
        if (ent != &cl_entities[0].render)
                R_PrepareBrushModel(ent);
-       R_DrawSurfaces(ent, SHADERSTAGE_SKY);
+       R_DrawSurfaces(ent, SHADERSTAGE_SKY, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_Draw (entity_render_t *ent)
@@ -1812,7 +1789,7 @@ void R_Model_Brush_Draw (entity_render_t *ent)
        c_bmodels++;
        if (ent != &cl_entities[0].render)
                R_PrepareBrushModel(ent);
-       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
+       R_DrawSurfaces(ent, SHADERSTAGE_NORMAL, ent->model->pvstexturechains);
 }
 
 void R_Model_Brush_DrawShadowVolume (entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
index 9e805ef..d4b1314 100644 (file)
@@ -236,6 +236,7 @@ static void Mod_LoadTextures (lump_t *l)
        // fill out all slots with notexture
        for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
        {
+               tx->number = i;
                tx->width = 16;
                tx->height = 16;
                tx->texture = r_notexture;
@@ -2738,6 +2739,42 @@ static void Mod_BuildSurfaceNeighbors (msurface_t *surfaces, int numsurfaces, me
 #endif
 }
 
+void Mod_BuildPVSTextureChains(model_t *model)
+{
+       int i, j;
+       for (i = 0;i < model->numtextures;i++)
+               model->pvstexturechainslength[i] = 0;
+       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+       {
+               if (model->surfacepvsframes[j] == model->pvsframecount)
+               {
+                       model->pvssurflist[model->pvssurflistlength++] = j;
+                       model->pvstexturechainslength[model->surfaces[j].texinfo->texture->number]++;
+               }
+       }
+       for (i = 0, j = 0;i < model->numtextures;i++)
+       {
+               if (model->pvstexturechainslength[i])
+               {
+                       model->pvstexturechains[i] = model->pvstexturechainsbuffer + j;
+                       j += model->pvstexturechainslength[i] + 1;
+               }
+               else
+                       model->pvstexturechains[i] = NULL;
+       }
+       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+               if (model->surfacepvsframes[j] == model->pvsframecount)
+                       *model->pvstexturechains[model->surfaces[j].texinfo->texture->number]++ = model->surfaces + j;
+       for (i = 0;i < model->numtextures;i++)
+       {
+               if (model->pvstexturechainslength[i])
+               {
+                       *model->pvstexturechains[i] = NULL;
+                       model->pvstexturechains[i] -= model->pvstexturechainslength[i];
+               }
+       }
+}
+
 /*
 =================
 Mod_LoadBrushModel
@@ -2818,11 +2855,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                float dist, modelyawradius, modelradius, *vec;
                msurface_t *surf;
 
-               mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
-               mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
-               modelyawradius = 0;
-               modelradius = 0;
-
                bm = &mod->submodels[i];
 
                mod->hulls[0].firstclipnode = bm->headnode[0];
@@ -2841,18 +2873,22 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->DrawFakeShadow = NULL;
                mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
                mod->DrawLight = R_Model_Brush_DrawLight;
-               mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
+               mod->pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t **));
+               mod->pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool, (mod->nummodelsurfaces + mod->numtextures) * sizeof(msurface_t *));
+               mod->pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(int));
+               Mod_BuildPVSTextureChains(mod);
                if (mod->nummodelsurfaces)
                {
                        // LordHavoc: calculate bmodel bounding box rather than trusting what it says
+                       mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+                       mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+                       modelyawradius = 0;
+                       modelradius = 0;
                        for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
                        {
                                // we only need to have a drawsky function if it is used (usually only on world model)
                                if (surf->texinfo->texture->shader == &Cshader_sky)
                                        mod->DrawSky = R_Model_Brush_DrawSky;
-                               // link into texture chain
-                               surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
-                               mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
                                // calculate bounding shapes
                                for (k = 0;k < surf->numedges;k++)
                                {
@@ -2884,28 +2920,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
                        mod->radius = modelradius;
                        mod->radius2 = modelradius * modelradius;
-                       // LordHavoc: build triangle meshs for entire model's geometry
-                       // (only used for shadow volumes)
-                       mod->shadowmesh = Mod_ShadowMesh_Begin(originalloadmodel->mempool, 1024);
-                       for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
-                               if (surf->flags & SURF_SHADOWCAST)
-                                       Mod_ShadowMesh_AddPolygon(originalloadmodel->mempool, mod->shadowmesh, surf->poly_numverts, surf->poly_verts);
-                       mod->shadowmesh = Mod_ShadowMesh_Finish(originalloadmodel->mempool, mod->shadowmesh);
-                       Mod_ShadowMesh_CalcBBox(mod->shadowmesh, mod->shadowmesh_mins, mod->shadowmesh_maxs, mod->shadowmesh_center, &mod->shadowmesh_radius);
                }
                else
                {
                        // LordHavoc: empty submodel (lacrima.bsp has such a glitch)
                        Con_Printf("warning: empty submodel *%i in %s\n", i+1, loadname);
-                       VectorClear(mod->normalmins);
-                       VectorClear(mod->normalmaxs);
-                       VectorClear(mod->yawmins);
-                       VectorClear(mod->yawmaxs);
-                       VectorClear(mod->rotatedmins);
-                       VectorClear(mod->rotatedmaxs);
-                       mod->radius = 0;
-                       mod->radius2 = 0;
-                       mod->shadowmesh = NULL;
                }
                Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);
 
index a034185..557c2ce 100644 (file)
@@ -82,7 +82,7 @@ struct msurface_s;
 // change this stuff when real shaders are added
 typedef struct Cshader_s
 {
-       void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, const struct msurface_s *firstsurf);
+       void (*shaderfunc[SHADERSTAGE_COUNT])(const struct entity_render_s *ent, const struct texture_s *texture, struct msurface_s **surfchain);
        int flags;
 }
 Cshader_t;
@@ -100,6 +100,9 @@ typedef struct texture_s
        // SURF_ flags
        unsigned int flags;
 
+       // position in the model's textures array
+       int number;
+
        // type of rendering (SURFRENDER_ value)
        int rendertype;
 
@@ -380,6 +383,7 @@ void Mod_FindNonSolidLocation(vec3_t pos, struct model_s *mod);
 mleaf_t *Mod_PointInLeaf (const float *p, struct model_s *model);
 int Mod_PointContents (const float *p, struct model_s *model);
 qbyte *Mod_LeafPVS (mleaf_t *leaf, struct model_s *model);
+void Mod_BuildPVSTextureChains(struct model_s *model);
 
 #endif
 
index 745f2ce..1bcd0a1 100644 (file)
@@ -188,8 +188,6 @@ typedef struct model_s
        int                             numtextures;
        texture_t               *textures;
 
-       msurface_t              **texturesurfacechains;
-
        qbyte                   *visdata;
        qbyte                   *lightdata;
        char                    *entities;
@@ -203,11 +201,6 @@ typedef struct model_s
        int                             numlights;
        mlight_t                *lights;
 
-       // used only for casting dynamic shadow volumes
-       shadowmesh_t    *shadowmesh;
-       vec3_t                  shadowmesh_mins, shadowmesh_maxs, shadowmesh_center;
-       float                   shadowmesh_radius;
-
        // pvs visibility marking
        mleaf_t                 *pvsviewleaf;
        int                             pvsviewleafnovis;
@@ -215,6 +208,12 @@ typedef struct model_s
        mleaf_t                 *pvsleafchain;
        int                             *pvssurflist;
        int                             pvssurflistlength;
+       // these get rebuilt as the player moves around if this is the world,
+       // otherwise they are left alone (no pvs for bmodels)
+       msurface_t              ***pvstexturechains;
+       msurface_t              **pvstexturechainsbuffer;
+       int                             *pvstexturechainslength;
+
 
        // skin animation info
        animscene_t             *skinscenes; // [numskins]