]> de.git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
no longer uses multiple meshes for model loading, they each use one mesh for all...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 29 Mar 2006 09:18:50 +0000 (09:18 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 29 Mar 2006 09:18:50 +0000 (09:18 +0000)
now puts all q3bsp map geometry into one mesh at load rather than splitting it into 65536 vertex meshes to crutch up broken drivers (they've been fixed already so this is no longer necessary)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6205 d7cf8633-e32d-0410-b094-e92efae38249

model_alias.c
model_brush.c
model_shared.c
model_shared.h
todo

index 4b43e42f340462834d92d5dd02045053b28ee268..833fbe2e9a6ef25d8c08e08a28cfbb9054718f76 100644 (file)
@@ -280,7 +280,7 @@ static void Mod_CalcAliasModelBBoxes (void)
        VectorClear(loadmodel->normalmaxs);
        yawradius = 0;
        radius = 0;
        VectorClear(loadmodel->normalmaxs);
        yawradius = 0;
        radius = 0;
-       for (meshnum = 0;meshnum < loadmodel->num_surfaces;meshnum++)
+       for (meshnum = 0;meshnum < loadmodel->nummeshes;meshnum++)
        {
                mesh = loadmodel->meshlist[meshnum];
                for (vnum = 0, v = mesh->data_morphvertex3f;vnum < mesh->num_vertices * mesh->num_morphframes;vnum++, v += 3)
        {
                mesh = loadmodel->meshlist[meshnum];
                for (vnum = 0, v = mesh->data_morphvertex3f;vnum < mesh->num_vertices * mesh->num_morphframes;vnum++, v += 3)
@@ -506,16 +506,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
 
        loadmodel->num_surfaces = 1;
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
 
        loadmodel->num_surfaces = 1;
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
-       loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       loadmodel->nummeshes = 1;
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + sizeof(surfmesh_t *) + sizeof(surfmesh_t));
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
-       for (i = 0;i < loadmodel->num_surfaces;i++)
-       {
-               loadmodel->surfacelist[i] = i;
-               loadmodel->meshlist[i] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
-       }
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->surfacelist[0] = 0;
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,65536);
 
        loadmodel->numskins = LittleLong(pinmodel->numskins);
        BOUNDI(loadmodel->numskins,0,65536);
@@ -617,7 +614,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
                for (j = 0;j < 3;j++)
                        loadmodel->meshlist[0]->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
        // validate (note numverts is used because this is the original data)
                for (j = 0;j < 3;j++)
                        loadmodel->meshlist[0]->data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
        // validate (note numverts is used because this is the original data)
-       Mod_ValidateElements(loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles, numverts, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles, 0, numverts, __FILE__, __LINE__);
        // now butcher the elements according to vertonseam and tri->facesfront
        // and then compact the vertex set to remove duplicates
        for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)
        // now butcher the elements according to vertonseam and tri->facesfront
        // and then compact the vertex set to remove duplicates
        for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)
@@ -848,16 +845,13 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
 
        loadmodel->num_surfaces = 1;
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
 
        loadmodel->num_surfaces = 1;
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
-       loadmodel->nummeshes = loadmodel->num_surfaces;
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+       loadmodel->nummeshes = 1;
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + sizeof(surfmesh_t *) + sizeof(surfmesh_t));
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
-       for (i = 0;i < loadmodel->num_surfaces;i++)
-       {
-               loadmodel->surfacelist[i] = i;
-               loadmodel->meshlist[i] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
-       }
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->surfacelist[0] = 0;
 
        loadmodel->numskins = LittleLong(pinmodel->num_skins);
        numxyz = LittleLong(pinmodel->num_xyz);
 
        loadmodel->numskins = LittleLong(pinmodel->num_skins);
        numxyz = LittleLong(pinmodel->num_xyz);
@@ -1034,10 +1028,9 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
 
 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
 {
 
 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
 {
-       int i, j, k, version;
+       int i, j, k, version, meshvertices, meshtriangles;
        unsigned char *data;
        msurface_t *surface;
        unsigned char *data;
        msurface_t *surface;
-       surfmesh_t *mesh;
        md3modelheader_t *pinmodel;
        md3frameinfo_t *pinframe;
        md3mesh_t *pinmesh;
        md3modelheader_t *pinmodel;
        md3frameinfo_t *pinframe;
        md3mesh_t *pinmesh;
@@ -1110,63 +1103,76 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
        }
 
        // load meshes
        }
 
        // load meshes
+       meshvertices = 0;
+       meshtriangles = 0;
+       for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
+       {
+               if (memcmp(pinmesh->identifier, "IDP3", 4))
+                       Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
+               if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
+                       Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
+               meshvertices += LittleLong(pinmesh->num_vertices);
+               meshtriangles += LittleLong(pinmesh->num_triangles);
+       }
+
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
        loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
-       loadmodel->nummeshes = loadmodel->num_surfaces;
        loadmodel->num_textures = loadmodel->num_surfaces;
        loadmodel->num_textures = loadmodel->num_surfaces;
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+       loadmodel->nummeshes = 1;
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + sizeof(surfmesh_t *) + sizeof(surfmesh_t) + meshtriangles * sizeof(int[6]) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(float[3]));
        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_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
-       loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
        loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
-       for (i = 0;i < loadmodel->num_surfaces;i++)
-       {
-               loadmodel->surfacelist[i] = i;
-               loadmodel->meshlist[i] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
-       }
+       loadmodel->meshlist = (surfmesh_t **)data;data += sizeof(surfmesh_t *);
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->meshlist[0]->num_vertices = meshvertices;
+       loadmodel->meshlist[0]->num_triangles = meshtriangles;
+       loadmodel->meshlist[0]->num_morphframes = loadmodel->numframes; // TODO: remove?
+       loadmodel->meshlist[0]->data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+       loadmodel->meshlist[0]->data_morphvertex3f = (float *)data;data += meshvertices * loadmodel->numframes * sizeof(float[3]);
+
+       meshvertices = 0;
+       meshtriangles = 0;
        for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
        {
                if (memcmp(pinmesh->identifier, "IDP3", 4))
                        Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
        for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
        {
                if (memcmp(pinmesh->identifier, "IDP3", 4))
                        Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
-               mesh = loadmodel->meshlist[i];
-               mesh->num_morphframes = LittleLong(pinmesh->num_frames);
-               mesh->num_vertices = LittleLong(pinmesh->num_vertices);
-               mesh->num_triangles = LittleLong(pinmesh->num_triangles);
-               mesh->data_element3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               mesh->data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               mesh->data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
-               mesh->data_morphvertex3f = (float *)Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_morphframes * sizeof(float[3]));
-               for (j = 0;j < mesh->num_triangles * 3;j++)
-                       mesh->data_element3i[j] = LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
-               for (j = 0;j < mesh->num_vertices;j++)
+               loadmodel->surfacelist[i] = i;
+               surface = loadmodel->data_surfaces + i;
+               surface->groupmesh = loadmodel->meshlist[0];
+               surface->texture = loadmodel->data_textures + i;
+               surface->num_firsttriangle = meshtriangles;
+               surface->num_triangles = LittleLong(pinmesh->num_triangles);
+               surface->num_firstvertex = meshvertices;
+               surface->num_vertices = LittleLong(pinmesh->num_vertices);
+               meshvertices += surface->num_vertices;
+               meshtriangles += surface->num_triangles;
+
+               for (j = 0;j < surface->num_triangles * 3;j++)
+                       surface->groupmesh->data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
+               for (j = 0;j < surface->num_vertices;j++)
                {
                {
-                       mesh->data_texcoordtexture2f[j * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
-                       mesh->data_texcoordtexture2f[j * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
+                       surface->groupmesh->data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
+                       surface->groupmesh->data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
                }
                }
-               for (j = 0;j < mesh->num_vertices * mesh->num_morphframes;j++)
+               for (j = 0;j < surface->num_vertices * loadmodel->numframes;j++)
                {
                {
-                       mesh->data_morphvertex3f[j * 3 + 0] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 0]) * (1.0f / 64.0f);
-                       mesh->data_morphvertex3f[j * 3 + 1] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 1]) * (1.0f / 64.0f);
-                       mesh->data_morphvertex3f[j * 3 + 2] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 2]) * (1.0f / 64.0f);
+                       surface->groupmesh->data_morphvertex3f[(j + surface->num_firstvertex) * 3 + 0] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 0]) * (1.0f / 64.0f);
+                       surface->groupmesh->data_morphvertex3f[(j + surface->num_firstvertex) * 3 + 1] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 1]) * (1.0f / 64.0f);
+                       surface->groupmesh->data_morphvertex3f[(j + surface->num_firstvertex) * 3 + 2] = LittleShort(((short *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)))[j * 4 + 2]) * (1.0f / 64.0f);
                }
 
                }
 
-               Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
-               Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-               Mod_Alias_Mesh_CompileFrameZero(mesh);
-
                if (LittleLong(pinmesh->num_shaders) >= 1)
                        Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
                else
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
                if (LittleLong(pinmesh->num_shaders) >= 1)
                        Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
                else
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
-               surface = loadmodel->data_surfaces + i;
-               surface->groupmesh = mesh;
-               surface->texture = loadmodel->data_textures + i;
-               surface->num_firsttriangle = 0;
-               surface->num_triangles = mesh->num_triangles;
-               surface->num_firstvertex = 0;
-               surface->num_vertices = mesh->num_vertices;
+               Mod_ValidateElements(surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
        }
        }
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
        Mod_CalcAliasModelBBoxes();
        Mod_FreeSkinFiles(skinfiles);
 }
        Mod_CalcAliasModelBBoxes();
        Mod_FreeSkinFiles(skinfiles);
 }
