]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_brush.c
made various things take const pointers (optimizer hint), commented out and/or remove...
[xonotic/darkplaces.git] / model_brush.c
index 9b0a3454de2a188ba36bc7c7f196ed24e442faf3..be7c3067c9aa9977f641b3311a9ccb3a8652cae9 100644 (file)
@@ -546,6 +546,66 @@ static void Mod_LoadLighting (lump_t *l)
        }
 }
 
+void Mod_LoadLightList(void)
+{
+       int a, n, numlights;
+       char lightsfilename[1024], *s, *t, *lightsstring;
+       mlight_t *e;
+
+       strcpy(lightsfilename, loadmodel->name);
+       COM_StripExtension(lightsfilename, lightsfilename);
+       strcat(lightsfilename, ".lights");
+       s = lightsstring = (char *) COM_LoadFile (lightsfilename, false);
+       if (s)
+       {
+               numlights = 0;
+               while (*s)
+               {
+                       while (*s && *s != '\n')
+                               s++;
+                       if (!*s)
+                       {
+                               Mem_Free(lightsstring);
+                               Host_Error("lights file must end with a newline\n");
+                       }
+                       s++;
+                       numlights++;
+               }
+               loadmodel->lights = Mem_Alloc(loadmodel->mempool, numlights * sizeof(mlight_t));
+               s = lightsstring;
+               n = 0;
+               while (*s && n < numlights)
+               {
+                       t = s;
+                       while (*s && *s != '\n')
+                               s++;
+                       if (!*s)
+                       {
+                               Mem_Free(lightsstring);
+                               Host_Error("misparsed lights file!\n");
+                       }
+                       e = loadmodel->lights + n;
+                       *s = 0;
+                       a = sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %d", &e->origin[0], &e->origin[1], &e->origin[2], &e->falloff, &e->light[0], &e->light[1], &e->light[2], &e->subtract, &e->spotdir[0], &e->spotdir[1], &e->spotdir[2], &e->spotcone, &e->distbias, &e->style);
+                       *s = '\n';
+                       if (a != 14)
+                       {
+                               Mem_Free(lightsstring);
+                               Host_Error("invalid lights file, found %d parameters on line %i, should be 13 parameters (origin[0] origin[1] origin[2] falloff light[0] light[1] light[2] subtract spotdir[0] spotdir[1] spotdir[2] spotcone style)\n", a, n + 1);
+                       }
+                       s++;
+                       n++;
+               }
+               if (*s)
+               {
+                       Mem_Free(lightsstring);
+                       Host_Error("misparsed lights file!\n");
+               }
+               loadmodel->numlights = numlights;
+               Mem_Free(lightsstring);
+       }
+}
+
 
 /*
 =================
@@ -968,14 +1028,14 @@ void Mod_GenerateWarpMesh (msurface_t *surf)
        subdivpolytriangles = 0;
        subdivpolyverts = 0;
        SubdividePolygon (surf->poly_numverts, surf->poly_verts);
+       if (subdivpolytriangles < 1)
+               Host_Error("Mod_GenerateWarpMesh: no triangles?\n");
 
-       mesh = &surf->mesh;
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + subdivpolytriangles * sizeof(int[3]) + subdivpolyverts * sizeof(surfvertex_t));
        mesh->numverts = subdivpolyverts;
        mesh->numtriangles = subdivpolytriangles;
-       if (mesh->numtriangles < 1)
-               Host_Error("Mod_GenerateWarpMesh: no triangles?\n");
-       mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
-       mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+       mesh->vertex = (surfvertex_t *)(mesh + 1);
+       mesh->index = (int *)(mesh->vertex + mesh->numverts);
        memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
 
        for (i = 0;i < mesh->numtriangles;i++)
@@ -1009,11 +1069,11 @@ void Mod_GenerateVertexLitMesh (msurface_t *surf)
        surf->lightmaptexturestride = 0;
        surf->lightmaptexture = NULL;
 
-       mesh = &surf->mesh;
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
        mesh->numverts = surf->poly_numverts;
        mesh->numtriangles = surf->poly_numverts - 2;
-       mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
-       mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+       mesh->vertex = (surfvertex_t *)(mesh + 1);
+       mesh->index = (int *)(mesh->vertex + mesh->numverts);
        memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
 
        index = mesh->index;
@@ -1076,11 +1136,11 @@ void Mod_GenerateLightmappedMesh (msurface_t *surf)
        xscale = (xscale - xbase) * 16.0 / ((surf->extents[0] & ~15) + 16);
        yscale = (yscale - ybase) * 16.0 / ((surf->extents[1] & ~15) + 16);
 
-       mesh = &surf->mesh;
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
        mesh->numverts = surf->poly_numverts;
        mesh->numtriangles = surf->poly_numverts - 2;
-       mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
-       mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+       mesh->vertex = (surfvertex_t *)(mesh + 1);
+       mesh->index = (int *)(mesh->vertex + mesh->numverts);
        memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
 
        index = mesh->index;
@@ -1127,11 +1187,11 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
        surf->lightmaptexturestride = 0;
        surf->lightmaptexture = NULL;
 
-       mesh = &surf->mesh;
+       surf->mesh = mesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + (surf->poly_numverts - 2) * sizeof(int[3]) + surf->poly_numverts * sizeof(surfvertex_t));
        mesh->numverts = surf->poly_numverts;
        mesh->numtriangles = surf->poly_numverts - 2;
-       mesh->index = Mem_Alloc(loadmodel->mempool, mesh->numtriangles * sizeof(int[3]) + mesh->numverts * sizeof(surfvertex_t));
-       mesh->vertex = (surfvertex_t *)((long) mesh->index + mesh->numtriangles * sizeof(int[3]));
+       mesh->vertex = (surfvertex_t *)(mesh + 1);
+       mesh->index = (int *)(mesh->vertex + mesh->numverts);
        memset(mesh->vertex, 0, mesh->numverts * sizeof(surfvertex_t));
 
        index = mesh->index;
@@ -1172,6 +1232,55 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
        }
 }
 
+static void Mod_SplitSurfMeshIfTooBig(msurface_t *s)
+{
+       int j, base, tricount, newvertexcount, *index, *vertexremap;
+       surfmesh_t *newmesh, *oldmesh, *firstmesh;
+       if (s->mesh->numtriangles > 1000)
+       {
+               vertexremap = Mem_Alloc(tempmempool, s->mesh->numverts * sizeof(int));
+               base = 0;
+               oldmesh = NULL;
+               firstmesh = NULL;
+               newmesh = NULL;
+               while (base < s->mesh->numtriangles)
+               {
+                       tricount = s->mesh->numtriangles - base;
+                       if (tricount > 1000)
+                               tricount = 1000;
+                       index = s->mesh->index + base * 3;
+                       base += tricount;
+
+                       newvertexcount = 0;
+                       memset(vertexremap, -1, s->mesh->numverts * sizeof(int));
+                       for (j = 0;j < tricount * 3;j++)
+                               if (vertexremap[index[j]] < 0)
+                                       vertexremap[index[j]] = newvertexcount++;
+
+                       newmesh = Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t) + newvertexcount * sizeof(surfvertex_t) + tricount * sizeof(int[3]));
+                       newmesh->chain = NULL;
+                       newmesh->numverts = newvertexcount;
+                       newmesh->numtriangles = tricount;
+                       newmesh->vertex = (surfvertex_t *)(newmesh + 1);
+                       newmesh->index = (int *)(newmesh->vertex + newvertexcount);
+                       for (j = 0;j < tricount * 3;j++)
+                       {
+                               newmesh->index[j] = vertexremap[index[j]];
+                               // yes this copies the same vertex multiple times in many cases...  but that's ok...
+                               memcpy(&newmesh->vertex[newmesh->index[j]], &s->mesh->vertex[index[j]], sizeof(surfvertex_t));
+                       }
+                       if (oldmesh)
+                               oldmesh->chain = newmesh;
+                       else
+                               firstmesh = newmesh;
+                       oldmesh = newmesh;
+               }
+               Mem_Free(vertexremap);
+               Mem_Free(s->mesh);
+               s->mesh = firstmesh;
+       }
+}
+
 /*
 =================
 Mod_LoadFaces
@@ -1239,10 +1348,8 @@ static void Mod_LoadFaces (lump_t *l)
                        out->shader = &Cshader_sky;
                        out->samples = NULL;
                        Mod_GenerateWarpMesh (out);
-                       continue;
                }
-
-               if (out->texinfo->texture->flags & SURF_DRAWTURB)
+               else if (out->texinfo->texture->flags & SURF_DRAWTURB)
                {
                        out->shader = &Cshader_water;
                        /*
@@ -1254,42 +1361,45 @@ static void Mod_LoadFaces (lump_t *l)
                        */
                        out->samples = NULL;
                        Mod_GenerateWarpMesh (out);
