]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Fix crash in q3bsp loading on submodels where it was adding the submodelsurfaces_star...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 29 Dec 2020 05:04:43 +0000 (05:04 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 29 Dec 2020 05:04:43 +0000 (05:04 +0000)
Fix missing submodels in q3bsp loading where it was allocating a separate modelsurfaces_sorted for each submodel which was probably coming out uninitialized.

Simplified Mod_MakeSortedSurfaces a little by sorting each submodel separately - no need to worry about sorting by submodel this way, they're going to stay in the same ranges.

Refactored away the many duplicates of the mod->DrawSky and mod->DrawAddWaterPlanes setting code into Mod_SetDrawSkyAndWater function which is called after loader (and in submodel creation), this also means it checks for NULL texture pointer consistently whereas that varied a bit in the past by loader.

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

gl_rmain.c
gl_rsurf.c
model_alias.c
model_brush.c
model_shared.c
model_shared.h
model_sprite.c

index 747c5f0ed0889c3aa286d95f4515f0763e9190b8..7764d9044af9c87a4afcd812b8dc6379f3907b2f 100644 (file)
@@ -10065,7 +10065,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep
        }
        else if (ui)
        {
-               // for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces)
+               // for ui we have to preserve the order of surfaces (not using modelsurfaces_sorted)
                for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++)
                        r_surfacelist[numsurfacelist++] = surfaces + i;
        }
index 603666a3ee4a99eda55e1da4968ac31df9b1da39..d9497d4367b76f867eaab72a8f07dd5d4429baab 100644 (file)
@@ -602,7 +602,7 @@ void R_Mod_DrawSky(entity_render_t *ent)
 
 void R_Mod_DrawAddWaterPlanes(entity_render_t *ent)
 {
-       int i, j, n, flagsmask;
+       int i, n, flagsmask;
        model_t *model = ent->model;
        msurface_t *surfaces;
        if (model == NULL)
@@ -617,12 +617,9 @@ void R_Mod_DrawAddWaterPlanes(entity_render_t *ent)
        if (ent == r_refdef.scene.worldentity)
        {
                for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
-               {
-                       j = model->modelsurfaces_sorted[i];
-                       if (r_refdef.viewcache.world_surfacevisible[j])
-                               if (surfaces[j].texture->basematerialflags & flagsmask)
-                                       R_Water_AddWaterPlane(surfaces + j, 0);
-               }
+                       if (r_refdef.viewcache.world_surfacevisible[i])
+                               if (surfaces[i].texture->basematerialflags & flagsmask)
+                                       R_Water_AddWaterPlane(surfaces + i, 0);
        }
        else
        {
@@ -631,11 +628,8 @@ void R_Mod_DrawAddWaterPlanes(entity_render_t *ent)
                else
                        n = 0;
                for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
-               {
-                       j = model->modelsurfaces_sorted[i];
-                       if (surfaces[j].texture->basematerialflags & flagsmask)
-                               R_Water_AddWaterPlane(surfaces + j, n);
-               }
+                       if (surfaces[i].texture->basematerialflags & flagsmask)
+                               R_Water_AddWaterPlane(surfaces + i, n);
        }
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 }
index f438da4b148e329311cfe162e91a3052597efd45..b9990beb6b28e5dd6e9c20082cbc99d567fa3c0a 100644 (file)
@@ -1004,8 +1004,6 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
        loadmodel->modeldatatypestring = "MDL";
 
        loadmodel->type = mod_alias;
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -1321,15 +1319,6 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
@@ -1364,8 +1353,6 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
        loadmodel->modeldatatypestring = "MD2";
 
        loadmodel->type = mod_alias;
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -1586,15 +1573,6 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
@@ -1624,8 +1602,6 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
        loadmodel->modeldatatypestring = "MD3";
 
        loadmodel->type = mod_alias;
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -1777,15 +1753,6 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
@@ -1860,8 +1827,6 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                return;
        }
 
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -2171,15 +2136,6 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
@@ -2238,8 +2194,6 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                return;
        }
 
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -2546,15 +2500,6 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 // no idea why PSK/PSA files contain weird quaternions but they do...
@@ -2588,8 +2533,6 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        loadmodel->modeldatatypestring = "PSK";
 
        loadmodel->type = mod_alias;
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -3218,15 +3161,6 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
                loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
        }
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
 
 void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend)