@@ -1175,7 +1181,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 {
        zymtype1header_t *pinmodel, *pheader;
        unsigned char *pbase;
 {
        zymtype1header_t *pinmodel, *pheader;
        unsigned char *pbase;
-       int i, j, k, l, numposes, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements, *remapvertices;
+       int i, j, k, l, numposes, meshvertices, meshtriangles, numvertexboneweights, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
        float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f;
        zymvertex_t *verts, *vertdata;
        zymscene_t *scene;
        float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f;
        zymvertex_t *verts, *vertdata;
        zymscene_t *scene;
@@ -1184,7 +1190,6 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        skinfile_t *skinfiles;
        unsigned char *data;
        msurface_t *surface;
        skinfile_t *skinfiles;
        unsigned char *data;
        msurface_t *surface;
-       surfmesh_t *mesh;
 
        pinmodel = (zymtype1header_t *)buffer;
        pbase = (unsigned char *)buffer;
 
        pinmodel = (zymtype1header_t *)buffer;
        pbase = (unsigned char *)buffer;
@@ -1309,13 +1314,6 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                scene++;
        }
 
                scene++;
        }
 
-       //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
-       loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
-       loadmodel->data_poses = (float *)Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
-       poses = (float *) (pheader->lump_poses.start + pbase);
-       for (i = 0;i < pheader->lump_poses.length / 4;i++)
-               loadmodel->data_poses[i] = BigFloat(poses[i]);
-
        //zymlump_t lump_bones; // zymbone_t bone[numbones];
        loadmodel->num_bones = pheader->numbones;
        loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
        //zymlump_t lump_bones; // zymbone_t bone[numbones];
        loadmodel->num_bones = pheader->numbones;
        loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
@@ -1339,19 +1337,56 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                        Host_Error("%s bonecount[%i] < 1", loadmodel->name, i);
        }
 
                        Host_Error("%s bonecount[%i] < 1", loadmodel->name, i);
        }
 
+       loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
+
+       meshvertices = pheader->numverts;
+       meshtriangles = pheader->numtris;
+       numvertexboneweights = pheader->lump_verts.length / sizeof(zymvertex_t);
+
+       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+       loadmodel->num_textures = loadmodel->num_surfaces;
+       loadmodel->nummeshes = 1;
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + sizeof(surfmesh_t *) + sizeof(surfmesh_t) + meshtriangles * sizeof(int[6]) + meshvertices * sizeof(float[2]) + numvertexboneweights * sizeof(surfmeshvertexboneweight_t) + loadmodel->num_poses * sizeof(float[3][4]));
+       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->meshlist = (surfmesh_t **)data;data += sizeof(surfmesh_t *);
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->meshlist[0]->num_vertices = meshvertices;
+       loadmodel->meshlist[0]->num_triangles = meshtriangles;
+       loadmodel->meshlist[0]->num_vertexboneweights = numvertexboneweights;
+       loadmodel->meshlist[0]->data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+       loadmodel->meshlist[0]->data_vertexboneweights = (surfmeshvertexboneweight_t *)data;data += numvertexboneweights * sizeof(surfmeshvertexboneweight_t);
+       loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[3][4]);
+
+       //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
+       poses = (float *) (pheader->lump_poses.start + pbase);
+       for (i = 0;i < pheader->lump_poses.length / 4;i++)
+               loadmodel->data_poses[i] = BigFloat(poses[i]);
+
        //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
        verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
        vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
        //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
        verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
        vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
-       for (i = 0;i < pheader->lump_verts.length / (int) sizeof(zymvertex_t);i++)
+       l = 0;
+       for (j = 0;j < pheader->numverts;j++)
        {
        {
-               verts[i].bonenum = BigLong(vertdata[i].bonenum);
-               verts[i].origin[0] = BigFloat(vertdata[i].origin[0]);
-               verts[i].origin[1] = BigFloat(vertdata[i].origin[1]);
-               verts[i].origin[2] = BigFloat(vertdata[i].origin[2]);
+               for (k = 0;k < vertbonecounts[j];k++, l++)
+               {
+                       // this format really should have had a per vertexweight weight value...
+                       float influence = 1.0f / vertbonecounts[j];
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].vertexindex = j;
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].boneindex = BigLong(vertdata[l].bonenum);
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].origin[0] = BigFloat(vertdata[l].origin[0]) * influence;
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].origin[1] = BigFloat(vertdata[l].origin[1]) * influence;
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].origin[2] = BigFloat(vertdata[l].origin[2]) * influence;
+                       loadmodel->meshlist[0]->data_vertexboneweights[l].origin[3] = influence;
+               }
        }
 
        //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
        }
 
        //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
-       outtexcoord2f = (float *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[2]));
+       outtexcoord2f = loadmodel->meshlist[0]->data_texcoordtexture2f;
        intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
        for (i = 0;i < pheader->numverts;i++)
        {
        intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
        for (i = 0;i < pheader->numverts;i++)
        {
@@ -1364,20 +1399,6 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
        //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
 
        //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
        //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
 
-       loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
-       loadmodel->nummeshes = loadmodel->num_surfaces;
-       loadmodel->num_textures = loadmodel->num_surfaces;
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
-       loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
-       loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
-       loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
-       loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
-       for (i = 0;i < loadmodel->num_surfaces;i++)
-       {
-               loadmodel->surfacelist[i] = i;
-               loadmodel->meshlist[i] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
-       }
-
        //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
        //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
        // byteswap, validate, and swap winding order of tris
        //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
        //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
        // byteswap, validate, and swap winding order of tris
@@ -1386,19 +1407,29 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
        renderlist = (int *) (pheader->lump_render.start + pbase);
        renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
                Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
        renderlist = (int *) (pheader->lump_render.start + pbase);
        renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
+       meshtriangles = 0;
        for (i = 0;i < loadmodel->num_surfaces;i++)
        {
        for (i = 0;i < loadmodel->num_surfaces;i++)
        {
+               int lastvertex;
                if (renderlist >= renderlistend)
                        Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
                count = BigLong(*renderlist);renderlist++;
                if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
                        Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
                if (renderlist >= renderlistend)
                        Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
                count = BigLong(*renderlist);renderlist++;
                if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
                        Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
-               mesh = loadmodel->meshlist[i];
-               mesh->num_triangles = count;
-               mesh->data_element3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               mesh->data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               outelements = mesh->data_element3i;
-               for (j = 0;j < mesh->num_triangles;j++)
+
+               loadmodel->surfacelist[i] = i;
+               surface = loadmodel->data_surfaces + i;
+               surface->groupmesh = loadmodel->meshlist[0];
+               surface->texture = loadmodel->data_textures + i;
+               surface->num_firsttriangle = meshtriangles;
+               surface->num_triangles = count;
+               surface->num_firstvertex = meshvertices;
+               surface->num_vertices = meshvertices;
+
+               // load the elements and find the used vertex range
+               lastvertex = 0;
+               outelements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
+               for (j = 0;j < surface->num_triangles;j++)
                {
                        outelements[2] = BigLong(renderlist[0]);
                        outelements[1] = BigLong(renderlist[1]);
                {
                        outelements[2] = BigLong(renderlist[0]);
                        outelements[1] = BigLong(renderlist[1]);
@@ -1409,76 +1440,33 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                                Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
                        if (vertbonecounts[outelements[0]] == 0 || vertbonecounts[outelements[1]] == 0 || vertbonecounts[outelements[2]] == 0)
                                Host_Error("%s corrupt renderlist (references vertex with no bone weights", loadmodel->name);
                                Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
                        if (vertbonecounts[outelements[0]] == 0 || vertbonecounts[outelements[1]] == 0 || vertbonecounts[outelements[2]] == 0)
                                Host_Error("%s corrupt renderlist (references vertex with no bone weights", loadmodel->name);
+                       surface->num_firstvertex = min(surface->num_firstvertex, outelements[0]);
+                       surface->num_firstvertex = min(surface->num_firstvertex, outelements[1]);
+                       surface->num_firstvertex = min(surface->num_firstvertex, outelements[2]);
+                       lastvertex = max(lastvertex, outelements[0]);
+                       lastvertex = max(lastvertex, outelements[1]);
+                       lastvertex = max(lastvertex, outelements[2]);
                        renderlist += 3;
                        outelements += 3;
                }
                        renderlist += 3;
                        outelements += 3;
                }
-               remapvertices = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
-               mesh->num_vertices = Mod_BuildVertexRemapTableFromElements(mesh->num_triangles * 3, mesh->data_element3i, pheader->numverts, remapvertices);
-               for (j = 0;j < mesh->num_triangles * 3;j++)
-                       mesh->data_element3i[j] = remapvertices[mesh->data_element3i[j]];
-               mesh->data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
-               for (j = 0;j < pheader->numverts;j++)
-               {
-                       if (remapvertices[j] >= 0)
-                       {
-                               mesh->data_texcoordtexture2f[remapvertices[j]*2+0] = outtexcoord2f[j*2+0];
-                               mesh->data_texcoordtexture2f[remapvertices[j]*2+1] = outtexcoord2f[j*2+1];
-                       }
-               }
-               mesh->num_vertexboneweights = 0;
-               for (j = 0;j < pheader->numverts;j++)
-                       if (remapvertices[j] >= 0)
-                               mesh->num_vertexboneweights += vertbonecounts[remapvertices[j]];
-               mesh->data_vertexboneweights = (surfmeshvertexboneweight_t *)Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t));
-               mesh->num_vertexboneweights = 0;
-               // note this vertexboneweight ordering requires that the remapvertices array is sequential numbers (separated by -1 values for omitted vertices)
-               l = 0;
-               for (j = 0;j < pheader->numverts;j++)
-               {
-                       if (remapvertices[j] < 0)
-                       {
-                               l += vertbonecounts[j];
-                               continue;
-                       }
-                       for (k = 0;k < vertbonecounts[j];k++)
-                       {
-                               // this format really should have had a per vertexweight weight value...
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].vertexindex = remapvertices[j];
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].boneindex = verts[l].bonenum;
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[3] = 1.0f / vertbonecounts[j];
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[0] = verts[l].origin[0] * mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[3];
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[1] = verts[l].origin[1] * mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[3];
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[2] = verts[l].origin[2] * mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[3];
-                               mesh->num_vertexboneweights++;
-                               l++;
-                       }
-               }
-               shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
+               surface->num_vertices = lastvertex + 1 - surface->num_firstvertex;
+
                // since zym models do not have named sections, reuse their shader
                // name as the section name
                // since zym models do not have named sections, reuse their shader
                // name as the section name
