From 22ab5b495c2c169dc7755003294e5431ad300265 Mon Sep 17 00:00:00 2001 From: havoc Date: Thu, 4 Mar 2004 07:06:00 +0000 Subject: [PATCH] separate collision curve geometry from rendering, this means lower detail collision curves for more performance git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3965 d7cf8633-e32d-0410-b094-e92efae38249 --- gl_rsurf.c | 14 ++++++++++ model_brush.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++---- model_shared.h | 5 ++++ 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/gl_rsurf.c b/gl_rsurf.c index 597206d2..3fd699d2 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -2037,6 +2037,17 @@ void R_DrawCollisionBrush(colbrushf_t *brush) R_Mesh_Draw(brush->numpoints, brush->numtriangles, brush->elements); } +void R_Q3BSP_DrawCollisionFace(entity_render_t *ent, q3mface_t *face) +{ + int i; + if (!face->num_collisiontriangles) + return; + i = ((int)face) / sizeof(q3mface_t); + GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f); + GL_VertexPointer(face->data_collisionvertex3f); + R_Mesh_Draw(face->num_collisionvertices, face->num_collisiontriangles, face->data_collisionelement3i); +} + void R_Q3BSP_DrawSkyFace(entity_render_t *ent, q3mface_t *face) { rmeshstate_t m; @@ -2504,6 +2515,9 @@ void R_Q3BSP_Draw(entity_render_t *ent) for (i = 0;i < model->brushq3.data_thismodel->numbrushes;i++) if (model->brushq3.data_thismodel->firstbrush[i].colbrushf && model->brushq3.data_thismodel->firstbrush[i].colbrushf->numtriangles) R_DrawCollisionBrush(model->brushq3.data_thismodel->firstbrush[i].colbrushf); + for (i = 0, face = model->brushq3.data_thismodel->firstface;i < model->brushq3.data_thismodel->numfaces;i++, face++) + if (face->num_collisiontriangles) + R_Q3BSP_DrawCollisionFace(ent, face); qglPolygonOffset(0, 0); } } diff --git a/model_brush.c b/model_brush.c index 1d872047..157e4a43 100644 --- a/model_brush.c +++ b/model_brush.c @@ -36,8 +36,12 @@ cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"}; cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"}; cvar_t r_subdivisions_tolerance = {0, "r_subdivisions_tolerance", "4"}; cvar_t r_subdivisions_minlevel = {0, "r_subdivisions_minlevel", "0"}; -cvar_t r_subdivisions_maxlevel = {0, "r_subdivisions_maxlevel", "4"}; +cvar_t r_subdivisions_maxlevel = {0, "r_subdivisions_maxlevel", "10"}; cvar_t r_subdivisions_maxvertices = {0, "r_subdivisions_maxvertices", "65536"}; +cvar_t r_subdivisions_collision_tolerance = {0, "r_subdivisions_collision_tolerance", "15"}; +cvar_t r_subdivisions_collision_minlevel = {0, "r_subdivisions_collision_minlevel", "0"}; +cvar_t r_subdivisions_collision_maxlevel = {0, "r_subdivisions_collision_maxlevel", "10"}; +cvar_t r_subdivisions_collision_maxvertices = {0, "r_subdivisions_collision_maxvertices", "4225"}; cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1"}; cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "1"}; cvar_t mod_q3bsp_debugtracebrush = {0, "mod_q3bsp_debugtracebrush", "0"}; @@ -55,6 +59,10 @@ void Mod_BrushInit(void) Cvar_RegisterVariable(&r_subdivisions_minlevel); Cvar_RegisterVariable(&r_subdivisions_maxlevel); Cvar_RegisterVariable(&r_subdivisions_maxvertices); + Cvar_RegisterVariable(&r_subdivisions_collision_tolerance); + Cvar_RegisterVariable(&r_subdivisions_collision_minlevel); + Cvar_RegisterVariable(&r_subdivisions_collision_maxlevel); + Cvar_RegisterVariable(&r_subdivisions_collision_maxvertices); Cvar_RegisterVariable(&mod_q3bsp_curves_collisions); Cvar_RegisterVariable(&mod_q3bsp_optimizedtraceline); Cvar_RegisterVariable(&mod_q3bsp_debugtracebrush); @@ -4173,7 +4181,59 @@ static void Mod_Q3BSP_LoadFaces(lump_t *l) Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_vertices, out->num_triangles); } // q3map does not put in collision brushes for curves... ugh + // build the lower quality collision geometry out->collisions = true; + xlevel = QuadraticSplinePatchSubdivisionLevelOnX(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10); + ylevel = QuadraticSplinePatchSubdivisionLevelOnY(patchsize[0], patchsize[1], 3, originalvertex3f, r_subdivisions_collision_tolerance.value, 10); + // bound to user settings + xlevel = bound(r_subdivisions_collision_minlevel.integer, xlevel, r_subdivisions_collision_maxlevel.integer); + ylevel = bound(r_subdivisions_collision_minlevel.integer, ylevel, r_subdivisions_collision_maxlevel.integer); + // bound to sanity settings + xlevel = bound(0, xlevel, 10); + ylevel = bound(0, ylevel, 10); + // bound to user limit on vertices + while ((xlevel > 0 || ylevel > 0) && (((patchsize[0] - 1) << xlevel) + 1) * (((patchsize[1] - 1) << ylevel) + 1) > min(r_subdivisions_collision_maxvertices.integer, 262144)) + { + if (xlevel > ylevel) + xlevel--; + else + ylevel--; + } + finalwidth = ((patchsize[0] - 1) << xlevel) + 1; + finalheight = ((patchsize[1] - 1) << ylevel) + 1; + finalvertices = finalwidth * finalheight; + finaltriangles = (finalwidth - 1) * (finalheight - 1) * 2; + out->data_collisionvertex3f = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * finalvertices); + out->data_collisionelement3i = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * finaltriangles); + out->num_collisionvertices = finalvertices; + out->num_collisiontriangles = finaltriangles; + QuadraticSplinePatchSubdivideFloatBuffer(patchsize[0], patchsize[1], xlevel, ylevel, 3, originalvertex3f, out->data_collisionvertex3f); + // generate elements + e = out->data_collisionelement3i; + for (y = 0;y < finalheight - 1;y++) + { + row0 = (y + 0) * finalwidth; + row1 = (y + 1) * finalwidth; + for (x = 0;x < finalwidth - 1;x++) + { + *e++ = row0; + *e++ = row1; + *e++ = row0 + 1; + *e++ = row1; + *e++ = row1 + 1; + *e++ = row0 + 1; + row0++; + row1++; + } + } + out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f); + if (developer.integer) + { + if (out->num_collisiontriangles < finaltriangles) + Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided for collisions to %i vertices / %i triangles, %i degenerate triangles removed (leaving %i)\n", patchsize[0], patchsize[1], out->num_collisionvertices, finaltriangles, finaltriangles - out->num_collisiontriangles, out->num_collisiontriangles); + else + Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve subdivided for collisions to %i vertices / %i triangles\n", patchsize[0], patchsize[1], out->num_collisionvertices, out->num_collisiontriangles); + } break; case Q3FACETYPE_FLARE: Con_DPrintf("Mod_Q3BSP_LoadFaces: face #%i (texture \"%s\"): Q3FACETYPE_FLARE not supported (yet)\n", i, out->texture->name); @@ -4762,7 +4822,7 @@ static void Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace_t *trace, q3mnode_t *node if (face->collisions && face->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs)) { face->collisionmarkframe = markframe; - Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs); if (startfrac > trace->realfraction) return; } @@ -5142,7 +5202,7 @@ static void Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace_t *trace, q3mnode_t *nod if (face->collisions && face->markframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, face->mins, face->maxs)) { face->markframe = markframe; - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } @@ -5196,7 +5256,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const { face = model->brushq3.data_thismodel->firstface + i; if (face->collisions) - Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceLineTriangleMeshFloat(trace, boxstartmins, boxendmins, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } @@ -5220,7 +5280,7 @@ static void Mod_Q3BSP_TraceBox(model_t *model, int frame, trace_t *trace, const { face = model->brushq3.data_thismodel->firstface + i; if (face->collisions) - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_triangles, face->data_element3i, face->data_vertex3f, face->texture->supercontents, segmentmins, segmentmaxs); + Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, face->num_collisiontriangles, face->data_collisionelement3i, face->data_collisionvertex3f, face->texture->supercontents, segmentmins, segmentmaxs); } } } diff --git a/model_shared.h b/model_shared.h index a8fac65a..9db93214 100644 --- a/model_shared.h +++ b/model_shared.h @@ -448,6 +448,11 @@ typedef struct q3mface_s int *data_element3i; int *data_neighbor3i; + int num_collisionvertices; + int num_collisiontriangles; + float *data_collisionvertex3f; + int *data_collisionelement3i; + // index into model->brush.shadowmesh int num_firstshadowmeshtriangle; -- 2.39.2