@@ -3413,8 +3347,6 @@ void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 
        text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
 
-       loadmodel->DrawSky = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
        loadmodel->Draw = R_Mod_Draw;
        loadmodel->DrawDepth = R_Mod_DrawDepth;
        loadmodel->DrawDebug = R_Mod_DrawDebug;
@@ -3966,13 +3898,4 @@ void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        if (joint1       ) Mem_Free(joint1       );joint1        = NULL;
        if (pose         ) Mem_Free(pose         );pose          = NULL;
        if (pose1        ) Mem_Free(pose1        );pose1         = NULL;
-
-       // because shaders can do somewhat unexpected things, check for unusual features now
-       for (i = 0;i < loadmodel->num_textures;i++)
-       {
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
-                       mod->DrawSky = R_Mod_DrawSky;
-               if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-       }
 }
index bf59730316867b606e3986d92130d5fe7823cb28..0c9c81c6e559c95888f0eb840681cee1f93501b8 100644 (file)
@@ -4123,26 +4123,10 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend)
                mod->radius = modelradius;
                mod->radius2 = modelradius * modelradius;
 
-               // this gets altered below if sky or water is used
-               mod->DrawSky = NULL;
-               mod->DrawAddWaterPlanes = NULL;
+               Mod_SetDrawSkyAndWater(mod);
 