+               shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
                if (shadername[0])
                        Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
                else
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
                if (shadername[0])
                        Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
                else
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
-               Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
-               Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-               Mod_Alias_Mesh_CompileFrameZero(mesh);
-
-               surface = loadmodel->data_surfaces + i;
-               surface->groupmesh = mesh;
-               surface->texture = loadmodel->data_textures + i;
-               surface->num_firsttriangle = 0;
-               surface->num_triangles = mesh->num_triangles;
-               surface->num_firstvertex = 0;
-               surface->num_vertices = mesh->num_vertices;
+               Mod_ValidateElements(surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
        }
        }
-
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
+       Mod_FreeSkinFiles(skinfiles);
        Mem_Free(vertbonecounts);
        Mem_Free(verts);
        Mem_Free(vertbonecounts);
        Mem_Free(verts);
-       Mem_Free(outtexcoord2f);
-       Mod_FreeSkinFiles(skinfiles);
 }
 
 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 }
 
 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
@@ -1488,7 +1476,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        dpmbone_t *bone;
        dpmmesh_t *dpmmesh;
        unsigned char *pbase;
        dpmbone_t *bone;
        dpmmesh_t *dpmmesh;
        unsigned char *pbase;
-       int i, j, k;
+       int i, j, k, meshvertices, meshtriangles, numvertexboneweights;
        skinfile_t *skinfiles;
        unsigned char *data;
 
        skinfile_t *skinfiles;
        unsigned char *data;
 
@@ -1557,21 +1545,54 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        if (loadmodel->numskins < 1)
                loadmodel->numskins = 1;
 
        if (loadmodel->numskins < 1)
                loadmodel->numskins = 1;
 
+       meshvertices = 0;
+       meshtriangles = 0;
+       numvertexboneweights = 0;
+
+       // load the meshes now
+       dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
+       for (i = 0;i < loadmodel->num_surfaces;i++)
+       {
+               int numverts = BigLong(dpmmesh->num_verts);
+               meshvertices += numverts;;
+               meshtriangles += BigLong(dpmmesh->num_tris);
+
+               // to find out how many weights exist we two a two-stage load...
+               data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
+               for (j = 0;j < numverts;j++)
+               {
+                       int numweights = BigLong(((dpmvertex_t *)data)->numbones);
+                       numvertexboneweights += numweights;
+                       data += sizeof(dpmvertex_t);
+                       data += numweights * sizeof(dpmbonevert_t);
+               }
+               dpmmesh++;
+       }
+
        loadmodel->numframes = pheader->num_frames;
        loadmodel->num_bones = pheader->num_bones;
        loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
        loadmodel->numframes = pheader->num_frames;
        loadmodel->num_bones = pheader->num_bones;
        loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
-       loadmodel->num_textures = loadmodel->nummeshes = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
-
+       loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
+       loadmodel->nummeshes = 1;
        // do most allocations as one merged chunk
        // do most allocations as one merged chunk
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->numframes * sizeof(animscene_t));
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + sizeof(surfmesh_t *) + sizeof(surfmesh_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[2]) + numvertexboneweights * sizeof(surfmeshvertexboneweight_t) + loadmodel->num_poses * sizeof(float[3][4]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
        loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
        loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
-       loadmodel->meshlist = (surfmesh_t **)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
        loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
        loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
+       loadmodel->meshlist = (surfmesh_t **)data;data += sizeof(surfmesh_t *);
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->meshlist[0]->num_vertices = meshvertices;
+       loadmodel->meshlist[0]->num_triangles = meshtriangles;
+       loadmodel->meshlist[0]->num_vertexboneweights = numvertexboneweights;
+       loadmodel->meshlist[0]->data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+       loadmodel->meshlist[0]->data_vertexboneweights = (surfmeshvertexboneweight_t *)data;data += numvertexboneweights * sizeof(surfmeshvertexboneweight_t);
+       loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[3][4]);
        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->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
        loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
-       loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
        loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
        loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+
        for (i = 0;i < loadmodel->numskins;i++)
        {
                loadmodel->skinscenes[i].firstframe = i;
        for (i = 0;i < loadmodel->numskins;i++)
        {
                loadmodel->skinscenes[i].firstframe = i;
@@ -1579,11 +1600,6 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                loadmodel->skinscenes[i].loop = true;
                loadmodel->skinscenes[i].framerate = 10;
        }
                loadmodel->skinscenes[i].loop = true;
                loadmodel->skinscenes[i].framerate = 10;
        }
-       for (i = 0;i < loadmodel->num_surfaces;i++)
-       {
-               loadmodel->surfacelist[i] = i;
-               loadmodel->meshlist[i] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
-       }
 
        // load the bone info
        bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
 
        // load the bone info
        bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
@@ -1616,55 +1632,45 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 
        // load the meshes now
        dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
 
        // load the meshes now
        dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
-       for (i = 0;i < loadmodel->num_surfaces;i++)
+       meshvertices = 0;
+       meshtriangles = 0;
+       numvertexboneweights = 0;
+       for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
        {
                const int *inelements;
                int *outelements;
                const float *intexcoord;
        {
                const int *inelements;
                int *outelements;
                const float *intexcoord;
-               surfmesh_t *mesh;
                msurface_t *surface;
 
                msurface_t *surface;
 
-               mesh = loadmodel->meshlist[i];
-               mesh->num_triangles = BigLong(dpmmesh->num_tris);
-               mesh->num_vertices = BigLong(dpmmesh->num_verts);
-
-               // to find out how many weights exist we two a two-stage load...
-               mesh->num_vertexboneweights = 0;
-               data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
-               for (j = 0;j < mesh->num_vertices;j++)
-               {
-                       int numweights = BigLong(((dpmvertex_t *)data)->numbones);
-                       mesh->num_vertexboneweights += numweights;
-                       data += sizeof(dpmvertex_t);
-                       data += numweights * sizeof(dpmbonevert_t);
-               }
-
-               // allocate things now that we know how many
-               mesh->data_vertexboneweights = (surfmeshvertexboneweight_t *)Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t));
-               mesh->data_element3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               mesh->data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-               mesh->data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
+               loadmodel->surfacelist[i] = i;
+               surface = loadmodel->data_surfaces + i;
+               surface->groupmesh = loadmodel->meshlist[0];
+               surface->texture = loadmodel->data_textures + i;
+               surface->num_firsttriangle = meshtriangles;
+               surface->num_triangles = BigLong(dpmmesh->num_tris);
+               surface->num_firstvertex = meshvertices;
+               surface->num_vertices = BigLong(dpmmesh->num_verts);
+               meshvertices += surface->num_vertices;
+               meshtriangles += surface->num_triangles;
 
                inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
 
                inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
-               outelements = mesh->data_element3i;
-               for (j = 0;j < mesh->num_triangles;j++)
+               outelements = surface->groupmesh->data_element3i + surface->num_firsttriangle * 3;
+               for (j = 0;j < surface->num_triangles;j++)
                {
                        // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
                {
                        // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
-                       outelements[0] = BigLong(inelements[2]);
-                       outelements[1] = BigLong(inelements[1]);
-                       outelements[2] = BigLong(inelements[0]);
+                       outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
+                       outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
+                       outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
                        inelements += 3;
                        outelements += 3;
                }
 
                intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
                        inelements += 3;
                        outelements += 3;
                }
 
                intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
-               for (j = 0;j < mesh->num_vertices*2;j++)
-                       mesh->data_texcoordtexture2f[j] = BigFloat(intexcoord[j]);
+               for (j = 0;j < surface->num_vertices*2;j++)
+                       surface->groupmesh->data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
 
 
-               // now load them for real
-               mesh->num_vertexboneweights = 0;
                data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
                data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
