From 81428659a4156981ed76f6167ef3be82d35a4bf8 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 19 Dec 2020 10:19:47 +0000 Subject: [PATCH] Replaced some model fields and changed their purpose slightly to simplify a lot of code: model->firstmodelsurface : model->submodelsurfaces_start model->nummodelsurfaces : replaced with model->submodelsurfaces_end model->sortedmodelsurfaces : replaced with model->modelsurfaces_sorted (which starts at surface 0, not firstmodelsurface). Changed the implementation of MakeSortedSurfaces so that it now sorts by effect, texture, lightmap, previously it didn't care about lightmap or effect. No behavior changes. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@13072 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 33 +++++------ gl_rsurf.c | 18 +++--- model_alias.c | 49 ++++++++------- model_brush.c | 157 +++++++++++++++++++++++++------------------------ model_shared.c | 122 ++++++++++++++++++++++---------------- model_shared.h | 63 +++++++++++--------- prvm_cmds.c | 10 ++-- r_shadow.c | 6 +- world.c | 4 +- 9 files changed, 246 insertions(+), 216 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index e348e3e9..5482cc5b 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -9315,11 +9315,8 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor model_t *model; const msurface_t *surface; const msurface_t *surfaces; - const int *surfacelist; const texture_t *texture; int numtriangles; - int numsurfacelist; - int surfacelistindex; int surfaceindex; int triangleindex; float localorigin[3]; @@ -9412,8 +9409,6 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor #endif dynamic = model->surfmesh.isanimated; - numsurfacelist = model->nummodelsurfaces; - surfacelist = model->sortedmodelsurfaces; surfaces = model->data_surfaces; bih = NULL; @@ -9449,9 +9444,8 @@ static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldor } else { - for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++) + for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++) { - surfaceindex = surfacelist[surfacelistindex]; surface = surfaces + surfaceindex; // check cull box first because it rejects more than any other check if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs)) @@ -9777,7 +9771,7 @@ static void R_DrawModelDecals(void) static void R_DrawDebugModel(void) { entity_render_t *ent = rsurface.entity; - int i, j, flagsmask; + int j, flagsmask; const msurface_t *surface; model_t *model = ent->model; @@ -9793,10 +9787,11 @@ static void R_DrawDebugModel(void) GL_DepthMask(false); GL_DepthRange(0, 1); GL_BlendFunc(GL_ONE, GL_ONE); - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -9887,10 +9882,11 @@ static void R_DrawDebugModel(void) GL_DepthMask(true); } qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -9925,10 +9921,11 @@ static void R_DrawDebugModel(void) GL_BlendFunc(GL_ONE, GL_ZERO); GL_DepthMask(true); } - for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j]) continue; + surface = model->data_surfaces + j; rsurface.texture = R_GetCurrentTexture(surface->texture); if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles) { @@ -10034,7 +10031,7 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep } // check if this is an empty model - if (model->nummodelsurfaces == 0) + if (model->submodelsurfaces_start >= model->submodelsurfaces_end) return; rsurface.lightmaptexture = NULL; @@ -10048,9 +10045,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qbool skysurfaces, qbool writedep if (ent == r_refdef.scene.worldentity) { // for the world entity, check surfacevisible - for (i = 0;i < model->nummodelsurfaces;i++) + for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++) { - j = model->sortedmodelsurfaces[i]; + j = model->modelsurfaces_sorted[i]; if (r_refdef.viewcache.world_surfacevisible[j]) r_surfacelist[numsurfacelist++] = surfaces + j; } @@ -10065,14 +10062,14 @@ 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 (i = 0; i < model->nummodelsurfaces; i++) - r_surfacelist[numsurfacelist++] = surfaces + model->firstmodelsurface + i; + for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++) + r_surfacelist[numsurfacelist++] = surfaces + i; } else { // add all surfaces - for (i = 0; i < model->nummodelsurfaces; i++) - r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i]; + for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++) + r_surfacelist[numsurfacelist++] = surfaces + model->modelsurfaces_sorted[i]; } /* diff --git a/gl_rsurf.c b/gl_rsurf.c index 512b9491..603666a3 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -411,8 +411,6 @@ void R_DrawPortals(void) static void R_View_WorldVisibility_CullSurfaces(void) { int surfaceindex; - int surfaceindexstart; - int surfaceindexend; unsigned char *surfacevisible; msurface_t *surfaces; model_t *model = r_refdef.scene.worldmodel; @@ -422,11 +420,9 @@ static void R_View_WorldVisibility_CullSurfaces(void) return; if (r_usesurfaceculling.integer < 1) return; - surfaceindexstart = model->firstmodelsurface; - surfaceindexend = surfaceindexstart + model->nummodelsurfaces; surfaces = model->data_surfaces; surfacevisible = r_refdef.viewcache.world_surfacevisible; - for (surfaceindex = surfaceindexstart; surfaceindex < surfaceindexend; surfaceindex++) + for (surfaceindex = model->submodelsurfaces_start; surfaceindex < model->submodelsurfaces_end; surfaceindex++) { if (surfacevisible[surfaceindex]) { @@ -620,9 +616,9 @@ void R_Mod_DrawAddWaterPlanes(entity_render_t *ent) // add visible surfaces to draw list if (ent == r_refdef.scene.worldentity) { - for (i = 0;i < model->nummodelsurfaces;i++) + for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++) { - j = model->sortedmodelsurfaces[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); @@ -634,9 +630,9 @@ void R_Mod_DrawAddWaterPlanes(entity_render_t *ent) n = ent->entitynumber; else n = 0; - for (i = 0;i < model->nummodelsurfaces;i++) + for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++) { - j = model->sortedmodelsurfaces[i]; + j = model->modelsurfaces_sorted[i]; if (surfaces[j].texture->basematerialflags & flagsmask) R_Water_AddWaterPlane(surfaces + j, n); } @@ -1140,7 +1136,7 @@ static void R_Q1BSP_CallRecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, qboo info->outnumleafs = 0; info->outnumsurfaces = 0; memset(info->outleafpvs, 0, (info->model->brush.num_leafs + 7) >> 3); - memset(info->outsurfacepvs, 0, (info->model->nummodelsurfaces + 7) >> 3); + memset(info->outsurfacepvs, 0, (info->model->num_surfaces + 7) >> 3); memset(info->outshadowtrispvs, 0, (info->model->surfmesh.num_triangles + 7) >> 3); memset(info->outlighttrispvs, 0, (info->model->surfmesh.num_triangles + 7) >> 3); } @@ -1246,7 +1242,7 @@ void R_Mod_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float VectorCopy(info.relativelightorigin, info.outmaxs); memset(visitingleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3); memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3); - memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3); + memset(outsurfacepvs, 0, (info.model->num_surfaces + 7) >> 3); memset(outshadowtrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3); memset(outlighttrispvs, 0, (info.model->surfmesh.num_triangles + 7) >> 3); if (info.model->brush.GetPVS && !info.noocclusion) diff --git a/model_alias.c b/model_alias.c index 95f61ab7..f438da4b 100644 --- a/model_alias.c +++ b/model_alias.c @@ -1020,11 +1020,12 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->num_surfaces = 1; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces; data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); - loadmodel->sortedmodelsurfaces[0] = 0; + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted[0] = 0; loadmodel->numskins = LittleLong(pinmodel->numskins); BOUNDI(loadmodel->numskins,0,65536); @@ -1411,11 +1412,12 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) iskinheight = 1.0f / skinheight; loadmodel->num_surfaces = 1; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces; data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3])); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); - loadmodel->sortedmodelsurfaces[0] = 0; + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted[0] = 0; loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]); loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); @@ -1692,12 +1694,13 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) meshtriangles += LittleLong(pinmesh->num_triangles); } - loadmodel->nummodelsurfaces = loadmodel->num_surfaces; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces; loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; loadmodel->num_texturesperskin = loadmodel->num_surfaces; data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; @@ -1717,7 +1720,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) { if (memcmp(pinmesh->identifier, "IDP3", 4)) Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)"); - loadmodel->sortedmodelsurfaces[i] = i; + loadmodel->modelsurfaces_sorted[i] = i; surface = loadmodel->data_surfaces + i; surface->texture = loadmodel->data_textures + i; surface->num_firsttriangle = meshtriangles; @@ -1959,12 +1962,13 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) meshvertices = pheader->numverts; meshtriangles = pheader->numtris; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces; loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; loadmodel->num_texturesperskin = loadmodel->num_surfaces; data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12])); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; @@ -2107,7 +2111,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend)) Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name); - loadmodel->sortedmodelsurfaces[i] = i; + loadmodel->modelsurfaces_sorted[i] = i; surface = loadmodel->data_surfaces + i; surface->texture = loadmodel->data_textures + i; surface->num_firsttriangle = meshtriangles; @@ -2283,13 +2287,14 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->numframes = pheader->num_frames; loadmodel->num_bones = pheader->num_bones; loadmodel->num_poses = loadmodel->numframes; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = pheader->num_meshs; loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; loadmodel->num_texturesperskin = loadmodel->num_surfaces; // do most allocations as one merged chunk data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; @@ -2413,7 +2418,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) const float *intexcoord; msurface_t *surface; - loadmodel->sortedmodelsurfaces[i] = i; + loadmodel->modelsurfaces_sorted[i] = i; surface = loadmodel->data_surfaces + i; surface->texture = loadmodel->data_textures + i; surface->num_firsttriangle = meshtriangles; @@ -2944,7 +2949,8 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->numskins = 1; loadmodel->num_bones = numbones; loadmodel->num_poses = loadmodel->numframes; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = nummatts; loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; loadmodel->num_texturesperskin = loadmodel->num_surfaces; loadmodel->surfmesh.num_vertices = meshvertices; @@ -2953,7 +2959,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0); data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]); @@ -2989,7 +2995,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) { // since psk models do not have named sections, reuse their shader name as the section name Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name); - loadmodel->sortedmodelsurfaces[index] = index; + loadmodel->modelsurfaces_sorted[index] = index; loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index; loadmodel->data_surfaces[index].num_firstvertex = 0; loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices; @@ -3429,7 +3435,8 @@ void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->numframes = max(header.num_anims, 1); loadmodel->num_bones = header.num_joints; loadmodel->num_poses = max(header.num_frames, 1); - loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes; + loadmodel->submodelsurfaces_start = 0; + loadmodel->submodelsurfaces_end = loadmodel->num_surfaces = header.num_meshes; loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; loadmodel->num_texturesperskin = loadmodel->num_surfaces; @@ -3439,7 +3446,7 @@ void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend) // do most allocations as one merged chunk data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; @@ -3922,7 +3929,7 @@ void Mod_INTERQUAKEMODEL_Load(model_t *mod, void *buffer, void *bufferend) mesh.first_triangle = LittleLong(meshes[i].first_triangle); mesh.num_triangles = LittleLong(meshes[i].num_triangles); - loadmodel->sortedmodelsurfaces[i] = i; + loadmodel->modelsurfaces_sorted[i] = i; surface = loadmodel->data_surfaces + i; surface->texture = loadmodel->data_textures + i; surface->num_firsttriangle = mesh.first_triangle; diff --git a/model_brush.c b/model_brush.c index cc52e72e..a40c8687 100644 --- a/model_brush.c +++ b/model_brush.c @@ -3246,12 +3246,13 @@ static void Mod_Q1BSP_LoadPlanes(sizebuf_t *sb) // fixes up sky surfaces that have SKY contents behind them, so that they do not cast shadows (e1m5 logo shadow trick). static void Mod_Q1BSP_AssignNoShadowSkySurfaces(model_t *mod) { - int i; + int surfaceindex; msurface_t *surface; vec3_t center; int contents; - for (i = 0, surface = mod->data_surfaces + mod->firstmodelsurface; i < mod->nummodelsurfaces; i++, surface++) + for (surfaceindex = mod->submodelsurfaces_start; surfaceindex < mod->submodelsurfaces_end;surfaceindex++) { + surface = mod->data_surfaces + surfaceindex; if (surface->texture->basematerialflags & MATERIALFLAG_SKY) { // check if the point behind the surface polygon is SOLID or SKY contents @@ -4049,6 +4050,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) } } datapointer = (unsigned char *)Mem_Alloc(mod->mempool, mod->num_surfaces * sizeof(int) + totalstyles * sizeof(model_brush_lightstyleinfo_t) + totalstylesurfaces * sizeof(int *)); + mod->modelsurfaces_sorted = (int*)datapointer;datapointer += mod->num_surfaces * sizeof(int); for (i = 0;i < mod->brush.numsubmodels;i++) { // LadyHavoc: this code was originally at the end of this loop, but @@ -4092,8 +4094,8 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->brushq1.hulls[j].lastclipnode = mod->brushq1.numclipnodes - 1; } - mod->firstmodelsurface = bm->firstface; - mod->nummodelsurfaces = bm->numfaces; + mod->submodelsurfaces_start = bm->firstface; + mod->submodelsurfaces_end = bm->firstface + bm->numfaces; // set node/leaf parents for this submodel Mod_BSP_LoadNodes_RecursiveSetParent(mod->brush.data_nodes + mod->brushq1.hulls[0].firstclipnode, NULL); @@ -4101,10 +4103,6 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) // this has to occur after hull info has been set, as it uses Mod_Q1BSP_PointSuperContents Mod_Q1BSP_AssignNoShadowSkySurfaces(mod); - // make the model surface list (used by shadowing/lighting) - mod->sortedmodelsurfaces = (int *)datapointer;datapointer += mod->nummodelsurfaces * sizeof(int); - Mod_MakeSortedSurfaces(mod); - // copy the submodel bounds, then enlarge the yaw and rotated bounds according to radius // (previously this code measured the radius of the vertices of surfaces in the submodel, but that broke submodels that contain only CLIP brushes, which do not produce surfaces) VectorCopy(bm->mins, mod->normalmins); @@ -4131,30 +4129,27 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) // 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->nummodelsurfaces) + if (mod->submodelsurfaces_start < mod->submodelsurfaces_end) { - for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) - if (surface->texture->basematerialflags & MATERIALFLAG_SKY) + for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++) + if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY) break; - if (j < mod->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawSky = R_Mod_DrawSky; - for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) - if (surface->texture && surface->texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)) + 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->nummodelsurfaces) + 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) memset(stylecounts, 0, sizeof(stylecounts)); - for (k = 0;k < mod->nummodelsurfaces;k++) - { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++) for (j = 0;j < MAXLIGHTMAPS;j++) - stylecounts[surface->lightmapinfo->styles[j]]++; - } + stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++; mod->brushq1.num_lightstyles = 0; for (k = 0;k < 255;k++) { @@ -4168,15 +4163,15 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->brushq1.num_lightstyles++; } } - for (k = 0;k < mod->nummodelsurfaces;k++) + for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++) { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + surface = mod->data_surfaces + k; for (j = 0;j < MAXLIGHTMAPS;j++) { if (surface->lightmapinfo->styles[j] != 255) { int r = remapstyles[surface->lightmapinfo->styles[j]]; - styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = mod->firstmodelsurface + k; + styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k; } } } @@ -4211,6 +4206,10 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer, void *bufferend) //Mod_Q1BSP_ProcessLightList(); } } + mod = loadmodel; + + // make the model surface list (used by shadowing/lighting) + Mod_MakeSortedSurfaces(loadmodel); Con_DPrintf("Stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces); } @@ -4984,6 +4983,7 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) } } datapointer = (unsigned char *)Mem_Alloc(mod->mempool, mod->num_surfaces * sizeof(int) + totalstyles * sizeof(model_brush_lightstyleinfo_t) + totalstylesurfaces * sizeof(int *)); + mod->modelsurfaces_sorted = (int*)datapointer; datapointer += mod->num_surfaces * sizeof(int); // set up the world model, then on each submodel copy from the world model // and set up the submodel with the respective model info. mod = loadmodel; @@ -5023,8 +5023,8 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) // we store the headnode (there's only one in Q2BSP) as if it were the first hull mod->brushq1.hulls[0].firstclipnode = bm->headnode[0]; - mod->firstmodelsurface = bm->firstface; - mod->nummodelsurfaces = bm->numfaces; + mod->submodelsurfaces_start = bm->firstface; + mod->submodelsurfaces_end = bm->firstface + bm->numfaces; // set node/leaf parents for this submodel // note: if the root of this submodel is a leaf (headnode[0] < 0) then there is nothing to do... @@ -5036,7 +5036,6 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) Mod_BSP_LoadNodes_RecursiveSetParent(rootnode, NULL); // make the model surface list (used by shadowing/lighting) - mod->sortedmodelsurfaces = (int *)datapointer;datapointer += mod->nummodelsurfaces * sizeof(int); Mod_Q2BSP_FindSubmodelBrushRange_r(mod, rootnode, &firstbrush, &lastbrush); if (firstbrush <= lastbrush) { @@ -5048,7 +5047,6 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->firstmodelbrush = 0; mod->nummodelbrushes = 0; } - Mod_MakeSortedSurfaces(mod); VectorCopy(bm->mins, mod->normalmins); VectorCopy(bm->maxs, mod->normalmaxs); @@ -5074,30 +5072,27 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) // 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->nummodelsurfaces) + if (mod->submodelsurfaces_start < mod->submodelsurfaces_end) { - for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) - if (surface->texture->basematerialflags & MATERIALFLAG_SKY) + 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->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawSky = R_Mod_DrawSky; - for (j = 0, surface = &mod->data_surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surface++) - if (surface->texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)) + 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->nummodelsurfaces) + 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) memset(stylecounts, 0, sizeof(stylecounts)); - for (k = 0;k < mod->nummodelsurfaces;k++) - { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++) for (j = 0;j < MAXLIGHTMAPS;j++) - stylecounts[surface->lightmapinfo->styles[j]]++; - } + stylecounts[mod->data_surfaces[k].lightmapinfo->styles[j]]++; mod->brushq1.num_lightstyles = 0; for (k = 0;k < 255;k++) { @@ -5111,15 +5106,15 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->brushq1.num_lightstyles++; } } - for (k = 0;k < mod->nummodelsurfaces;k++) + for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++) { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + surface = mod->data_surfaces + k; for (j = 0;j < MAXLIGHTMAPS;j++) { if (surface->lightmapinfo->styles[j] != 255) { int r = remapstyles[surface->lightmapinfo->styles[j]]; - styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = mod->firstmodelsurface + k; + styleinfo[r].surfacelist[styleinfo[r].numsurfaces++] = k; } } } @@ -5144,6 +5139,9 @@ static void Mod_Q2BSP_Load(model_t *mod, void *buffer, void *bufferend) } mod = loadmodel; + // make the model surface list (used by shadowing/lighting) + Mod_MakeSortedSurfaces(loadmodel); + Con_DPrintf("Stats for q2bsp model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces); } @@ -7227,7 +7225,6 @@ bih_t *Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out) int triangleindex; int bihleafindex; int nummodelbrushes = model->nummodelbrushes; - int nummodelsurfaces = model->nummodelsurfaces; const int *e; const int *collisionelement3i; const float *collisionvertex3f; @@ -7244,20 +7241,20 @@ bih_t *Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out) bihnumleafs = 0; if (userendersurfaces) { - for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++) - bihnumleafs += surface->num_triangles; + for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++) + bihnumleafs += model->data_surfaces[j].num_triangles; } else { for (brushindex = 0, brush = model->brush.data_brushes + brushindex+model->firstmodelbrush;brushindex < nummodelbrushes;brushindex++, brush++) if (brush->colbrushf) bihnumleafs++; - for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++) + for (j = model->submodelsurfaces_start;j < model->submodelsurfaces_end;j++) { - if (surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS) - bihnumleafs += surface->num_triangles + surface->num_collisiontriangles; + if (model->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS) + bihnumleafs += model->data_surfaces[j].num_triangles + model->data_surfaces[j].num_collisiontriangles; else - bihnumleafs += surface->num_collisiontriangles; + bihnumleafs += model->data_surfaces[j].num_collisiontriangles; } } @@ -7273,8 +7270,9 @@ bih_t *Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out) // add render surfaces renderelement3i = model->surfmesh.data_element3i; rendervertex3f = model->surfmesh.data_vertex3f; - for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { + surface = model->data_surfaces + j; for (triangleindex = 0, e = renderelement3i + 3*surface->num_firsttriangle;triangleindex < surface->num_triangles;triangleindex++, e += 3) { if (!userendersurfaces && !(surface->texture->basematerialflags & MATERIALFLAG_MESHCOLLISIONS)) @@ -7312,8 +7310,9 @@ bih_t *Mod_MakeCollisionBIH(model_t *model, qbool userendersurfaces, bih_t *out) // add collision surfaces collisionelement3i = model->brush.data_collisionelement3i; collisionvertex3f = model->brush.data_collisionvertex3f; - for (j = 0, surface = model->data_surfaces + model->firstmodelsurface;j < nummodelsurfaces;j++, surface++) + for (j = model->submodelsurfaces_start; j < model->submodelsurfaces_end; j++) { + surface = model->data_surfaces + j; for (triangleindex = 0, e = collisionelement3i + 3*surface->num_firstcollisiontriangle;triangleindex < surface->num_collisiontriangles;triangleindex++, e += 3) { bihleafs[bihleafindex].type = BIH_COLLISIONTRIANGLE; @@ -7595,12 +7594,11 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->brush.submodels[i] = mod; // make the model surface list (used by shadowing/lighting) - mod->firstmodelsurface = mod->brushq3.data_models[i].firstface; - mod->nummodelsurfaces = mod->brushq3.data_models[i].numfaces; + mod->submodelsurfaces_start = mod->brushq3.data_models[i].firstface; + 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->sortedmodelsurfaces = (int *)Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces)); - Mod_MakeSortedSurfaces(mod); + 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,9 +7608,9 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend) // outside the level - an unimportant concern) //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 = 0;j < mod->nummodelsurfaces;j++) + for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++) { - const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface; + const msurface_t *surface = mod->data_surfaces + j + mod->submodelsurfaces_start; const float *v = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex; int k; if (!surface->num_vertices) @@ -7646,16 +7644,16 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend) mod->DrawSky = NULL; mod->DrawAddWaterPlanes = NULL; - for (j = 0;j < mod->nummodelsurfaces;j++) - if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY) + 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->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawSky = R_Mod_DrawSky; - for (j = 0;j < mod->nummodelsurfaces;j++) - if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)) + 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->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes; Mod_MakeCollisionBIH(mod, false, &mod->collision_bih); @@ -7665,6 +7663,10 @@ static void Mod_Q3BSP_Load(model_t *mod, void *buffer, void *bufferend) if (i == 0) Mod_BuildVBOs(); } + mod = loadmodel; + + // make the model surface list (used by shadowing/lighting) + Mod_MakeSortedSurfaces(loadmodel); if (mod_q3bsp_sRGBlightmaps.integer) { @@ -8137,7 +8139,7 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->num_texturesperskin = numtextures; data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + numtriangles * sizeof(int[3]) + (numvertices <= 65536 ? numtriangles * sizeof(unsigned short[3]) : 0) + numvertices * sizeof(float[14]) + loadmodel->brush.numsubmodels * sizeof(model_t *)); loadmodel->brush.submodels = (model_t **)data;data += loadmodel->brush.numsubmodels * sizeof(model_t *); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); + loadmodel->modelsurfaces_sorted = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); loadmodel->surfmesh.num_vertices = numvertices; loadmodel->surfmesh.num_triangles = numtriangles; @@ -8198,7 +8200,7 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->brush.data_pvsclusters = nobsp_pvs; //if (loadmodel->num_nodes) loadmodel->data_nodes = (mnode_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_nodes * sizeof(mnode_t)); //loadmodel->data_leafsurfaces = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_leafsurfaces * sizeof(int)); - loadmodel->brush.data_leafsurfaces = loadmodel->sortedmodelsurfaces; + loadmodel->brush.data_leafsurfaces = loadmodel->modelsurfaces_sorted; VectorCopy(loadmodel->normalmins, loadmodel->brush.data_leafs->mins); VectorCopy(loadmodel->normalmaxs, loadmodel->brush.data_leafs->maxs); loadmodel->brush.data_leafs->combinedsupercontents = 0; // FIXME? @@ -8244,19 +8246,17 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->brush.submodels[i] = mod; // make the model surface list (used by shadowing/lighting) - mod->firstmodelsurface = submodelfirstsurface[i]; - mod->nummodelsurfaces = submodelfirstsurface[i+1] - submodelfirstsurface[i]; + mod->submodelsurfaces_start = submodelfirstsurface[i]; + mod->submodelsurfaces_end = submodelfirstsurface[i+1]; mod->firstmodelbrush = 0; mod->nummodelbrushes = 0; - mod->sortedmodelsurfaces = loadmodel->sortedmodelsurfaces + mod->firstmodelsurface; - Mod_MakeSortedSurfaces(mod); VectorClear(mod->normalmins); VectorClear(mod->normalmaxs); l = false; - for (j = 0;j < mod->nummodelsurfaces;j++) + for (j = mod->submodelsurfaces_start;j < mod->submodelsurfaces_end;j++) { - const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface; + const msurface_t *surface = mod->data_surfaces + j; const float *v3f = mod->surfmesh.data_vertex3f + 3 * surface->num_firstvertex; int k; if (!surface->num_vertices) @@ -8295,16 +8295,16 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend) mod->DrawSky = NULL; mod->DrawAddWaterPlanes = NULL; - for (j = 0;j < mod->nummodelsurfaces;j++) - if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & MATERIALFLAG_SKY) + for (j = mod->submodelsurfaces_start; j < mod->submodelsurfaces_end; j++) + if (mod->data_surfaces[j].texture->basematerialflags & MATERIALFLAG_SKY) break; - if (j < mod->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawSky = R_Mod_DrawSky; - for (j = 0;j < mod->nummodelsurfaces;j++) - if (mod->data_surfaces[j + mod->firstmodelsurface].texture->basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)) + 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->nummodelsurfaces) + if (j < mod->submodelsurfaces_end) mod->DrawAddWaterPlanes = R_Mod_DrawAddWaterPlanes; Mod_MakeCollisionBIH(mod, true, &mod->collision_bih); @@ -8317,5 +8317,8 @@ void Mod_OBJ_Load(model_t *mod, void *buffer, void *bufferend) mod = loadmodel; Mem_Free(submodelfirstsurface); + // make the model surface list (used by shadowing/lighting) + Mod_MakeSortedSurfaces(loadmodel); + Con_DPrintf("Stats for obj model \"%s\": %i faces, %i nodes, %i leafs, %i clusters, %i clusterportals, mesh: %i vertices, %i triangles, %i surfaces\n", loadmodel->name, loadmodel->num_surfaces, loadmodel->brush.num_nodes, loadmodel->brush.num_leafs, mod->brush.num_pvsclusters, loadmodel->brush.num_portals, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->num_surfaces); } diff --git a/model_shared.c b/model_shared.c index 55b4673e..f43229ca 100644 --- a/model_shared.c +++ b/model_shared.c @@ -1197,9 +1197,9 @@ void Mod_CreateCollisionMesh(model_t *mod) // make a single combined collision mesh for physics engine use // TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface numcollisionmeshtriangles = 0; - for (k = 0;k < mod->nummodelsurfaces;k++) + for (k = mod->submodelsurfaces_start;k < mod->submodelsurfaces_end;k++) { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + surface = mod->data_surfaces + k; if (!strcmp(surface->texture->name, "collision") || !strcmp(surface->texture->name, "collisionconvex")) // found collision mesh { usesinglecollisionmesh = true; @@ -1215,9 +1215,9 @@ void Mod_CreateCollisionMesh(model_t *mod) Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); else { - for (k = 0;k < mod->nummodelsurfaces;k++) + for (k = mod->submodelsurfaces_start; k < mod->submodelsurfaces_end; k++) { - surface = mod->data_surfaces + mod->firstmodelsurface + k; + surface = mod->data_surfaces + k; if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID)) continue; Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); @@ -2881,41 +2881,65 @@ void Mod_VertexRangeFromElements(int numelements, const int *elements, int *firs *lastvertexpointer = lastvertex; } +typedef struct Mod_MakeSortedSurfaces_qsortsurface_s +{ + int submodel; + int surfaceindex; + q3deffect_t* effect; + texture_t* texture; + rtexture_t* lightmaptexture; +} +Mod_MakeSortedSurfaces_qsortsurface_t; + +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) + return 1; + if (l->texture < r->texture) + return -1; + if (l->texture > r->texture) + return 1; + if (l->lightmaptexture < r->lightmaptexture) + return -1; + if (l->lightmaptexture > r->lightmaptexture) + return 1; + if (l->surfaceindex < r->surfaceindex) + return -1; + if (l->surfaceindex > r->surfaceindex) + return 1; + return 0; +} + void Mod_MakeSortedSurfaces(model_t *mod) { // make an optimal set of texture-sorted batches to draw... - int j, t; - int *firstsurfacefortexture; - int *numsurfacesfortexture; - if (!mod->sortedmodelsurfaces) - mod->sortedmodelsurfaces = (int *) Mem_Alloc(loadmodel->mempool, mod->nummodelsurfaces * sizeof(*mod->sortedmodelsurfaces)); - firstsurfacefortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*firstsurfacefortexture)); - numsurfacesfortexture = (int *) Mem_Alloc(tempmempool, mod->num_textures * sizeof(*numsurfacesfortexture)); - memset(numsurfacesfortexture, 0, mod->num_textures * sizeof(*numsurfacesfortexture)); - for (j = 0;j < mod->nummodelsurfaces;j++) + int j, k; + Mod_MakeSortedSurfaces_qsortsurface_t *info = (Mod_MakeSortedSurfaces_qsortsurface_t*)R_FrameData_Alloc(mod->num_surfaces * sizeof(*info)); + if (!mod->modelsurfaces_sorted) + mod->modelsurfaces_sorted = (int *) Mem_Alloc(loadmodel->mempool, mod->num_surfaces * sizeof(*mod->modelsurfaces_sorted)); + // 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++) { - const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface; - if(!surface->texture) - continue; - t = (int)(surface->texture - mod->data_textures); - numsurfacesfortexture[t]++; + 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; } - j = 0; - for (t = 0;t < mod->num_textures;t++) - { - firstsurfacefortexture[t] = j; - j += numsurfacesfortexture[t]; - } - for (j = 0;j < mod->nummodelsurfaces;j++) - { - const msurface_t *surface = mod->data_surfaces + j + mod->firstmodelsurface; - if (!surface->texture) - continue; - t = (int)(surface->texture - mod->data_textures); - mod->sortedmodelsurfaces[firstsurfacefortexture[t]++] = j + mod->firstmodelsurface; - } - Mem_Free(firstsurfacefortexture); - Mem_Free(numsurfacesfortexture); + 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); + for (j = 0; j < mod->num_surfaces; j++) + mod->modelsurfaces_sorted[j] = info[j].surfaceindex; } void Mod_BuildVBOs(void) @@ -3068,9 +3092,9 @@ static void Mod_Decompile_OBJ(model_t *model, const char *filename, const char * if (l > 0) outbufferpos += l; submodel = model->brush.numsubmodels ? model->brush.submodels[submodelindex] : model; - for (surfaceindex = 0;surfaceindex < submodel->nummodelsurfaces;surfaceindex++) + for (surfaceindex = submodel->submodelsurfaces_start;surfaceindex < submodel->submodelsurfaces_end;surfaceindex++) { - surface = model->data_surfaces + submodel->sortedmodelsurfaces[surfaceindex]; + surface = model->data_surfaces + surfaceindex; l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default"); if (l > 0) outbufferpos += l; @@ -3614,8 +3638,9 @@ static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP_InsertSurfaces(const const int *element3i = model->surfmesh.data_element3i; const int *e; float v2[3][3]; - for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->nummodelsurfaces;surfaceindex++, surface++) + for (surfaceindex = model->submodelsurfaces_start;surfaceindex < model->submodelsurfaces_end;surfaceindex++) { + surface = model->data_surfaces + surfaceindex; if (!BoxesOverlap(surface->mins, surface->maxs, mins, maxs)) continue; if (surface->texture->basematerialflags & MATERIALFLAG_NOSHADOW) @@ -4491,7 +4516,7 @@ msurface_t *Mod_Mesh_AddSurface(model_t *mod, texture_t *tex, qbool batchwithpre { mod->max_surfaces = 2 * max(mod->num_surfaces, 64); mod->data_surfaces = (msurface_t *)Mem_Realloc(mod->mempool, mod->data_surfaces, mod->max_surfaces * sizeof(*mod->data_surfaces)); - mod->sortedmodelsurfaces = (int *)Mem_Realloc(mod->mempool, mod->sortedmodelsurfaces, mod->max_surfaces * sizeof(*mod->sortedmodelsurfaces)); + mod->modelsurfaces_sorted = (int *)Mem_Realloc(mod->mempool, mod->modelsurfaces_sorted, mod->max_surfaces * sizeof(*mod->modelsurfaces_sorted)); } surf = mod->data_surfaces + mod->num_surfaces; mod->num_surfaces++; @@ -4633,29 +4658,26 @@ static void Mod_Mesh_MakeSortedSurfaces(model_t *mod) { int i, j; texture_t *tex; - msurface_t *surf, *surf2; + unsigned char* included = R_FrameData_Alloc(mod->num_surfaces * sizeof(unsigned char)); // build the sorted surfaces list properly to reduce material setup // this is easy because we're just sorting on texture and don't care about the order of textures - mod->nummodelsurfaces = 0; + mod->submodelsurfaces_start = 0; + mod->submodelsurfaces_end = 0; for (i = 0; i < mod->num_surfaces; i++) - mod->data_surfaces[i].included = false; + included[i] = 0; for (i = 0; i < mod->num_surfaces; i++) { - surf = mod->data_surfaces + i; - if (surf->included) + if (included[i]) continue; - tex = surf->texture; + tex = mod->data_surfaces[i].texture; // j = i is intentional for (j = i; j < mod->num_surfaces; j++) { - surf2 = mod->data_surfaces + j; - if (surf2->included) - continue; - if (surf2->texture == tex) + if (!included[j] && mod->data_surfaces[j].texture == tex) { - surf2->included = true; - mod->sortedmodelsurfaces[mod->nummodelsurfaces++] = j; + included[j] = 1; + mod->modelsurfaces_sorted[mod->submodelsurfaces_end++] = j; } } } diff --git a/model_shared.h b/model_shared.h index 6b0530a8..b5312b8c 100644 --- a/model_shared.h +++ b/model_shared.h @@ -370,36 +370,40 @@ typedef struct msurface_lightmapinfo_s msurface_lightmapinfo_t; struct q3deffect_s; + +/// +/// describes the textures to use on a range of triangles in the model, and mins/maxs (AABB) for culling. +/// typedef struct msurface_s { - // bounding box for onscreen checks - vec3_t mins; - vec3_t maxs; - // the texture to use on the surface + /// range of triangles and vertices in model->surfmesh + int num_triangles; // triangles + int num_firsttriangle; // first element is this *3 + int num_vertices; // length of the range referenced by elements + int num_firstvertex; // min vertex referenced by elements + + /// the texture to use on the surface texture_t *texture; - // the lightmap texture fragment to use on the rendering mesh + /// the lightmap texture fragment to use on the rendering mesh struct rtexture_s *lightmaptexture; - // the lighting direction texture fragment to use on the rendering mesh + /// the lighting direction texture fragment to use on the rendering mesh struct rtexture_s *deluxemaptexture; - // lightmaptexture rebuild information not used in q3bsp - msurface_lightmapinfo_t *lightmapinfo; // q1bsp - // fog volume info in q3bsp - struct q3deffect_s *effect; // q3bsp - // mesh information for collisions (only used by q3bsp curves) - int num_firstcollisiontriangle; - - // surfaces own ranges of vertices and triangles in the model->surfmesh - int num_triangles; // number of triangles - int num_firsttriangle; // first triangle - int num_vertices; // number of vertices - int num_firstvertex; // first vertex - - // mesh information for collisions (only used by q3bsp curves) - int num_collisiontriangles; // q3bsp - int num_collisionvertices; // q3bsp - - // used by Mod_Mesh_Finalize when building sortedmodelsurfaces - qbool included; + + // the following fields are used situationally and are not part of rendering in typical usage + + /// bounding box for onscreen checks + vec3_t mins; + vec3_t maxs; + + /// lightmaptexture rebuild information not used in q3bsp + msurface_lightmapinfo_t* lightmapinfo; // q1bsp + /// fog volume info in q3bsp + struct q3deffect_s* effect; // q3bsp + + /// mesh information for collisions (only used by q3bsp curves) + int num_firstcollisiontriangle; // q3bsp only + int num_collisiontriangles; // number of triangles (if surface has collisions enabled) + int num_collisionvertices; // number of vertices referenced by collision triangles (if surface has collisions enabled) } msurface_t; @@ -455,10 +459,11 @@ typedef struct model_s animscene_t *skinscenes; // [numskins] // skin animation info animscene_t *animscenes; // [numframes] - // range of surface numbers in this (sub)model - int firstmodelsurface; - int nummodelsurfaces; - int *sortedmodelsurfaces; + // range of surface numbers in this model + int submodelsurfaces_start; + int submodelsurfaces_end; + /// surface indices of model in an optimal draw order (submodelindex -> texture -> lightmap -> index) + int *modelsurfaces_sorted; // same size as num_surfaces // range of collision brush numbers in this (sub)model int firstmodelbrush; int nummodelbrushes; diff --git a/prvm_cmds.c b/prvm_cmds.c index 4990834d..c83598b6 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -6122,9 +6122,9 @@ static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, model_t *mod static msurface_t *getsurface(model_t *model, int surfacenum) { - if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) + if (surfacenum < 0 || surfacenum >= model->submodelsurfaces_end - model->submodelsurfaces_start) return NULL; - return model->data_surfaces + surfacenum + model->firstmodelsurface; + return model->data_surfaces + surfacenum + model->submodelsurfaces_start; } @@ -6299,9 +6299,9 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) applytransform_inverted(prog, point, ed, p); best = -1; bestdist = 1000000000; - for (surfacenum = 0;surfacenum < model->nummodelsurfaces;surfacenum++) + for (surfacenum = model->submodelsurfaces_start;surfacenum < model->submodelsurfaces_end;surfacenum++) { - surface = model->data_surfaces + surfacenum + model->firstmodelsurface; + surface = model->data_surfaces + surfacenum; // first see if the nearest point on the surface's box is closer than the previous match clipped[0] = bound(surface->mins[0], p[0], surface->maxs[0]) - p[0]; clipped[1] = bound(surface->mins[1], p[1], surface->maxs[1]) - p[1]; @@ -6316,7 +6316,7 @@ void VM_getsurfacenearpoint(prvm_prog_t *prog) if (dist < bestdist) { // that's closer too, store it as the best match - best = surfacenum; + best = surfacenum - model->submodelsurfaces_start; bestdist = dist; } } diff --git a/r_shadow.c b/r_shadow.c index 884e07a7..dcb5104d 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -3376,7 +3376,7 @@ static void R_Shadow_DrawEntityShadow(entity_render_t *ent) relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius; relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius; relativeshadowmaxs[2] = relativeshadoworigin[2] + relativeshadowradius; - ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs); + ent->model->DrawShadowMap(r_shadow_shadowmapside, ent, relativeshadoworigin, NULL, relativeshadowradius, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs); rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity } @@ -3415,7 +3415,7 @@ static void R_Shadow_DrawEntityLight(entity_render_t *ent) R_Shadow_SetupEntityLight(ent); - model->DrawLight(ent, model->nummodelsurfaces, model->sortedmodelsurfaces, NULL); + model->DrawLight(ent, model->submodelsurfaces_end - model->submodelsurfaces_start, model->modelsurfaces_sorted + model->submodelsurfaces_start, NULL); rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity } @@ -4431,7 +4431,7 @@ static void R_Shadow_DrawModelShadowMaps(void) relativeshadowmaxs[1] = relativelightorigin[1] + r_shadows_throwdistance.value * fabs(relativelightdirection[1]) + radius * (fabs(relativeforward[1]) + fabs(relativeright[1])); relativeshadowmaxs[2] = relativelightorigin[2] + r_shadows_throwdistance.value * fabs(relativelightdirection[2]) + radius * (fabs(relativeforward[2]) + fabs(relativeright[2])); RSurf_ActiveModelEntity(ent, false, false, false); - ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->nummodelsurfaces, ent->model->sortedmodelsurfaces, NULL, relativeshadowmins, relativeshadowmaxs); + ent->model->DrawShadowMap(0, ent, relativelightorigin, relativelightdirection, relativethrowdistance, ent->model->submodelsurfaces_end - ent->model->submodelsurfaces_start, ent->model->modelsurfaces_sorted + ent->model->submodelsurfaces_start, NULL, relativeshadowmins, relativeshadowmaxs); rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity } diff --git a/world.c b/world.c index 9a20fd72..42ed670d 100644 --- a/world.c +++ b/world.c @@ -2290,9 +2290,9 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) // check if trimesh can be defined with convex convex_compatible = false; - for (i = 0;i < model->nummodelsurfaces;i++) + for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++) { - if (!strcmp(((msurface_t *)(model->data_surfaces + model->firstmodelsurface + i))->texture->name, "collisionconvex")) + if (!strcmp(model->data_surfaces[i].texture->name, "collisionconvex")) { convex_compatible = true; break; -- 2.39.2