-                       continue;
-               }
-
-               if (!R_TextureHasAlpha(out->texinfo->texture->texture))
-                       out->flags |= SURF_CLIPSOLID;
-               if (out->texinfo->flags & TEX_SPECIAL)
-               {
-                       // qbsp couldn't find the texture for this surface, but it was either turb or sky...  assume turb
-                       out->shader = &Cshader_water;
-                       out->samples = NULL;
-                       Mod_GenerateWarpMesh (out);
-               }
-               else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16))
-               {
-                       Con_Printf ("Bad surface extents, converting to fullbright polygon");
-                       out->shader = &Cshader_wall_fullbright;
-                       out->samples = NULL;
-                       Mod_GenerateVertexMesh(out);
                }
                else
                {
-                       // stainmap for permanent marks on walls
-                       out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
-                       // clear to white
-                       memset(out->stainsamples, 255, ssize * tsize * 3);
-                       if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
+                       if (!R_TextureHasAlpha(out->texinfo->texture->texture))
+                               out->flags |= SURF_CLIPSOLID;
+                       if (out->texinfo->flags & TEX_SPECIAL)
+                       {
+                               // qbsp couldn't find the texture for this surface, but it was either turb or sky...  assume turb
+                               out->shader = &Cshader_water;
+                               out->shader = &Cshader_water;
+                               out->samples = NULL;
+                               Mod_GenerateWarpMesh (out);
+                       }
+                       else if ((out->extents[0]+1) > (256*16) || (out->extents[1]+1) > (256*16))
                        {
-                               out->shader = &Cshader_wall_vertex;
-                               Mod_GenerateVertexLitMesh(out);
+                               Con_Printf ("Bad surface extents, converting to fullbright polygon");
+                               out->shader = &Cshader_wall_fullbright;
+                               out->samples = NULL;
+                               Mod_GenerateVertexMesh(out);
                        }
                        else
                        {
-                               out->shader = &Cshader_wall_lightmap;
-                               Mod_GenerateLightmappedMesh(out);
+                               // stainmap for permanent marks on walls
+                               out->stainsamples = Mem_Alloc(loadmodel->mempool, ssize * tsize * 3);
+                               // clear to white
+                               memset(out->stainsamples, 255, ssize * tsize * 3);
+                               if (out->extents[0] < r_vertexsurfacesthreshold.integer && out->extents[1] < r_vertexsurfacesthreshold.integer)
+                               {
+                                       out->shader = &Cshader_wall_vertex;
+                                       Mod_GenerateVertexLitMesh(out);
+                               }
+                               else
+                               {
+                                       out->shader = &Cshader_wall_lightmap;
+                                       Mod_GenerateLightmappedMesh(out);
+                               }
                        }
                }
