cvar_t r_subdivisions_collision_maxvertices = {0, "r_subdivisions_collision_maxvertices", "4225", "maximum vertices allowed per subdivided curve"};
cvar_t mod_q3bsp_curves_collisions = {0, "mod_q3bsp_curves_collisions", "1", "enables collisions with curves (SLOW)"};
cvar_t mod_q3bsp_curves_collisions_stride = {0, "mod_q3bsp_curves_collisions_stride", "32", "collisions against curves: optimize performance by doing a combined collision check for this triangle amount first"};
+cvar_t mod_q3bsp_curves_stride = {0, "mod_q3bsp_curves_stride", "32", "particle effect collisions against curves: optimize performance by doing a combined collision check for this triangle amount first"};
cvar_t mod_q3bsp_optimizedtraceline = {0, "mod_q3bsp_optimizedtraceline", "1", "whether to use optimized traceline code for line traces (as opposed to tracebox code)"};
cvar_t mod_q3bsp_debugtracebrush = {0, "mod_q3bsp_debugtracebrush", "0", "selects different tracebrush bsp recursion algorithms (for debugging purposes only)"};
cvar_t mod_q3bsp_lightmapmergepower = {CVAR_SAVE, "mod_q3bsp_lightmapmergepower", "4", "merges the quake3 128x128 lightmap textures into larger lightmap group textures to speed up rendering, 1 = 256x256, 2 = 512x512, 3 = 1024x1024, 4 = 2048x2048, 5 = 4096x4096, ..."};
Cvar_RegisterVariable(&r_subdivisions_collision_maxvertices);
Cvar_RegisterVariable(&mod_q3bsp_curves_collisions);
Cvar_RegisterVariable(&mod_q3bsp_curves_collisions_stride);
+ Cvar_RegisterVariable(&mod_q3bsp_curves_stride);
Cvar_RegisterVariable(&mod_q3bsp_optimizedtraceline);
Cvar_RegisterVariable(&mod_q3bsp_debugtracebrush);
Cvar_RegisterVariable(&mod_q3bsp_lightmapmergepower);
}
}
+static void Mod_Q3BSP_BuildBBoxes(const int *element3i, int num_triangles, const float *vertex3f, float **collisionbbox6f, int *collisionstride, int stride)
+{
+ int j, k, cnt, tri;
+ float *mins, *maxs;
+ const float *vert;
+ if(stride > 0)
+ {
+ *collisionstride = stride;
+ cnt = (num_triangles + stride - 1) / stride;
+ *collisionbbox6f = (float *) Mem_Alloc(loadmodel->mempool, sizeof(float[6]) * cnt);
+ for(j = 0; j < cnt; ++j)
+ {
+ mins = &((*collisionbbox6f)[6 * j + 0]);
+ maxs = &((*collisionbbox6f)[6 * j + 3]);
+ for(k = 0; k < stride; ++k)
+ {
+ tri = j * stride;
+ if(tri >= num_triangles)
+ break;
+ vert = &(vertex3f[element3i[3 * tri + 0] * 3]);
+ if(!k || vert[0] < mins[0]) mins[0] = vert[0];
+ if(!k || vert[1] < mins[1]) mins[1] = vert[1];
+ if(!k || vert[2] < mins[2]) mins[2] = vert[2];
+ if(!k || vert[0] > maxs[0]) maxs[0] = vert[0];
+ if(!k || vert[1] > maxs[1]) maxs[1] = vert[1];
+ if(!k || vert[2] > maxs[2]) maxs[2] = vert[2];
+ vert = &(vertex3f[element3i[3 * tri + 1] * 3]);
+ if(vert[0] < mins[0]) mins[0] = vert[0];
+ if(vert[1] < mins[1]) mins[1] = vert[1];
+ if(vert[2] < mins[2]) mins[2] = vert[2];
+ if(vert[0] > maxs[0]) maxs[0] = vert[0];
+ if(vert[1] > maxs[1]) maxs[1] = vert[1];
+ if(vert[2] > maxs[2]) maxs[2] = vert[2];
+ vert = &(vertex3f[element3i[3 * tri + 2] * 3]);
+ if(vert[0] < mins[0]) mins[0] = vert[0];
+ if(vert[1] < mins[1]) mins[1] = vert[1];
+ if(vert[2] < mins[2]) mins[2] = vert[2];
+ if(vert[0] > maxs[0]) maxs[0] = vert[0];
+ if(vert[1] > maxs[1]) maxs[1] = vert[1];
+ if(vert[2] > maxs[2]) maxs[2] = vert[2];
+ }
+ }
+ }
+ else
+ {
+ *collisionstride = 0;
+ *collisionbbox6f = NULL;
+ }
+}
+
typedef struct patchtess_s
{
patchinfo_t info;
Q3PatchTesselateFloat(4, sizeof(float[4]), (loadmodel->surfmesh.data_lightmapcolor4f + 4 * out->num_firstvertex), patchsize[0], patchsize[1], sizeof(float[4]), originalcolor4f, xtess, ytess);
Q3PatchTriangleElements((loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), finalwidth, finalheight, out->num_firstvertex);
- out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, (loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), (loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), loadmodel->surfmesh.data_vertex3f);
+ out->num_triangles = Mod_RemoveDegenerateTriangles(out->num_triangles, (loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), (loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle), loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex);
if (developer.integer >= 100)
{
out->num_collisiontriangles = Mod_RemoveDegenerateTriangles(out->num_collisiontriangles, out->data_collisionelement3i, out->data_collisionelement3i, out->data_collisionvertex3f);
// now optimize the collision mesh by finding triangle bboxes...
- if(mod_q3bsp_curves_collisions_stride.integer > 0)
- {
- int k, cnt, tri;
- float *mins, *maxs, *vert;
- out->num_collisionstride = mod_q3bsp_curves_collisions_stride.integer;
- cnt = (out->num_collisiontriangles + out->num_collisionstride - 1) / out->num_collisionstride;
- out->data_collisionbbox6f = (float *) Mem_Alloc(loadmodel->mempool, sizeof(float[6]) * cnt);
- for(j = 0; j < cnt; ++j)
- {
- mins = &(out->data_collisionbbox6f[6 * j + 0]);
- maxs = &(out->data_collisionbbox6f[6 * j + 3]);
- for(k = 0; k < out->num_collisionstride; ++k)
- {
- tri = j * out->num_collisionstride + k;
- if(tri >= out->num_collisiontriangles)
- break;
- vert = &(out->data_collisionvertex3f[out->data_collisionelement3i[3 * tri + 0] * 3]);
- if(!k || vert[0] < mins[0]) mins[0] = vert[0];
- if(!k || vert[1] < mins[1]) mins[1] = vert[1];
- if(!k || vert[2] < mins[2]) mins[2] = vert[2];
- if(!k || vert[0] > maxs[0]) maxs[0] = vert[0];
- if(!k || vert[1] > maxs[1]) maxs[1] = vert[1];
- if(!k || vert[2] > maxs[2]) maxs[2] = vert[2];
- vert = &(out->data_collisionvertex3f[out->data_collisionelement3i[3 * tri + 1] * 3]);
- if(vert[0] < mins[0]) mins[0] = vert[0];
- if(vert[1] < mins[1]) mins[1] = vert[1];
- if(vert[2] < mins[2]) mins[2] = vert[2];
- if(vert[0] > maxs[0]) maxs[0] = vert[0];
- if(vert[1] > maxs[1]) maxs[1] = vert[1];
- if(vert[2] > maxs[2]) maxs[2] = vert[2];
- vert = &(out->data_collisionvertex3f[out->data_collisionelement3i[3 * tri + 2] * 3]);
- if(vert[0] < mins[0]) mins[0] = vert[0];
- if(vert[1] < mins[1]) mins[1] = vert[1];
- if(vert[2] < mins[2]) mins[2] = vert[2];
- if(vert[0] > maxs[0]) maxs[0] = vert[0];
- if(vert[1] > maxs[1]) maxs[1] = vert[1];
- if(vert[2] > maxs[2]) maxs[2] = vert[2];
- }
- }
- }
- else
- {
- out->num_collisionstride = 0;
- }
+ Mod_Q3BSP_BuildBBoxes(out->data_collisionelement3i, out->num_collisiontriangles, out->data_collisionvertex3f, &out->data_collisionbbox6f, &out->num_collisionbboxstride, mod_q3bsp_curves_collisions_stride.integer);
+ Mod_Q3BSP_BuildBBoxes(loadmodel->surfmesh.data_element3i + 3 * out->num_firsttriangle, out->num_triangles, loadmodel->surfmesh.data_vertex3f + 3 * out->num_firstvertex, &out->data_bbox6f, &out->num_bboxstride, mod_q3bsp_curves_stride.integer);
if (developer.integer >= 100)
Con_Printf("Mod_Q3BSP_LoadFaces: %ix%i curve became %i:%i vertices / %i:%i triangles (%i:%i degenerate)\n", patchsize[0], patchsize[1], out->num_vertices, out->num_collisionvertices, oldnumtriangles, oldnumtriangles2, oldnumtriangles - out->num_triangles, oldnumtriangles2 - out->num_collisiontriangles);
if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
{
surface->collisionmarkframe = markframe;
- Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceLineTriangleMeshFloat(trace, linestart, lineend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
}
}
}
if (surface->num_collisiontriangles && surface->collisionmarkframe != markframe && BoxesOverlap(nodesegmentmins, nodesegmentmaxs, surface->mins, surface->maxs))
{
surface->collisionmarkframe = markframe;
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
}
}
}
if (mod_q3bsp_curves_collisions.integer)
for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
if (surface->num_collisiontriangles)
- Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
}
else
Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, shiftstart, shiftend, 0, 1, shiftstart, shiftend, ++markframe, segmentmins, segmentmaxs);
if (mod_q3bsp_curves_collisions.integer)
for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
if (surface->num_collisiontriangles)
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, surface->num_collisionbboxstride, surface->data_collisionbbox6f, surface->texture->supercontents, surface->texture->surfaceflags, surface->texture, segmentmins, segmentmaxs);
}
else
Mod_Q3BSP_TraceBrush_RecursiveBSPNode(trace, model, model->brush.data_nodes, thisbrush_start, thisbrush_end, ++markframe, segmentmins, segmentmaxs);