-               for (j = 0;j < mesh->num_vertices;j++)
+               for (j = 0;j < surface->num_vertices;j++)
                {
                        int numweights = BigLong(((dpmvertex_t *)data)->numbones);
                        data += sizeof(dpmvertex_t);
                {
                        int numweights = BigLong(((dpmvertex_t *)data)->numbones);
                        data += sizeof(dpmvertex_t);
@@ -1672,13 +1678,13 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                        {
                                const dpmbonevert_t *vert = (dpmbonevert_t *) data;
                                // stuff not processed here: normal
                        {
                                const dpmbonevert_t *vert = (dpmbonevert_t *) data;
                                // stuff not processed here: normal
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].vertexindex = j;
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].boneindex = BigLong(vert->bonenum);
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[0] = BigFloat(vert->origin[0]);
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[1] = BigFloat(vert->origin[1]);
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[2] = BigFloat(vert->origin[2]);
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin[3] = BigFloat(vert->influence);
-                               mesh->num_vertexboneweights++;
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].vertexindex = j;
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].boneindex = BigLong(vert->bonenum);
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].origin[0] = BigFloat(vert->origin[0]);
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].origin[1] = BigFloat(vert->origin[1]);
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].origin[2] = BigFloat(vert->origin[2]);
+                               surface->groupmesh->data_vertexboneweights[numvertexboneweights].origin[3] = BigFloat(vert->influence);
+                               numvertexboneweights++;
                                data += sizeof(dpmbonevert_t);
                        }
                }
                                data += sizeof(dpmbonevert_t);
                        }
                }
@@ -1690,20 +1696,10 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
                        for (j = 0;j < loadmodel->numskins;j++)
                                Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
 
-               Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
-               Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-               Mod_Alias_Mesh_CompileFrameZero(mesh);
-
-               surface = loadmodel->data_surfaces + i;
-               surface->groupmesh = mesh;
-               surface->texture = loadmodel->data_textures + i;
-               surface->num_firsttriangle = 0;
-               surface->num_triangles = mesh->num_triangles;
-               surface->num_firstvertex = 0;
-               surface->num_vertices = mesh->num_vertices;
-
-               dpmmesh++;
+               Mod_ValidateElements(surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
        }
        }
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
        Mod_FreeSkinFiles(skinfiles);
 }
 
        Mod_FreeSkinFiles(skinfiles);
 }
 
@@ -1720,7 +1716,7 @@ static void Mod_PSKMODEL_AnimKeyToMatrix(float *origin, float *quat, matrix4x4_t
 #define PSKQUATNEGATIONS
 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 {
 #define PSKQUATNEGATIONS
 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
 {
-       int i, j, index, version, recordsize, numrecords;
+       int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles, numvertexboneweights;
        int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
        fs_offset_t filesize;
        pskpnts_t *pnts;
        int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
        fs_offset_t filesize;
        pskpnts_t *pnts;
@@ -1733,8 +1729,8 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        pskaniminfo_t *anims;
        pskanimkeys_t *animkeys;
        void *animfilebuffer, *animbuffer, *animbufferend;
        pskaniminfo_t *anims;
        pskanimkeys_t *animkeys;
        void *animfilebuffer, *animbuffer, *animbufferend;
+       unsigned char *data;
        pskchunk_t *pchunk;
        pskchunk_t *pchunk;
-       surfmesh_t *mesh;
        skinfile_t *skinfiles;
        char animname[MAX_QPATH];
 
        skinfile_t *skinfiles;
        char animname[MAX_QPATH];
 
@@ -1752,19 +1748,6 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        loadmodel->flags = 0; // there are no flags on zym models
        loadmodel->synctype = ST_RAND;
 
        loadmodel->flags = 0; // there are no flags on zym models
        loadmodel->synctype = ST_RAND;
 
-       // load external .skin files if present
-       skinfiles = Mod_LoadSkinFiles();
-       if (loadmodel->numskins < 1)
-               loadmodel->numskins = 1;
-       loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
-       for (i = 0;i < loadmodel->numskins;i++)
-       {
-               loadmodel->skinscenes[i].firstframe = i;
-               loadmodel->skinscenes[i].framecount = 1;
-               loadmodel->skinscenes[i].loop = true;
-               loadmodel->skinscenes[i].framerate = 10;
-       }
-
        FS_StripExtension(loadmodel->name, animname, sizeof(animname));
        strlcat(animname, ".psa", sizeof(animname));
        animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
        FS_StripExtension(loadmodel->name, animname, sizeof(animname));
        strlcat(animname, ".psa", sizeof(animname));
        animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
@@ -2110,27 +2093,51 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        for (index = 0;index < numanims;index++)
                loadmodel->numframes += anims[index].numframes;
 
        for (index = 0;index < numanims;index++)
                loadmodel->numframes += anims[index].numframes;
 
+       if (numanimkeys != numbones * loadmodel->numframes)
+               Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+
+       meshvertices = numvtxw;
+       meshtriangles = numfaces;
+       numvertexboneweights = 0;
+       for (index = 0;index < numvtxw;index++)
+               for (j = 0;j < numrawweights;j++)
+                       if (rawweights[j].pntsindex == vtxw[index].pntsindex)
+                               numvertexboneweights++;
+
+       // load external .skin files if present
+       skinfiles = Mod_LoadSkinFiles();
+       if (loadmodel->numskins < 1)
+               loadmodel->numskins = 1;
        loadmodel->num_bones = numbones;
        loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
        loadmodel->num_bones = numbones;
        loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
-       loadmodel->num_textures = loadmodel->nummeshes = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
-
-       if (numanimkeys != loadmodel->num_bones * loadmodel->numframes)
-               Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+       loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
+       loadmodel->nummeshes = 1;
+       // do most allocations as one merged chunk
+       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + sizeof(surfmesh_t *) + sizeof(surfmesh_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[2]) + numvertexboneweights * sizeof(surfmeshvertexboneweight_t) + loadmodel->num_poses * sizeof(float[3][4]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+       loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+       loadmodel->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->meshlist = (surfmesh_t **)data;data += sizeof(surfmesh_t *);
+       loadmodel->meshlist[0] = (surfmesh_t *)data;data += sizeof(surfmesh_t);
+       loadmodel->meshlist[0]->num_vertices = meshvertices;
+       loadmodel->meshlist[0]->num_triangles = meshtriangles;
+       loadmodel->meshlist[0]->num_vertexboneweights = numvertexboneweights;
+       loadmodel->meshlist[0]->data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+       loadmodel->meshlist[0]->data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+       loadmodel->meshlist[0]->data_vertexboneweights = (surfmeshvertexboneweight_t *)data;data += numvertexboneweights * sizeof(surfmeshvertexboneweight_t);
+       loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[3][4]);
+       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);
 
 
-       loadmodel->data_poses = (float *)Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
-       loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
-       loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
-       loadmodel->data_surfaces = (msurface_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t));
-       loadmodel->surfacelist = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(int));
-       loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
-
-       loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
-       mesh = loadmodel->meshlist[0] = (surfmesh_t *)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t));
-       mesh->num_vertices = numvtxw;
-       mesh->num_triangles = numfaces;
-       mesh->data_element3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-       mesh->data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
-       mesh->data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
+       for (i = 0;i < loadmodel->numskins;i++)
+       {
+               loadmodel->skinscenes[i].firstframe = i;
+               loadmodel->skinscenes[i].framecount = 1;
+               loadmodel->skinscenes[i].loop = true;
+               loadmodel->skinscenes[i].framerate = 10;
+       }
 
        // create surfaces
        for (index = 0, i = 0;index < nummatts;index++)
 
        // create surfaces
        for (index = 0, i = 0;index < nummatts;index++)
@@ -2151,8 +2158,8 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        // copy over the texcoords
        for (index = 0;index < numvtxw;index++)
        {
        // copy over the texcoords
        for (index = 0;index < numvtxw;index++)
        {
-               mesh->data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
-               mesh->data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
+               loadmodel->meshlist[0]->data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
        }
 
        // loading the faces is complicated because we need to sort them into surfaces by mattindex
        }
 
        // loading the faces is complicated because we need to sort them into surfaces by mattindex
@@ -2167,9 +2174,9 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        for (index = 0;index < numfaces;index++)
        {
                i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
        for (index = 0;index < numfaces;index++)
        {
                i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
-               mesh->data_element3i[i+0] = faces[index].vtxwindex[0];
-               mesh->data_element3i[i+1] = faces[index].vtxwindex[1];
-               mesh->data_element3i[i+2] = faces[index].vtxwindex[2];
+               loadmodel->meshlist[0]->data_element3i[i+0] = faces[index].vtxwindex[0];
+               loadmodel->meshlist[0]->data_element3i[i+1] = faces[index].vtxwindex[1];
+               loadmodel->meshlist[0]->data_element3i[i+2] = faces[index].vtxwindex[2];
        }
 
        // copy over the bones
        }
 
        // copy over the bones
@@ -2182,13 +2189,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        }
 
        // build bone-relative vertex weights from the psk point weights
        }
 
        // build bone-relative vertex weights from the psk point weights
