int nummodels = Mem_ExpandableArray_IndexRange(&models);
dp_model_t *mod;
- R_SkinFrame_PrepareForPurge();
for (i = 0;i < nummodels;i++)
{
- if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool && mod->data_textures)
+ if ((mod = (dp_model_t*) Mem_ExpandableArray_RecordAtIndex(&models, i)) && mod->mempool)
{
- for (j = 0;j < mod->num_textures;j++)
+ for (j = 0;j < mod->num_textures && mod->data_textures;j++)
{
for (k = 0;k < mod->data_textures[j].numskinframes;k++)
R_SkinFrame_MarkUsed(mod->data_textures[j].skinframes[k]);
for (k = 0;k < mod->data_textures[j].backgroundnumskinframes;k++)
R_SkinFrame_MarkUsed(mod->data_textures[j].backgroundskinframes[k]);
}
+ if (mod->brush.solidskyskinframe)
+ R_SkinFrame_MarkUsed(mod->brush.solidskyskinframe);
+ if (mod->brush.alphaskyskinframe)
+ R_SkinFrame_MarkUsed(mod->brush.alphaskyskinframe);
}
}
- R_SkinFrame_Purge();
if (!cl_stainmaps_clearonload.integer)
return;
if (!COM_ParseToken_Simple(&bufptr, true, false))
break;
if (strcmp(com_token, "\n"))
- loop = atoi(com_token);
+ loop = atoi(com_token) != 0;
else
loop = true;
}
Con_Printf("loading model %s\n", mod->name);
mod->used = true;
- mod->crc = -1;
+ mod->crc = (unsigned int)-1;
mod->loaded = false;
VectorClear(mod->normalmins);
buf = FS_LoadFile (va("%s.framegroups", mod->name), tempmempool, false, &filesize);
if(buf)
{
- Mod_FrameGroupify(mod, buf);
+ Mod_FrameGroupify(mod, (const char *)buf);
Mem_Free(buf);
}
newmesh->maxtriangles = maxtriangles;
newmesh->numverts = 0;
newmesh->numtriangles = 0;
+ memset(newmesh->sideoffsets, 0, sizeof(newmesh->sideoffsets));
+ memset(newmesh->sidetotals, 0, sizeof(newmesh->sidetotals));
newmesh->vertex3f = (float *)data;data += maxverts * sizeof(float[3]);
if (light)
newmesh = Mod_ShadowMesh_Alloc(mempool, oldmesh->numverts, oldmesh->numtriangles, oldmesh->map_diffuse, oldmesh->map_specular, oldmesh->map_normal, light, neighbors, false);
newmesh->numverts = oldmesh->numverts;
newmesh->numtriangles = oldmesh->numtriangles;
+ memcpy(newmesh->sideoffsets, oldmesh->sideoffsets, sizeof(oldmesh->sideoffsets));
+ memcpy(newmesh->sidetotals, oldmesh->sidetotals, sizeof(oldmesh->sidetotals));
memcpy(newmesh->vertex3f, oldmesh->vertex3f, oldmesh->numverts * sizeof(float[3]));
if (newmesh->svector3f && oldmesh->svector3f)
}
}
+void Mod_CreateCollisionMesh(dp_model_t *mod)
+{
+ int k;
+ int numcollisionmeshtriangles;
+ const msurface_t *surface;
+ mempool_t *mempool = mod->mempool;
+ if (!mempool && mod->brush.parentmodel)
+ mempool = mod->brush.parentmodel->mempool;
+ // make a single combined collision mesh for physics engine use
+ // TODO rewrite this to use the collision brushes as source, to fix issues with e.g. common/caulk which creates no drawsurface
+ numcollisionmeshtriangles = 0;
+ for (k = 0;k < mod->nummodelsurfaces;k++)
+ {
+ surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
+ continue;
+ numcollisionmeshtriangles += surface->num_triangles;
+ }
+ mod->brush.collisionmesh = Mod_ShadowMesh_Begin(mempool, numcollisionmeshtriangles * 3, numcollisionmeshtriangles, NULL, NULL, NULL, false, false, true);
+ for (k = 0;k < mod->nummodelsurfaces;k++)
+ {
+ surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID))
+ continue;
+ Mod_ShadowMesh_AddMesh(mempool, mod->brush.collisionmesh, NULL, NULL, NULL, mod->surfmesh.data_vertex3f, NULL, NULL, NULL, NULL, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+ }
+ mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, true, false);
+}
+
void Mod_GetTerrainVertex3fTexCoord2fFromBGRA(const unsigned char *imagepixels, int imagewidth, int imageheight, int ix, int iy, float *vertex3f, float *texcoord2f, matrix4x4_t *pixelstepmatrix, matrix4x4_t *pixeltexturestepmatrix)
{
float v[3], tc[3];
Mod_GetTerrainVertexFromBGRA(imagepixels, imagewidth, imageheight, ix, iy, vertex3f, texcoord2f, svector3f, tvector3f, normal3f, pixelstepmatrix, pixeltexturestepmatrix);
}
+#if 0
+void Mod_Terrain_SurfaceRecurseChunk(dp_model_t *model, int stepsize, int x, int y)
+{
+ float mins[3];
+ float maxs[3];
+ float chunkwidth = min(stepsize, model->terrain.width - 1 - x);
+ float chunkheight = min(stepsize, model->terrain.height - 1 - y);
+ float viewvector[3];
+ unsigned int firstvertex;
+ unsigned int *e;
+ float *v;
+ if (chunkwidth < 2 || chunkheight < 2)
+ return;
+ VectorSet(mins, model->terrain.mins[0] + x * stepsize * model->terrain.scale[0], model->terrain.mins[1] + y * stepsize * model->terrain.scale[1], model->terrain.mins[2]);
+ VectorSet(maxs, model->terrain.mins[0] + (x+1) * stepsize * model->terrain.scale[0], model->terrain.mins[1] + (y+1) * stepsize * model->terrain.scale[1], model->terrain.maxs[2]);
+ viewvector[0] = bound(mins[0], localvieworigin, maxs[0]) - model->terrain.vieworigin[0];
+ viewvector[1] = bound(mins[1], localvieworigin, maxs[1]) - model->terrain.vieworigin[1];
+ viewvector[2] = bound(mins[2], localvieworigin, maxs[2]) - model->terrain.vieworigin[2];
+ if (stepsize > 1 && VectorLength(viewvector) < stepsize*model->terrain.scale[0]*r_terrain_lodscale.value)
+ {
+ // too close for this stepsize, emit as 4 chunks instead
+ stepsize /= 2;
+ Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y);
+ Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y);
+ Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y+stepsize);
+ Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y+stepsize);
+ return;
+ }
+ // emit the geometry at stepsize into our vertex buffer / index buffer
+ // we add two columns and two rows for skirt
+ outwidth = chunkwidth+2;
+ outheight = chunkheight+2;
+ outwidth2 = outwidth-1;
+ outheight2 = outheight-1;
+ outwidth3 = outwidth+1;
+ outheight3 = outheight+1;
+ firstvertex = numvertices;
+ e = model->terrain.element3i + numtriangles;
+ numtriangles += chunkwidth*chunkheight*2+chunkwidth*2*2+chunkheight*2*2;
+ v = model->terrain.vertex3f + numvertices;
+ numvertices += (chunkwidth+1)*(chunkheight+1)+(chunkwidth+1)*2+(chunkheight+1)*2;
+ // emit the triangles (note: the skirt is treated as two extra rows and two extra columns)
+ for (ty = 0;ty < outheight;ty++)
+ {
+ for (tx = 0;tx < outwidth;tx++)
+ {
+ *e++ = firstvertex + (ty )*outwidth3+(tx );
+ *e++ = firstvertex + (ty )*outwidth3+(tx+1);
+ *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+ *e++ = firstvertex + (ty )*outwidth3+(tx );
+ *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+ *e++ = firstvertex + (ty+1)*outwidth3+(tx );
+ }
+ }
+ // TODO: emit surface vertices (x+tx*stepsize, y+ty*stepsize)
+ for (ty = 0;ty <= outheight;ty++)
+ {
+ skirtrow = ty == 0 || ty == outheight;
+ ry = y+bound(1, ty, outheight)*stepsize;
+ for (tx = 0;tx <= outwidth;tx++)
+ {
+ skirt = skirtrow || tx == 0 || tx == outwidth;
+ rx = x+bound(1, tx, outwidth)*stepsize;
+ v[0] = rx*scale[0];
+ v[1] = ry*scale[1];
+ v[2] = heightmap[ry*terrainwidth+rx]*scale[2];
+ v += 3;
+ }
+ }
+ // TODO: emit skirt vertices
+}
+
+void Mod_Terrain_UpdateSurfacesForViewOrigin(dp_model_t *model)
+{
+ for (y = 0;y < model->terrain.size[1];y += model->terrain.
+ Mod_Terrain_SurfaceRecurseChunk(model, model->terrain.maxstepsize, x, y);
+ Mod_Terrain_BuildChunk(model,
+}
+#endif
+
q3wavefunc_t Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
{
if (!strcasecmp(s, "sin")) return Q3WAVEFUNC_SIN;
shader.reflectfactor = 1;
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
+ shader.specularscalemod = 1;
+ shader.specularpowermod = 1;
strlcpy(shader.name, com_token, sizeof(shader.name));
if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
if (!COM_ParseToken_QuakeC(&text, true))
break;
}
- for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
- parameter[j][0] = 0;
+ //for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
+ // parameter[j][0] = 0;
if (developer.integer >= 100)
{
Con_Printf("%s %i: ", shader.name, shader.numlayers - 1);
if (!COM_ParseToken_QuakeC(&text, true))
break;
}
- for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
- parameter[j][0] = 0;
+ //for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
+ // parameter[j][0] = 0;
if (fileindex == 0 && !strcasecmp(com_token, "}"))
break;
if (developer.integer >= 100)
Vector4Set(shader.reflectcolor4f, atof(parameter[8]), atof(parameter[9]), atof(parameter[10]), 1);
shader.r_water_wateralpha = atof(parameter[11]);
}
+ else if (!strcasecmp(parameter[0], "dp_glossintensitymod") && numparameters >= 2)
+ {
+ shader.specularscalemod = atof(parameter[1]);
+ }
+ else if (!strcasecmp(parameter[0], "dp_glossexponentmod") && numparameters >= 2)
+ {
+ shader.specularpowermod = atof(parameter[1]);
+ }
else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
{
int i, deformindex;
}
Mem_Free(f);
}
+ FS_FreeSearch(search);
}
q3shaderinfo_t *Mod_LookupQ3Shader(const char *name)
texflagsmask &= ~TEXF_PICMIP;
if(!(defaulttexflags & TEXF_COMPRESS))
texflagsmask &= ~TEXF_COMPRESS;
+ texture->specularscalemod = 1; // unless later loaded from the shader
+ texture->specularpowermod = 1; // unless later loaded from the shader
if (shader)
{
texture->reflectfactor = shader->reflectfactor;
Vector4Copy(shader->reflectcolor4f, texture->reflectcolor4f);
texture->r_water_wateralpha = shader->r_water_wateralpha;
+ texture->specularscalemod = shader->specularscalemod;
+ texture->specularpowermod = shader->specularpowermod;
}
else if (!strcmp(texture->name, "noshader") || !texture->name[0])
{
tag_torso,
*/
memset(word, 0, sizeof(word));
- for (i = 0;i < MAX_SKINS && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
+ for (i = 0;i < 256 && (data = text = (char *)FS_LoadFile(va("%s_%i.skin", loadmodel->name, i), tempmempool, true, NULL));i++)
{
// If it's the first file we parse
if (skinfile == NULL)
static void Mod_BuildVBOs(void)
{
+ if (developer.integer && loadmodel->surfmesh.data_element3s && loadmodel->surfmesh.data_element3i)
+ {
+ int i;
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ {
+ if (loadmodel->surfmesh.data_element3s[i] != loadmodel->surfmesh.data_element3i[i])
+ {
+ Con_Printf("Mod_BuildVBOs: element %u is incorrect (%u should be %u)\n", i, loadmodel->surfmesh.data_element3s[i], loadmodel->surfmesh.data_element3i[i]);
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+ }
+ }
+
if (!gl_support_arb_vertex_buffer_object)
return;
if (loadmodel->surfmesh.num_triangles)
{
if (loadmodel->surfmesh.data_element3s)
- {
- int i;
- for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
- loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
loadmodel->surfmesh.ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]), loadmodel->name);
- }
else
loadmodel->surfmesh.ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(unsigned int[3]), loadmodel->name);
}
countvertices += surface->num_vertices;
countfaces += surface->num_triangles;
texname = (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default";
- for (textureindex = 0;textureindex < maxtextures && texturenames[textureindex*MAX_QPATH];textureindex++)
+ for (textureindex = 0;textureindex < counttextures;textureindex++)
if (!strcmp(texturenames + textureindex * MAX_QPATH, texname))
break;
+ if (textureindex < counttextures)
+ continue; // already wrote this material entry
if (textureindex >= maxtextures)
continue; // just a precaution
- if (counttextures < textureindex + 1)
- counttextures = textureindex + 1;
+ textureindex = counttextures++;
strlcpy(texturenames + textureindex * MAX_QPATH, texname, MAX_QPATH);
if (outbufferpos >= outbuffermax >> 1)
{