an attempt at optimizing msurface_t dlight_cache checks by moving them
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 5 Jul 2008 07:31:46 +0000 (07:31 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 5 Jul 2008 07:31:46 +0000 (07:31 +0000)
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
gl_rsurf.c
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h

index 70eb82e..2c65e85 100644 (file)
@@ -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);
 }
index d14cc1f..3998249 100644 (file)
@@ -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;
                }
        }
 
index 8cf13d0..b756f91 100644 (file)
@@ -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;
 }
 
index 0f3f602..f61696a 100644 (file)
@@ -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);
index a0a9268..854faf5 100644 (file)
@@ -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];
index f54b6da..80c2237 100644 (file)
@@ -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;
                                }
                        }
                }
index 035cfe4..2302383 100644 (file)
@@ -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;