-       mesh->num_vertexboneweights = 0;
-       for (index = 0;index < numvtxw;index++)
-               for (j = 0;j < numrawweights;j++)
-                       if (rawweights[j].pntsindex == vtxw[index].pntsindex)
-                               mesh->num_vertexboneweights++;
-       mesh->data_vertexboneweights = (surfmeshvertexboneweight_t *)Mem_Alloc(loadmodel->mempool, mesh->num_vertexboneweights * sizeof(surfmeshvertexboneweight_t));
-       mesh->num_vertexboneweights = 0;
+       numvertexboneweights = 0;
        for (index = 0;index < numvtxw;index++)
        {
                for (j = 0;j < numrawweights;j++)
        for (index = 0;index < numvtxw;index++)
        {
                for (j = 0;j < numrawweights;j++)
@@ -2196,9 +2197,9 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                        if (rawweights[j].pntsindex == vtxw[index].pntsindex)
                        {
                                matrix4x4_t matrix, inversematrix;
                        if (rawweights[j].pntsindex == vtxw[index].pntsindex)
                        {
                                matrix4x4_t matrix, inversematrix;
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].vertexindex = index;
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].boneindex = rawweights[j].boneindex;
-                               mesh->data_vertexboneweights[mesh->num_vertexboneweights].weight = rawweights[j].weight;
+                               loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].vertexindex = index;
+                               loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].boneindex = rawweights[j].boneindex;
+                               loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].weight = rawweights[j].weight;
                                matrix = identitymatrix;
                                for (i = rawweights[j].boneindex;i >= 0;i = loadmodel->data_bones[i].parent)
                                {
                                matrix = identitymatrix;
                                for (i = rawweights[j].boneindex;i >= 0;i = loadmodel->data_bones[i].parent)
                                {
@@ -2208,9 +2209,9 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
                                        Matrix4x4_Concat(&matrix, &tempmatrix, &childmatrix);
                                }
                                Matrix4x4_Invert_Simple(&inversematrix, &matrix);
                                        Matrix4x4_Concat(&matrix, &tempmatrix, &childmatrix);
                                }
                                Matrix4x4_Invert_Simple(&inversematrix, &matrix);
-                               Matrix4x4_Transform(&inversematrix, pnts[rawweights[j].pntsindex].origin, mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin);
-                               VectorScale(mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin, mesh->data_vertexboneweights[mesh->num_vertexboneweights].weight, mesh->data_vertexboneweights[mesh->num_vertexboneweights].origin);
-                               mesh->num_vertexboneweights++;
+                               Matrix4x4_Transform(&inversematrix, pnts[rawweights[j].pntsindex].origin, loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].origin);
+                               VectorScale(loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].origin, loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].weight, loadmodel->meshlist[0]->data_vertexboneweights[numvertexboneweights].origin);
+                               numvertexboneweights++;
                        }
                }
        }
                        }
                }
        }
@@ -2248,11 +2249,11 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
        }
 
        // compile extra data we want
        }
 
        // compile extra data we want
-       Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
-       Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
-       Mod_Alias_Mesh_CompileFrameZero(mesh);
+       Mod_ValidateElements(loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles, 0, loadmodel->meshlist[0]->num_vertices, __FILE__, __LINE__);
+       Mod_BuildTriangleNeighbors(loadmodel->meshlist[0]->data_neighbor3i, loadmodel->meshlist[0]->data_element3i, loadmodel->meshlist[0]->num_triangles);
+       Mod_Alias_Mesh_CompileFrameZero(loadmodel->meshlist[0]);
+       Mod_FreeSkinFiles(skinfiles);
 
        Mem_Free(animfilebuffer);
 
        Mem_Free(animfilebuffer);
-       Mod_FreeSkinFiles(skinfiles);
 }
 
 }
 
index a2524fe8e6fda84c227ff812c0ee9324ff4b91a1..bf3f0009a0eab002f074ee063a7751e9a7c016fe 100644 (file)
@@ -2053,8 +2053,6 @@ static void Mod_Q1BSP_LoadFaces(lump_t *l)
                totaltris += numedges - 2;
        }
 
                totaltris += numedges - 2;
        }
 
-       // TODO: split up into multiple meshes as needed to avoid exceeding 65536
-       // vertex limit
        loadmodel->nummeshes = 1;
        loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
        loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false, false);
        loadmodel->nummeshes = 1;
        loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
        loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, totalverts, totaltris, true, false, false);
@@ -4455,7 +4453,7 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
 {
        q3dface_t *in, *oldin;
        msurface_t *out, *oldout;
 {
        q3dface_t *in, *oldin;
        msurface_t *out, *oldout;
-       int i, oldi, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2, meshnum, meshvertices, meshtriangles, numvertices, numtriangles;
+       int i, oldi, j, n, count, invalidelements, patchsize[2], finalwidth, finalheight, xtess, ytess, finalvertices, finaltriangles, firstvertex, firstelement, type, oldnumtriangles, oldnumtriangles2, meshvertices, meshtriangles, numvertices, numtriangles;
        //int *originalelement3i;
        //int *originalneighbor3i;
        float *originalvertex3f;
        //int *originalelement3i;
        //int *originalneighbor3i;
        float *originalvertex3f;
@@ -4466,7 +4464,6 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
        float *originaltexcoordtexture2f;
        float *originaltexcoordlightmap2f;
        float *v;
        float *originaltexcoordtexture2f;
        float *originaltexcoordlightmap2f;
        float *v;
-       surfmesh_t *mesh, *tempmeshlist[1024];
 
        in = (q3dface_t *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
 
        in = (q3dface_t *)(mod_base + l->fileofs);
        if (l->filelen % sizeof(*in))
@@ -4501,316 +4498,305 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l)
        Con_DPrintf("%s is %sdeluxemapped\n", loadmodel->name, loadmodel->brushq3.deluxemapping ? "" : "not ");
 
        i = 0;
        Con_DPrintf("%s is %sdeluxemapped\n", loadmodel->name, loadmodel->brushq3.deluxemapping ? "" : "not ");
 
        i = 0;
-       for (meshnum = 0;i < count;meshnum++)
-       {
-               oldi = i;
-               oldin = in;
-               oldout = out;
-               meshvertices = 0;
-               meshtriangles = 0;
-               for (;i < count;i++, in++, out++)
-               {
-                       // check face type first
-                       type = LittleLong(in->type);
-                       if (type != Q3FACETYPE_POLYGON
-                        && type != Q3FACETYPE_PATCH
-                        && type != Q3FACETYPE_MESH
-                        && type != Q3FACETYPE_FLARE)
-                       {
-                               Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, type);
-                               continue;
-                       }
+       oldi = i;
+       oldin = in;
+       oldout = out;
+       meshvertices = 0;
+       meshtriangles = 0;
+       for (;i < count;i++, in++, out++)
+       {
+               // check face type first
+               type = LittleLong(in->type);
+               if (type != Q3FACETYPE_POLYGON
+                && type != Q3FACETYPE_PATCH
+                && type != Q3FACETYPE_MESH
+                && type != Q3FACETYPE_FLARE)
+               {
+                       Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: unknown face type %i\n", i, type);
+                       continue;
+               }
 
 
-                       n = LittleLong(in->textureindex);
-                       if (n < 0 || n >= loadmodel->num_textures)
-                       {
-                               Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->num_textures);
-                               continue;
-                       }
-                       out->texture = loadmodel->data_textures + n;
-                       n = LittleLong(in->effectindex);
-                       if (n < -1 || n >= loadmodel->brushq3.num_effects)
-                       {
-                               if (developer.integer >= 100)
-                                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
-                               n = -1;
-                       }
-                       if (n == -1)
-                               out->effect = NULL;
+               n = LittleLong(in->textureindex);
+               if (n < 0 || n >= loadmodel->num_textures)
+               {
+                       Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i: invalid textureindex %i (%i textures)\n", i, n, loadmodel->num_textures);
+                       continue;
+               }
+               out->texture = loadmodel->data_textures + n;
+               n = LittleLong(in->effectindex);
+               if (n < -1 || n >= loadmodel->brushq3.num_effects)
+               {
+                       if (developer.integer >= 100)
+                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid effectindex %i (%i effects)\n", i, out->texture->name, n, loadmodel->brushq3.num_effects);
+                       n = -1;
+               }
+               if (n == -1)
+                       out->effect = NULL;
+               else
+                       out->effect = loadmodel->brushq3.data_effects + n;
+               n = LittleLong(in->lightmapindex);
+               if (n >= loadmodel->brushq3.num_lightmaps)
+               {
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
+                       n = -1;
+               }
+               else if (n < 0)
+                       n = -1;
+               if (n == -1)
+               {
+                       out->lightmaptexture = NULL;
+                       out->deluxemaptexture = r_texture_blanknormalmap;
+               }
+               else
+               {
+                       out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n];
+                       if (loadmodel->brushq3.deluxemapping)
+                               out->deluxemaptexture = loadmodel->brushq3.data_lightmaps[n+1];
                        else
                        else
-                               out->effect = loadmodel->brushq3.data_effects + n;
-                       n = LittleLong(in->lightmapindex);
-                       if (n >= loadmodel->brushq3.num_lightmaps)
-                       {
-                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid lightmapindex %i (%i lightmaps)\n", i, out->texture->name, n, loadmodel->brushq3.num_lightmaps);
-                               n = -1;
-                       }
-                       else if (n < 0)
-                               n = -1;
-                       if (n == -1)
-                       {
-                               out->lightmaptexture = NULL;
                                out->deluxemaptexture = r_texture_blanknormalmap;
                                out->deluxemaptexture = r_texture_blanknormalmap;
+               }
+
+               firstvertex = LittleLong(in->firstvertex);
+               numvertices = LittleLong(in->numvertices);
+               firstelement = LittleLong(in->firstelement);
+               numtriangles = LittleLong(in->numelements) / 3;
+               if (numtriangles * 3 != LittleLong(in->numelements))
+               {
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements));
+                       continue;
+               }
+               if (firstvertex < 0 || firstvertex + numvertices > loadmodel->brushq3.num_vertices)
+               {
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, firstvertex, firstvertex + numvertices, loadmodel->brushq3.num_vertices);
+                       continue;
+               }
+               if (firstelement < 0 || firstelement + numtriangles * 3 > loadmodel->brushq3.num_triangles * 3)
+               {
+                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, firstelement, firstelement + numtriangles * 3, loadmodel->brushq3.num_triangles * 3);
+                       continue;
+               }
+               switch(type)
+               {
+               case Q3FACETYPE_POLYGON:
+               case Q3FACETYPE_MESH:
+                       // no processing necessary
+                       break;
+               case Q3FACETYPE_PATCH:
+                       patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
+                       patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
+                       if (numvertices != (patchsize[0] * patchsize[1]) || patchsize[0] < 3 || patchsize[1] < 3 || !(patchsize[0] & 1) || !(patchsize[1] & 1) || patchsize[0] * patchsize[1] >= min(r_subdivisions_maxvertices.integer, r_subdivisions_collision_maxvertices.integer))
+                       {
+                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]);
+                               continue;
                        }
                        }