-               // scan surfaces for sky and water and flag the submodel as possessing these features or not
-               // build lightstyle lists for quick marking of dirty lightmaps when lightstyles flicker
                if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
                {
-                       for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
-                               if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
-                                       break;
-                       if (j < mod->submodelsurfaces_end)
-                               mod->DrawSky = R_Mod_DrawSky;
-
-                       for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
-                               if (mod->data_surfaces[j].texture && mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                                       break;
-                       if (j < mod->submodelsurfaces_end)
-                               mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
                        // build lightstyle update chains
                        // (used to rapidly mark lightmapupdateflags on many surfaces
                        // when d_lightstylevalue changes)
@@ -5066,26 +5050,11 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend)
                mod->radius = modelradius;
                mod->radius2 = modelradius * modelradius;
 
-               // this gets altered below if sky or water is used
-               mod->DrawSky = NULL;
-               mod->DrawAddWaterPlanes = NULL;
+               Mod_SetDrawSkyAndWater(mod);
 
-               // scan surfaces for sky and water and flag the submodel as possessing these features or not
                // build lightstyle lists for quick marking of dirty lightmaps when lightstyles flicker
                if (mod->submodelsurfaces_start < mod->submodelsurfaces_end)
                {
-                       for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
-                               if (mod->data_surfaces[j].texture && (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY))
-                                       break;
-                       if (j < mod->submodelsurfaces_end)
-                               mod->DrawSky = R_Mod_DrawSky;
-
-                       for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
-                               if (mod->data_surfaces[j].texture && (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
-                                       break;
-                       if (j < mod->submodelsurfaces_end)
-                               mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
                        // build lightstyle update chains
                        // (used to rapidly mark lightmapupdateflags on many surfaces
                        // when d_lightstylevalue changes)
@@ -7564,6 +7533,7 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->brush.submodels = (model_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brush.numsubmodels * sizeof(model_t *));
 
        mod = loadmodel;
+       mod->modelsurfaces_sorted = (int*)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
        for (i = 0;i < loadmodel->brush.numsubmodels;i++)
        {
                if (i > 0)
@@ -7598,7 +7568,6 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                mod->submodelsurfaces_end = mod->brushq3.data_models[i].firstface + mod->brushq3.data_models[i].numfaces;
                mod->firstmodelbrush = mod->brushq3.data_models[i].firstbrush;
                mod->nummodelbrushes = mod->brushq3.data_models[i].numbrushes;
-               mod->modelsurfaces_sorted = (int *)Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted));
 
                VectorCopy(mod->brushq3.data_models[i].mins, mod->normalmins);
                VectorCopy(mod->brushq3.data_models[i].maxs, mod->normalmaxs);
@@ -7610,7 +7579,7 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                //printf("Editing model %d... BEFORE re-bounding: %f %f %f - %f %f %f\n", i, mod->normalmins[0], mod->normalmins[1], mod->normalmins[2], mod->normalmaxs[0], mod->normalmaxs[1], mod->normalmaxs[2]);
                for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
                {
-                       const msurface_t *surface = mod->data_surfaces + j + mod->submodelsurfaces_start;
+                       const msurface_t *surface = mod->data_surfaces + j;
                        const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex;
                        int k;
                        if (!surface->num_vertices)
@@ -7640,22 +7609,7 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend)
                mod->radius = modelradius;
                mod->radius2 = modelradius * modelradius;
 
-               // this gets altered below if sky or water is used
-               mod->DrawSky = NULL;
-               mod->DrawAddWaterPlanes = NULL;
-
-               for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++)
-                       if (mod->data_surfaces[j].texture && mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
-                               break;
-               if (j < mod->submodelsurfaces_end)
-                       mod->DrawSky = R_Mod_DrawSky;
-
-               for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
-                       if (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                               break;
-               if (j < mod->submodelsurfaces_end)
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
-
+               Mod_SetDrawSkyAndWater(mod);
                Mod_MakeCollisionBIH(mod, false, &mod->collision_bih);
                Mod_MakeCollisionBIH(mod, true, &mod->render_bih);
 
@@ -8291,21 +8245,7 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend)
                mod->radius = modelradius;
                mod->radius2 = modelradius * modelradius;
 
-               // this gets altered below if sky or water is used
-               mod->DrawSky = NULL;
-               mod->DrawAddWaterPlanes = NULL;
-
-               for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
-                       if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY)
-                               break;
-               if (j < mod->submodelsurfaces_end)
-                       mod->DrawSky = R_Mod_DrawSky;
-
-               for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
-                       if (mod->data_surfaces[j].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
-                               break;
-               if (j < mod->submodelsurfaces_end)
-                       mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
+               Mod_SetDrawSkyAndWater(mod);
 
                Mod_MakeCollisionBIH(mod, true, &mod->collision_bih);
                mod->render_bih = mod->collision_bih;
index 15e9fd9895c6e7e5e0fa54083b39587c3dccd9d3..e29e3f8dac4ddaa21f24770bbd263c6985b39a39 100644 (file)
@@ -540,6 +540,7 @@ model_t *Mod_LoadModel(model_t *mod, qbool crash, qbool checkdisk)
                                        Mem_Free(buf);
                                }
 
+                               Mod_SetDrawSkyAndWater(mod);
                                Mod_BuildVBOs();
                                break;
                        }
@@ -2881,9 +2882,25 @@ void Mod_VertexRangeFromElements(int numelements, const int *elements, int *firs
                *lastvertexpointer = lastvertex;
 }
 
+void Mod_SetDrawSkyAndWater(model_t* mod)
+{
+       size_t j;
+       uint64_t basematerialflags = 0;
+       // by default assume there is no sky or water used in this model
+       mod->DrawSky = NULL;
+       mod->DrawAddWaterPlanes = NULL;
+       // combine all basematerialflags observed in the submodelsurfaces range, then check for special flags
+       for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++)
+               if (mod->data_surfaces[j].texture)
+                       basematerialflags |= mod->data_surfaces[j].texture->basematerialflags;
+       if (basematerialflags & MATERIALFLAG_SKY)
+               mod->DrawSky = R_Mod_DrawSky;
+       if (basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
+               mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes;
+}
+
 typedef struct Mod_MakeSortedSurfaces_qsortsurface_s
 {
-       int submodel;
        int surfaceindex;
        q3deffect_t* effect;
        texture_t* texture;
@@ -2895,10 +2912,6 @@ static int Mod_MakeSortedSurfaces_qsortfunc(const void *a, const void *b)
 {
        const Mod_MakeSortedSurfaces_qsortsurface_t* l = (Mod_MakeSortedSurfaces_qsortsurface_t*)a;
        const Mod_MakeSortedSurfaces_qsortsurface_t* r = (Mod_MakeSortedSurfaces_qsortsurface_t*)b;
-       if (l->submodel < r->submodel)
-               return -1;
-       if (l->submodel > r->submodel)
-               return 1;
        if (l->effect < r->effect)
                return -1;
        if (l->effect > r->effect)
@@ -2928,16 +2941,14 @@ void Mod_MakeSortedSurfaces(model_t *mod)
        // the goal is to sort by submodel (can't change which submodel a surface belongs to), and then by effects and textures
        for (j = 0; j < mod->num_surfaces; j++)
        {
-               info[j].submodel = 0;
                info[j].surfaceindex = j;
                info[j].effect = mod->data_surfaces[j].effect;
                info[j].texture = mod->data_surfaces[j].texture;
                info[j].lightmaptexture = mod->data_surfaces[j].lightmaptexture;
        }
        for (k = 0; k < mod->brush.numsubmodels; k++)
-               for (j = mod->brush.submodels[k]->submodelsurfaces_start; j < mod->brush.submodels[k]->submodelsurfaces_end; j++)
-                       info[j].submodel = k;
-       qsort(info, mod->num_surfaces, sizeof(*info), Mod_MakeSortedSurfaces_qsortfunc);
+               if (mod->brush.submodels[k]->submodelsurfaces_end > mod->brush.submodels[k]->submodelsurfaces_start + 1)
+                       qsort(info + mod->brush.submodels[k]->submodelsurfaces_start, (size_t)mod->brush.submodels[k]->submodelsurfaces_end - mod->brush.submodels[k]->submodelsurfaces_start, sizeof(*info), Mod_MakeSortedSurfaces_qsortfunc);
        for (j = 0; j < mod->num_surfaces; j++)
                mod->modelsurfaces_sorted[j] = info[j].surfaceindex;
 }
index b5312b8c6f37322dd55ca57452357cfb55abe655..d131fb8bccf9f0e5bfa756775ec67ad5ecb28f37 100644 (file)
@@ -501,9 +501,9 @@ typedef struct model_s
        const char              *modeldatatypestring;
        // generates vertex data for a given frameblend
        void(*AnimateVertices)(const struct model_s * RESTRICT model, const struct frameblend_s * RESTRICT frameblend, const struct skeleton_s *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f);
-       // draw the model's sky polygons (only used by brush models)
+       // draw the model's sky polygons
        void(*DrawSky)(struct entity_render_s *ent);
-       // draw refraction/reflection textures for the model's water polygons (only used by brush models)
+       // draw refraction/reflection textures for the model's water polygons
        void(*DrawAddWaterPlanes)(struct entity_render_s *ent);
        // draw the model using lightmap/dlight shading
        void(*Draw)(struct entity_render_s *ent);
@@ -606,6 +606,11 @@ void Mod_MakeSortedSurfaces(model_t *mod);
 // automatically called after model loader returns
 void Mod_BuildVBOs(void);
 
+/// Sets the mod->DrawSky and mod->DrawAddWaterPlanes pointers conditionally based on whether surfaces in this submodel use these features
+/// called specifically by brush model loaders when generating submodels
+/// automatically called after model loader returns
+void Mod_SetDrawSkyAndWater(model_t* mod);
+
 shadowmesh_t *Mod_ShadowMesh_Alloc(struct mempool_s *mempool, int maxverts, int maxtriangles);
 int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, const float *vertex3f);
 void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i);
index d21d88ff97da2ebd5667a074e3896473934bb0d2..44d8f0aee893c34bfbd4bc07b52ec3d401189a6a 100644 (file)
@@ -274,11 +274,9 @@ void Mod_IDSP_Load(model_t *mod, void *buffer, void *bufferend)
 
        loadmodel->type = mod_sprite;
 
-       loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Sprite_Draw;
        loadmodel->DrawDepth = NULL;
        loadmodel->DrawLight = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
 
        version = LittleLong(((dsprite_t *)buffer)->version);
        if (version == SPRITE_VERSION || version == SPRITE32_VERSION)
@@ -389,11 +387,9 @@ void Mod_IDS2_Load(model_t *mod, void *buffer, void *bufferend)
 
        loadmodel->type = mod_sprite;
 
-       loadmodel->DrawSky = NULL;
        loadmodel->Draw = R_Model_Sprite_Draw;
        loadmodel->DrawDepth = NULL;
        loadmodel->DrawLight = NULL;
-       loadmodel->DrawAddWaterPlanes = NULL;
 
        pinqsprite = (dsprite2_t *)buffer;