From 91642e0dd9ae0445824471d689d8023af3da31e8 Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 29 Dec 2020 05:04:43 +0000 Subject: [PATCH] Fix crash in q3bsp loading on submodels where it was adding the submodelsurfaces_start and shouldn't (reported by Cloudwalk - thanks). 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 | 2 +- gl_rsurf.c | 18 ++++-------- model_alias.c | 77 -------------------------------------------------- model_brush.c | 72 ++++------------------------------------------ model_shared.c | 29 +++++++++++++------ model_shared.h | 9 ++++-- model_sprite.c | 4 --- 7 files changed, 40 insertions(+), 171 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 747c5f0e..7764d904 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -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; } diff --git a/gl_rsurf.c b/gl_rsurf.c index 603666a3..d9497d43 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -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 } diff --git a/model_alias.c b/model_alias.c index f438da4b..b9990beb 100644 --- a/model_alias.c +++ b/model_alias.c @@ -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; - } } diff --git a/model_brush.c b/model_brush.c index bf597303..0c9c81c6 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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; diff --git a/model_shared.c b/model_shared.c index 15e9fd98..e29e3f8d 100644 --- a/model_shared.c +++ b/model_shared.c @@ -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; } diff --git a/model_shared.h b/model_shared.h index b5312b8c..d131fb8b 100644 --- a/model_shared.h +++ b/model_shared.h @@ -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); diff --git a/model_sprite.c b/model_sprite.c index d21d88ff..44d8f0ae 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -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; -- 2.39.2