]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
changed format of aliasvertex_t to use floats (hopefully this is a speedup, it sure...
[xonotic/darkplaces.git] / model_brush.c
index 050fed9eb64ed0a7f561e367092fc5434ca5cc74..4959d8c32887cb48585abe14b9c9e5a6625e5177 100644 (file)
@@ -236,6 +236,7 @@ static void Mod_LoadTextures (lump_t *l)
        // fill out all slots with notexture
        for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++)
        {
+               tx->number = i;
                tx->width = 16;
                tx->height = 16;
                tx->texture = r_notexture;
@@ -245,6 +246,7 @@ static void Mod_LoadTextures (lump_t *l)
                        tx->flags = SURF_DRAWTURB | SURF_LIGHTBOTHSIDES;
                        tx->shader = &Cshader_water;
                }
+               tx->currentframe = tx;
        }
 
        // just to work around bounds checking when debugging with it (array index out of bounds error thing)
@@ -383,10 +385,10 @@ static void Mod_LoadTextures (lump_t *l)
                                                        Image_Copy8bitRGBA(mtdata, basepixels, basepixels_width * basepixels_height, palette_nofullbrights);
                                                        if (!glowpixels)
                                                        {
-                                                               for (j = 0;j < tx->width*tx->height;j++)
+                                                               for (j = 0;j < (int)(tx->width*tx->height);j++)
                                                                        if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright
                                                                                break;
-                                                               if (j < tx->width * tx->height)
+                                                               if (j < (int)(tx->width * tx->height))
                                                                {
                                                                        glowpixels_width = tx->width;
                                                                        glowpixels_height = tx->height;
@@ -783,8 +785,10 @@ void Mod_ProcessLightList(void)
                                                dist = -dist;
                                        if (dist > 0 && dist < e->cullradius)
                                        {
-                                               VectorSubtract(e->origin, surf->poly_center, temp);
-                                               if (DotProduct(temp, temp) - surf->poly_radius2 < e->cullradius2)
+                                               temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
+                                               temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
+                                               temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
+                                               if (DotProduct(temp, temp) < lightradius2)
                                                        loadmodel->surfacevisframes[*mark] = -2;
                                        }
                                }
@@ -1237,58 +1241,6 @@ static void Mod_LoadTexinfo (lump_t *l)
        }
 }
 
-/*
-================
-CalcSurfaceExtents
-
-Fills in s->texturemins[] and s->extents[]
-================
-*/
-static void CalcSurfaceExtents (msurface_t *s)
-{
-       float   mins[2], maxs[2], val;
-       int             i,j, e;
-       mvertex_t       *v;
-       mtexinfo_t      *tex;
-       int             bmins[2], bmaxs[2];
-
-       mins[0] = mins[1] = 999999999;
-       maxs[0] = maxs[1] = -999999999;
-
-       tex = s->texinfo;
-
-       for (i=0 ; i<s->numedges ; i++)
-       {
-               e = loadmodel->surfedges[s->firstedge+i];
-               if (e >= 0)
-                       v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
-               else
-                       v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
-
-               for (j=0 ; j<2 ; j++)
-               {
-                       val = v->position[0] * tex->vecs[j][0] +
-                               v->position[1] * tex->vecs[j][1] +
-                               v->position[2] * tex->vecs[j][2] +
-                               tex->vecs[j][3];
-                       if (val < mins[j])
-                               mins[j] = val;
-                       if (val > maxs[j])
-                               maxs[j] = val;
-               }
-       }
-
-       for (i=0 ; i<2 ; i++)
-       {
-               bmins[i] = floor(mins[i]/16);
-               bmaxs[i] = ceil(maxs[i]/16);
-
-               s->texturemins[i] = bmins[i] * 16;
-               s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
-       }
-}
-
-
 void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
 {
        int             i, j;
@@ -1584,17 +1536,18 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
        Mod_BuildTextureVectorsAndNormals(mesh->numverts, mesh->numtriangles, mesh->verts, mesh->str, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals);
 }
 
