#include "r_shadow.h"
#include "polygon.h"
+cvar_t r_enableshadowvolumes = {CVAR_SAVE, "r_enableshadowvolumes", "1", "Enables use of Stencil Shadow Volume shadowing methods, saves some memory if turned off"};
cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0", "mipmaps model skins so they render faster in the distance and do not display noise artifacts, can cause discoloration of skins if they contain undesirable border colors"};
+cvar_t r_mipnormalmaps = {CVAR_SAVE, "r_mipnormalmaps", "1", "mipmaps normalmaps (turning it off looks sharper but may have aliasing)"};
cvar_t mod_generatelightmaps_unitspersample = {CVAR_SAVE, "mod_generatelightmaps_unitspersample", "8", "lightmap resolution"};
cvar_t mod_generatelightmaps_borderpixels = {CVAR_SAVE, "mod_generatelightmaps_borderpixels", "2", "extra space around polygons to prevent sampling artifacts"};
cvar_t mod_generatelightmaps_texturesize = {CVAR_SAVE, "mod_generatelightmaps_texturesize", "1024", "size of lightmap textures"};
Mod_UnloadModel(mod);
Mod_FreeQ3Shaders();
+ Mod_Skeletal_FreeBuffers();
}
static void mod_newmap(void)
static void Mod_Print(void);
static void Mod_Precache (void);
static void Mod_Decompile_f(void);
-static void Mod_BuildVBOs(void);
static void Mod_GenerateLightmaps_f(void);
void Mod_Init (void)
{
Mod_AliasInit();
Mod_SpriteInit();
+ Cvar_RegisterVariable(&r_enableshadowvolumes);
Cvar_RegisterVariable(&r_mipskins);
+ Cvar_RegisterVariable(&r_mipnormalmaps);
Cvar_RegisterVariable(&mod_generatelightmaps_unitspersample);
Cvar_RegisterVariable(&mod_generatelightmaps_borderpixels);
Cvar_RegisterVariable(&mod_generatelightmaps_texturesize);
void Mod_RenderInit(void)
{
- R_RegisterModule("Models", mod_start, mod_shutdown, mod_newmap);
+ R_RegisterModule("Models", mod_start, mod_shutdown, mod_newmap, NULL, NULL);
}
void Mod_UnloadModel (dp_model_t *mod)
strlcpy(name, mod->name, sizeof(name));
parentmodel = mod->brush.parentmodel;
used = mod->used;
- if (mod->surfmesh.ebo3i)
- R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3i);
- if (mod->surfmesh.ebo3s)
- R_Mesh_DestroyBufferObject(mod->surfmesh.ebo3s);
- if (mod->surfmesh.vbo)
- R_Mesh_DestroyBufferObject(mod->surfmesh.vbo);
+ if (mod->mempool)
+ {
+ if (mod->surfmesh.vertex3fbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertex3fbuffer);
+ mod->surfmesh.vertex3fbuffer = NULL;
+ if (mod->surfmesh.vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vertexmeshbuffer);
+ mod->surfmesh.vertexmeshbuffer = NULL;
+ if (mod->surfmesh.data_element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3i_indexbuffer);
+ mod->surfmesh.data_element3i_indexbuffer = NULL;
+ if (mod->surfmesh.data_element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.data_element3s_indexbuffer);
+ mod->surfmesh.data_element3s_indexbuffer = NULL;
+ if (mod->surfmesh.vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(mod->surfmesh.vbo_vertexbuffer);
+ mod->surfmesh.vbo_vertexbuffer = NULL;
+ }
// free textures/memory attached to the model
R_FreeTexturePool(&mod->texturepool);
Mem_FreePool(&mod->mempool);
{
dp_model_t *mod = (dp_model_t *) pass;
animscene_t *anim = &mod->animscenes[i];
- dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d", i);
+ dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
anim->firstframe = bound(0, start, mod->num_poses - 1);
anim->framecount = bound(1, len, mod->num_poses - anim->firstframe);
anim->framerate = max(1, fps);
Mod_FrameGroupify_ParseGroups(buf, Mod_FrameGroupify_ParseGroups_Store, mod);
}
+void Mod_FindPotentialDeforms(dp_model_t *mod)
+{
+ int i, j;
+ texture_t *texture;
+ mod->wantnormals = false;
+ mod->wanttangents = false;
+ for (i = 0;i < mod->num_textures;i++)
+ {
+ texture = mod->data_textures + i;
+ if (texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
+ mod->wantnormals = true;
+ for (j = 0;j < Q3MAXDEFORMS;j++)
+ {
+ if (texture->deforms[j].deform == Q3DEFORM_AUTOSPRITE)
+ {
+ mod->wanttangents = true;
+ mod->wantnormals = true;
+ break;
+ }
+ if (texture->deforms[j].deform != Q3DEFORM_NONE)
+ mod->wantnormals = true;
+ }
+ }
+}
+
/*
==================
Mod_LoadModel
int num;
unsigned int crc;
void *buf;
- fs_offset_t filesize;
+ fs_offset_t filesize = 0;
mod->used = true;
num = LittleLong(*((int *)buf));
// call the apropriate loader
loadmodel = mod;
- if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
+ if (!strcasecmp(FS_FileExtension(mod->name), "obj")) Mod_OBJ_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDPO", 4)) Mod_IDP0_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP2", 4)) Mod_IDP2_Load(mod, buf, bufend);
else if (!memcmp(buf, "IDP3", 4)) Mod_IDP3_Load(mod, buf, bufend);
else if (!memcmp(buf, "ZYMOTICMODEL", 12)) Mod_ZYMOTICMODEL_Load(mod, buf, bufend);
else if (!memcmp(buf, "DARKPLACESMODEL", 16)) Mod_DARKPLACESMODEL_Load(mod, buf, bufend);
else if (!memcmp(buf, "ACTRHEAD", 8)) Mod_PSKMODEL_Load(mod, buf, bufend);
+ else if (!memcmp(buf, "INTERQUAKEMODEL", 16)) Mod_INTERQUAKEMODEL_Load(mod, buf, bufend);
else if (strlen(mod->name) >= 4 && !strcmp(mod->name + strlen(mod->name) - 4, ".map")) Mod_MAP_Load(mod, buf, bufend);
else if (num == BSPVERSION || num == 30) Mod_Q1BSP_Load(mod, buf, bufend);
else Con_Printf("Mod_LoadModel: model \"%s\" is of unknown/unsupported type\n", mod->name);
Mem_Free(buf);
+ Mod_FindPotentialDeforms(mod);
+
buf = FS_LoadFile (va("%s.framegroups", mod->name), tempmempool, false, &filesize);
if(buf)
{
int element[2];
}
edgehashentry_t;
- static edgehashentry_t *edgehash[TRIANGLEEDGEHASH];
+ static edgehashentry_t **edgehash;
edgehashentry_t *edgehashentries, *hash;
if (!numtriangles)
return;
- memset(edgehash, 0, sizeof(edgehash));
+ edgehash = (edgehashentry_t **)Mem_Alloc(tempmempool, TRIANGLEEDGEHASH * sizeof(*edgehash));
// if there are too many triangles for the stack array, allocate larger buffer
edgehashentries = (edgehashentry_t *)Mem_Alloc(tempmempool, numtriangles * 3 * sizeof(edgehashentry_t));
// find neighboring triangles
}
// free the allocated buffer
Mem_Free(edgehashentries);
+ Mem_Free(edgehash);
}
#else
// very slow but simple way
return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles, map_diffuse, map_specular, map_normal, light, neighbors, expandable);
}
-static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh)
+static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool)
{
- if (!vid.support.arb_vertex_buffer_object)
+ if (!mesh->numverts)
return;
- // element buffer is easy because it's just one array
- if (mesh->numtriangles)
+ // build r_vertexmesh_t array
+ // (compressed interleaved array for D3D)
+ if (!mesh->vertexmesh && mesh->texcoord2f && vid.useinterleavedarrays)
{
- if (mesh->element3s)
- mesh->ebo3s = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3s, mesh->numtriangles * sizeof(unsigned short[3]), "shadowmesh");
- else
- mesh->ebo3i = R_Mesh_CreateStaticBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->element3i, mesh->numtriangles * sizeof(unsigned int[3]), "shadowmesh");
+ int vertexindex;
+ int numvertices = mesh->numverts;
+ r_vertexmesh_t *vertexmesh;
+ mesh->vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(mempool, numvertices * sizeof(*mesh->vertexmesh));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++)
+ {
+ VectorCopy(mesh->vertex3f + 3*vertexindex, vertexmesh->vertex3f);
+ VectorScale(mesh->svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f);
+ VectorScale(mesh->tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f);
+ VectorScale(mesh->normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f);
+ Vector2Copy(mesh->texcoord2f + 2*vertexindex, vertexmesh->texcoordtexture2f);
+ }
}
+ // upload r_vertexmesh_t array as a buffer
+ if (mesh->vertexmesh && !mesh->vertexmeshbuffer)
+ mesh->vertexmeshbuffer = R_Mesh_CreateMeshBuffer(mesh->vertexmesh, mesh->numverts * sizeof(*mesh->vertexmesh), loadmodel->name, false, false, false);
+
+ // upload vertex3f array as a buffer
+ if (mesh->vertex3f && !mesh->vertex3fbuffer)
+ mesh->vertex3fbuffer = R_Mesh_CreateMeshBuffer(mesh->vertex3f, mesh->numverts * sizeof(float[3]), loadmodel->name, false, false, false);
+
+ // 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, 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);
+
// vertex buffer is several arrays and we put them in the same buffer
//
// is this wise? the texcoordtexture2f array is used with dynamic
// vertex/svector/tvector/normal when rendering animated models, on the
// other hand animated models don't use a lot of vertices anyway...
- if (mesh->numverts)
+ if (!mesh->vbo_vertexbuffer && !vid.useinterleavedarrays)
{
size_t size;
unsigned char *mem;
if (mesh->tvector3f ) memcpy(mem + mesh->vbooffset_tvector3f , mesh->tvector3f , mesh->numverts * sizeof(float[3]));
if (mesh->normal3f ) memcpy(mem + mesh->vbooffset_normal3f , mesh->normal3f , mesh->numverts * sizeof(float[3]));
if (mesh->texcoord2f ) memcpy(mem + mesh->vbooffset_texcoord2f , mesh->texcoord2f , mesh->numverts * sizeof(float[2]));
- mesh->vbo = R_Mesh_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, "shadowmesh");
+ mesh->vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, "shadowmesh", false, false, false);
Mem_Free(mem);
}
}
newmesh->element3s[i] = newmesh->element3i[i];
}
if (createvbo)
- Mod_ShadowMesh_CreateVBOs(newmesh);
+ Mod_ShadowMesh_CreateVBOs(newmesh, mempool);
}
Mem_Free(mesh);
}
shadowmesh_t *nextmesh;
for (;mesh;mesh = nextmesh)
{
- if (mesh->ebo3i)
- R_Mesh_DestroyBufferObject(mesh->ebo3i);
- if (mesh->ebo3s)
- R_Mesh_DestroyBufferObject(mesh->ebo3s);
- if (mesh->vbo)
- R_Mesh_DestroyBufferObject(mesh->vbo);
+ if (mesh->vertex3fbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vertex3fbuffer);
+ if (mesh->vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vertexmeshbuffer);
+ if (mesh->element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->element3i_indexbuffer);
+ if (mesh->element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->element3s_indexbuffer);
+ if (mesh->vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(mesh->vbo_vertexbuffer);
nextmesh = mesh->next;
Mem_Free(mesh);
}
void Mod_CreateCollisionMesh(dp_model_t *mod)
{
- int k;
- int numcollisionmeshtriangles;
- const msurface_t *surface;
+ int k, numcollisionmeshtriangles;
+ qboolean usesinglecollisionmesh = false;
+ const msurface_t *surface = NULL;
+
mempool_t *mempool = mod->mempool;
if (!mempool && mod->brush.parentmodel)
mempool = mod->brush.parentmodel->mempool;
for (k = 0;k < mod->nummodelsurfaces;k++)
{
surface = mod->data_surfaces + mod->firstmodelsurface + k;
+ if (!strcmp(surface->texture->name, "collision")) // found collision mesh
+ {
+ usesinglecollisionmesh = true;
+ numcollisionmeshtriangles = surface->num_triangles;
+ break;
+ }
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;
+ if (usesinglecollisionmesh)
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));
+ else
+ {
+ 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);
+ mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mempool, mod->brush.collisionmesh, false, false, 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)
}
#endif
-q3wavefunc_t Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
+int Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
{
- if (!strcasecmp(s, "sin")) return Q3WAVEFUNC_SIN;
- if (!strcasecmp(s, "square")) return Q3WAVEFUNC_SQUARE;
- if (!strcasecmp(s, "triangle")) return Q3WAVEFUNC_TRIANGLE;
- if (!strcasecmp(s, "sawtooth")) return Q3WAVEFUNC_SAWTOOTH;
- if (!strcasecmp(s, "inversesawtooth")) return Q3WAVEFUNC_INVERSESAWTOOTH;
- if (!strcasecmp(s, "noise")) return Q3WAVEFUNC_NOISE;
+ int offset = 0;
+ if (!strncasecmp(s, "user", 4)) // parse stuff like "user1sin", always user<n>func
+ {
+ offset = bound(0, s[4] - '0', 9);
+ offset = (offset + 1) << Q3WAVEFUNC_USER_SHIFT;
+ s += 4;
+ if(*s)
+ ++s;
+ }
+ if (!strcasecmp(s, "sin")) return offset | Q3WAVEFUNC_SIN;
+ if (!strcasecmp(s, "square")) return offset | Q3WAVEFUNC_SQUARE;
+ if (!strcasecmp(s, "triangle")) return offset | Q3WAVEFUNC_TRIANGLE;
+ if (!strcasecmp(s, "sawtooth")) return offset | Q3WAVEFUNC_SAWTOOTH;
+ if (!strcasecmp(s, "inversesawtooth")) return offset | Q3WAVEFUNC_INVERSESAWTOOTH;
+ if (!strcasecmp(s, "noise")) return offset | Q3WAVEFUNC_NOISE;
+ if (!strcasecmp(s, "none")) return offset | Q3WAVEFUNC_NONE;
Con_DPrintf("Mod_LoadQ3Shaders: unknown wavefunc %s\n", s);
- return Q3WAVEFUNC_NONE;
+ return offset | Q3WAVEFUNC_NONE;
}
void Mod_FreeQ3Shaders(void)
end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END);
start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START);
if(memcmp(start, start2, end - start))
- Con_Printf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
+ Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
else
Con_DPrintf("Shader '%s' already defined\n", shader->name);
return;
memcpy (&entry->shader, shader, sizeof (q3shaderinfo_t));
}
-extern cvar_t r_picmipworld;
+extern cvar_t mod_q3shader_default_offsetmapping;
+extern cvar_t mod_q3shader_default_polygonoffset;
+extern cvar_t mod_q3shader_default_polygonfactor;
void Mod_LoadQ3Shaders(void)
{
int j;
q3shaderinfo_layer_t *layer;
int numparameters;
char parameter[TEXTURE_MAXFRAMES + 4][Q3PATHLENGTH];
+ char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
+ unsigned long custsurfaceparms[256];
+ int numcustsurfaceparms;
Mod_FreeQ3Shaders();
Mem_ExpandableArray_NewArray (&q3shader_data->char_ptrs,
q3shaders_mem, sizeof (char**), 256);
+ // parse custinfoparms.txt
+ numcustsurfaceparms = 0;
+ if ((text = f = (char *)FS_LoadFile("scripts/custinfoparms.txt", tempmempool, false, NULL)) != NULL)
+ {
+ if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
+ Con_DPrintf("scripts/custinfoparms.txt: contentflags section parsing error - expected \"{\", found \"%s\"\n", com_token);
+ else
+ {
+ while (COM_ParseToken_QuakeC(&text, false))
+ if (!strcasecmp(com_token, "}"))
+ break;
+ // custom surfaceflags section
+ if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
+ Con_DPrintf("scripts/custinfoparms.txt: surfaceflags section parsing error - expected \"{\", found \"%s\"\n", com_token);
+ else
+ {
+ while(COM_ParseToken_QuakeC(&text, false))
+ {
+ if (!strcasecmp(com_token, "}"))
+ break;
+ // register surfaceflag
+ if (numcustsurfaceparms >= 256)
+ {
+ Con_Printf("scripts/custinfoparms.txt: surfaceflags section parsing error - max 256 surfaceflags exceeded\n");
+ break;
+ }
+ // name
+ j = strlen(com_token)+1;
+ custsurfaceparmnames[numcustsurfaceparms] = (char *)Mem_Alloc(tempmempool, j);
+ strlcpy(custsurfaceparmnames[numcustsurfaceparms], com_token, j+1);
+ // value
+ if (COM_ParseToken_QuakeC(&text, false))
+ custsurfaceparms[numcustsurfaceparms] = strtol(com_token, NULL, 0);
+ else
+ custsurfaceparms[numcustsurfaceparms] = 0;
+ numcustsurfaceparms++;
+ }
+ }
+ }
+ Mem_Free(f);
+ }
+
+ // parse shaders
search = FS_Search("scripts/*.shader", true, false);
if (!search)
return;
shader.reflectfactor = 1;
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
+ shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
+ shader.offsetscale = 1;
shader.specularscalemod = 1;
shader.specularpowermod = 1;
+ shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value;
+ shader.biaspolygonfactor = mod_q3shader_default_polygonfactor.value;
strlcpy(shader.name, com_token, sizeof(shader.name));
if (!COM_ParseToken_QuakeC(&text, false) || strcasecmp(com_token, "{"))
{
- Con_Printf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[fileindex], com_token);
+ Con_DPrintf("%s parsing error - expected \"{\", found \"%s\"\n", search->filenames[fileindex], com_token);
break;
}
while (COM_ParseToken_QuakeC(&text, false))
{
if (j < TEXTURE_MAXFRAMES + 4)
{
- strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+ // remap dp_water to dpwater, dp_reflect to dpreflect, etc.
+ if(j == 0 && !strncasecmp(com_token, "dp_", 3))
+ dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
+ else
+ strlcpy(parameter[j], com_token, sizeof(parameter[j]));
numparameters = j + 1;
}
if (!COM_ParseToken_QuakeC(&text, true))
}
//for (j = numparameters;j < TEXTURE_MAXFRAMES + 4;j++)
// parameter[j][0] = 0;
- if (developer.integer >= 100)
+ if (developer_insane.integer)
{
- Con_Printf("%s %i: ", shader.name, shader.numlayers - 1);
+ Con_DPrintf("%s %i: ", shader.name, shader.numlayers - 1);
for (j = 0;j < numparameters;j++)
- Con_Printf(" %s", parameter[j]);
- Con_Print("\n");
+ Con_DPrintf(" %s", parameter[j]);
+ Con_DPrint("\n");
}
if (numparameters >= 2 && !strcasecmp(parameter[0], "blendfunc"))
{
{
if (j < TEXTURE_MAXFRAMES + 4)
{
- strlcpy(parameter[j], com_token, sizeof(parameter[j]));
+ // remap dp_water to dpwater, dp_reflect to dpreflect, etc.
+ if(j == 0 && !strncasecmp(com_token, "dp_", 3))
+ dpsnprintf(parameter[j], sizeof(parameter[j]), "dp%s", &com_token[3]);
+ else
+ strlcpy(parameter[j], com_token, sizeof(parameter[j]));
numparameters = j + 1;
}
if (!COM_ParseToken_QuakeC(&text, true))
// parameter[j][0] = 0;
if (fileindex == 0 && !strcasecmp(com_token, "}"))
break;
- if (developer.integer >= 100)
+ if (developer_insane.integer)
{
- Con_Printf("%s: ", shader.name);
+ Con_DPrintf("%s: ", shader.name);
for (j = 0;j < numparameters;j++)
- Con_Printf(" %s", parameter[j]);
- Con_Print("\n");
+ Con_DPrintf(" %s", parameter[j]);
+ Con_DPrint("\n");
}
if (numparameters < 1)
continue;
else if (!strcasecmp(parameter[1], "antiportal"))
shader.surfaceparms |= Q3SURFACEPARM_ANTIPORTAL;
else
- Con_DPrintf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
+ {
+ // try custom surfaceparms
+ for (j = 0; j < numcustsurfaceparms; j++)
+ {
+ if (!strcasecmp(custsurfaceparmnames[j], parameter[1]))
+ {
+ shader.surfaceparms |= custsurfaceparms[j];
+ break;
+ }
+ }
+ // failed all
+ if (j == numcustsurfaceparms)
+ Con_DPrintf("%s parsing warning: unknown surfaceparm \"%s\"\n", search->filenames[fileindex], parameter[1]);
+ }
}
else if (!strcasecmp(parameter[0], "dpshadow"))
shader.dpshadow = true;
else if (!strcasecmp(parameter[0], "dpnoshadow"))
shader.dpnoshadow = true;
+ else if (!strcasecmp(parameter[0], "dpreflectcube"))
+ strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube));
+ else if (!strcasecmp(parameter[0], "dpmeshcollisions"))
+ shader.dpmeshcollisions = true;
else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
{
// some q3 skies don't have the sky parm set
shader.textureflags |= Q3TEXTUREFLAG_NOPICMIP;
else if (!strcasecmp(parameter[0], "polygonoffset"))
shader.textureflags |= Q3TEXTUREFLAG_POLYGONOFFSET;
- else if (!strcasecmp(parameter[0], "dp_refract") && numparameters >= 5)
+ else if (!strcasecmp(parameter[0], "dppolygonoffset"))
+ {
+ shader.textureflags |= Q3TEXTUREFLAG_POLYGONOFFSET;
+ if(numparameters >= 2)
+ {
+ shader.biaspolygonfactor = atof(parameter[1]);
+ if(numparameters >= 3)
+ shader.biaspolygonoffset = atof(parameter[2]);
+ else
+ shader.biaspolygonoffset = 0;
+ }
+ }
+ else if (!strcasecmp(parameter[0], "dprefract") && numparameters >= 5)
{
shader.textureflags |= Q3TEXTUREFLAG_REFRACTION;
shader.refractfactor = atof(parameter[1]);
Vector4Set(shader.refractcolor4f, atof(parameter[2]), atof(parameter[3]), atof(parameter[4]), 1);
}
- else if (!strcasecmp(parameter[0], "dp_reflect") && numparameters >= 6)
+ else if (!strcasecmp(parameter[0], "dpreflect") && numparameters >= 6)
{
shader.textureflags |= Q3TEXTUREFLAG_REFLECTION;
shader.reflectfactor = atof(parameter[1]);
Vector4Set(shader.reflectcolor4f, atof(parameter[2]), atof(parameter[3]), atof(parameter[4]), atof(parameter[5]));
}
- else if (!strcasecmp(parameter[0], "dp_water") && numparameters >= 12)
+ else if (!strcasecmp(parameter[0], "dpcamera"))
+ {
+ shader.textureflags |= Q3TEXTUREFLAG_CAMERA;
+ }
+ else if (!strcasecmp(parameter[0], "dpwater") && numparameters >= 12)
{
shader.textureflags |= Q3TEXTUREFLAG_WATERSHADER;
shader.reflectmin = atof(parameter[1]);
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)
+ else if (!strcasecmp(parameter[0], "dpwaterscroll") && numparameters >= 3)
+ {
+ shader.r_water_waterscroll[0] = 1/atof(parameter[1]);
+ shader.r_water_waterscroll[1] = 1/atof(parameter[2]);
+ }
+ else if (!strcasecmp(parameter[0], "dpglossintensitymod") && numparameters >= 2)
{
shader.specularscalemod = atof(parameter[1]);
}
- else if (!strcasecmp(parameter[0], "dp_glossexponentmod") && numparameters >= 2)
+ else if (!strcasecmp(parameter[0], "dpglossexponentmod") && numparameters >= 2)
{
shader.specularpowermod = atof(parameter[1]);
}
+ else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 3)
+ {
+ if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off"))
+ shader.offsetmapping = OFFSETMAPPING_OFF;
+ else if (!strcasecmp(parameter[1], "default"))
+ shader.offsetmapping = OFFSETMAPPING_DEFAULT;
+ else if (!strcasecmp(parameter[1], "linear"))
+ shader.offsetmapping = OFFSETMAPPING_LINEAR;
+ else if (!strcasecmp(parameter[1], "relief"))
+ shader.offsetmapping = OFFSETMAPPING_RELIEF;
+ shader.offsetscale = atof(parameter[2]);
+ }
else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
{
int i, deformindex;
}
// fix up multiple reflection types
if(shader.textureflags & Q3TEXTUREFLAG_WATERSHADER)
- shader.textureflags &= ~(Q3TEXTUREFLAG_REFRACTION | Q3TEXTUREFLAG_REFLECTION);
+ shader.textureflags &= ~(Q3TEXTUREFLAG_REFRACTION | Q3TEXTUREFLAG_REFLECTION | Q3TEXTUREFLAG_CAMERA);
Q3Shader_AddToHash (&shader);
}
Mem_Free(f);
}
FS_FreeSearch(search);
+ // free custinfoparm values
+ for (j = 0; j < numcustsurfaceparms; j++)
+ Mem_Free(custsurfaceparmnames[j]);
}
q3shaderinfo_t *Mod_LookupQ3Shader(const char *name)
qboolean Mod_LoadTextureFromQ3Shader(texture_t *texture, const char *name, qboolean warnmissing, qboolean fallback, int defaulttexflags)
{
int j;
- int texflagsmask;
+ int texflagsmask, texflagsor;
qboolean success = true;
q3shaderinfo_t *shader;
if (!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
+ texflagsor = 0;
+ if(defaulttexflags & TEXF_ISWORLD)
+ texflagsor |= TEXF_ISWORLD;
+ if(defaulttexflags & TEXF_ISSPRITE)
+ texflagsor |= TEXF_ISSPRITE;
+ // unless later loaded from the shader
+ texture->offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
+ texture->offsetscale = 1;
+ texture->specularscalemod = 1;
+ texture->specularpowermod = 1;
// WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE
// HERE, AND Q1BSP LOADING
// JUST GREP FOR "specularscalemod = 1".
texture->surfaceparms = shader->surfaceparms;
// allow disabling of picmip or compression by defaulttexflags
- texture->textureflags = shader->textureflags & texflagsmask;
+ texture->textureflags = (shader->textureflags & texflagsmask) | texflagsor;
if (shader->surfaceparms & Q3SURFACEPARM_SKY)
{
if (shader->textureflags & Q3TEXTUREFLAG_TWOSIDED)
texture->basematerialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
if (shader->textureflags & Q3TEXTUREFLAG_POLYGONOFFSET)
- texture->biaspolygonoffset -= 2;
+ {
+ texture->biaspolygonoffset += shader->biaspolygonoffset;
+ texture->biaspolygonfactor += shader->biaspolygonfactor;
+ }
if (shader->textureflags & Q3TEXTUREFLAG_REFRACTION)
texture->basematerialflags |= MATERIALFLAG_REFRACTION;
if (shader->textureflags & Q3TEXTUREFLAG_REFLECTION)
texture->basematerialflags |= MATERIALFLAG_REFLECTION;
if (shader->textureflags & Q3TEXTUREFLAG_WATERSHADER)
texture->basematerialflags |= MATERIALFLAG_WATERSHADER;
+ if (shader->textureflags & Q3TEXTUREFLAG_CAMERA)
+ texture->basematerialflags |= MATERIALFLAG_CAMERA;
texture->customblendfunc[0] = GL_ONE;
texture->customblendfunc[1] = GL_ZERO;
if (shader->numlayers > 0)
{
texture->skinframes[j] = NULL;
}
- else if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], primarylayer->texflags & texflagsmask, false)))
+ else if (!(texture->skinframes[j] = R_SkinFrame_LoadExternal(primarylayer->texturename[j], (primarylayer->texflags & texflagsmask) | texflagsor, false)))
{
Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (frame %i) for shader ^2\"%s\"\n", loadmodel->name, primarylayer->texturename[j], j, texture->name);
texture->skinframes[j] = R_SkinFrame_LoadMissing();
{
texture->skinframes[j] = NULL;
}
- else if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], backgroundlayer->texflags & texflagsmask, false)))
+ else if (!(texture->backgroundskinframes[j] = R_SkinFrame_LoadExternal(backgroundlayer->texturename[j], (backgroundlayer->texflags & texflagsmask) | texflagsor, false)))
{
Con_Printf("^1%s:^7 could not load texture ^3\"%s\"^7 (background frame %i) for shader ^2\"%s\"\n", loadmodel->name, backgroundlayer->texturename[j], j, texture->name);
texture->backgroundskinframes[j] = R_SkinFrame_LoadMissing();
texture->reflectfactor = shader->reflectfactor;
Vector4Copy(shader->reflectcolor4f, texture->reflectcolor4f);
texture->r_water_wateralpha = shader->r_water_wateralpha;
+ Vector2Copy(shader->r_water_waterscroll, texture->r_water_waterscroll);
+ texture->offsetmapping = shader->offsetmapping;
+ texture->offsetscale = shader->offsetscale;
texture->specularscalemod = shader->specularscalemod;
texture->specularpowermod = shader->specularpowermod;
+ if (shader->dpreflectcube[0])
+ texture->reflectcubetexture = R_GetCubemap(shader->dpreflectcube);
+
+ // set up default supercontents (on q3bsp this is overridden by the q3bsp loader)
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
+ if (shader->surfaceparms & Q3SURFACEPARM_LAVA ) texture->supercontents = SUPERCONTENTS_LAVA ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SLIME ) texture->supercontents = SUPERCONTENTS_SLIME ;
+ if (shader->surfaceparms & Q3SURFACEPARM_WATER ) texture->supercontents = SUPERCONTENTS_WATER ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NONSOLID ) texture->supercontents = 0 ;
+ if (shader->surfaceparms & Q3SURFACEPARM_PLAYERCLIP ) texture->supercontents = SUPERCONTENTS_PLAYERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_BOTCLIP ) texture->supercontents = SUPERCONTENTS_MONSTERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY ) texture->supercontents = SUPERCONTENTS_SKY ;
+
+ // if (shader->surfaceparms & Q3SURFACEPARM_ALPHASHADOW ) texture->supercontents |= SUPERCONTENTS_ALPHASHADOW ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_AREAPORTAL ) texture->supercontents |= SUPERCONTENTS_AREAPORTAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_CLUSTERPORTAL) texture->supercontents |= SUPERCONTENTS_CLUSTERPORTAL;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DETAIL ) texture->supercontents |= SUPERCONTENTS_DETAIL ;
+ if (shader->surfaceparms & Q3SURFACEPARM_DONOTENTER ) texture->supercontents |= SUPERCONTENTS_DONOTENTER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_FOG ) texture->supercontents |= SUPERCONTENTS_FOG ;
+ if (shader->surfaceparms & Q3SURFACEPARM_LAVA ) texture->supercontents |= SUPERCONTENTS_LAVA ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LIGHTFILTER ) texture->supercontents |= SUPERCONTENTS_LIGHTFILTER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_METALSTEPS ) texture->supercontents |= SUPERCONTENTS_METALSTEPS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODAMAGE ) texture->supercontents |= SUPERCONTENTS_NODAMAGE ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODLIGHT ) texture->supercontents |= SUPERCONTENTS_NODLIGHT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NODRAW ) texture->supercontents |= SUPERCONTENTS_NODRAW ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NODROP ) texture->supercontents |= SUPERCONTENTS_NODROP ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOIMPACT ) texture->supercontents |= SUPERCONTENTS_NOIMPACT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOLIGHTMAP ) texture->supercontents |= SUPERCONTENTS_NOLIGHTMAP ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOMARKS ) texture->supercontents |= SUPERCONTENTS_NOMARKS ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_NOMIPMAPS ) texture->supercontents |= SUPERCONTENTS_NOMIPMAPS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_NONSOLID ) texture->supercontents &=~SUPERCONTENTS_SOLID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ORIGIN ) texture->supercontents |= SUPERCONTENTS_ORIGIN ;
+ if (shader->surfaceparms & Q3SURFACEPARM_PLAYERCLIP ) texture->supercontents |= SUPERCONTENTS_PLAYERCLIP ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SKY ) texture->supercontents |= SUPERCONTENTS_SKY ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_SLICK ) texture->supercontents |= SUPERCONTENTS_SLICK ;
+ if (shader->surfaceparms & Q3SURFACEPARM_SLIME ) texture->supercontents |= SUPERCONTENTS_SLIME ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_STRUCTURAL ) texture->supercontents |= SUPERCONTENTS_STRUCTURAL ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_TRANS ) texture->supercontents |= SUPERCONTENTS_TRANS ;
+ if (shader->surfaceparms & Q3SURFACEPARM_WATER ) texture->supercontents |= SUPERCONTENTS_WATER ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_POINTLIGHT ) texture->supercontents |= SUPERCONTENTS_POINTLIGHT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_HINT ) texture->supercontents |= SUPERCONTENTS_HINT ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_DUST ) texture->supercontents |= SUPERCONTENTS_DUST ;
+ if (shader->surfaceparms & Q3SURFACEPARM_BOTCLIP ) texture->supercontents |= SUPERCONTENTS_BOTCLIP | SUPERCONTENTS_MONSTERCLIP;
+ // if (shader->surfaceparms & Q3SURFACEPARM_LIGHTGRID ) texture->supercontents |= SUPERCONTENTS_LIGHTGRID ;
+ // if (shader->surfaceparms & Q3SURFACEPARM_ANTIPORTAL ) texture->supercontents |= SUPERCONTENTS_ANTIPORTAL ;
+
+ if (shader->dpmeshcollisions)
+ texture->basematerialflags |= MATERIALFLAG_MESHCOLLISIONS;
}
else if (!strcmp(texture->name, "noshader") || !texture->name[0])
{
- if (developer.integer >= 100)
- Con_Printf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", loadmodel->name, name);
+ if (developer_extra.integer)
+ Con_DPrintf("^1%s:^7 using fallback noshader material for ^3\"%s\"\n", loadmodel->name, name);
texture->surfaceparms = 0;
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
}
else if (!strcmp(texture->name, "common/nodraw") || !strcmp(texture->name, "textures/common/nodraw"))
{
- if (developer.integer >= 100)
- Con_Printf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", loadmodel->name, name);
+ if (developer_extra.integer)
+ Con_DPrintf("^1%s:^7 using fallback nodraw material for ^3\"%s\"\n", loadmodel->name, name);
texture->surfaceparms = 0;
texture->basematerialflags = MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SOLID;
}
else
{
- if (developer.integer >= 100)
- Con_Printf("^1%s:^7 No shader found for texture ^3\"%s\"\n", loadmodel->name, texture->name);
+ if (developer_extra.integer)
+ Con_DPrintf("^1%s:^7 No shader found for texture ^3\"%s\"\n", loadmodel->name, texture->name);
texture->surfaceparms = 0;
if (texture->surfaceflags & Q3SURFACEFLAG_NODRAW)
+ {
texture->basematerialflags |= MATERIALFLAG_NODRAW | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SOLID;
+ }
else if (texture->surfaceflags & Q3SURFACEFLAG_SKY)
+ {
texture->basematerialflags |= MATERIALFLAG_SKY | MATERIALFLAG_NOSHADOW;
+ texture->supercontents = SUPERCONTENTS_SKY;
+ }
else
+ {
texture->basematerialflags |= MATERIALFLAG_WALL;
+ texture->supercontents = SUPERCONTENTS_SOLID | SUPERCONTENTS_OPAQUE;
+ }
texture->numskinframes = 1;
if(cls.state == ca_dedicated)
{
Mem_Free(numsurfacesfortexture);
}
-static void Mod_BuildVBOs(void)
+void Mod_BuildVBOs(void)
{
- if (developer.integer && loadmodel->surfmesh.data_element3s && loadmodel->surfmesh.data_element3i)
+ if (!loadmodel->surfmesh.num_vertices)
+ return;
+
+ if (gl_paranoid.integer && loadmodel->surfmesh.data_element3s && loadmodel->surfmesh.data_element3i)
{
int i;
for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
}
}
- if (!vid.support.arb_vertex_buffer_object)
- return;
-
- // element buffer is easy because it's just one array
- if (loadmodel->surfmesh.num_triangles)
+ // build r_vertexmesh_t array
+ // (compressed interleaved array for D3D)
+ if (!loadmodel->surfmesh.vertexmesh && vid.useinterleavedarrays)
{
- if (loadmodel->surfmesh.data_element3s)
- 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);
+ int vertexindex;
+ int numvertices = loadmodel->surfmesh.num_vertices;
+ r_vertexmesh_t *vertexmesh;
+ loadmodel->surfmesh.vertexmesh = vertexmesh = (r_vertexmesh_t*)Mem_Alloc(loadmodel->mempool, numvertices * sizeof(*loadmodel->surfmesh.vertexmesh));
+ for (vertexindex = 0;vertexindex < numvertices;vertexindex++, vertexmesh++)
+ {
+ VectorCopy(loadmodel->surfmesh.data_vertex3f + 3*vertexindex, vertexmesh->vertex3f);
+ VectorScale(loadmodel->surfmesh.data_svector3f + 3*vertexindex, 1.0f, vertexmesh->svector3f);
+ VectorScale(loadmodel->surfmesh.data_tvector3f + 3*vertexindex, 1.0f, vertexmesh->tvector3f);
+ VectorScale(loadmodel->surfmesh.data_normal3f + 3*vertexindex, 1.0f, vertexmesh->normal3f);
+ if (loadmodel->surfmesh.data_lightmapcolor4f)
+ Vector4Scale(loadmodel->surfmesh.data_lightmapcolor4f + 4*vertexindex, 255.0f, vertexmesh->color4ub);
+ Vector2Copy(loadmodel->surfmesh.data_texcoordtexture2f + 2*vertexindex, vertexmesh->texcoordtexture2f);
+ if (loadmodel->surfmesh.data_texcoordlightmap2f)
+ Vector2Scale(loadmodel->surfmesh.data_texcoordlightmap2f + 2*vertexindex, 1.0f, vertexmesh->texcoordlightmap2f);
+ }
}
+ // upload r_vertexmesh_t array as a buffer
+ if (loadmodel->surfmesh.vertexmesh && !loadmodel->surfmesh.vertexmeshbuffer)
+ loadmodel->surfmesh.vertexmeshbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.vertexmesh, loadmodel->surfmesh.num_vertices * sizeof(*loadmodel->surfmesh.vertexmesh), loadmodel->name, false, false, false);
+
+ // upload vertex3f array as a buffer
+ if (loadmodel->surfmesh.data_vertex3f && !loadmodel->surfmesh.vertex3fbuffer)
+ loadmodel->surfmesh.vertex3fbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]), loadmodel->name, false, false, false);
+
+ // upload short indices as a buffer
+ if (loadmodel->surfmesh.data_element3s && !loadmodel->surfmesh.data_element3s_indexbuffer)
+ loadmodel->surfmesh.data_element3s_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles * sizeof(short[3]), loadmodel->name, true, false, true);
+
+ // upload int indices as a buffer
+ if (loadmodel->surfmesh.data_element3i && !loadmodel->surfmesh.data_element3i_indexbuffer && !loadmodel->surfmesh.data_element3s)
+ loadmodel->surfmesh.data_element3i_indexbuffer = R_Mesh_CreateMeshBuffer(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles * sizeof(int[3]), loadmodel->name, true, false, false);
+
+ // only build a vbo if one has not already been created (this is important for brush models which load specially)
// vertex buffer is several arrays and we put them in the same buffer
//
// is this wise? the texcoordtexture2f array is used with dynamic
// vertex/svector/tvector/normal when rendering animated models, on the
// other hand animated models don't use a lot of vertices anyway...
- if (loadmodel->surfmesh.num_vertices)
+ if (!loadmodel->surfmesh.vbo_vertexbuffer && !vid.useinterleavedarrays)
{
size_t size;
unsigned char *mem;
if (loadmodel->surfmesh.data_texcoordtexture2f ) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordtexture2f , loadmodel->surfmesh.data_texcoordtexture2f , loadmodel->surfmesh.num_vertices * sizeof(float[2]));
if (loadmodel->surfmesh.data_texcoordlightmap2f) memcpy(mem + loadmodel->surfmesh.vbooffset_texcoordlightmap2f, loadmodel->surfmesh.data_texcoordlightmap2f, loadmodel->surfmesh.num_vertices * sizeof(float[2]));
if (loadmodel->surfmesh.data_lightmapcolor4f ) memcpy(mem + loadmodel->surfmesh.vbooffset_lightmapcolor4f , loadmodel->surfmesh.data_lightmapcolor4f , loadmodel->surfmesh.num_vertices * sizeof(float[4]));
- loadmodel->surfmesh.vbo = R_Mesh_CreateStaticBufferObject(GL_ARRAY_BUFFER_ARB, mem, size, loadmodel->name);
+ loadmodel->surfmesh.vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, loadmodel->name, false, false, false);
Mem_Free(mem);
}
}
static void Mod_Decompile_OBJ(dp_model_t *model, const char *filename, const char *mtlfilename, const char *originalfilename)
{
- int vertexindex, surfaceindex, triangleindex, textureindex, countvertices = 0, countsurfaces = 0, countfaces = 0, counttextures = 0;
+ int submodelindex, vertexindex, surfaceindex, triangleindex, textureindex, countvertices = 0, countsurfaces = 0, countfaces = 0, counttextures = 0;
int a, b, c;
const char *texname;
const int *e;
const msurface_t *surface;
const int maxtextures = 256;
char *texturenames = (char *) Z_Malloc(maxtextures * MAX_QPATH);
+ dp_model_t *submodel;
// construct the mtllib file
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# mtllib for %s exported by darkplaces engine\n", originalfilename);
// write the mtllib file
FS_WriteFile(mtlfilename, outbuffer, outbufferpos);
- outbufferpos = 0;
// construct the obj file
+ outbufferpos = 0;
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "# model exported from %s by darkplaces engine\n# %i vertices, %i faces, %i surfaces\nmtllib %s\n", originalfilename, countvertices, countfaces, countsurfaces, mtlfilename);
if (l > 0)
outbufferpos += l;
+
for (vertexindex = 0, v = model->surfmesh.data_vertex3f, vn = model->surfmesh.data_normal3f, vt = model->surfmesh.data_texcoordtexture2f;vertexindex < model->surfmesh.num_vertices;vertexindex++, v += 3, vn += 3, vt += 2)
{
if (outbufferpos >= outbuffermax >> 1)
memcpy(outbuffer, oldbuffer, outbufferpos);
Z_Free(oldbuffer);
}
- l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "v %f %f %f\nvn %f %f %f\nvt %f %f\n", v[0], v[2], -v[1], vn[0], vn[2], -vn[1], vt[0], 1-vt[1]);
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "v %f %f %f\nvn %f %f %f\nvt %f %f\n", v[0], v[2], v[1], vn[0], vn[2], vn[1], vt[0], 1-vt[1]);
if (l > 0)
outbufferpos += l;
}
- for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->num_surfaces;surfaceindex++, surface++)
+
+ for (submodelindex = 0;submodelindex < max(1, model->brush.numsubmodels);submodelindex++)
{
- l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "o %i\n", submodelindex);
if (l > 0)
outbufferpos += l;
- for (triangleindex = 0, e = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
+ submodel = model->brush.numsubmodels ? model->brush.submodels[submodelindex] : model;
+ for (surfaceindex = 0;surfaceindex < submodel->nummodelsurfaces;surfaceindex++)
{
- if (outbufferpos >= outbuffermax >> 1)
- {
- outbuffermax *= 2;
- oldbuffer = outbuffer;
- outbuffer = (char *) Z_Malloc(outbuffermax);
- memcpy(outbuffer, oldbuffer, outbufferpos);
- Z_Free(oldbuffer);
- }
- a = e[0]+1;
- b = e[2]+1;
- c = e[1]+1;
- l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", a,a,a,b,b,b,c,c,c);
+ surface = model->data_surfaces + submodel->sortedmodelsurfaces[surfaceindex];
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "usemtl %s\n", (surface->texture && surface->texture->name[0]) ? surface->texture->name : "default");
if (l > 0)
outbufferpos += l;
+ for (triangleindex = 0, e = model->surfmesh.data_element3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
+ {
+ if (outbufferpos >= outbuffermax >> 1)
+ {
+ outbuffermax *= 2;
+ oldbuffer = outbuffer;
+ outbuffer = (char *) Z_Malloc(outbuffermax);
+ memcpy(outbuffer, oldbuffer, outbufferpos);
+ Z_Free(oldbuffer);
+ }
+ a = e[0]+1;
+ b = e[1]+1;
+ c = e[2]+1;
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", a,a,a,b,b,b,c,c,c);
+ if (l > 0)
+ outbufferpos += l;
+ }
}
}
int transformindex;
int poseindex;
int cornerindex;
- float modelscale;
const int *e;
- const float *pose;
size_t l;
size_t outbufferpos = 0;
size_t outbuffermax = 0x100000;
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "version 1\nnodes\n");
if (l > 0)
outbufferpos += l;
- modelscale = 1;
- if(model->num_poses >= 0)
- modelscale = sqrt(model->data_poses[0] * model->data_poses[0] + model->data_poses[1] * model->data_poses[1] + model->data_poses[2] * model->data_poses[2]);
- if(fabs(modelscale - 1) > 1e-4)
- {
- if(firstpose == 0) // only print the when writing the reference pose
- Con_Printf("The model has an old-style model scale of %f\n", modelscale);
- }
- else
- modelscale = 1;
for (transformindex = 0;transformindex < model->num_bones;transformindex++)
{
if (outbufferpos >= outbuffermax >> 1)
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "end\nskeleton\n");
if (l > 0)
outbufferpos += l;
- for (poseindex = 0, pose = model->data_poses + model->num_bones * 12 * firstpose;poseindex < numposes;poseindex++)
+ for (poseindex = 0;poseindex < numposes;poseindex++)
{
countframes++;
l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "time %i\n", poseindex);
if (l > 0)
outbufferpos += l;
- for (transformindex = 0;transformindex < model->num_bones;transformindex++, pose += 12)
+ for (transformindex = 0;transformindex < model->num_bones;transformindex++)
{
- float a, b, c;
float angles[3];
- float mtest[3][4];
+ float mtest[4][3];
+ matrix4x4_t posematrix;
if (outbufferpos >= outbuffermax >> 1)
{
outbuffermax *= 2;
// strangely the smd angles are for a transposed matrix, so we
// have to generate a transposed matrix, then convert that...
- mtest[0][0] = pose[ 0];
- mtest[0][1] = pose[ 4];
- mtest[0][2] = pose[ 8];
- mtest[0][3] = pose[ 3];
- mtest[1][0] = pose[ 1];
- mtest[1][1] = pose[ 5];
- mtest[1][2] = pose[ 9];
- mtest[1][3] = pose[ 7];
- mtest[2][0] = pose[ 2];
- mtest[2][1] = pose[ 6];
- mtest[2][2] = pose[10];
- mtest[2][3] = pose[11];
+ Matrix4x4_FromBonePose6s(&posematrix, model->num_posescale, model->data_poses6s + 6*(model->num_bones * poseindex + transformindex));
+ Matrix4x4_ToArray12FloatGL(&posematrix, mtest[0]);
AnglesFromVectors(angles, mtest[0], mtest[2], false);
if (angles[0] >= 180) angles[0] -= 360;
if (angles[1] >= 180) angles[1] -= 360;
if (angles[2] >= 180) angles[2] -= 360;
- a = DEG2RAD(angles[ROLL]);
- b = DEG2RAD(angles[PITCH]);
- c = DEG2RAD(angles[YAW]);
-
#if 0
{
+ float a = DEG2RAD(angles[ROLL]);
+ float b = DEG2RAD(angles[PITCH]);
+ float c = DEG2RAD(angles[YAW]);
float cy, sy, cp, sp, cr, sr;
- float test[3][4];
- // smd matrix construction, for comparing to non-transposed m
+ float test[4][3];
+ // smd matrix construction, for comparing
sy = sin(c);
cy = cos(c);
sp = sin(b);
cr = cos(a);
test[0][0] = cp*cy;
- test[1][0] = cp*sy;
- test[2][0] = -sp;
- test[0][1] = sr*sp*cy+cr*-sy;
+ test[0][1] = cp*sy;
+ test[0][2] = -sp;
+ test[1][0] = sr*sp*cy+cr*-sy;
test[1][1] = sr*sp*sy+cr*cy;
- test[2][1] = sr*cp;
- test[0][2] = (cr*sp*cy+-sr*-sy);
- test[1][2] = (cr*sp*sy+-sr*cy);
+ test[1][2] = sr*cp;
+ test[2][0] = (cr*sp*cy+-sr*-sy);
+ test[2][1] = (cr*sp*sy+-sr*cy);
test[2][2] = cr*cp;
- test[0][3] = pose[3];
- test[1][3] = pose[7];
- test[2][3] = pose[11];
+ test[3][0] = pose[9];
+ test[3][1] = pose[10];
+ test[3][2] = pose[11];
}
#endif
- l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f\n", transformindex, pose[3] * modelscale, pose[7] * modelscale, pose[11] * modelscale, DEG2RAD(angles[ROLL]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[YAW]));
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f\n", transformindex, mtest[3][0], mtest[3][1], mtest[3][2], DEG2RAD(angles[ROLL]), DEG2RAD(angles[PITCH]), DEG2RAD(angles[YAW]));
if (l > 0)
outbufferpos += l;
}
const float *v = model->surfmesh.data_vertex3f + index * 3;
const float *vn = model->surfmesh.data_normal3f + index * 3;
const float *vt = model->surfmesh.data_texcoordtexture2f + index * 2;
- const int *wi = model->surfmesh.data_vertexweightindex4i + index * 4;
- const float *wf = model->surfmesh.data_vertexweightinfluence4f + index * 4;
- if (wf[3]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 4 %i %f %i %f %i %f %i %f\n", wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2], wi[3], wf[3]);
- else if (wf[2]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 3 %i %f %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1], wi[2], wf[2]);
- else if (wf[1]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 2 %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0], wi[1], wf[1]);
- else l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ const int b = model->surfmesh.blends[index];
+ if (b < model->num_bones)
+ l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , b, v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ else
+ {
+ const blendweights_t *w = model->surfmesh.data_blendweights + b - model->num_bones;
+ const unsigned char *wi = w->index;
+ const unsigned char *wf = w->influence;
+ if (wf[3]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 4 %i %f %i %f %i %f %i %f\n", wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f, wi[2], wf[2]/255.0f, wi[3], wf[3]/255.0f);
+ else if (wf[2]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 3 %i %f %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f, wi[2], wf[2]/255.0f);
+ else if (wf[1]) l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f 2 %i %f %i %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1], wi[0], wf[0]/255.0f, wi[1], wf[1]/255.0f);
+ else l = dpsnprintf(outbuffer + outbufferpos, outbuffermax - outbufferpos, "%3i %f %f %f %f %f %f %f %f\n" , wi[0], v[0], v[1], v[2], vn[0], vn[1], vn[2], vt[0], 1 - vt[1]);
+ }
if (l > 0)
outbufferpos += l;
}
char animname2[MAX_QPATH];
char zymtextbuffer[16384];
char dpmtextbuffer[16384];
+ char framegroupstextbuffer[16384];
int zymtextsize = 0;
int dpmtextsize = 0;
+ int framegroupstextsize = 0;
if (Cmd_Argc() != 2)
{
// individual frame
// check for additional frames with same name
for (l = 0, k = strlen(animname);animname[l];l++)
- if ((animname[l] < '0' || animname[l] > '9') && animname[l] != '_')
+ if(animname[l] < '0' || animname[l] > '9')
k = l + 1;
+ if(k > 0 && animname[k-1] == '_')
+ --k;
animname[k] = 0;
count = mod->num_poses - first;
for (j = i + 1;j < mod->numframes;j++)
{
strlcpy(animname2, mod->animscenes[j].name, sizeof(animname2));
for (l = 0, k = strlen(animname2);animname2[l];l++)
- if ((animname2[l] < '0' || animname2[l] > '9') && animname2[l] != '_')
+ if(animname2[l] < '0' || animname2[l] > '9')
k = l + 1;
+ if(k > 0 && animname[k-1] == '_')
+ --k;
animname2[k] = 0;
if (strcmp(animname2, animname) || mod->animscenes[j].framecount > 1)
{
Mod_Decompile_SMD(mod, outname, first, count, false);
if (zymtextsize < (int)sizeof(zymtextbuffer) - 100)
{
- l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g\n", animname, mod->animscenes[i].framerate);
+ l = dpsnprintf(zymtextbuffer + zymtextsize, sizeof(zymtextbuffer) - zymtextsize, "scene %s.smd fps %g %s\n", animname, mod->animscenes[i].framerate, mod->animscenes[i].loop ? "" : " noloop");
if (l > 0) zymtextsize += l;
}
if (dpmtextsize < (int)sizeof(dpmtextbuffer) - 100)
{
- l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd\n", animname);
+ l = dpsnprintf(dpmtextbuffer + dpmtextsize, sizeof(dpmtextbuffer) - dpmtextsize, "scene %s.smd fps %g %s\n", animname, mod->animscenes[i].framerate, mod->animscenes[i].loop ? "" : " noloop");
if (l > 0) dpmtextsize += l;
}
+ if (framegroupstextsize < (int)sizeof(framegroupstextbuffer) - 100)
+ {
+ l = dpsnprintf(framegroupstextbuffer + framegroupstextsize, sizeof(framegroupstextbuffer) - framegroupstextsize, "%d %d %f %d // %s\n", first, count, mod->animscenes[i].framerate, mod->animscenes[i].loop, animname);
+ if (l > 0) framegroupstextsize += l;
+ }
}
if (zymtextsize)
FS_WriteFile(va("%s_decompiled/out_zym.txt", basename), zymtextbuffer, (fs_offset_t)zymtextsize);
if (dpmtextsize)
FS_WriteFile(va("%s_decompiled/out_dpm.txt", basename), dpmtextbuffer, (fs_offset_t)dpmtextsize);
+ if (framegroupstextsize)
+ FS_WriteFile(va("%s_decompiled.framegroups", basename), framegroupstextbuffer, (fs_offset_t)framegroupstextsize);
}
}
state->width = width;
state->height = height;
state->currentY = 0;
- state->rows = Mem_Alloc(loadmodel->mempool, state->height * sizeof(*state->rows));
+ state->rows = (mod_alloclightmap_row_t *)Mem_Alloc(loadmodel->mempool, state->height * sizeof(*state->rows));
for (y = 0;y < state->height;y++)
{
state->rows[y].currentX = 0;
static int mod_generatelightmaps_numlights;
static lightmaplight_t *mod_generatelightmaps_lightinfo;
+extern int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color);
+extern cvar_t r_shadow_lightattenuationdividebias;
+extern cvar_t r_shadow_lightattenuationlinearscale;
+
+static void Mod_GenerateLightmaps_LightPoint(dp_model_t *model, const vec3_t pos, vec3_t ambient, vec3_t diffuse, vec3_t lightdir)
+{
+ int i;
+ int index;
+ int result;
+ float relativepoint[3];
+ float color[3];
+ float dir[3];
+ float dist;
+ float dist2;
+ float intensity;
+ float sample[5*3];
+ float lightorigin[3];
+ float lightradius;
+ float lightradius2;
+ float lightiradius;
+ float lightcolor[3];
+ trace_t trace;
+ for (i = 0;i < 5*3;i++)
+ sample[i] = 0.0f;
+ for (index = 0;;index++)
+ {
+ result = R_Shadow_GetRTLightInfo(index, lightorigin, &lightradius, lightcolor);
+ if (result < 0)
+ break;
+ if (result == 0)
+ continue;
+ lightradius2 = lightradius * lightradius;
+ VectorSubtract(lightorigin, pos, relativepoint);
+ dist2 = VectorLength2(relativepoint);
+ if (dist2 >= lightradius2)
+ continue;
+ lightiradius = 1.0f / lightradius;
+ dist = sqrt(dist2) * lightiradius;
+ intensity = (1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
+ if (intensity <= 0.0f)
+ continue;
+ if (model && model->TraceLine)
+ {
+ model->TraceLine(model, NULL, NULL, &trace, pos, lightorigin, SUPERCONTENTS_VISBLOCKERMASK);
+ if (trace.fraction < 1)
+ continue;
+ }
+ // scale down intensity to add to both ambient and diffuse
+ //intensity *= 0.5f;
+ VectorNormalize(relativepoint);
+ VectorScale(lightcolor, intensity, color);
+ VectorMA(sample , 0.5f , color, sample );
+ VectorMA(sample + 3, relativepoint[0], color, sample + 3);
+ VectorMA(sample + 6, relativepoint[1], color, sample + 6);
+ VectorMA(sample + 9, relativepoint[2], color, sample + 9);
+ // calculate a weighted average light direction as well
+ intensity *= VectorLength(color);
+ VectorMA(sample + 12, intensity, relativepoint, sample + 12);
+ }
+ // calculate the direction we'll use to reduce the sample to a directional light source
+ VectorCopy(sample + 12, dir);
+ //VectorSet(dir, sample[3] + sample[4] + sample[5], sample[6] + sample[7] + sample[8], sample[9] + sample[10] + sample[11]);
+ VectorNormalize(dir);
+ // extract the diffuse color along the chosen direction and scale it
+ diffuse[0] = (dir[0]*sample[3] + dir[1]*sample[6] + dir[2]*sample[ 9] + sample[ 0]);
+ diffuse[1] = (dir[0]*sample[4] + dir[1]*sample[7] + dir[2]*sample[10] + sample[ 1]);
+ diffuse[2] = (dir[0]*sample[5] + dir[1]*sample[8] + dir[2]*sample[11] + sample[ 2]);
+ // subtract some of diffuse from ambient
+ VectorMA(sample, -0.333f, diffuse, ambient);
+ // store the normalized lightdir
+ VectorCopy(dir, lightdir);
+}
+
static void Mod_GenerateLightmaps_CreateLights_ComputeSVBSP_InsertSurfaces(const dp_model_t *model, svbsp_t *svbsp, const float *mins, const float *maxs)
{
int surfaceindex;
const float *vertex3f = model->surfmesh.data_vertex3f;
const int *element3i = model->surfmesh.data_element3i;
const int *e;
- double v2[3][3];
+ float v2[3][3];
for (surfaceindex = 0, surface = model->data_surfaces;surfaceindex < model->nummodelsurfaces;surfaceindex++, surface++)
{
if (!BoxesOverlap(surface->mins, surface->maxs, mins, maxs))
continue;
- if (R_GetCurrentTexture(surface->texture)->currentmaterialflags & MATERIALFLAG_NOSHADOW)
+ if (surface->texture->basematerialflags & MATERIALFLAG_NOSHADOW)
continue;
for (triangleindex = 0, e = element3i + 3*surface->num_firsttriangle;triangleindex < surface->num_triangles;triangleindex++, e += 3)
{
{
int maxnodes = 1<<14;
svbsp_node_t *nodes;
- double origin[3];
+ float origin[3];
float mins[3];
float maxs[3];
svbsp_t svbsp;
VectorSet(mins, lightinfo->origin[0] - lightinfo->radius, lightinfo->origin[1] - lightinfo->radius, lightinfo->origin[2] - lightinfo->radius);
VectorSet(maxs, lightinfo->origin[0] + lightinfo->radius, lightinfo->origin[1] + lightinfo->radius, lightinfo->origin[2] + lightinfo->radius);
VectorCopy(lightinfo->origin, origin);
- nodes = Mem_Alloc(tempmempool, maxnodes * sizeof(*nodes));
+ nodes = (svbsp_node_t *)Mem_Alloc(tempmempool, maxnodes * sizeof(*nodes));
for (;;)
{
SVBSP_Init(&svbsp, origin, maxnodes, nodes);
Mod_GenerateLightmaps_CreateLights_ComputeSVBSP_InsertSurfaces(model, &svbsp, mins, maxs);
if (svbsp.ranoutofnodes)
{
- maxnodes *= 2;
- if (maxnodes >= 1<<22)
+ maxnodes *= 16;
+ if (maxnodes > 1<<22)
{
Mem_Free(nodes);
return;
}
Mem_Free(nodes);
- nodes = Mem_Alloc(tempmempool, maxnodes * sizeof(*nodes));
+ nodes = (svbsp_node_t *)Mem_Alloc(tempmempool, maxnodes * sizeof(*nodes));
}
else
break;
}
if (svbsp.numnodes > 0)
{
- svbsp.nodes = Mem_Alloc(tempmempool, svbsp.numnodes * sizeof(*nodes));
+ svbsp.nodes = (svbsp_node_t *)Mem_Alloc(tempmempool, svbsp.numnodes * sizeof(*nodes));
memcpy(svbsp.nodes, nodes, svbsp.numnodes * sizeof(*nodes));
lightinfo->svbsp = svbsp;
}
Mem_Free(nodes);
}
-extern int R_Shadow_GetRTLightInfo(unsigned int lightindex, float *origin, float *radius, float *color);
static void Mod_GenerateLightmaps_CreateLights(dp_model_t *model)
{
int index;
}
if (mod_generatelightmaps_numlights > 0)
{
- mod_generatelightmaps_lightinfo = Mem_Alloc(tempmempool, mod_generatelightmaps_numlights * sizeof(*mod_generatelightmaps_lightinfo));
+ mod_generatelightmaps_lightinfo = (lightmaplight_t *)Mem_Alloc(tempmempool, mod_generatelightmaps_numlights * sizeof(*mod_generatelightmaps_lightinfo));
lightinfo = mod_generatelightmaps_lightinfo;
for (index = 0;;index++)
{
return num == -1; // true if empty, false if solid (shadowed)
}
-extern cvar_t r_shadow_lightattenuationdividebias;
-extern cvar_t r_shadow_lightattenuationlinearscale;
static void Mod_GenerateLightmaps_SamplePoint(const float *pos, const float *normal, float *sample, int numoffsets, const float *offsets)
{
int i;
if (model->brushq3.data_lightmaps)
{
for (i = 0;i < model->brushq3.num_mergedlightmaps;i++)
- R_FreeTexture(model->brushq3.data_lightmaps[i]);
+ if (model->brushq3.data_lightmaps[i])
+ R_FreeTexture(model->brushq3.data_lightmaps[i]);
Mem_Free(model->brushq3.data_lightmaps);
model->brushq3.data_lightmaps = NULL;
}
if (model->brushq3.data_deluxemaps)
{
for (i = 0;i < model->brushq3.num_mergedlightmaps;i++)
- R_FreeTexture(model->brushq3.data_deluxemaps[i]);
+ if (model->brushq3.data_deluxemaps[i])
+ R_FreeTexture(model->brushq3.data_deluxemaps[i]);
Mem_Free(model->brushq3.data_deluxemaps);
model->brushq3.data_deluxemaps = NULL;
}
if (model->surfmesh.num_vertices > 65536)
model->surfmesh.data_element3s = NULL;
- if (model->surfmesh.vbo)
- R_Mesh_DestroyBufferObject(model->surfmesh.vbo);
- model->surfmesh.vbo = 0;
- if (model->surfmesh.ebo3i)
- R_Mesh_DestroyBufferObject(model->surfmesh.ebo3i);
- model->surfmesh.ebo3i = 0;
- if (model->surfmesh.ebo3s)
- R_Mesh_DestroyBufferObject(model->surfmesh.ebo3s);
- model->surfmesh.ebo3s = 0;
+ if (model->surfmesh.vertexmesh)
+ Mem_Free(model->surfmesh.vertexmesh);
+ model->surfmesh.vertexmesh = NULL;
+ if (model->surfmesh.vertex3fbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vertex3fbuffer);
+ model->surfmesh.vertex3fbuffer = NULL;
+ if (model->surfmesh.vertexmeshbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vertexmeshbuffer);
+ model->surfmesh.vertexmeshbuffer = NULL;
+ if (model->surfmesh.data_element3i_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3i_indexbuffer);
+ model->surfmesh.data_element3i_indexbuffer = NULL;
+ if (model->surfmesh.data_element3s_indexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.data_element3s_indexbuffer);
+ model->surfmesh.data_element3s_indexbuffer = NULL;
+ if (model->surfmesh.vbo_vertexbuffer)
+ R_Mesh_DestroyMeshBuffer(model->surfmesh.vbo_vertexbuffer);
+ model->surfmesh.vbo_vertexbuffer = 0;
// convert all triangles to unique vertex data
outvertexindex = 0;
model->surfmesh.data_tvector3f[outvertexindex*3+2] = oldsurfmesh.data_tvector3f[vertexindex*3+2];
model->surfmesh.data_texcoordtexture2f[outvertexindex*2+0] = oldsurfmesh.data_texcoordtexture2f[vertexindex*2+0];
model->surfmesh.data_texcoordtexture2f[outvertexindex*2+1] = oldsurfmesh.data_texcoordtexture2f[vertexindex*2+1];
- model->surfmesh.data_texcoordlightmap2f[outvertexindex*2+0] = oldsurfmesh.data_texcoordlightmap2f[vertexindex*2+0];
- model->surfmesh.data_texcoordlightmap2f[outvertexindex*2+1] = oldsurfmesh.data_texcoordlightmap2f[vertexindex*2+1];
- model->surfmesh.data_lightmapcolor4f[outvertexindex*4+0] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+0];
- model->surfmesh.data_lightmapcolor4f[outvertexindex*4+1] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+1];
- model->surfmesh.data_lightmapcolor4f[outvertexindex*4+2] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+2];
- model->surfmesh.data_lightmapcolor4f[outvertexindex*4+3] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+3];
+ if (oldsurfmesh.data_texcoordlightmap2f)
+ {
+ model->surfmesh.data_texcoordlightmap2f[outvertexindex*2+0] = oldsurfmesh.data_texcoordlightmap2f[vertexindex*2+0];
+ model->surfmesh.data_texcoordlightmap2f[outvertexindex*2+1] = oldsurfmesh.data_texcoordlightmap2f[vertexindex*2+1];
+ }
+ if (oldsurfmesh.data_lightmapcolor4f)
+ {
+ model->surfmesh.data_lightmapcolor4f[outvertexindex*4+0] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+0];
+ model->surfmesh.data_lightmapcolor4f[outvertexindex*4+1] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+1];
+ model->surfmesh.data_lightmapcolor4f[outvertexindex*4+2] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+2];
+ model->surfmesh.data_lightmapcolor4f[outvertexindex*4+3] = oldsurfmesh.data_lightmapcolor4f[vertexindex*4+3];
+ }
+ else
+ Vector4Set(model->surfmesh.data_lightmapcolor4f + 4*outvertexindex, 1, 1, 1, 1);
model->surfmesh.data_element3i[surface->num_firsttriangle*3+i] = outvertexindex;
outvertexindex++;
}
const int *e;
lightmaptriangle_t *triangle;
// generate lightmap triangle structs
- mod_generatelightmaps_lightmaptriangles = Mem_Alloc(model->mempool, model->surfmesh.num_triangles * sizeof(lightmaptriangle_t));
+ mod_generatelightmaps_lightmaptriangles = (lightmaptriangle_t *)Mem_Alloc(model->mempool, model->surfmesh.num_triangles * sizeof(lightmaptriangle_t));
for (surfaceindex = 0;surfaceindex < model->num_surfaces;surfaceindex++)
{
surface = model->data_surfaces + surfaceindex;
float lm_basescalepixels;
int lm_borderpixels;
int lm_texturesize;
- int lm_maxpixels;
+ //int lm_maxpixels;
const int *e;
lightmaptriangle_t *triangle;
unsigned char *lightmappixels;
lm_basescalepixels = 1.0f / max(0.0001f, mod_generatelightmaps_unitspersample.value);
lm_borderpixels = mod_generatelightmaps_borderpixels.integer;
lm_texturesize = bound(lm_borderpixels*2+1, 64, (int)vid.maxtexturesize_2d);
- lm_maxpixels = lm_texturesize-(lm_borderpixels*2+1);
+ //lm_maxpixels = lm_texturesize-(lm_borderpixels*2+1);
Mod_AllocLightmap_Init(&lmstate, lm_texturesize, lm_texturesize);
lightmapnumber = 0;
for (surfaceindex = 0;surfaceindex < model->num_surfaces;surfaceindex++)
lightmapnumber++;
Mod_AllocLightmap_Free(&lmstate);
- // now together lightmap textures
+ // now put triangles together into lightmap textures, and do not allow
+ // triangles of a surface to go into different textures (as that would
+ // require rewriting the surface list)
model->brushq3.deluxemapping_modelspace = true;
model->brushq3.deluxemapping = true;
model->brushq3.num_mergedlightmaps = lightmapnumber;
- model->brushq3.data_lightmaps = Mem_Alloc(model->mempool, model->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
- model->brushq3.data_deluxemaps = Mem_Alloc(model->mempool, model->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
- lightmappixels = Mem_Alloc(tempmempool, model->brushq3.num_mergedlightmaps * lm_texturesize * lm_texturesize * 4);
- deluxemappixels = Mem_Alloc(tempmempool, model->brushq3.num_mergedlightmaps * lm_texturesize * lm_texturesize * 4);
+ model->brushq3.data_lightmaps = (rtexture_t **)Mem_Alloc(model->mempool, model->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
+ model->brushq3.data_deluxemaps = (rtexture_t **)Mem_Alloc(model->mempool, model->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
+ lightmappixels = (unsigned char *)Mem_Alloc(tempmempool, model->brushq3.num_mergedlightmaps * lm_texturesize * lm_texturesize * 4);
+ deluxemappixels = (unsigned char *)Mem_Alloc(tempmempool, model->brushq3.num_mergedlightmaps * lm_texturesize * lm_texturesize * 4);
for (surfaceindex = 0;surfaceindex < model->num_surfaces;surfaceindex++)
{
surface = model->data_surfaces + surfaceindex;
for (lightmapindex = 0;lightmapindex < model->brushq3.num_mergedlightmaps;lightmapindex++)
{
- model->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("lightmap%i", lightmapindex), lm_texturesize, lm_texturesize, lightmappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, NULL);
- model->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("deluxemap%i", lightmapindex), lm_texturesize, lm_texturesize, deluxemappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, NULL);
+ model->brushq3.data_lightmaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("lightmap%i", lightmapindex), lm_texturesize, lm_texturesize, lightmappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
+ model->brushq3.data_deluxemaps[lightmapindex] = R_LoadTexture2D(model->texturepool, va("deluxemap%i", lightmapindex), lm_texturesize, lm_texturesize, deluxemappixels + lightmapindex * lm_texturesize * lm_texturesize * 4, TEXTYPE_BGRA, TEXF_FORCELINEAR, -1, NULL);
}
if (lightmappixels)
lightmapindex = mod_generatelightmaps_lightmaptriangles[surface->num_firsttriangle].lightmapindex;
surface->lightmaptexture = model->brushq3.data_lightmaps[lightmapindex];
surface->deluxemaptexture = model->brushq3.data_deluxemaps[lightmapindex];
+ surface->lightmapinfo = NULL;
+ }
+
+ model->brush.LightPoint = Mod_GenerateLightmaps_LightPoint;
+ model->brushq1.lightdata = NULL;
+ model->brushq1.lightmapupdateflags = NULL;
+ model->brushq1.firstrender = false;
+ model->brushq1.num_lightstyles = 0;
+ model->brushq1.data_lightstyleinfo = NULL;
+ for (i = 0;i < model->brush.numsubmodels;i++)
+ {
+ model->brush.submodels[i]->brushq1.lightmapupdateflags = NULL;
+ model->brush.submodels[i]->brushq1.firstrender = false;
+ model->brush.submodels[i]->brushq1.num_lightstyles = 0;
+ model->brush.submodels[i]->brushq1.data_lightstyleinfo = NULL;
}
}