Refactored and improved Mod_ValidateElements so it also validates element3s and has...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 1 May 2018 06:49:00 +0000 (06:49 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 1 May 2018 06:49:00 +0000 (06:49 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12413 d7cf8633-e32d-0410-b094-e92efae38249

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

index cdf0ede..e642704 100644 (file)
@@ -1131,7 +1131,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                for (j = 0;j < 3;j++)
                        loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
        // validate (note numverts is used because this is the original data)
-       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.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->surfmesh.num_triangles;i++)
@@ -1769,7 +1769,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
 
                Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
 
-               Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
+               Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, loadmodel->surfmesh.data_element3s + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
        }
        if (loadmodel->surfmesh.data_element3s)
                for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
@@ -2174,7 +2174,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if (loadmodel->surfmesh.data_element3s)
                for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
                        loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
-       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
        Mod_BuildBaseBonePoses();
        Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
        Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
@@ -2543,7 +2543,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                // since dpm models do not have named sections, reuse their shader name as the section name
                Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
 
-               Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
+               Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, loadmodel->surfmesh.data_element3s + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
        }
        if (loadmodel->surfmesh.num_blends < meshvertices)
                loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
@@ -3233,7 +3233,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if (loadmodel->surfmesh.data_element3s)
                for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
                        loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
-       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
        Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
        Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
        if (loadmodel->surfmesh.data_neighbor3i)
@@ -3845,7 +3845,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                outelements += 3;
                inelements += 3;
        }
-       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
 
        if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
        {
index 9887f5f..c355b1a 100644 (file)
@@ -8631,7 +8631,7 @@ void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
        if (loadmodel->surfmesh.data_element3s)
                for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
                        loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
-       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
+       Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
        // generate normals if the file did not have them
        if (!VectorLength2(loadmodel->surfmesh.data_normal3f))
                Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
index 6adbef6..c4a716a 100644 (file)
@@ -816,21 +816,71 @@ void Mod_BuildTriangleNeighbors(int *neighbors, const int *elements, int numtria
 }
 #endif
 
-void Mod_ValidateElements(int *elements, int numtriangles, int firstvertex, int numverts, const char *filename, int fileline)
+qboolean Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline)
 {
-       int i, warned = false, endvertex = firstvertex + numverts;
-       for (i = 0;i < numtriangles * 3;i++)
+       int first = firstvertex, last = first + numvertices - 1, numelements = numtriangles * 3;
+       int i;
+       int invalidintcount = 0, invalidintexample = 0;
+       int invalidshortcount = 0, invalidshortexample = 0;
+       int invalidmismatchcount = 0, invalidmismatchexample = 0;
+       if (element3i)
        {
-               if (elements[i] < firstvertex || elements[i] >= endvertex)
+               for (i = 0; i < numelements; i++)
                {
-                       if (!warned)
+                       if (element3i[i] < first || element3i[i] > last)
                        {
-                               warned = true;
-                               Con_Printf("Mod_ValidateElements: out of bounds elements detected at %s:%d\n", filename, fileline);
+                               invalidintcount++;
+                               invalidintexample = i;
                        }
-                       elements[i] = firstvertex;
                }
        }
+       if (element3s)
+       {
+               for (i = 0; i < numelements; i++)
+               {
+                       if (element3s[i] < first || element3s[i] > last)
+                       {
+                               invalidintcount++;
+                               invalidintexample = i;
+                       }
+               }
+       }
+       if (element3i && element3s)
+       {
+               for (i = 0; i < numelements; i++)
+               {
+                       if (element3s[i] != element3i[i])
+                       {
+                               invalidmismatchcount++;
+                               invalidmismatchexample = i;
+                       }
+               }
+       }
+       if (invalidintcount || invalidshortcount || invalidmismatchcount)
+       {
+               Con_Printf("Mod_ValidateElements(%i, %i, %i, %p, %p) called at %s:%d", numelements, first, last, element3i, element3s, filename, fileline);
+               Con_Printf(", %i elements are invalid in element3i (example: element3i[%i] == %i)", invalidintcount, invalidintexample, element3i ? element3i[invalidintexample] : 0);
+               Con_Printf(", %i elements are invalid in element3s (example: element3s[%i] == %i)", invalidshortcount, invalidshortexample, element3s ? element3s[invalidshortexample] : 0);
+               Con_Printf(", %i elements mismatch between element3i and element3s (example: element3s[%i] is %i and element3i[i] is %i)", invalidmismatchcount, invalidmismatchexample, element3i ? element3i[invalidmismatchexample] : 0, invalidmismatchexample, element3s ? element3s[invalidmismatchexample] : 0);
+               Con_Print(".  Please debug the engine code - these elements have been modified to not crash, but nothing more.\n");
+
+               // edit the elements to make them safer, as the driver will crash otherwise
+               if (element3i)
+                       for (i = 0; i < numelements; i++)
+                               if (element3i[i] < first || element3i[i] > last)
+                                       element3i[i] = first;
+               if (element3s)
+                       for (i = 0; i < numelements; i++)
+                               if (element3s[i] < first || element3s[i] > last)
+                                       element3s[i] = first;
+               if (element3i && element3s)
+                       for (i = 0; i < numelements; i++)
+                               if (element3s[i] != element3i[i])
+                                       element3s[i] = element3i[i];
+
+               return false;
+       }
+       return true;
 }
 
 // warning: this is an expensive function!
@@ -1214,6 +1264,9 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool)
        if (!mesh->numverts)
                return;
 
+       // make sure we don't crash inside the driver if something went wrong, as it's annoying to debug
+       Mod_ValidateElements(mesh->element3i, mesh->element3s, mesh->numtriangles, 0, mesh->numverts, __FILE__, __LINE__);
+
        // build r_vertexmesh_t array
        // (compressed interleaved array for D3D)
        if (!mesh->vertexmesh && mesh->texcoord2f && vid.useinterleavedarrays)
index 9b5bf7b..d83fe2c 100644 (file)
@@ -1157,10 +1157,10 @@ 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);
-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_BuildTextureVectorsFromNormals(int firstvertex, int numvertices, int numtriangles, const float *vertex3f, const float *texcoord2f, const float *normal3f, const int *elements, float *svector3f, float *tvector3f, qboolean areaweighting);
 
+qboolean Mod_ValidateElements(int *element3i, unsigned short *element3s, int numtriangles, int firstvertex, int numvertices, const char *filename, int fileline);
 void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qboolean lightmapoffsets, qboolean vertexcolors, qboolean neighbors);
 void Mod_MakeSortedSurfaces(dp_model_t *mod);