-void Mod_GenerateSurfacePolygon (msurface_t *surf)
+void Mod_GenerateSurfacePolygon (msurface_t *surf, int firstedge, int numedges)
 {
-       int i, lindex;
-       float *vec, *vert, mins[3], maxs[3], temp[3], dist;
+       int i, lindex, j;
+       float *vec, *vert, mins[3], maxs[3], val, *v;
+       mtexinfo_t *tex;
 
        // convert edges back to a normal polygon
-       surf->poly_numverts = surf->numedges;
-       vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * surf->numedges);
-       for (i = 0;i < surf->numedges;i++)
+       surf->poly_numverts = numedges;
+       vert = surf->poly_verts = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * numedges);
+       for (i = 0;i < numedges;i++)
        {
-               lindex = loadmodel->surfedges[surf->firstedge + i];
+               lindex = loadmodel->surfedges[firstedge + i];
                if (lindex > 0)
                        vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
                else
@@ -1602,33 +1555,44 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
                VectorCopy (vec, vert);
                vert += 3;
        }
+
+       // calculate polygon bounding box and center
        vert = surf->poly_verts;
        VectorCopy(vert, mins);
        VectorCopy(vert, maxs);
        vert += 3;
-       for (i = 1;i < surf->poly_numverts;i++)
+       for (i = 1;i < surf->poly_numverts;i++, vert += 3)
        {
                if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0];
                if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1];
                if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2];
-               vert += 3;
        }
        VectorCopy(mins, surf->poly_mins);
        VectorCopy(maxs, surf->poly_maxs);
        surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
        surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
        surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
-       surf->poly_radius2 = 0;
-       vert = surf->poly_verts;
-       for (i = 0;i < surf->poly_numverts;i++)
+
+       // generate surface extents information
+       tex = surf->texinfo;
+       mins[0] = maxs[0] = DotProduct(surf->poly_verts, tex->vecs[0]) + tex->vecs[0][3];
+       mins[1] = maxs[1] = DotProduct(surf->poly_verts, tex->vecs[1]) + tex->vecs[1][3];
+       for (i = 1, v = surf->poly_verts + 3;i < surf->poly_numverts;i++, v += 3)
        {
-               VectorSubtract(vert, surf->poly_center, temp);
-               dist = DotProduct(temp, temp);
-               if (surf->poly_radius2 < dist)
-                       surf->poly_radius2 = dist;
-               vert += 3;
+               for (j = 0;j < 2;j++)
+               {
+                       val = DotProduct(v, tex->vecs[j]) + tex->vecs[j][3];
+                       if (mins[j] > val)
+                               mins[j] = val;
+                       if (maxs[j] < val)
+                               maxs[j] = val;
+               }
+       }
+       for (i = 0;i < 2;i++)
+       {
+               surf->texturemins[i] = (int) floor(mins[i] / 16) * 16;
+               surf->extents[i] = (int) ceil(maxs[i] / 16) * 16 - surf->texturemins[i];
        }