-                       else
+                       originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+                       // convert patch to Q3FACETYPE_MESH
+                       xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+                       ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+                       // bound to user settings
+                       xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
+                       ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
+                       // bound to sanity settings
+                       xtess = bound(1, xtess, 1024);
+                       ytess = bound(1, ytess, 1024);
+                       // bound to user limit on vertices
+                       while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
                        {
                        {
-                               out->lightmaptexture = loadmodel->brushq3.data_lightmaps[n];
-                               if (loadmodel->brushq3.deluxemapping)
-                                       out->deluxemaptexture = loadmodel->brushq3.data_lightmaps[n+1];
+                               if (xtess > ytess)
+                                       xtess--;
                                else
                                else
-                                       out->deluxemaptexture = r_texture_blanknormalmap;
+                                       ytess--;
                        }
                        }
+                       finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+                       finalheight = ((patchsize[1] - 1) * ytess) + 1;
+                       numvertices = finalwidth * finalheight;
+                       numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+                       break;
+               case Q3FACETYPE_FLARE:
+                       if (developer.integer >= 100)
+                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
+                       // don't render it
+                       continue;
+               }
+               out->num_vertices = numvertices;
+               out->num_triangles = numtriangles;
+               meshvertices += out->num_vertices;
+               meshtriangles += out->num_triangles;
+       }
 
 
-                       firstvertex = LittleLong(in->firstvertex);
-                       numvertices = LittleLong(in->numvertices);
-                       firstelement = LittleLong(in->firstelement);
-                       numtriangles = LittleLong(in->numelements) / 3;
-                       if (numtriangles * 3 != LittleLong(in->numelements))
+       i = oldi;
+       in = oldin;
+       out = oldout;
+       loadmodel->nummeshes = 1;
+       loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *));
+       loadmodel->meshlist[0] = Mod_AllocSurfMesh(loadmodel->mempool, meshvertices, meshtriangles, false, true, false);
+       meshvertices = 0;
+       meshtriangles = 0;
+       for (;i < count && meshvertices + out->num_vertices <= loadmodel->meshlist[0]->num_vertices;i++, in++, out++)
+       {
+               if (out->num_vertices < 3 || out->num_triangles < 1)
+                       continue;
+
+               type = LittleLong(in->type);
+               firstvertex = LittleLong(in->firstvertex);
+               firstelement = LittleLong(in->firstelement);
+               out->groupmesh = loadmodel->meshlist[0];
+               out->num_firstvertex = meshvertices;
+               out->num_firsttriangle = meshtriangles;
+               switch(type)
+               {
+               case Q3FACETYPE_POLYGON:
+               case Q3FACETYPE_MESH:
+                       // no processing necessary
+                       for (j = 0;j < out->num_vertices;j++)
                        {
                        {
-                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): numelements %i is not a multiple of 3\n", i, out->texture->name, LittleLong(in->numelements));
-                               continue;
+                               (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 0];
+                               (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 1];
+                               (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 2];
+                               (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 0];
+                               (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 1];
+                               (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 0];
+                               (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 1];
+                               (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 0] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 0];
+                               (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 1] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 1];
+                               (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 2] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 2];
+                               (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 3] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 3];
                        }
                        }
-                       if (firstvertex < 0 || firstvertex + numvertices > loadmodel->brushq3.num_vertices)
+                       for (j = 0;j < out->num_triangles*3;j++)
+                               (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] = loadmodel->brushq3.data_element3i[firstelement + j] + out->num_firstvertex;
+                       break;
+               case Q3FACETYPE_PATCH:
+                       patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
+                       patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
+                       originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
+                       originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
+                       originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
+                       originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
+                       // convert patch to Q3FACETYPE_MESH
+                       xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+                       ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
+                       // bound to user settings
+                       xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
+                       ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
+                       // bound to sanity settings
+                       xtess = bound(1, xtess, 1024);
+                       ytess = bound(1, ytess, 1024);
+                       // bound to user limit on vertices
+                       while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
                        {
                        {
-                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid vertex range %i : %i (%i vertices)\n", i, out->texture->name, firstvertex, firstvertex + numvertices, loadmodel->brushq3.num_vertices);
-                               continue;
+                               if (xtess > ytess)
+                                       xtess--;
+                               else
+                                       ytess--;
                        }
                        }
-                       if (firstelement < 0 || firstelement + numtriangles * 3 > loadmodel->brushq3.num_triangles * 3)
+                       finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+                       finalheight = ((patchsize[1] - 1) * ytess) + 1;
+                       finalvertices = finalwidth * finalheight;
+                       finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+                       type = Q3FACETYPE_MESH;
+                       // generate geometry
+                       // (note: normals are skipped because they get recalculated)
+                       Q3PatchTesselateFloat(3, sizeof(float[3]), (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
+                       Q3PatchTesselateFloat(2, sizeof(float[2]), (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
+                       Q3PatchTesselateFloat(2, sizeof(float[2]), (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
+                       Q3PatchTesselateFloat(4, sizeof(float[4]), (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
+                       Q3PatchTriangleElements((out->groupmesh->data_element3i + 3 * out->num_firsttriangle), finalwidth, finalheight, out->num_firstvertex);
+                       out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_vertex3f);
+                       if (developer.integer >= 100)
                        {
                        {
-                               Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid element range %i : %i (%i elements)\n", i, out->texture->name, firstelement, firstelement + numtriangles * 3, loadmodel->brushq3.num_triangles * 3);
-                               continue;
+                               if (out->num_triangles < finaltriangles)
+                                       Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_vertices, finaltriangles, finaltriangles - out->num_triangles, out->num_triangles);
+                               else
+                                       Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_vertices, out->num_triangles);
                        }
                        }
-                       switch(type)
+                       // q3map does not put in collision brushes for curves... ugh
+                       // build the lower quality collision geometry
+                       xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
+                       ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
+                       // bound to user settings
+                       xtess = bound(r_subdivisions_collision_mintess.integer, xtess, r_subdivisions_collision_maxtess.integer);
+                       ytess = bound(r_subdivisions_collision_mintess.integer, ytess, r_subdivisions_collision_maxtess.integer);
+                       // bound to sanity settings
+                       xtess = bound(1, xtess, 1024);
+                       ytess = bound(1, ytess, 1024);
+                       // bound to user limit on vertices
+                       while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144))
                        {
                        {
-                       case Q3FACETYPE_POLYGON:
-                       case Q3FACETYPE_MESH:
-                               // no processing necessary
-                               break;
-                       case Q3FACETYPE_PATCH:
-                               patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
-                               patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
-                               if (numvertices != (patchsize[0] * patchsize[1]) || patchsize[0] < 3 || patchsize[1] < 3 || !(patchsize[0] & 1) || !(patchsize[1] & 1) || patchsize[0] * patchsize[1] >= min(r_subdivisions_maxvertices.integer, r_subdivisions_collision_maxvertices.integer))
-                               {
-                                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): invalid patchsize %ix%i\n", i, out->texture->name, patchsize[0], patchsize[1]);
-                                       continue;
-                               }
-                               originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
-                               // convert patch to Q3FACETYPE_MESH
-                               xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
-                               ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
-                               // bound to user settings
-                               xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
-                               ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
-                               // bound to sanity settings
-                               xtess = bound(1, xtess, 1024);
-                               ytess = bound(1, ytess, 1024);
-                               // bound to user limit on vertices
-                               while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
-                               {
-                                       if (xtess > ytess)
-                                               xtess--;
-                                       else
-                                               ytess--;
-                               }
-                               finalwidth = ((patchsize[0] - 1) * xtess) + 1;
-                               finalheight = ((patchsize[1] - 1) * ytess) + 1;
-                               numvertices = finalwidth * finalheight;
-                               numtriangles = (finalwidth - 1) * (finalheight - 1) * 2;
-                               break;
-                       case Q3FACETYPE_FLARE:
-                               if (developer.integer >= 100)
-                                       Con_Printf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name);
-                               // don't render it
-                               continue;
+                               if (xtess > ytess)
+                                       xtess--;
+                               else
+                                       ytess--;
                        }
                        }
-                       out->num_vertices = numvertices;
-                       out->num_triangles = numtriangles;
-                       if (meshvertices + out->num_vertices > 65536)
-                               break;
-                       meshvertices += out->num_vertices;
-                       meshtriangles += out->num_triangles;
+                       finalwidth = ((patchsize[0] - 1) * xtess) + 1;
+                       finalheight = ((patchsize[1] - 1) * ytess) + 1;
+                       finalvertices = finalwidth * finalheight;
+                       finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
+
+                       out->data_collisionvertex3f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices);
+                       out->data_collisionelement3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles);
+                       out->num_collisionvertices = finalvertices;
+                       out->num_collisiontriangles = finaltriangles;
+                       Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
+                       Q3PatchTriangleElements(out->data_collisionelement3i, finalwidth, finalheight, 0);
+
+                       //Mod_SnapVertices(3, out->num_vertices, (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), 0.25);
+                       Mod_SnapVertices(3, out->num_collisionvertices, out->data_collisionvertex3f, 1);
+
+                       oldnumtriangles = out->num_triangles;
+                       oldnumtriangles2 = out->num_collisiontriangles;
+                       out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
+                       if (developer.integer >= 100)
+                               Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
+                       break;
+               default:
+                       break;
                }
                }