+               Mod_SplitSurfMeshIfTooBig(out);
        }
 }
 
@@ -1301,7 +1411,7 @@ static int Mod_SurfaceQSortCompare(const void *voida, const void *voidb)
        a = *((const msurface_t **)voida);
        b = *((const msurface_t **)voidb);
        if (a->shader != b->shader)
-               return (long) a->shader - (long) b->shader;
+               return (qbyte *) a->shader - (qbyte *) b->shader;
        if (a->texinfo->texture != b->texinfo->texture);
                return a->texinfo->texture - b->texinfo->texture;
        return 0;
@@ -1469,6 +1579,7 @@ static void Mod_LoadClipnodes (lump_t *l)
                hull->clip_maxs[0] = 16;
                hull->clip_maxs[1] = 16;
                hull->clip_maxs[2] = 36;
+               VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
 
                hull = &loadmodel->hulls[2];
                hull->clipnodes = out;
@@ -1481,6 +1592,7 @@ static void Mod_LoadClipnodes (lump_t *l)
                hull->clip_maxs[0] = 32;
                hull->clip_maxs[1] = 32;
                hull->clip_maxs[2] = 32;
+               VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
 
                hull = &loadmodel->hulls[3];
                hull->clipnodes = out;
@@ -1493,6 +1605,7 @@ static void Mod_LoadClipnodes (lump_t *l)
                hull->clip_maxs[0] = 16;
                hull->clip_maxs[1] = 16;
                hull->clip_maxs[2] = 18;