-       surf->poly_radius = sqrt(surf->poly_radius2);
 }
 
 /*
@@ -1640,7 +1604,7 @@ static void Mod_LoadFaces (lump_t *l)
 {
        dface_t *in;
        msurface_t      *out;
-       int i, count, surfnum, planenum, ssize, tsize;
+       int i, count, surfnum, planenum, ssize, tsize, firstedge, numedges;
 
        in = (void *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -1658,10 +1622,10 @@ static void Mod_LoadFaces (lump_t *l)
        {
                out->number = surfnum;
                // FIXME: validate edges, texinfo, etc?
-               out->firstedge = LittleLong(in->firstedge);
-               out->numedges = LittleShort(in->numedges);
-               if ((unsigned int) out->firstedge + (unsigned int) out->numedges > (unsigned int) loadmodel->numsurfedges)
-                       Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", out->firstedge, out->numedges, loadmodel->numsurfedges);
+               firstedge = LittleLong(in->firstedge);
+               numedges = LittleShort(in->numedges);
+               if ((unsigned int) firstedge + (unsigned int) numedges > (unsigned int) loadmodel->numsurfedges)
+                       Host_Error("Mod_LoadFaces: invalid edge range (firstedge %i, numedges %i, model edges %i)\n", firstedge, numedges, loadmodel->numsurfedges);
 
                i = LittleShort (in->texinfo);
                if ((unsigned int) i >= (unsigned int) loadmodel->numtexinfo)
@@ -1684,7 +1648,7 @@ static void Mod_LoadFaces (lump_t *l)
                // force lightmap upload on first time seeing the surface
                out->cached_dlight = true;
 
-               CalcSurfaceExtents (out);
+               Mod_GenerateSurfacePolygon(out, firstedge, numedges);
 
                ssize = (out->extents[0] >> 4) + 1;
                tsize = (out->extents[1] >> 4) + 1;
@@ -1700,7 +1664,6 @@ static void Mod_LoadFaces (lump_t *l)
                else // LordHavoc: white lighting (bsp version 29)
                        out->samples = loadmodel->lightdata + (i * 3);
 
-               Mod_GenerateSurfacePolygon(out);
                if (out->texinfo->texture->shader == &Cshader_wall_lightmap)
                {
                        if ((out->extents[0] >> 4) + 1 > (256) || (out->extents[1] >> 4) + 1 > (256))
@@ -2747,6 +2710,95 @@ static void Mod_BuildSurfaceNeighbors (msurface_t *surfaces, int numsurfaces, me
 #endif
 }
 
+void Mod_BuildLightmapUpdateChains(mempool_t *mempool, model_t *model)
+{
+       int i, j, stylecounts[256], totalcount, remapstyles[256];
+       msurface_t *surf;
+       memset(stylecounts, 0, sizeof(stylecounts));
+       for (i = 0;i < model->nummodelsurfaces;i++)
+       {
+               surf = model->surfaces + model->firstmodelsurface + i;
+               for (j = 0;j < MAXLIGHTMAPS;j++)
+                       stylecounts[surf->styles[j]]++;
+       }
+       totalcount = 0;
+       model->light_styles = 0;
+       for (i = 0;i < 255;i++)
+       {
+               if (stylecounts[i])
+               {
+                       remapstyles[i] = model->light_styles++;
+                       totalcount += stylecounts[i] + 1;
+               }
+       }
+       if (!totalcount)
+               return;
+       model->light_style = Mem_Alloc(mempool, model->light_styles * sizeof(qbyte));
+       model->light_stylevalue = Mem_Alloc(mempool, model->light_styles * sizeof(int));
+       model->light_styleupdatechains = Mem_Alloc(mempool, model->light_styles * sizeof(msurface_t **));
+       model->light_styleupdatechainsbuffer = Mem_Alloc(mempool, totalcount * sizeof(msurface_t *));
+       model->light_styles = 0;
+       for (i = 0;i < 255;i++)
+               if (stylecounts[i])
+                       model->light_style[model->light_styles++] = i;
+       j = 0;
+       for (i = 0;i < model->light_styles;i++)
+       {
+               model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j;
+               j += stylecounts[model->light_style[i]] + 1;
+       }
+       for (i = 0;i < model->nummodelsurfaces;i++)
+       {
+               surf = model->surfaces + model->firstmodelsurface + i;
+               for (j = 0;j < MAXLIGHTMAPS;j++)
+                       if (surf->styles[j] != 255)
+                               *model->light_styleupdatechains[remapstyles[surf->styles[j]]]++ = surf;
+       }
+       j = 0;
+       for (i = 0;i < model->light_styles;i++)
+       {
+               *model->light_styleupdatechains[i] = NULL;
+               model->light_styleupdatechains[i] = model->light_styleupdatechainsbuffer + j;
+               j += stylecounts[model->light_style[i]] + 1;
+       }
+}
+
+void Mod_BuildPVSTextureChains(model_t *model)
+{
+       int i, j;
+       for (i = 0;i < model->numtextures;i++)
+               model->pvstexturechainslength[i] = 0;
+       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+       {
+               if (model->surfacepvsframes[j] == model->pvsframecount)
+               {
+                       model->pvssurflist[model->pvssurflistlength++] = j;
+                       model->pvstexturechainslength[model->surfaces[j].texinfo->texture->number]++;
+               }
+       }
+       for (i = 0, j = 0;i < model->numtextures;i++)
+       {
+               if (model->pvstexturechainslength[i])
+               {
+                       model->pvstexturechains[i] = model->pvstexturechainsbuffer + j;
+                       j += model->pvstexturechainslength[i] + 1;
+               }
+               else
+                       model->pvstexturechains[i] = NULL;
+       }
+       for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
+               if (model->surfacepvsframes[j] == model->pvsframecount)
+                       *model->pvstexturechains[model->surfaces[j].texinfo->texture->number]++ = model->surfaces + j;
+       for (i = 0;i < model->numtextures;i++)
+       {
+               if (model->pvstexturechainslength[i])
+               {
+                       *model->pvstexturechains[i] = NULL;
+                       model->pvstexturechains[i] -= model->pvstexturechainslength[i];
+               }
+       }
+}
+
 /*
 =================
 Mod_LoadBrushModel
@@ -2758,12 +2810,15 @@ extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relative
 extern void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor);
 void Mod_LoadBrushModel (model_t *mod, void *buffer)
 {
-       int                     i, j;
-       dheader_t       *header;
-       dmodel_t        *bm;
-       mempool_t       *mainmempool;
-       char            *loadname;
-       model_t         *originalloadmodel;
+       int i, j, k;
+       dheader_t *header;
+       dmodel_t *bm;
+       mempool_t *mainmempool;
+       char *loadname;
+       model_t *originalloadmodel;
+       float dist, modelyawradius, modelradius, *vec;
+       msurface_t *surf;
+       surfmesh_t *mesh;
 
        mod->type = mod_brush;
 
@@ -2783,7 +2838,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
 // swap all the lumps
        mod_base = (qbyte *)header;
 
-       for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
+       for (i = 0;i < (int) sizeof(dheader_t) / 4;i++)
                ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
 
 // load into heap
@@ -2823,15 +2878,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
 //
        for (i = 0;i < mod->numsubmodels;i++)
        {
-               int k, l;
-               float dist, modelyawradius, modelradius, *vec;
-               msurface_t *surf;
-
-               mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
-               mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
-               modelyawradius = 0;
-               modelradius = 0;
-
                bm = &mod->submodels[i];
 
                mod->hulls[0].firstclipnode = bm->headnode[0];
@@ -2850,38 +2896,41 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->DrawFakeShadow = NULL;
                mod->DrawShadowVolume = R_Model_Brush_DrawShadowVolume;
                mod->DrawLight = R_Model_Brush_DrawLight;
-               mod->texturesurfacechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t *));
+               mod->pvstexturechains = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(msurface_t **));
+               mod->pvstexturechainsbuffer = Mem_Alloc(originalloadmodel->mempool, (mod->nummodelsurfaces + mod->numtextures) * sizeof(msurface_t *));
+               mod->pvstexturechainslength = Mem_Alloc(originalloadmodel->mempool, mod->numtextures * sizeof(int));
+               Mod_BuildPVSTextureChains(mod);
+               Mod_BuildLightmapUpdateChains(originalloadmodel->mempool, mod);
                if (mod->nummodelsurfaces)
                {
                        // LordHavoc: calculate bmodel bounding box rather than trusting what it says
+                       mod->normalmins[0] = mod->normalmins[1] = mod->normalmins[2] = 1000000000.0f;
+                       mod->normalmaxs[0] = mod->normalmaxs[1] = mod->normalmaxs[2] = -1000000000.0f;
+                       modelyawradius = 0;
+                       modelradius = 0;
                        for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
                        {
                                // we only need to have a drawsky function if it is used (usually only on world model)
                                if (surf->texinfo->texture->shader == &Cshader_sky)
                                        mod->DrawSky = R_Model_Brush_DrawSky;
-                               // link into texture chain
-                               surf->texturechain = mod->texturesurfacechains[surf->texinfo->texture - mod->textures];
-                               mod->texturesurfacechains[surf->texinfo->texture - mod->textures] = surf;
                                // calculate bounding shapes
-                               for (k = 0;k < surf->numedges;k++)
+                               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                                {
-                                       l = mod->surfedges[k + surf->firstedge];
-                                       if (l > 0)
-                                               vec = mod->vertexes[mod->edges[l].v[0]].position;
-                                       else
-                                               vec = mod->vertexes[mod->edges[-l].v[1]].position;
-                                       if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
-                                       if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
-                                       if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
-                                       if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
-                                       if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
-                                       if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
-                                       dist = vec[0]*vec[0]+vec[1]*vec[1];
-                                       if (modelyawradius < dist)
-                                               modelyawradius = dist;
-                                       dist += vec[2]*vec[2];
-                                       if (modelradius < dist)
-                                               modelradius = dist;
+                                       for (k = 0, vec = mesh->verts;k < mesh->numverts;k++, vec += 4)
+                                       {
+                                               if (mod->normalmins[0] > vec[0]) mod->normalmins[0] = vec[0];
+                                               if (mod->normalmins[1] > vec[1]) mod->normalmins[1] = vec[1];
+                                               if (mod->normalmins[2] > vec[2]) mod->normalmins[2] = vec[2];
+                                               if (mod->normalmaxs[0] < vec[0]) mod->normalmaxs[0] = vec[0];
+                                               if (mod->normalmaxs[1] < vec[1]) mod->normalmaxs[1] = vec[1];
+                                               if (mod->normalmaxs[2] < vec[2]) mod->normalmaxs[2] = vec[2];
+                                               dist = vec[0]*vec[0]+vec[1]*vec[1];
+                                               if (modelyawradius < dist)
+                                                       modelyawradius = dist;
+                                               dist += vec[2]*vec[2];
+                                               if (modelradius < dist)
+                                                       modelradius = dist;
+                                       }
                                }
                        }
                        modelyawradius = sqrt(modelyawradius);
@@ -2893,28 +2942,11 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                        mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
                        mod->radius = modelradius;
                        mod->radius2 = modelradius * modelradius;
-                       // LordHavoc: build triangle meshs for entire model's geometry
-                       // (only used for shadow volumes)
-                       mod->shadowmesh = Mod_ShadowMesh_Begin(originalloadmodel->mempool, 1024);
-                       for (j = 0, surf = &mod->surfaces[mod->firstmodelsurface];j < mod->nummodelsurfaces;j++, surf++)
-                               if (surf->flags & SURF_SHADOWCAST)
-                                       Mod_ShadowMesh_AddPolygon(originalloadmodel->mempool, mod->shadowmesh, surf->poly_numverts, surf->poly_verts);
-                       mod->shadowmesh = Mod_ShadowMesh_Finish(originalloadmodel->mempool, mod->shadowmesh);
-                       Mod_ShadowMesh_CalcBBox(mod->shadowmesh, mod->shadowmesh_mins, mod->shadowmesh_maxs, mod->shadowmesh_center, &mod->shadowmesh_radius);
                }
                else
                {
                        // LordHavoc: empty submodel (lacrima.bsp has such a glitch)
                        Con_Printf("warning: empty submodel *%i in %s\n", i+1, loadname);
-                       VectorClear(mod->normalmins);
-                       VectorClear(mod->normalmaxs);
-                       VectorClear(mod->yawmins);
-                       VectorClear(mod->yawmaxs);
-                       VectorClear(mod->rotatedmins);
-                       VectorClear(mod->rotatedmaxs);
-                       mod->radius = 0;
-                       mod->radius2 = 0;
-                       mod->shadowmesh = NULL;
                }
                Mod_BuildSurfaceNeighbors(mod->surfaces + mod->firstmodelsurface, mod->nummodelsurfaces, originalloadmodel->mempool);