-
-               i = oldi;
-               in = oldin;
-               out = oldout;
-               mesh = tempmeshlist[meshnum] = Mod_AllocSurfMesh(loadmodel->mempool, meshvertices, meshtriangles, false, true, false);
-               meshvertices = 0;
-               meshtriangles = 0;
-               for (;i < count && meshvertices + out->num_vertices <= mesh->num_vertices;i++, in++, out++)
+               meshvertices += out->num_vertices;
+               meshtriangles += out->num_triangles;
+               for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
+                       if ((out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] < out->num_firstvertex || (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] >= out->num_firstvertex + out->num_vertices)
+                               invalidelements++;
+               if (invalidelements)
                {
                {
-                       if (out->num_vertices < 3 || out->num_triangles < 1)
-                               continue;
-
-                       type = LittleLong(in->type);
-                       firstvertex = LittleLong(in->firstvertex);
-                       firstelement = LittleLong(in->firstelement);
-                       out->groupmesh = mesh;
-                       out->num_firstvertex = meshvertices;
-                       out->num_firsttriangle = meshtriangles;
-                       switch(type)
+                       Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, firstvertex, out->num_vertices, firstelement, out->num_triangles * 3);
+                       for (j = 0;j < out->num_triangles * 3;j++)
                        {
                        {
-                       case Q3FACETYPE_POLYGON:
-                       case Q3FACETYPE_MESH:
-                               // no processing necessary
-                               for (j = 0;j < out->num_vertices;j++)
-                               {
-                                       (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 0] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 0];
-                                       (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 1] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 1];
-                                       (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex)[j * 3 + 2] = loadmodel->brushq3.data_vertex3f[(firstvertex + j) * 3 + 2];
-                                       (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 0];
-                                       (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordtexture2f[(firstvertex + j) * 2 + 1];
-                                       (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 0] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 0];
-                                       (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex)[j * 2 + 1] = loadmodel->brushq3.data_texcoordlightmap2f[(firstvertex + j) * 2 + 1];
-                                       (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 0] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 0];
-                                       (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 1] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 1];
-                                       (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 2] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 2];
-                                       (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex)[j * 4 + 3] = loadmodel->brushq3.data_color4f[(firstvertex + j) * 4 + 3];
-                               }
-                               for (j = 0;j < out->num_triangles*3;j++)
-                                       (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] = loadmodel->brushq3.data_element3i[firstelement + j] + out->num_firstvertex;
-                               break;
-                       case Q3FACETYPE_PATCH:
-                               patchsize[0] = LittleLong(in->specific.patch.patchsize[0]);
-                               patchsize[1] = LittleLong(in->specific.patch.patchsize[1]);
-                               originalvertex3f = loadmodel->brushq3.data_vertex3f + firstvertex * 3;
-                               originaltexcoordtexture2f = loadmodel->brushq3.data_texcoordtexture2f + firstvertex * 2;
-                               originaltexcoordlightmap2f = loadmodel->brushq3.data_texcoordlightmap2f + firstvertex * 2;
-                               originalcolor4f = loadmodel->brushq3.data_color4f + firstvertex * 4;
-                               // convert patch to Q3FACETYPE_MESH
-                               xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
-                               ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_tolerance.value);
-                               // bound to user settings
-                               xtess = bound(r_subdivisions_mintess.integer, xtess, r_subdivisions_maxtess.integer);
-                               ytess = bound(r_subdivisions_mintess.integer, ytess, r_subdivisions_maxtess.integer);
-                               // bound to sanity settings
-                               xtess = bound(1, xtess, 1024);
-                               ytess = bound(1, ytess, 1024);
-                               // bound to user limit on vertices
-                               while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_maxvertices.integer, 262144))
-                               {
-                                       if (xtess > ytess)
-                                               xtess--;
-                                       else
-                                               ytess--;
-                               }
-                               finalwidth = ((patchsize[0] - 1) * xtess) + 1;
-                               finalheight = ((patchsize[1] - 1) * ytess) + 1;
-                               finalvertices = finalwidth * finalheight;
-                               finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
-                               type = Q3FACETYPE_MESH;
-                               // generate geometry
-                               // (note: normals are skipped because they get recalculated)
-                               Q3PatchTesselateFloat(3, sizeof(float[3]), (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
-                               Q3PatchTesselateFloat(2, sizeof(float[2]), (out->groupmesh->data_texcoordtexture2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordtexture2f, xtess, ytess);
-                               Q3PatchTesselateFloat(2, sizeof(float[2]), (out->groupmesh->data_texcoordlightmap2f + 2 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[2]), originaltexcoordlightmap2f, xtess, ytess);
-                               Q3PatchTesselateFloat(4, sizeof(float[4]), (out->groupmesh->data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
-                               Q3PatchTriangleElements((out->groupmesh->data_element3i + 3 * out->num_firsttriangle), finalwidth, finalheight, out->num_firstvertex);
-                               out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_vertex3f);
-                               if (developer.integer >= 100)
-                               {
-                                       if (out->num_triangles < finaltriangles)
-                                               Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_vertices, finaltriangles, finaltriangles - out->num_triangles, out->num_triangles);
-                                       else
-                                               Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_vertices, out->num_triangles);
-                               }
-                               // q3map does not put in collision brushes for curves... ugh
-                               // build the lower quality collision geometry
-                               xtess = Q3PatchTesselationOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
-                               ytess = Q3PatchTesselationOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value);
-                               // bound to user settings
-                               xtess = bound(r_subdivisions_collision_mintess.integer, xtess, r_subdivisions_collision_maxtess.integer);
-                               ytess = bound(r_subdivisions_collision_mintess.integer, ytess, r_subdivisions_collision_maxtess.integer);
-                               // bound to sanity settings
-                               xtess = bound(1, xtess, 1024);
-                               ytess = bound(1, ytess, 1024);
-                               // bound to user limit on vertices
-                               while ((xtess > 1 || ytess > 1) && (((patchsize[0] - 1) * xtess) + 1) * (((patchsize[1] - 1) * ytess) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144))
-                               {
-                                       if (xtess > ytess)
-                                               xtess--;
-                                       else
-                                               ytess--;
-                               }
-                               finalwidth = ((patchsize[0] - 1) * xtess) + 1;
-                               finalheight = ((patchsize[1] - 1) * ytess) + 1;
-                               finalvertices = finalwidth * finalheight;
-                               finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2;
-
-                               out->data_collisionvertex3f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices);
-                               out->data_collisionelement3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles);
-                               out->num_collisionvertices = finalvertices;
-                               out->num_collisiontriangles = finaltriangles;
-                               Q3PatchTesselateFloat(3, sizeof(float[3]), out->data_collisionvertex3f, patchsize[0], patchsize[1], sizeof(float[3]), originalvertex3f, xtess, ytess);
-                               Q3PatchTriangleElements(out->data_collisionelement3i, finalwidth, finalheight, 0);
-
-                               //Mod_SnapVertices(3, out->num_vertices, (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), 0.25);
-                               Mod_SnapVertices(3, out->num_collisionvertices, out->data_collisionvertex3f, 1);
-
-                               oldnumtriangles = out->num_triangles;
-                               oldnumtriangles2 = out->num_collisiontriangles;
-                               out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
-                               if (developer.integer >= 100)
-                                       Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
-                               break;
-                       default:
-                               break;
-                       }
-                       meshvertices += out->num_vertices;
-                       meshtriangles += out->num_triangles;
-                       for (j = 0, invalidelements = 0;j < out->num_triangles * 3;j++)
+                               Con_Printf(" %i", (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] - out->num_firstvertex);
                                if ((out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] < out->num_firstvertex || (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] >= out->num_firstvertex + out->num_vertices)
                                if ((out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] < out->num_firstvertex || (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] >= out->num_firstvertex + out->num_vertices)
