From 04ff9e9b94566e25ebea87e4251eba8814cc14e0 Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 5 Jul 2008 07:31:46 +0000 Subject: [PATCH] an attempt at optimizing msurface_t dlight_cache checks by moving them to a separate array added support for a Q3BSP format variant git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8386 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rmain.c | 143 ++++++++++++++++++++++++++++--------------------- gl_rsurf.c | 4 +- model_alias.c | 58 +++++++++----------- model_brush.c | 43 +++++++++++++-- model_brush.h | 9 ++++ model_shared.c | 2 +- model_shared.h | 4 +- 7 files changed, 161 insertions(+), 102 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 70eb82ea..2c65e85c 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -2486,11 +2486,14 @@ static void R_View_UpdateEntityVisible (void) if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs) { // worldmodel can check visibility + memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities); for (i = 0;i < r_refdef.scene.numentities;i++) { ent = r_refdef.scene.entities[i]; - r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)); - + if (!(ent->flags & renderimask)) + if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE))) + if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs)) + r_refdef.viewcache.entityvisible[i] = true; } if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight) { @@ -6613,20 +6616,32 @@ void R_DrawDebugModel(entity_render_t *ent) } extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface); +int r_maxsurfacelist = 0; +msurface_t **r_surfacelist = NULL; void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { int i, j, endj, f, flagsmask; - msurface_t *surface; texture_t *t; dp_model_t *model = r_refdef.scene.worldmodel; - const int maxsurfacelist = 1024; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + RSurf_ActiveWorldEntity(); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles on this submodel if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6635,11 +6650,10 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } @@ -6659,54 +6673,60 @@ void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean dep rsurface.texture = NULL; rsurface.rtlight = NULL; numsurfacelist = 0; + // add visible surfaces to draw list j = model->firstmodelsurface; endj = j + model->nummodelsurfaces; - while (j < endj) + if (update) { - // quickly skip over non-visible surfaces - for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++) - ; - // quickly iterate over visible surfaces - for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++) + for (;j < endj;j++) { - // process this surface - surface = model->data_surfaces + j; - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) + if (r_refdef.viewcache.world_surfacevisible[j]) { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(r_refdef.scene.worldentity, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.world_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.world_surfaces += numsurfacelist; - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } + r_surfacelist[numsurfacelist++] = surfaces + j; + // update lightmap if needed + if (update[j]) + R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j); } } } - r_refdef.stats.world_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + else + for (;j < endj;j++) + if (r_refdef.viewcache.world_surfacevisible[j]) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) + { + r_refdef.stats.world_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles; + } } void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug) { - int i, j, f, flagsmask; - msurface_t *surface, *endsurface; + int i, j, endj, f, flagsmask; texture_t *t; dp_model_t *model = ent->model; - const int maxsurfacelist = 1024; + msurface_t *surfaces; + unsigned char *update; int numsurfacelist = 0; - msurface_t *surfacelist[1024]; if (model == NULL) return; + if (r_maxsurfacelist < model->num_surfaces) + { + r_maxsurfacelist = model->num_surfaces; + if (r_surfacelist) + Mem_Free(r_surfacelist); + r_surfacelist = Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist)); + } + // if the model is static it doesn't matter what value we give for // wantnormals and wanttangents, so this logic uses only rules applicable // to a model, knowing that they are meaningless otherwise @@ -6717,6 +6737,9 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr else RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly); + surfaces = model->data_surfaces; + update = model->brushq1.lightmapupdateflags; + // update light styles if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0) { @@ -6725,11 +6748,10 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr { if (style->value != r_refdef.scene.lightstylevalue[style->style]) { - msurface_t *surfaces = model->data_surfaces; int *list = style->surfacelist; style->value = r_refdef.scene.lightstylevalue[style->style]; for (j = 0;j < style->numsurfaces;j++) - surfaces[list[j]].cached_dlight = true; + update[list[j]] = true; } } } @@ -6749,29 +6771,28 @@ void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean wr rsurface.texture = NULL; rsurface.rtlight = NULL; numsurfacelist = 0; - surface = model->data_surfaces + model->firstmodelsurface; - endsurface = surface + model->nummodelsurfaces; - for (;surface < endsurface;surface++) + // add visible surfaces to draw list + j = model->firstmodelsurface; + endj = j + model->nummodelsurfaces; + for (;j < endj;j++) + r_surfacelist[numsurfacelist++] = surfaces + j; + // don't do anything if there were no surfaces + if (!numsurfacelist) + return; + // update lightmaps if needed + if (update) + for (j = model->firstmodelsurface;j < endj;j++) + if (update[j]) + R_BuildLightMap(ent, surfaces + j); + R_QueueSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); + GL_AlphaTest(false); + + // add to stats if desired + if (r_speeds.integer && !skysurfaces && !depthonly && !addwaterplanes) { - // if this surface fits the criteria, add it to the list - if (surface->num_triangles) - { - // if lightmap parameters changed, rebuild lightmap texture - if (surface->cached_dlight) - R_BuildLightMap(ent, surface); - // add face to draw list - surfacelist[numsurfacelist++] = surface; - r_refdef.stats.entities_triangles += surface->num_triangles; - if (numsurfacelist >= maxsurfacelist) - { - r_refdef.stats.entities_surfaces += numsurfacelist; - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - numsurfacelist = 0; - } - } + r_refdef.stats.entities++; + r_refdef.stats.entities_surfaces += numsurfacelist; + for (j = 0;j < numsurfacelist;j++) + r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles; } - r_refdef.stats.entities_surfaces += numsurfacelist; - if (numsurfacelist) - R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes); - GL_AlphaTest(false); } diff --git a/gl_rsurf.c b/gl_rsurf.c index d14cc1fb..39982495 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -69,7 +69,7 @@ void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface) templight = (unsigned char *)cl.buildlightmapmemory; // update cached lighting info - surface->cached_dlight = 0; + model->brushq1.lightmapupdateflags[surface - model->data_surfaces] = false; lightmap = surface->lightmapinfo->samples; @@ -259,7 +259,7 @@ loc0: } // force lightmap upload if (stained) - surface->cached_dlight = true; + model->brushq1.lightmapupdateflags[surface - model->data_surfaces] = true; } } diff --git a/model_alias.c b/model_alias.c index 8cf13d0c..b756f91d 100644 --- a/model_alias.c +++ b/model_alias.c @@ -52,6 +52,12 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f int blends; float boneposerelative[MAX_BONES][12]; float *matrix, m[12], bonepose[MAX_BONES][12]; + size_t size; + + size = model->num_surfaces * sizeof(msurface_t) + model->num_surfaces * sizeof(int) + model->num_surfaces * model->numskins * sizeof(texture_t) + model->surfmesh.num_triangles * sizeof(int[3]) + model->surfmesh.num_triangles * sizeof(int[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[2]) + model->surfmesh.num_vertices * sizeof(int[4]) + model->surfmesh.num_vertices * sizeof(float[4]) + model->num_poses * sizeof(float[12]) + model->num_bones * sizeof(float[12]) + model->numskins * sizeof(animscene_t) + model->num_bones * sizeof(aliasbone_t) + model->numframes * sizeof(animscene_t) + ((model->surfmesh.num_vertices <= 65536) ? (model->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0); + if (size != ((memheader_t *)model->data_surfaces)[-1].size) + Sys_Error("%s:%i: %i != %i", __FILE__, __LINE__, (int)size, (int)((memheader_t *)model->data_surfaces)[-1].size); + // interpolate matrices and concatenate them to their parents for (i = 0;i < model->num_bones;i++) { @@ -60,6 +66,8 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++) { matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12; + if ((unsigned char *)(matrix + 12) >(unsigned char *)model->data_surfaces + ((memheader_t *)model->data_surfaces)[-1].size) + Sys_Error("%s:%i: matrix %p >= data %p + size %i\n", __FILE__, __LINE__, matrix, model->data_surfaces, (int)((memheader_t *)model->data_surfaces)[-1].size); for (k = 0;k < 12;k++) m[k] += matrix[k] * frameblend[blends].lerp; } @@ -2142,7 +2150,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) #define PSKQUATNEGATIONS void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { - int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles, size; + int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles; int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys; fs_offset_t filesize; pskpnts_t *pnts; @@ -2159,6 +2167,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) pskchunk_t *pchunk; skinfile_t *skinfiles; char animname[MAX_QPATH]; + size_t size; pchunk = (pskchunk_t *)buffer; if (strcmp(pchunk->id, "ACTRHEAD")) @@ -2528,47 +2537,28 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; // do most allocations as one merged chunk - size = 0; - size += loadmodel->num_surfaces * sizeof(msurface_t); - size += loadmodel->num_surfaces * sizeof(int); - size += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); - size += meshtriangles * sizeof(int[3]); - size += meshtriangles * sizeof(int[3]); - size += meshvertices * sizeof(float[3]); - size += meshvertices * sizeof(float[3]); - size += meshvertices * sizeof(float[3]); - size += meshvertices * sizeof(float[3]); - size += meshvertices * sizeof(float[2]); - size += meshvertices * sizeof(int[4]); - size += meshvertices * sizeof(float[4]); - size += loadmodel->num_poses * sizeof(float[12]); - size += loadmodel->num_bones * sizeof(float[12]); - size += loadmodel->numskins * sizeof(animscene_t); - size += loadmodel->num_bones * sizeof(aliasbone_t); - size += loadmodel->numframes * sizeof(animscene_t); - if (meshvertices <= 65536) - size += meshtriangles * sizeof(unsigned short[3]); + 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_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(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + 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->surfacelist = (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 += meshtriangles * sizeof(int[3]); - loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]); - loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]); - loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]); - loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]); - loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]); - loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]); - loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]); - loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]); + loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); + loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); + loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]); + loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]); + loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]); loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]); loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t); loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t); loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); - if (meshvertices <= 65536) + if (loadmodel->surfmesh.num_vertices <= 65536) { - loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); + loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; } @@ -2705,6 +2695,10 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_CalculateBoundingBox(); + 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_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(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + 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); + if (size != ((memheader_t *)loadmodel->data_surfaces)[-1].size) + Sys_Error("%s:%i: %i != %i", __FILE__, __LINE__, (int)size, (int)((memheader_t *)loadmodel->data_surfaces)[-1].size); + loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; } diff --git a/model_brush.c b/model_brush.c index 0f3f6024..f61696a0 100644 --- a/model_brush.c +++ b/model_brush.c @@ -2233,6 +2233,8 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) loadmodel->num_surfaces = count; + loadmodel->brushq1.lightmapupdateflags = (unsigned char *)Mem_Alloc(loadmodel->mempool, count*sizeof(unsigned char)); + totalverts = 0; totaltris = 0; for (surfacenum = 0, in = (dface_t *)(mod_base + l->fileofs);surfacenum < count;surfacenum++, in++) @@ -2380,7 +2382,7 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l) // additionally this is used by the later code to see if a // lightmap is needed on this surface (rather than duplicating the // logic above) - surface->cached_dlight = true; + loadmodel->brushq1.lightmapupdateflags[surfacenum] = true; } } @@ -3660,7 +3662,7 @@ void Mod_Q1BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) mod->radius2 = modelradius * modelradius; // build lightstyle update chains - // (used to rapidly mark surface->cached_dlight on many surfaces + // (used to rapidly mark lightmapupdateflags on many surfaces // when d_lightstylevalue changes) memset(stylecounts, 0, sizeof(stylecounts)); for (k = 0;k < mod->nummodelsurfaces;k++) @@ -4279,6 +4281,34 @@ static void Mod_Q3BSP_LoadBrushSides(lump_t *l) } } +static void Mod_Q3BSP_LoadBrushSides_IG(lump_t *l) +{ + q3dbrushside_ig_t *in; + q3mbrushside_t *out; + int i, n, count; + + in = (q3dbrushside_ig_t *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + Host_Error("Mod_Q3BSP_LoadBrushSides: funny lump size in %s",loadmodel->name); + count = l->filelen / sizeof(*in); + out = (q3mbrushside_t *)Mem_Alloc(loadmodel->mempool, count * sizeof(*out)); + + loadmodel->brush.data_brushsides = out; + loadmodel->brush.num_brushsides = count; + + for (i = 0;i < count;i++, in++, out++) + { + n = LittleLong(in->planeindex); + if (n < 0 || n >= loadmodel->brush.num_planes) + Host_Error("Mod_Q3BSP_LoadBrushSides: invalid planeindex %i (%i planes)", n, loadmodel->brush.num_planes); + out->plane = loadmodel->brush.data_planes + n; + n = LittleLong(in->textureindex); + if (n < 0 || n >= loadmodel->num_textures) + Host_Error("Mod_Q3BSP_LoadBrushSides: invalid textureindex %i (%i textures)", n, loadmodel->num_textures); + out->texture = loadmodel->data_textures + n; + } +} + static void Mod_Q3BSP_LoadBrushes(lump_t *l) { q3dbrush_t *in; @@ -5636,7 +5666,7 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) header = (q3dheader_t *)buffer; i = LittleLong(header->version); - if (i != Q3BSPVERSION) + if (i != Q3BSPVERSION && i != Q3BSPVERSION_IG) Host_Error("Mod_Q3BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q3BSPVERSION); mod->brush.ishlbsp = false; if (loadmodel->isworldmodel) @@ -5692,7 +5722,10 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_Q3BSP_LoadEntities(&header->lumps[Q3LUMP_ENTITIES]); Mod_Q3BSP_LoadTextures(&header->lumps[Q3LUMP_TEXTURES]); Mod_Q3BSP_LoadPlanes(&header->lumps[Q3LUMP_PLANES]); - Mod_Q3BSP_LoadBrushSides(&header->lumps[Q3LUMP_BRUSHSIDES]); + if (header->version == Q3BSPVERSION_IG) + Mod_Q3BSP_LoadBrushSides_IG(&header->lumps[Q3LUMP_BRUSHSIDES]); + else + Mod_Q3BSP_LoadBrushSides(&header->lumps[Q3LUMP_BRUSHSIDES]); Mod_Q3BSP_LoadBrushes(&header->lumps[Q3LUMP_BRUSHES]); Mod_Q3BSP_LoadEffects(&header->lumps[Q3LUMP_EFFECTS]); Mod_Q3BSP_LoadVertices(&header->lumps[Q3LUMP_VERTICES]); @@ -5832,7 +5865,7 @@ void Mod_Q3BSP_Load(dp_model_t *mod, void *buffer, void *bufferend) void Mod_IBSP_Load(dp_model_t *mod, void *buffer, void *bufferend) { int i = LittleLong(((int *)buffer)[1]); - if (i == Q3BSPVERSION) + if (i == Q3BSPVERSION || i == Q3BSPVERSION_IG) Mod_Q3BSP_Load(mod,buffer, bufferend); else if (i == Q2BSPVERSION) Mod_Q2BSP_Load(mod,buffer, bufferend); diff --git a/model_brush.h b/model_brush.h index a0a92687..854faf50 100644 --- a/model_brush.h +++ b/model_brush.h @@ -393,6 +393,7 @@ typedef struct q2darea_s //Q3 bsp stuff #define Q3BSPVERSION 46 +#define Q3BSPVERSION_IG 48 #define Q3LUMP_ENTITIES 0 // entities to spawn (used by server and client) #define Q3LUMP_TEXTURES 1 // textures used (used by faces) @@ -484,6 +485,14 @@ typedef struct q3dbrushside_s } q3dbrushside_t; +typedef struct q3dbrushside_ig_s +{ + int planeindex; + int textureindex; + int surfaceflags; +} +q3dbrushside_ig_t; + typedef struct q3dvertex_s { float origin3f[3]; diff --git a/model_shared.c b/model_shared.c index f54b6da0..80c22379 100644 --- a/model_shared.c +++ b/model_shared.c @@ -113,7 +113,7 @@ static void mod_newmap(void) ssize = (surface->lightmapinfo->extents[0] >> 4) + 1; tsize = (surface->lightmapinfo->extents[1] >> 4) + 1; memset(surface->lightmapinfo->stainsamples, 255, ssize * tsize * 3); - surface->cached_dlight = true; + mod->brushq1.lightmapupdateflags[surfacenum] = true; } } } diff --git a/model_shared.h b/model_shared.h index 035cfe4b..2302383d 100644 --- a/model_shared.h +++ b/model_shared.h @@ -548,7 +548,6 @@ typedef struct msurface_s int num_firstshadowmeshtriangle; // index into model->brush.shadowmesh // lightmaptexture rebuild information not used in q3bsp - int cached_dlight; // q1bsp // forces rebuild of lightmaptexture msurface_lightmapinfo_t *lightmapinfo; // q1bsp // mesh information for collisions (only used by q3bsp curves) @@ -706,6 +705,9 @@ typedef struct model_brushq1_s // lightmap update chains for light styles int num_lightstyles; model_brush_lightstyleinfo_t *data_lightstyleinfo; + + // this contains bytes that are 1 if a surface needs its lightmap rebuilt + unsigned char *lightmapupdateflags; } model_brushq1_t; -- 2.39.2