cvar_t r_subdivisions_collision_maxtess = {0, "r_subdivisions_collision_maxtess", "1024", "maximum number of subdivisions (prevents curves beyond a certain detail level, limits smoothing)"};
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", "16", "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", "16", "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_maxtess);
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);
typedef struct findnonsolidlocationinfo_s
{
vec3_t center;
+ vec3_t absmin, absmax;
vec_t radius;
vec3_t nudge;
vec_t bestdist;
}
findnonsolidlocationinfo_t;
-static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *info, mleaf_t *leaf)
+static void Mod_Q1BSP_FindNonSolidLocation_r_Triangle(findnonsolidlocationinfo_t *info, msurface_t *surface, int k)
{
- int i, surfacenum, k, *tri, *mark;
+ int i, *tri;
float dist, f, vert[3][3], edge[3][3], facenormal[3], edgenormal[3][3], point[3];
+
+ tri = (info->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle) + k * 3;
+ VectorCopy((info->model->surfmesh.data_vertex3f + tri[0] * 3), vert[0]);
+ VectorCopy((info->model->surfmesh.data_vertex3f + tri[1] * 3), vert[1]);
+ VectorCopy((info->model->surfmesh.data_vertex3f + tri[2] * 3), vert[2]);
+ VectorSubtract(vert[1], vert[0], edge[0]);
+ VectorSubtract(vert[2], vert[1], edge[1]);
+ CrossProduct(edge[1], edge[0], facenormal);
+ if (facenormal[0] || facenormal[1] || facenormal[2])
+ {
+ VectorNormalize(facenormal);
+ f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
+ if (f <= info->bestdist && f >= -info->bestdist)
+ {
+ VectorSubtract(vert[0], vert[2], edge[2]);
+ VectorNormalize(edge[0]);
+ VectorNormalize(edge[1]);
+ VectorNormalize(edge[2]);
+ CrossProduct(facenormal, edge[0], edgenormal[0]);
+ CrossProduct(facenormal, edge[1], edgenormal[1]);
+ CrossProduct(facenormal, edge[2], edgenormal[2]);
+ // face distance
+ if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0])
+ && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1])
+ && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2]))
+ {
+ // we got lucky, the center is within the face
+ dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
+ if (dist < 0)
+ {
+ dist = -dist;
+ if (info->bestdist > dist)
+ {
+ info->bestdist = dist;
+ VectorScale(facenormal, (info->radius - -dist), info->nudge);
+ }
+ }
+ else
+ {
+ if (info->bestdist > dist)
+ {
+ info->bestdist = dist;
+ VectorScale(facenormal, (info->radius - dist), info->nudge);
+ }
+ }
+ }
+ else
+ {
+ // check which edge or vertex the center is nearest
+ for (i = 0;i < 3;i++)
+ {
+ f = DotProduct(info->center, edge[i]);
+ if (f >= DotProduct(vert[0], edge[i])
+ && f <= DotProduct(vert[1], edge[i]))
+ {
+ // on edge
+ VectorMA(info->center, -f, edge[i], point);
+ dist = sqrt(DotProduct(point, point));
+ if (info->bestdist > dist)
+ {
+ info->bestdist = dist;
+ VectorScale(point, (info->radius / dist), info->nudge);
+ }
+ // skip both vertex checks
+ // (both are further away than this edge)
+ i++;
+ }
+ else
+ {
+ // not on edge, check first vertex of edge
+ VectorSubtract(info->center, vert[i], point);
+ dist = sqrt(DotProduct(point, point));
+ if (info->bestdist > dist)
+ {
+ info->bestdist = dist;
+ VectorScale(point, (info->radius / dist), info->nudge);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void Mod_Q1BSP_FindNonSolidLocation_r_Leaf(findnonsolidlocationinfo_t *info, mleaf_t *leaf)
+{
+ int surfacenum, k, *mark;
msurface_t *surface;
for (surfacenum = 0, mark = leaf->firstleafsurface;surfacenum < leaf->numleafsurfaces;surfacenum++, mark++)
{
surface = info->model->data_surfaces + *mark;
if (surface->texture->supercontents & SUPERCONTENTS_SOLID)
{
- for (k = 0;k < surface->num_triangles;k++)
+ if(surface->num_bboxstride)
{
- tri = (info->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle) + k * 3;
- VectorCopy((info->model->surfmesh.data_vertex3f + tri[0] * 3), vert[0]);
- VectorCopy((info->model->surfmesh.data_vertex3f + tri[1] * 3), vert[1]);
- VectorCopy((info->model->surfmesh.data_vertex3f + tri[2] * 3), vert[2]);
- VectorSubtract(vert[1], vert[0], edge[0]);
- VectorSubtract(vert[2], vert[1], edge[1]);
- CrossProduct(edge[1], edge[0], facenormal);
- if (facenormal[0] || facenormal[1] || facenormal[2])
+ int i, cnt, tri;
+ cnt = (surface->num_triangles + surface->num_bboxstride - 1) / surface->num_bboxstride;
+ for(i = 0; i < cnt; ++i)
{
- VectorNormalize(facenormal);
- f = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
- if (f <= info->bestdist && f >= -info->bestdist)
+ if(BoxesOverlap(surface->data_bbox6f + i * 6, surface->data_bbox6f + i * 6 + 3, info->absmin, info->absmax))
{
- VectorSubtract(vert[0], vert[2], edge[2]);
- VectorNormalize(edge[0]);
- VectorNormalize(edge[1]);
- VectorNormalize(edge[2]);
- CrossProduct(facenormal, edge[0], edgenormal[0]);
- CrossProduct(facenormal, edge[1], edgenormal[1]);
- CrossProduct(facenormal, edge[2], edgenormal[2]);
- // face distance
- if (DotProduct(info->center, edgenormal[0]) < DotProduct(vert[0], edgenormal[0])
- && DotProduct(info->center, edgenormal[1]) < DotProduct(vert[1], edgenormal[1])
- && DotProduct(info->center, edgenormal[2]) < DotProduct(vert[2], edgenormal[2]))
+ for(k = 0; k < surface->num_bboxstride; ++k)
{
- // we got lucky, the center is within the face
- dist = DotProduct(info->center, facenormal) - DotProduct(vert[0], facenormal);
- if (dist < 0)
- {
- dist = -dist;
- if (info->bestdist > dist)
- {
- info->bestdist = dist;
- VectorScale(facenormal, (info->radius - -dist), info->nudge);
- }
- }
- else
- {
- if (info->bestdist > dist)
- {
- info->bestdist = dist;
- VectorScale(facenormal, (info->radius - dist), info->nudge);
- }
- }
- }
- else
- {
- // check which edge or vertex the center is nearest
- for (i = 0;i < 3;i++)
- {
- f = DotProduct(info->center, edge[i]);
- if (f >= DotProduct(vert[0], edge[i])
- && f <= DotProduct(vert[1], edge[i]))
- {
- // on edge
- VectorMA(info->center, -f, edge[i], point);
- dist = sqrt(DotProduct(point, point));
- if (info->bestdist > dist)
- {
- info->bestdist = dist;
- VectorScale(point, (info->radius / dist), info->nudge);
- }
- // skip both vertex checks
- // (both are further away than this edge)
- i++;
- }
- else
- {
- // not on edge, check first vertex of edge
- VectorSubtract(info->center, vert[i], point);
- dist = sqrt(DotProduct(point, point));
- if (info->bestdist > dist)
- {
- info->bestdist = dist;
- VectorScale(point, (info->radius / dist), info->nudge);
- }
- }
- }
+ tri = i * surface->num_bboxstride + k;
+ if(tri >= surface->num_triangles)
+ break;
+ Mod_Q1BSP_FindNonSolidLocation_r_Triangle(info, surface, tri);
}
}
}
}
+ else
+ {
+ for (k = 0;k < surface->num_triangles;k++)
+ {
+ Mod_Q1BSP_FindNonSolidLocation_r_Triangle(info, surface, k);
+ }
+ }
}
}
}
{
VectorClear(info.nudge);
info.bestdist = radius;
+ VectorCopy(info.center, info.absmin);
+ VectorCopy(info.center, info.absmax);
+ info.absmin[0] -= info.radius + 1;
+ info.absmin[1] -= info.radius + 1;
+ info.absmin[2] -= info.radius + 1;
+ info.absmax[0] += info.radius + 1;
+ info.absmax[1] += info.radius + 1;
+ info.absmax[2] += info.radius + 1;
Mod_Q1BSP_FindNonSolidLocation_r(&info, model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode);
VectorAdd(info.center, info.nudge, info.center);
}
out->firstleafsurface = loadmodel->brush.data_leafsurfaces + (unsigned short)LittleShort(in->firstmarksurface);
out->numleafsurfaces = (unsigned short)LittleShort(in->nummarksurfaces);
- if (out->firstleafsurface < 0 || (unsigned short)LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
+ if ((unsigned short)LittleShort(in->firstmarksurface) + out->numleafsurfaces > loadmodel->brush.num_leafsurfaces)
{
Con_Printf("Mod_Q1BSP_LoadLeafs: invalid leafsurface range %i:%i outside range %i:%i\n", (int)(out->firstleafsurface - loadmodel->brush.data_leafsurfaces), (int)(out->firstleafsurface + out->numleafsurfaces - loadmodel->brush.data_leafsurfaces), 0, loadmodel->brush.num_leafsurfaces);
out->firstleafsurface = NULL;
Con_DPrintf("%s is %sdeluxemapped\n", loadmodel->name, loadmodel->brushq3.deluxemapping ? "" : "not ");
// figure out what the most reasonable merge power is within limits
+
loadmodel->brushq3.num_lightmapmergepower = 0;
- for (power = 1;power <= mod_q3bsp_lightmapmergepower.integer && (128 << power) <= gl_max_texture_size && (1 << (power * 2)) < 4 * (count >> loadmodel->brushq3.deluxemapping);power++)
- loadmodel->brushq3.num_lightmapmergepower = power;
- // as the lightmap size may actually be another power of 2, adjust for this
- // (and interpret it as the power for 128x128 lightmaps above)
for(i = 0; (128 << i) < size; ++i)
- loadmodel->brushq3.num_lightmapmergepower -= 1;
- if(loadmodel->brushq3.num_lightmapmergepower < 0)
- loadmodel->brushq3.num_lightmapmergepower = 0;
+ ;
+ // i is now 0 for 128, 1 for 256, etc
+
+ for (power = 1;power + i <= mod_q3bsp_lightmapmergepower.integer && (size << power) <= gl_max_texture_size && (1 << (power * 2)) < 4 * (count >> (loadmodel->brushq3.deluxemapping ? 1 : 0)); power++)
+ loadmodel->brushq3.num_lightmapmergepower = power;
loadmodel->brushq3.num_lightmapmerge = 1 << loadmodel->brushq3.num_lightmapmergepower;
- loadmodel->brushq3.num_mergedlightmaps = ((count >> loadmodel->brushq3.deluxemapping) + (1 << (loadmodel->brushq3.num_lightmapmergepower * 2)) - 1) >> (loadmodel->brushq3.num_lightmapmergepower * 2);
+ loadmodel->brushq3.num_mergedlightmaps = ((count >> (loadmodel->brushq3.deluxemapping ? 1 : 0)) + (1 << (loadmodel->brushq3.num_lightmapmergepower * 2)) - 1) >> (loadmodel->brushq3.num_lightmapmergepower * 2);
loadmodel->brushq3.data_lightmaps = (rtexture_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
if (loadmodel->brushq3.deluxemapping)
loadmodel->brushq3.data_deluxemaps = (rtexture_t **)Mem_Alloc(loadmodel->mempool, loadmodel->brushq3.num_mergedlightmaps * sizeof(rtexture_t *));
// all be full size except the last one which may be smaller
// because it only needs to the remaining blocks, and it will often
// be odd sizes like 2048x512 due to only being 25% full or so.
- j = (count >> loadmodel->brushq3.deluxemapping) - (lightmapindex << power2);
+ j = (count >> (loadmodel->brushq3.deluxemapping ? 1 : 0)) - (lightmapindex << power2);
for (mergewidth = 1;mergewidth < j && mergewidth < (1 << power);mergewidth *= 2)
;
for (mergeheight = 1;mergewidth*mergeheight < j && mergeheight < (1 << power);mergeheight *= 2)
}
mergewidth = R_TextureWidth(loadmodel->brushq3.data_lightmaps[lightmapindex]) / size;
mergeheight = R_TextureHeight(loadmodel->brushq3.data_lightmaps[lightmapindex]) / size;
- j = (i >> loadmodel->brushq3.deluxemapping) & ((1 << power2) - 1);
+ j = (i >> (loadmodel->brushq3.deluxemapping ? 1 : 0)) & ((1 << power2) - 1);
if (loadmodel->brushq3.deluxemapping && (i & 1))
R_UpdateTexture(loadmodel->brushq3.data_deluxemaps[lightmapindex], convertedpixels, (j % mergewidth) * size, (j / mergewidth) * size, size, size);
else
}
}
+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 + k;
+ 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;
oldnumtriangles = out->num_triangles;
oldnumtriangles2 = out->num_collisiontriangles;
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...
+ 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, &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);
break;
if (cls.state != ca_dedicated && out->lightmaptexture)
{
// figure out which part of the merged lightmap this fits into
- int lightmapindex = LittleLong(in->lightmapindex) >> loadmodel->brushq3.deluxemapping;
+ int lightmapindex = LittleLong(in->lightmapindex) >> (loadmodel->brushq3.deluxemapping ? 1 : 0);
int mergewidth = R_TextureWidth(out->lightmaptexture) / loadmodel->brushq3.lightmapsize;
int mergeheight = R_TextureHeight(out->lightmaptexture) / loadmodel->brushq3.lightmapsize;
lightmapindex &= mergewidth * mergeheight - 1;
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->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->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);
}
}
}
static void Mod_Q3BSP_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
{
int i;
+ vec3_t shiftstart, shiftend;
float segmentmins[3], segmentmaxs[3];
static int markframe = 0;
msurface_t *surface;
trace->fraction = 1;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- if (mod_q3bsp_optimizedtraceline.integer && VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
+ if (mod_q3bsp_optimizedtraceline.integer && VectorCompare(boxmins, boxmaxs))
{
- if (VectorCompare(start, end))
+ VectorAdd(start, boxmins, shiftstart);
+ VectorAdd(end, boxmins, shiftend);
+ if (VectorCompare(shiftstart, shiftend))
{
// point trace
if (model->brush.submodel)
{
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
if (brush->colbrushf)
- Collision_TracePointBrushFloat(trace, start, brush->colbrushf);
+ Collision_TracePointBrushFloat(trace, shiftstart, brush->colbrushf);
}
else
- Mod_Q3BSP_TracePoint_RecursiveBSPNode(trace, model, model->brush.data_nodes, start, ++markframe);
+ Mod_Q3BSP_TracePoint_RecursiveBSPNode(trace, model, model->brush.data_nodes, shiftstart, ++markframe);
}
else
{
// line trace
- segmentmins[0] = min(start[0], end[0]) - 1;
- segmentmins[1] = min(start[1], end[1]) - 1;
- segmentmins[2] = min(start[2], end[2]) - 1;
- segmentmaxs[0] = max(start[0], end[0]) + 1;
- segmentmaxs[1] = max(start[1], end[1]) + 1;
- segmentmaxs[2] = max(start[2], end[2]) + 1;
+ segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
+ segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
+ segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
+ segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
+ segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
+ segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
if (model->brush.submodel)
{
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
if (brush->colbrushf)
- Collision_TraceLineBrushFloat(trace, start, end, brush->colbrushf, brush->colbrushf);
+ Collision_TraceLineBrushFloat(trace, shiftstart, shiftend, brush->colbrushf, brush->colbrushf);
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, start, end, surface->num_collisiontriangles, surface->data_collisionelement3i, surface->data_collisionvertex3f, 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, start, end, 0, 1, start, end, ++markframe, segmentmins, segmentmaxs);
+ Mod_Q3BSP_TraceLine_RecursiveBSPNode(trace, model, model->brush.data_nodes, shiftstart, shiftend, 0, 1, shiftstart, shiftend, ++markframe, segmentmins, segmentmaxs);
}
}
else
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->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);