}
#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)
+ {
+ for (i = 0; i < numelements; i++)
+ {
+ if (element3i[i] < first || element3i[i] > last)
+ {
+ invalidintcount++;
+ invalidintexample = i;
+ }
+ }
+ }
+ if (element3s)
{
- if (elements[i] < firstvertex || elements[i] >= endvertex)
+ for (i = 0; i < numelements; i++)
{
- if (!warned)
+ if (element3s[i] < first || element3s[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 (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!
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)
// upload short indices as a buffer
if (mesh->element3s && !mesh->element3s_indexbuffer)
- mesh->element3s_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3s, mesh->numtriangles * sizeof(short[3]), loadmodel->name, true, false, false, true);
+ mesh->element3s_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3s, mesh->numtriangles * sizeof(short[3]), "shadowmesh", true, false, false, true);
// upload int indices as a buffer
if (mesh->element3i && !mesh->element3i_indexbuffer && !mesh->element3s)
- mesh->element3i_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3i, mesh->numtriangles * sizeof(int[3]), loadmodel->name, true, false, false, false);
+ mesh->element3i_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3i, mesh->numtriangles * sizeof(int[3]), "shadowmesh", true, false, false, false);
// vertex buffer is several arrays and we put them in the same buffer
//
return shaderpass;
}
-qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags)
+qboolean Mod_LoadTextureFromQ3Shader(mempool_t *mempool, const char *modelname, texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags, int defaultmaterialflags)
{
int texflagsmask, texflagsor;
qboolean success = true;
materiallayer = rgbgenvertexlayer;
endofprelayers = rgbgenvertexlayer;
firstpostlayer = rgbgenvertexlayer + 1;
+ // special case for rgbgen vertex if MATERIALFLAG_VERTEXCOLOR is expected on this material
+ if (defaultmaterialflags & MATERIALFLAG_VERTEXCOLOR)
+ texture->basematerialflags |= MATERIALFLAG_VERTEXCOLOR;
}
else if (rgbgendiffuselayer >= 0)
{
Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", modelname, texture->name);
if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW)
{
- texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
+ texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
texture->supercontents = SUPERCONTENTS_SOLID;
}
else if (texture->surfaceflags & Q3SURFACEFLAG_SKY)
{
- texture->basematerialflags |= MATERIALFLAG_SKY;
+ texture->basematerialflags = MATERIALFLAG_SKY;
texture->supercontents = SUPERCONTENTS_SKY;
}
else
{
- texture->basematerialflags |= MATERIALFLAG_WALL;
+ texture->basematerialflags = defaultmaterialflags;
texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
}
if(cls.state == ca_dedicated)
}
else
{
- if (fallback)
+ skinframe_t *skinframe = R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false, fallback);
+ if (skinframe)
{
- texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, R_SkinFrame_LoadExternal(texture->name, defaulttexflags, false, true));
+ texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(mempool, skinframe);
if (texture->materialshaderpass->skinframes[0]->hasalpha)
texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
if (texture->q2contents)
mod->DrawAddWaterPlanes = NULL; // will be set if a texture needs it
}
-texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int addmaterialflags)
+texture_t *Mod_Mesh_GetTexture(dp_model_t *mod, const char *name, int defaultdrawflags, int defaulttexflags, int defaultmaterialflags)
{
int i;
texture_t *t;
mod->data_surfaces[i].texture = mod->data_textures + (mod->data_surfaces[i].texture - oldtextures);
}
t = &mod->data_textures[mod->num_textures++];
- Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags);
- t->basematerialflags |= addmaterialflags;
+ Mod_LoadTextureFromQ3Shader(mod->mempool, mod->name, t, name, false, true, defaulttexflags, defaultmaterialflags);
switch (defaultdrawflags & DRAWFLAG_MASK)
{
case DRAWFLAG_ADDITIVE: