From: havoc Date: Fri, 4 May 2018 04:37:14 +0000 (+0000) Subject: Simplify Mod_ShadowMesh_* functions - removed support for every unused feature of... X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=5107695c43a34852b947e3aff2c77ca4315206df;hp=8f47ee7b6e3c66303e5199b42d79dc6d534987cb Simplify Mod_ShadowMesh_* functions - removed support for every unused feature of shadowmeshes (e.g. texcoords, and linked list meshes). Add back Mod_CreateCollisionMesh which was mistakenly removed. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12417 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_rsurf.c b/gl_rsurf.c index b66fafdd..06badd70 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -1306,7 +1306,7 @@ void R_Q1BSP_CompileShadowMap(entity_render_t *ent, vec3_t relativelightorigin, // exceeding the number of triangles in a single mesh) we have to make sure // that we make only a single mesh - so over-estimate the size of the mesh // to match the model. - r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap = Mod_ShadowMesh_Begin(r_main_mempool, model->surfmesh.num_vertices, model->surfmesh.num_triangles, NULL, NULL, NULL, false, true); + r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap = Mod_ShadowMesh_Begin(r_main_mempool, model->surfmesh.num_vertices, model->surfmesh.num_triangles); R_Shadow_PrepareShadowSides(model->surfmesh.num_triangles); for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { @@ -1314,7 +1314,7 @@ void R_Q1BSP_CompileShadowMap(entity_render_t *ent, vec3_t relativelightorigin, sidemasks |= R_Shadow_ChooseSidesFromBox(surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_vertex3f, model->surfmesh.data_element3i, &r_shadow_compilingrtlight->matrix_worldtolight, relativelightorigin, relativelightdirection, r_shadow_compilingrtlight->cullmins, r_shadow_compilingrtlight->cullmaxs, surface->mins, surface->maxs, surface->texture->basematerialflags & MATERIALFLAG_NOSHADOW ? NULL : sidetotals); } R_Shadow_ShadowMapFromList(model->surfmesh.num_vertices, model->surfmesh.num_triangles, model->surfmesh.data_vertex3f, model->surfmesh.data_element3i, numshadowsides, sidetotals, shadowsides, shadowsideslist); - r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap = Mod_ShadowMesh_Finish(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, false, true); + r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap = Mod_ShadowMesh_Finish(r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, true); r_shadow_compilingrtlight->static_shadowmap_receivers &= sidemasks; for(i = 0;i<6;i++) if(!sidetotals[i]) diff --git a/model_shared.c b/model_shared.c index ab44ba1e..05c6fe57 100644 --- a/model_shared.c +++ b/model_shared.c @@ -963,25 +963,11 @@ void Mod_AllocSurfMesh(mempool_t *mempool, int numvertices, int numtriangles, qb } } -shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int expandable) +shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles) { shadowmesh_t *newmesh; - unsigned char *data; - int size; - size = sizeof(shadowmesh_t); - size += maxverts * sizeof(float[3]); - if (light) - size += maxverts * sizeof(float[11]); - size += maxtriangles * sizeof(int[3]); - if (maxverts <= 65536) - size += maxtriangles * sizeof(unsigned short[3]); - if (expandable) - size += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *) + maxverts * sizeof(shadowmeshvertexhash_t); - data = (unsigned char *)Mem_Alloc(mempool, size); - newmesh = (shadowmesh_t *)data;data += sizeof(*newmesh); - newmesh->map_diffuse = map_diffuse; - newmesh->map_specular = map_specular; - newmesh->map_normal = map_normal; + newmesh = (shadowmesh_t *)Mem_Alloc(mempool, sizeof(shadowmesh_t)); + newmesh->mempool = mempool; newmesh->maxverts = maxverts; newmesh->maxtriangles = maxtriangles; newmesh->numverts = 0; @@ -989,152 +975,60 @@ shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtria 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->svector3f = (float *)data;data += maxverts * sizeof(float[3]); - newmesh->tvector3f = (float *)data;data += maxverts * sizeof(float[3]); - newmesh->normal3f = (float *)data;data += maxverts * sizeof(float[3]); - newmesh->texcoord2f = (float *)data;data += maxverts * sizeof(float[2]); - } - newmesh->element3i = (int *)data;data += maxtriangles * sizeof(int[3]); - if (expandable) - { - newmesh->vertexhashtable = (shadowmeshvertexhash_t **)data;data += SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *); - newmesh->vertexhashentries = (shadowmeshvertexhash_t *)data;data += maxverts * sizeof(shadowmeshvertexhash_t); - } - if (maxverts <= 65536) - newmesh->element3s = (unsigned short *)data;data += maxtriangles * sizeof(unsigned short[3]); - return newmesh; -} - -shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh, int light) -{ - shadowmesh_t *newmesh; - newmesh = Mod_ShadowMesh_Alloc(mempool, oldmesh->numverts, oldmesh->numtriangles, oldmesh->map_diffuse, oldmesh->map_specular, oldmesh->map_normal, light, 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) - { - memcpy(newmesh->svector3f, oldmesh->svector3f, oldmesh->numverts * sizeof(float[3])); - memcpy(newmesh->tvector3f, oldmesh->tvector3f, oldmesh->numverts * sizeof(float[3])); - memcpy(newmesh->normal3f, oldmesh->normal3f, oldmesh->numverts * sizeof(float[3])); - memcpy(newmesh->texcoord2f, oldmesh->texcoord2f, oldmesh->numverts * sizeof(float[2])); - } - memcpy(newmesh->element3i, oldmesh->element3i, oldmesh->numtriangles * sizeof(int[3])); + newmesh->vertex3f = (float *)Mem_Alloc(mempool, maxverts * sizeof(float[3])); + newmesh->element3i = (int *)Mem_Alloc(mempool, maxtriangles * sizeof(int[3])); + newmesh->vertexhashtable = (shadowmeshvertexhash_t **)Mem_Alloc(mempool, SHADOWMESHVERTEXHASH * sizeof(shadowmeshvertexhash_t *)); + newmesh->vertexhashentries = (shadowmeshvertexhash_t *)Mem_Alloc(mempool, maxverts * sizeof(shadowmeshvertexhash_t)); return newmesh; } -static int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, float *vertex14f) +int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, const float *vertex3f) { int hashindex, vnum; shadowmeshvertexhash_t *hash; // this uses prime numbers intentionally - hashindex = (unsigned int) (vertex14f[0] * 2003 + vertex14f[1] * 4001 + vertex14f[2] * 7919) % SHADOWMESHVERTEXHASH; + hashindex = (unsigned int) (vertex3f[0] * 2003 + vertex3f[1] * 4001 + vertex3f[2] * 7919) % SHADOWMESHVERTEXHASH; for (hash = mesh->vertexhashtable[hashindex];hash;hash = hash->next) { vnum = (hash - mesh->vertexhashentries); - if ((mesh->vertex3f == NULL || (mesh->vertex3f[vnum * 3 + 0] == vertex14f[0] && mesh->vertex3f[vnum * 3 + 1] == vertex14f[1] && mesh->vertex3f[vnum * 3 + 2] == vertex14f[2])) - && (mesh->svector3f == NULL || (mesh->svector3f[vnum * 3 + 0] == vertex14f[3] && mesh->svector3f[vnum * 3 + 1] == vertex14f[4] && mesh->svector3f[vnum * 3 + 2] == vertex14f[5])) - && (mesh->tvector3f == NULL || (mesh->tvector3f[vnum * 3 + 0] == vertex14f[6] && mesh->tvector3f[vnum * 3 + 1] == vertex14f[7] && mesh->tvector3f[vnum * 3 + 2] == vertex14f[8])) - && (mesh->normal3f == NULL || (mesh->normal3f[vnum * 3 + 0] == vertex14f[9] && mesh->normal3f[vnum * 3 + 1] == vertex14f[10] && mesh->normal3f[vnum * 3 + 2] == vertex14f[11])) - && (mesh->texcoord2f == NULL || (mesh->texcoord2f[vnum * 2 + 0] == vertex14f[12] && mesh->texcoord2f[vnum * 2 + 1] == vertex14f[13]))) + if (mesh->vertex3f[vnum * 3 + 0] == vertex3f[0] && mesh->vertex3f[vnum * 3 + 1] == vertex3f[1] && mesh->vertex3f[vnum * 3 + 2] == vertex3f[2]) return hash - mesh->vertexhashentries; } vnum = mesh->numverts++; hash = mesh->vertexhashentries + vnum; hash->next = mesh->vertexhashtable[hashindex]; mesh->vertexhashtable[hashindex] = hash; - if (mesh->vertex3f) {mesh->vertex3f[vnum * 3 + 0] = vertex14f[0];mesh->vertex3f[vnum * 3 + 1] = vertex14f[1];mesh->vertex3f[vnum * 3 + 2] = vertex14f[2];} - if (mesh->svector3f) {mesh->svector3f[vnum * 3 + 0] = vertex14f[3];mesh->svector3f[vnum * 3 + 1] = vertex14f[4];mesh->svector3f[vnum * 3 + 2] = vertex14f[5];} - if (mesh->tvector3f) {mesh->tvector3f[vnum * 3 + 0] = vertex14f[6];mesh->tvector3f[vnum * 3 + 1] = vertex14f[7];mesh->tvector3f[vnum * 3 + 2] = vertex14f[8];} - if (mesh->normal3f) {mesh->normal3f[vnum * 3 + 0] = vertex14f[9];mesh->normal3f[vnum * 3 + 1] = vertex14f[10];mesh->normal3f[vnum * 3 + 2] = vertex14f[11];} - if (mesh->texcoord2f) {mesh->texcoord2f[vnum * 2 + 0] = vertex14f[12];mesh->texcoord2f[vnum * 2 + 1] = vertex14f[13];} + mesh->vertex3f[vnum * 3 + 0] = vertex3f[0]; + mesh->vertex3f[vnum * 3 + 1] = vertex3f[1]; + mesh->vertex3f[vnum * 3 + 2] = vertex3f[2]; return vnum; } -static void Mod_ShadowMesh_AddTriangle(mempool_t *mempool, shadowmesh_t *mesh, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, float *vertex14f) +void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i) { - if (mesh->numtriangles == 0) - { - // set the properties on this empty mesh to be more favorable... - // (note: this case only occurs for the first triangle added to a new mesh chain) - mesh->map_diffuse = map_diffuse; - mesh->map_specular = map_specular; - mesh->map_normal = map_normal; - } - while (mesh->map_diffuse != map_diffuse || mesh->map_specular != map_specular || mesh->map_normal != map_normal || mesh->numverts + 3 > mesh->maxverts || mesh->numtriangles + 1 > mesh->maxtriangles) - { - if (mesh->next == NULL) - mesh->next = Mod_ShadowMesh_Alloc(mempool, max(mesh->maxverts, 300), max(mesh->maxtriangles, 100), map_diffuse, map_specular, map_normal, mesh->svector3f != NULL, true); - mesh = mesh->next; - } - mesh->element3i[mesh->numtriangles * 3 + 0] = Mod_ShadowMesh_AddVertex(mesh, vertex14f + 14 * 0); - mesh->element3i[mesh->numtriangles * 3 + 1] = Mod_ShadowMesh_AddVertex(mesh, vertex14f + 14 * 1); - mesh->element3i[mesh->numtriangles * 3 + 2] = Mod_ShadowMesh_AddVertex(mesh, vertex14f + 14 * 2); - mesh->numtriangles++; -} + int i; -void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, int numtris, const int *element3i) -{ - int i, j, e; - float vbuf[3*14], *v; - memset(vbuf, 0, sizeof(vbuf)); for (i = 0;i < numtris;i++) { - for (j = 0, v = vbuf;j < 3;j++, v += 14) - { - e = *element3i++; - if (vertex3f) - { - v[0] = vertex3f[e * 3 + 0]; - v[1] = vertex3f[e * 3 + 1]; - v[2] = vertex3f[e * 3 + 2]; - } - if (svector3f) - { - v[3] = svector3f[e * 3 + 0]; - v[4] = svector3f[e * 3 + 1]; - v[5] = svector3f[e * 3 + 2]; - } - if (tvector3f) - { - v[6] = tvector3f[e * 3 + 0]; - v[7] = tvector3f[e * 3 + 1]; - v[8] = tvector3f[e * 3 + 2]; - } - if (normal3f) - { - v[9] = normal3f[e * 3 + 0]; - v[10] = normal3f[e * 3 + 1]; - v[11] = normal3f[e * 3 + 2]; - } - if (texcoord2f) - { - v[12] = texcoord2f[e * 2 + 0]; - v[13] = texcoord2f[e * 2 + 1]; - } - } - Mod_ShadowMesh_AddTriangle(mempool, mesh, map_diffuse, map_specular, map_normal, vbuf); + mesh->element3i[mesh->numtriangles * 3 + 0] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 0]); + mesh->element3i[mesh->numtriangles * 3 + 1] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 1]); + mesh->element3i[mesh->numtriangles * 3 + 2] = Mod_ShadowMesh_AddVertex(mesh, vertex3f + 3 * element3i[i * 3 + 2]); + mesh->numtriangles++; } // the triangle calculation can take a while, so let's do a keepalive here CL_KeepaliveMessage(false); } -shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int expandable) +shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles) { // the preparation before shadow mesh initialization can take a while, so let's do a keepalive here CL_KeepaliveMessage(false); - return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles, map_diffuse, map_specular, map_normal, light, expandable); + return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles); } -static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) +static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh) { if (!mesh->numverts) return; @@ -1142,24 +1036,6 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) // 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) - { - 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 short indices as a buffer if (mesh->element3s && !mesh->element3s_indexbuffer) mesh->element3s_indexbuffer = R_Mesh_CreateMeshBuffer(mesh->element3s, mesh->numtriangles * sizeof(short[3]), "shadowmesh", true, false, false, true); @@ -1173,96 +1049,77 @@ static void Mod_ShadowMesh_CreateVBOs(shadowmesh_t *mesh, mempool_t *mempool) // 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->vbo_vertexbuffer && !vid.useinterleavedarrays) + if (!mesh->vbo_vertexbuffer) { - int size; - unsigned char *mem; - size = 0; - mesh->vbooffset_vertexmesh = size;if (mesh->vertexmesh ) size += mesh->numverts * sizeof(r_vertexmesh_t); - mesh->vbooffset_vertex3f = size;if (mesh->vertex3f ) size += mesh->numverts * sizeof(float[3]); - mesh->vbooffset_svector3f = size;if (mesh->svector3f ) size += mesh->numverts * sizeof(float[3]); - mesh->vbooffset_tvector3f = size;if (mesh->tvector3f ) size += mesh->numverts * sizeof(float[3]); - mesh->vbooffset_normal3f = size;if (mesh->normal3f ) size += mesh->numverts * sizeof(float[3]); - mesh->vbooffset_texcoord2f = size;if (mesh->texcoord2f ) size += mesh->numverts * sizeof(float[2]); - mem = (unsigned char *)Mem_Alloc(tempmempool, size); - if (mesh->vertexmesh ) memcpy(mem + mesh->vbooffset_vertexmesh , mesh->vertexmesh , mesh->numverts * sizeof(r_vertexmesh_t)); - if (mesh->vertex3f ) memcpy(mem + mesh->vbooffset_vertex3f , mesh->vertex3f , mesh->numverts * sizeof(float[3])); - if (mesh->svector3f ) memcpy(mem + mesh->vbooffset_svector3f , mesh->svector3f , mesh->numverts * sizeof(float[3])); - 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_vertexbuffer = R_Mesh_CreateMeshBuffer(mem, size, "shadowmesh", false, false, false, false); - Mem_Free(mem); + mesh->vbooffset_vertex3f = 0; + mesh->vbo_vertexbuffer = R_Mesh_CreateMeshBuffer(mesh->vertex3f, mesh->numverts * sizeof(float[3]), "shadowmesh", false, false, false, false); } } -shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh, qboolean light, qboolean createvbo) +shadowmesh_t *Mod_ShadowMesh_Finish(shadowmesh_t *mesh, qboolean createvbo) { - shadowmesh_t *mesh, *newmesh, *nextmesh; - // reallocate meshs to conserve space - for (mesh = firstmesh, firstmesh = NULL;mesh;mesh = nextmesh) + if (mesh->numverts >= 3 && mesh->numtriangles >= 1) { - nextmesh = mesh->next; - if (mesh->numverts >= 3 && mesh->numtriangles >= 1) + if (mesh->vertexhashentries) + Mem_Free(mesh->vertexhashentries); + mesh->vertexhashentries = NULL; + if (mesh->vertexhashtable) + Mem_Free(mesh->vertexhashtable); + mesh->vertexhashtable = NULL; + if (mesh->maxverts > mesh->numverts) { - newmesh = Mod_ShadowMesh_ReAlloc(mempool, mesh, light); - newmesh->next = firstmesh; - firstmesh = newmesh; - if (newmesh->element3s) - { - int i; - for (i = 0;i < newmesh->numtriangles*3;i++) - newmesh->element3s[i] = newmesh->element3i[i]; - } - if (createvbo) - Mod_ShadowMesh_CreateVBOs(newmesh, mempool); + mesh->vertex3f = (float *)Mem_Realloc(mesh->mempool, mesh->vertex3f, mesh->numverts * sizeof(float[3])); + mesh->maxverts = mesh->numverts; + } + if (mesh->maxtriangles > mesh->numtriangles) + { + mesh->element3i = (int *)Mem_Realloc(mesh->mempool, mesh->element3i, mesh->numtriangles * sizeof(int[3])); + mesh->maxtriangles = mesh->numtriangles; } - Mem_Free(mesh); + if (mesh->numverts <= 65536) + { + int i; + mesh->element3s = (unsigned short *)Mem_Alloc(mesh->mempool, mesh->numtriangles * sizeof(unsigned short[3])); + for (i = 0;i < mesh->numtriangles*3;i++) + mesh->element3s[i] = mesh->element3i[i]; + } + if (createvbo) + Mod_ShadowMesh_CreateVBOs(mesh); } // this can take a while, so let's do a keepalive here CL_KeepaliveMessage(false); - return firstmesh; + return mesh; } -void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius) +void Mod_ShadowMesh_CalcBBox(shadowmesh_t *mesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius) { int i; - shadowmesh_t *mesh; vec3_t nmins, nmaxs, ncenter, temp; float nradius2, dist2, *v; VectorClear(nmins); VectorClear(nmaxs); // calculate bbox - for (mesh = firstmesh;mesh;mesh = mesh->next) + VectorCopy(mesh->vertex3f, nmins); + VectorCopy(mesh->vertex3f, nmaxs); + for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3) { - if (mesh == firstmesh) - { - VectorCopy(mesh->vertex3f, nmins); - VectorCopy(mesh->vertex3f, nmaxs); - } - for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3) - { - if (nmins[0] > v[0]) nmins[0] = v[0];if (nmaxs[0] < v[0]) nmaxs[0] = v[0]; - if (nmins[1] > v[1]) nmins[1] = v[1];if (nmaxs[1] < v[1]) nmaxs[1] = v[1]; - if (nmins[2] > v[2]) nmins[2] = v[2];if (nmaxs[2] < v[2]) nmaxs[2] = v[2]; - } + if (nmins[0] > v[0]) nmins[0] = v[0];if (nmaxs[0] < v[0]) nmaxs[0] = v[0]; + if (nmins[1] > v[1]) nmins[1] = v[1];if (nmaxs[1] < v[1]) nmaxs[1] = v[1]; + if (nmins[2] > v[2]) nmins[2] = v[2];if (nmaxs[2] < v[2]) nmaxs[2] = v[2]; } // calculate center and radius ncenter[0] = (nmins[0] + nmaxs[0]) * 0.5f; ncenter[1] = (nmins[1] + nmaxs[1]) * 0.5f; ncenter[2] = (nmins[2] + nmaxs[2]) * 0.5f; nradius2 = 0; - for (mesh = firstmesh;mesh;mesh = mesh->next) + for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3) { - for (i = 0, v = mesh->vertex3f;i < mesh->numverts;i++, v += 3) - { - VectorSubtract(v, ncenter, temp); - dist2 = DotProduct(temp, temp); - if (nradius2 < dist2) - nradius2 = dist2; - } + VectorSubtract(v, ncenter, temp); + dist2 = DotProduct(temp, temp); + if (nradius2 < dist2) + nradius2 = dist2; } // return data if (mins) @@ -1277,18 +1134,64 @@ void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, void Mod_ShadowMesh_Free(shadowmesh_t *mesh) { - shadowmesh_t *nextmesh; - for (;mesh;mesh = nextmesh) + 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); + if (mesh->vertex3f) + Mem_Free(mesh->vertex3f); + if (mesh->element3i) + Mem_Free(mesh->element3i); + if (mesh->element3s) + Mem_Free(mesh->element3s); + if (mesh->vertexhashentries) + Mem_Free(mesh->vertexhashentries); + if (mesh->vertexhashtable) + Mem_Free(mesh->vertexhashtable); + Mem_Free(mesh); +} + +void Mod_CreateCollisionMesh(dp_model_t *mod) +{ + 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; + // 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 (!strcmp(surface->texture->name, "collision") || !strcmp(surface->texture->name, "collisionconvex")) // 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); + if (usesinglecollisionmesh) + Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); + else { - 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); + for (k = 0;k < mod->nummodelsurfaces;k++) + { + surface = mod->data_surfaces + mod->firstmodelsurface + k; + if (!(surface->texture->supercontents & SUPERCONTENTS_SOLID)) + continue; + Mod_ShadowMesh_AddMesh(mod->brush.collisionmesh, mod->surfmesh.data_vertex3f, surface->num_triangles, (mod->surfmesh.data_element3i + 3 * surface->num_firsttriangle)); + } } + mod->brush.collisionmesh = Mod_ShadowMesh_Finish(mod->brush.collisionmesh, false); } #if 0 diff --git a/model_shared.h b/model_shared.h index 12536075..5977d180 100644 --- a/model_shared.h +++ b/model_shared.h @@ -210,44 +210,29 @@ shadowmeshvertexhash_t; typedef struct shadowmesh_s { - // next mesh in chain - struct shadowmesh_s *next; - // used for light mesh (NULL on shadow mesh) - rtexture_t *map_diffuse; - rtexture_t *map_specular; - rtexture_t *map_normal; - // buffer sizes - int numverts, maxverts; - int numtriangles, maxtriangles; - // used always + mempool_t *mempool; + + int numverts; + int maxverts; float *vertex3f; - // used for light mesh (NULL on shadow mesh) - float *svector3f; - float *tvector3f; - float *normal3f; - float *texcoord2f; - // used always + r_meshbuffer_t *vbo_vertexbuffer; + int vbooffset_vertex3f; + + int numtriangles; + int maxtriangles; int *element3i; r_meshbuffer_t *element3i_indexbuffer; int element3i_bufferoffset; unsigned short *element3s; r_meshbuffer_t *element3s_indexbuffer; int element3s_bufferoffset; - // vertex/index buffers for rendering - // (created by Mod_ShadowMesh_Finish if possible) - r_vertexmesh_t *vertexmesh; // usually NULL + // used for shadow mapping cubemap side partitioning int sideoffsets[6], sidetotals[6]; + // these are NULL after Mod_ShadowMesh_Finish is performed, only used // while building meshes shadowmeshvertexhash_t **vertexhashtable, *vertexhashentries; - r_meshbuffer_t *vbo_vertexbuffer; - int vbooffset_vertex3f; - int vbooffset_svector3f; - int vbooffset_tvector3f; - int vbooffset_normal3f; - int vbooffset_texcoord2f; - int vbooffset_vertexmesh; } shadowmesh_t; @@ -1156,14 +1141,16 @@ void Mod_MakeSortedSurfaces(dp_model_t *mod); // automatically called after model loader returns void Mod_BuildVBOs(void); -shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int expandable); -shadowmesh_t *Mod_ShadowMesh_ReAlloc(mempool_t *mempool, shadowmesh_t *oldmesh, int light); -void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *texcoord2f, int numtris, const int *element3i); -shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int expandable); -shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh, qboolean light, qboolean createvbo); +shadowmesh_t *Mod_ShadowMesh_Alloc(mempool_t *mempool, int maxverts, int maxtriangles); +int Mod_ShadowMesh_AddVertex(shadowmesh_t *mesh, const float *vertex3f); +void Mod_ShadowMesh_AddMesh(shadowmesh_t *mesh, const float *vertex3f, int numtris, const int *element3i); +shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles); +shadowmesh_t *Mod_ShadowMesh_Finish(shadowmesh_t *firstmesh, qboolean createvbo); void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius); void Mod_ShadowMesh_Free(shadowmesh_t *mesh); +void Mod_CreateCollisionMesh(dp_model_t *mod); + void Mod_FreeQ3Shaders(void); void Mod_LoadQ3Shaders(void); q3shaderinfo_t *Mod_LookupQ3Shader(const char *name); diff --git a/r_shadow.c b/r_shadow.c index ac97241c..398659b9 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -1190,8 +1190,8 @@ void R_Shadow_ShadowMapFromList(int numverts, int numtris, const float *vertex3f } } } - - Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements); + + Mod_ShadowMesh_AddMesh(r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, vertex3f, outtriangles, shadowelements); } static void R_Shadow_MakeTextures_MakeCorona(void) @@ -3348,24 +3348,20 @@ static void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight) static void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides) { - shadowmesh_t *mesh; - RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false); if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer) { - CHECKGLERROR - GL_CullFace(GL_NONE); - mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap; - for (;mesh;mesh = mesh->next) + shadowmesh_t *mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap; + if (mesh->sidetotals[r_shadow_shadowmapside]) { - if (!mesh->sidetotals[r_shadow_shadowmapside]) - continue; + CHECKGLERROR + GL_CullFace(GL_NONE); r_refdef.stats[r_stat_lights_shadowtriangles] += mesh->sidetotals[r_shadow_shadowmapside]; R_Mesh_PrepareVertices_Vertex3f(mesh->numverts, mesh->vertex3f, mesh->vbo_vertexbuffer, mesh->vbooffset_vertex3f); R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset); + CHECKGLERROR } - CHECKGLERROR } else if (r_refdef.scene.worldentity->model) r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);