From 9ac6f1395459b9ab4093f690365ce1e3d62d0577 Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 1 May 2018 06:49:00 +0000 Subject: [PATCH] Refactored and improved Mod_ValidateElements so it also validates element3s and has more useful output. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12413 d7cf8633-e32d-0410-b094-e92efae38249 --- model_alias.c | 12 ++++----- model_brush.c | 2 +- model_shared.c | 69 ++++++++++++++++++++++++++++++++++++++++++++------ model_shared.h | 2 +- 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/model_alias.c b/model_alias.c index cdf0edee..e6427044 100644 --- a/model_alias.c +++ b/model_alias.c @@ -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) { diff --git a/model_brush.c b/model_brush.c index 9887f5f4..c355b1a2 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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); diff --git a/model_shared.c b/model_shared.c index 6adbef62..c4a716a7 100644 --- a/model_shared.c +++ b/model_shared.c @@ -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) diff --git a/model_shared.h b/model_shared.h index 9b5bf7b3..d83fe2cc 100644 --- a/model_shared.h +++ b/model_shared.h @@ -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); -- 2.39.2