-                                       invalidelements++;
-                       if (invalidelements)
-                       {
-                               Con_Printf("Mod_Q3BSP_LoadFaces: Warning: face #%i has %i invalid elements, type = %i, texture->name = \"%s\", texture->surfaceflags = %i, firstvertex = %i, numvertices = %i, firstelement = %i, numelements = %i, elements list:\n", i, invalidelements, type, out->texture->name, out->texture->surfaceflags, firstvertex, out->num_vertices, firstelement, out->num_triangles * 3);
-                               for (j = 0;j < out->num_triangles * 3;j++)
-                               {
-                                       Con_Printf(" %i", (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] - out->num_firstvertex);
-                                       if ((out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] < out->num_firstvertex || (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] >= out->num_firstvertex + out->num_vertices)
-                                               (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] = out->num_firstvertex;
-                               }
-                               Con_Print("\n");
+                                       (out->groupmesh->data_element3i + 3 * out->num_firsttriangle)[j] = out->num_firstvertex;
                        }
                        }
-                       // for per pixel lighting
-                       Mod_BuildTextureVectorsAndNormals(out->num_firstvertex, out->num_vertices, out->num_triangles, out->groupmesh->data_vertex3f, out->groupmesh->data_texcoordtexture2f, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_svector3f, out->groupmesh->data_tvector3f, out->groupmesh->data_normal3f, true);
-                       // calculate a bounding box
-                       VectorClear(out->mins);
-                       VectorClear(out->maxs);
-                       if (out->num_vertices)
+                       Con_Print("\n");
+               }
+               // for per pixel lighting
+               Mod_BuildTextureVectorsAndNormals(out->num_firstvertex, out->num_vertices, out->num_triangles, out->groupmesh->data_vertex3f, out->groupmesh->data_texcoordtexture2f, (out->groupmesh->data_element3i + 3 * out->num_firsttriangle), out->groupmesh->data_svector3f, out->groupmesh->data_tvector3f, out->groupmesh->data_normal3f, true);
+               // calculate a bounding box
+               VectorClear(out->mins);
+               VectorClear(out->maxs);
+               if (out->num_vertices)
+               {
+                       VectorCopy((out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), out->mins);
+                       VectorCopy((out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), out->maxs);
+                       for (j = 1, v = (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex) + 3;j < out->num_vertices;j++, v += 3)
                        {
                        {
-                               VectorCopy((out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), out->mins);
-                               VectorCopy((out->groupmesh->data_vertex3f + 3 * out->num_firstvertex), out->maxs);
-                               for (j = 1, v = (out->groupmesh->data_vertex3f + 3 * out->num_firstvertex) + 3;j < out->num_vertices;j++, v += 3)
-                               {
-                                       out->mins[0] = min(out->mins[0], v[0]);
-                                       out->maxs[0] = max(out->maxs[0], v[0]);
-                                       out->mins[1] = min(out->mins[1], v[1]);
-                                       out->maxs[1] = max(out->maxs[1], v[1]);
-                                       out->mins[2] = min(out->mins[2], v[2]);
-                                       out->maxs[2] = max(out->maxs[2], v[2]);
-                               }
-                               out->mins[0] -= 1.0f;
-                               out->mins[1] -= 1.0f;
-                               out->mins[2] -= 1.0f;
-                               out->maxs[0] += 1.0f;
-                               out->maxs[1] += 1.0f;
-                               out->maxs[2] += 1.0f;
+                               out->mins[0] = min(out->mins[0], v[0]);
+                               out->maxs[0] = max(out->maxs[0], v[0]);
+                               out->mins[1] = min(out->mins[1], v[1]);
+                               out->maxs[1] = max(out->maxs[1], v[1]);
+                               out->mins[2] = min(out->mins[2], v[2]);
+                               out->maxs[2] = max(out->maxs[2], v[2]);
                        }
                        }
-                       // set lightmap styles for consistency with q1bsp
-                       //out->lightmapinfo->styles[0] = 0;
-                       //out->lightmapinfo->styles[1] = 255;
-                       //out->lightmapinfo->styles[2] = 255;
-                       //out->lightmapinfo->styles[3] = 255;
+                       out->mins[0] -= 1.0f;
+                       out->mins[1] -= 1.0f;
+                       out->mins[2] -= 1.0f;
+                       out->maxs[0] += 1.0f;
+                       out->maxs[1] += 1.0f;
+                       out->maxs[2] += 1.0f;
                }
                }
-       }
-
-       // now store the completed list of meshes
-       loadmodel->nummeshes = meshnum;
-       if (loadmodel->nummeshes)
-       {
-               loadmodel->meshlist = (surfmesh_t **)Mem_Alloc(loadmodel->mempool, sizeof(surfmesh_t *) * loadmodel->nummeshes);
-               memcpy(loadmodel->meshlist, tempmeshlist, sizeof(surfmesh_t *) * loadmodel->nummeshes);
+               // set lightmap styles for consistency with q1bsp
+               //out->lightmapinfo->styles[0] = 0;
+               //out->lightmapinfo->styles[1] = 255;
+               //out->lightmapinfo->styles[2] = 255;
+               //out->lightmapinfo->styles[3] = 255;
        }
 
        // free the no longer needed vertex data
        }
 
        // free the no longer needed vertex data
index 5277a4e76d31886a8c6c463db80d3d605b247c63..ae555e8540b7801599a12027c4bf8a587c619b96 100644 (file)
@@ -502,19 +502,19 @@ void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtria
 }
 #endif
 
 }
 #endif
 
-void Mod_ValidateElements(int *elements, int numtriangles, int numverts, const char *filename, int fileline)
+void Mod_ValidateElements(int *elements, int numtriangles, int firstvertex, int numverts, const char *filename, int fileline)
 {
 {
-       int i, warned = false;
+       int i, warned = false, endvertex = firstvertex + numverts;
        for (i = 0;i < numtriangles * 3;i++)
        {
        for (i = 0;i < numtriangles * 3;i++)
        {
-               if ((unsigned int)elements[i] >= (unsigned int)numverts)
+               if (elements[i] < firstvertex || elements[i] >= endvertex)
                {
                        if (!warned)
                        {
                                warned = true;
                                Con_Printf("Mod_ValidateElements: out of bounds elements detected at %s:%d\n", filename, fileline);
                        }
                {
                        if (!warned)
                        {
                                warned = true;
                                Con_Printf("Mod_ValidateElements: out of bounds elements detected at %s:%d\n", filename, fileline);
                        }
-                       elements[i] = 0;
+                       elements[i] = firstvertex;
                }
        }
 }
                }
        }
 }
index 8d7b62642b91b261c52af6ebf0cd3fa3a9ff95a2..811b4d3cebad48ce846852db37a63a5ca6b33cff 100644 (file)
@@ -618,7 +618,7 @@ extern char loadname[32];   // for hunk tags
 
 int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices);
 void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles);
 
 int Mod_BuildVertexRemapTableFromElements(int numelements, const int *elements, int numvertices, int *remapvertices);
 void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtriangles);
-void Mod_ValidateElements(int *elements, int numtriangles, int numverts, const char *filename, int fileline);
+void Mod_ValidateElements(int *elements, int numtriangles, int firstvertex, int numverts, const char *filename, int fileline);
 void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting);
 void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals, qboolean areaweighting);
 
 void Mod_BuildNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const int *elements, float *normal3f, qboolean areaweighting);
 void Mod_BuildTextureVectorsAndNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex, const float *texcoord, const int *elements, float *svectors, float *tvectors, float *normals, qboolean areaweighting);
 
diff --git a/todo b/todo
index 210deeaac2a13fca32df0a4a59aa2059e49f722d..a61ce3f865f6e7667af581a1285b33c4fac24337 100644 (file)
--- a/todo
+++ b/todo
@@ -45,6 +45,7 @@
 0 bug darkplaces renderer: deluxemaps are not detected in some maps that do have them?  (SavageX)
 0 bug darkplaces renderer: modify r_showtris_polygonoffset to push back all filled geometry, not lines, because polygonoffset will not affect GL_LINES at all
 0 bug darkplaces renderer: monsters teleporting in really slow down rendering, perhaps the teleport light is casting huge shadows?  new information suggests it is the particles. (romi, lcatlnx)
 0 bug darkplaces renderer: deluxemaps are not detected in some maps that do have them?  (SavageX)
 0 bug darkplaces renderer: modify r_showtris_polygonoffset to push back all filled geometry, not lines, because polygonoffset will not affect GL_LINES at all
 0 bug darkplaces renderer: monsters teleporting in really slow down rendering, perhaps the teleport light is casting huge shadows?  new information suggests it is the particles. (romi, lcatlnx)
+0 bug darkplaces renderer: r_wateralpha 0.9 is invisible on r_glsl 0;gl_combine 0 path (Lardarse]
 0 bug darkplaces renderer: r_wateralpha on maps that are not watervised shows sky, this is a known glquake bug but it is fixable in darkplaces at load time by marking opposite-content (water-empty, empty-water) leafs as visible in their pvs sets, this involves checking the portal flow...  (knghtbrd)
 0 bug darkplaces renderer: showfps values 2 and 3 are printing bogus numbers like -2 billion (Willis)
 0 bug darkplaces server: Blood Mage monsters are stuck in place apparently (steven a)
 0 bug darkplaces renderer: r_wateralpha on maps that are not watervised shows sky, this is a known glquake bug but it is fixable in darkplaces at load time by marking opposite-content (water-empty, empty-water) leafs as visible in their pvs sets, this involves checking the portal flow...  (knghtbrd)
 0 bug darkplaces renderer: showfps values 2 and 3 are printing bogus numbers like -2 billion (Willis)
 0 bug darkplaces server: Blood Mage monsters are stuck in place apparently (steven a)