+               VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
        }
        else
        {
@@ -1507,6 +1620,7 @@ static void Mod_LoadClipnodes (lump_t *l)
                hull->clip_maxs[0] = 16;
                hull->clip_maxs[1] = 16;
                hull->clip_maxs[2] = 32;
+               VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
 
                hull = &loadmodel->hulls[2];
                hull->clipnodes = out;
@@ -1519,6 +1633,7 @@ static void Mod_LoadClipnodes (lump_t *l)
                hull->clip_maxs[0] = 32;
                hull->clip_maxs[1] = 32;
                hull->clip_maxs[2] = 64;
+               VectorSubtract(hull->clip_maxs, hull->clip_mins, hull->clip_size);
        }
 
        for (i=0 ; i<count ; i++, out++, in++)
@@ -2048,7 +2163,7 @@ static void Mod_FinalizePortals(void)
        }
        loadmodel->portals = Mem_Alloc(loadmodel->mempool, numportals * sizeof(mportal_t) + numpoints * sizeof(mvertex_t));
        loadmodel->numportals = numportals;
-       loadmodel->portalpoints = (void *) ((long) loadmodel->portals + numportals * sizeof(mportal_t));
+       loadmodel->portalpoints = (void *) ((qbyte *) loadmodel->portals + numportals * sizeof(mportal_t));
        loadmodel->numportalpoints = numpoints;
        // clear all leaf portal chains
        for (i = 0;i < loadmodel->numleafs;i++)
@@ -2379,6 +2494,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        dheader_t       *header;
        dmodel_t        *bm;
        mempool_t       *mainmempool;
+       char            *loadname;
 
        mod->type = mod_brush;
 
@@ -2444,6 +2560,9 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
        mod->numframes = 2;             // regular and alternate animation
 
        mainmempool = mod->mempool;
+       loadname = mod->name;
+
+       Mod_LoadLightList ();
 
 //
 // set up the submodels (FIXME: this is confusing)
@@ -2507,6 +2626,18 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
                mod->rotatedmins[0] = mod->rotatedmins[1] = mod->rotatedmins[2] = -modelradius;
                mod->rotatedmaxs[0] = mod->rotatedmaxs[1] = mod->rotatedmaxs[2] = modelradius;
 //             mod->modelradius = modelradius;
+               // LordHavoc: check for empty submodels (lacrima.bsp has such a glitch)
+               if (mod->normalmins[0] > mod->normalmaxs[0] || mod->normalmins[1] > mod->normalmaxs[1] || mod->normalmins[2] > mod->normalmaxs[2])
+               {
+                       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->modelradius = 0;
+               }
 
 //             VectorCopy (bm->maxs, mod->maxs);
 //             VectorCopy (bm->mins, mod->mins);