trace.fraction = 1;
VectorCopy (end, trace.endpos);
#if QW
- PM_RecursiveHullCheck (cl.model_precache[1]->brushq1.hulls, 0, 0, 1, start, end, &trace);
+ PM_RecursiveHullCheck (cl.model_precache[1]->hulls, 0, 0, 1, start, end, &trace);
#else
- RecursiveHullCheck (cl.worldmodel->brushq1.hulls, 0, 0, 1, start, end, &trace);
+ RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
#endif
VectorCopy(trace.endpos, impact);
VectorCopy(trace.plane.normal, normal);
}
#endif
-void Collision_RoundUpToHullSize(const model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
-{
- vec3_t size;
- const hull_t *hull;
-
- VectorSubtract(inmaxs, inmins, size);
- if (cmodel->brushq1.ishlbsp)
- {
- if (size[0] < 3)
- hull = &cmodel->brushq1.hulls[0]; // 0x0x0
- else if (size[0] <= 32)
- {
- if (size[2] < 54) // pick the nearest of 36 or 72
- hull = &cmodel->brushq1.hulls[3]; // 32x32x36
- else
- hull = &cmodel->brushq1.hulls[1]; // 32x32x72
- }
- else
- hull = &cmodel->brushq1.hulls[2]; // 64x64x64
- }
- else
- {
- if (size[0] < 3)
- hull = &cmodel->brushq1.hulls[0]; // 0x0x0
- else if (size[0] <= 32)
- hull = &cmodel->brushq1.hulls[1]; // 32x32x56
- else
- hull = &cmodel->brushq1.hulls[2]; // 64x64x88
- }
- VectorCopy(inmins, outmins);
- VectorAdd(inmins, hull->clip_size, outmaxs);
-}
-
static hull_t box_hull;
static dclipnode_t box_clipnodes[6];
static mplane_t box_planes[6];
Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, &polyf_brushstart, &polyf_brushend);
}
-colbrushd_t *Collision_AllocBrushDouble(mempool_t *mempool, int numpoints, int numplanes)
-{
- colbrushd_t *brush;
- brush = Mem_Alloc(mempool, sizeof(colbrushd_t) + sizeof(colpointd_t) * numpoints + sizeof(colplaned_t) * numplanes);
- brush->numpoints = numpoints;
- brush->numplanes = numplanes;
- brush->planes = (void *)(brush + 1);
- brush->points = (void *)(brush->planes + brush->numplanes);
- return brush;
-}
-
-void Collision_CalcPlanesForPolygonBrushDouble(colbrushd_t *brush)
-{
- int i;
- double edge0[3], edge1[3], normal[3], dist, bestdist;
- colpointd_t *p, *p2;
-
- // choose best surface normal for polygon's plane
- bestdist = 0;
- for (i = 2, p = brush->points + 2;i < brush->numpoints;i++, p++)
- {
- VectorSubtract(p[-1].v, p[0].v, edge0);
- VectorSubtract(p[1].v, p[0].v, edge1);
- CrossProduct(edge0, edge1, normal);
- dist = DotProduct(normal, normal);
- if (i == 2 || bestdist < dist)
- {
- bestdist = dist;
- VectorCopy(normal, brush->planes->normal);
- }
- }
-
- VectorNormalize(brush->planes->normal);
- brush->planes->dist = DotProduct(brush->points->v, brush->planes->normal);
-
- // negate plane to create other side
- VectorNegate(brush->planes[0].normal, brush->planes[1].normal);
- brush->planes[1].dist = -brush->planes[0].dist;
- for (i = 0, p = brush->points + (brush->numpoints - 1), p2 = brush->points + 2;i < brush->numpoints;i++, p = p2, p2++)
- {
- VectorSubtract(p->v, p2->v, edge0);
- CrossProduct(edge0, brush->planes->normal, brush->planes[i].normal);
- VectorNormalize(brush->planes[i].normal);
- brush->planes[i].dist = DotProduct(p->v, brush->planes[i].normal);
- }
-
-#if 1
- // validity check - will be disabled later
- for (i = 0;i < brush->numplanes;i++)
- {
- int j;
- for (j = 0, p = brush->points;j < brush->numpoints;j++, p++)
- if (DotProduct(p->v, brush->planes[i].normal) > brush->planes[i].dist + (1.0 / 32.0))
- Con_Printf("Error in brush plane generation, plane %i\n");
- }
-#endif
-}
-
-colbrushd_t *Collision_AllocBrushFromPermanentPolygonDouble(mempool_t *mempool, int numpoints, double *points)
-{
- colbrushd_t *brush;
- brush = Mem_Alloc(mempool, sizeof(colbrushd_t) + sizeof(colplaned_t) * (numpoints + 2));
- brush->numpoints = numpoints;
- brush->numplanes = numpoints + 2;
- brush->planes = (void *)(brush + 1);
- brush->points = (colpointd_t *)points;
- return brush;
-}
-
-
-double nearestplanedist_double(const double *normal, const colpointd_t *points, int numpoints)
-{
- double dist, bestdist;
- bestdist = DotProduct(points->v, normal);
- points++;
- while(--numpoints)
- {
- dist = DotProduct(points->v, normal);
- if (bestdist > dist)
- bestdist = dist;
- points++;
- }
- return bestdist;
-}
-
-double furthestplanedist_double(const double *normal, const colpointd_t *points, int numpoints)
-{
- double dist, bestdist;
- bestdist = DotProduct(points->v, normal);
- points++;
- while(--numpoints)
- {
- dist = DotProduct(points->v, normal);
- if (bestdist < dist)
- bestdist = dist;
- points++;
- }
- return bestdist;
-}
-
-// NOTE: start and end of each brush pair must have same numplanes/numpoints
-void Collision_TraceBrushBrushDouble(trace_t *trace, const colbrushd_t *thisbrush_start, const colbrushd_t *thisbrush_end, const colbrushd_t *thatbrush_start, const colbrushd_t *thatbrush_end)
-{
- int nplane, nplane2, fstartsolid, fendsolid;
- double enterfrac, leavefrac, d1, d2, f, newimpactnormal[3];
- const colplaned_t *startplane, *endplane;
-
- enterfrac = -1;
- leavefrac = 1;
- fstartsolid = true;
- fendsolid = true;
-
- for (nplane = 0;nplane < thatbrush_start->numplanes + thisbrush_start->numplanes;nplane++)
- {
- nplane2 = nplane;
- if (nplane2 >= thatbrush_start->numplanes)
- {
- nplane2 -= thatbrush_start->numplanes;
- startplane = thisbrush_start->planes + nplane2;
- endplane = thisbrush_end->planes + nplane2;
- }
- else
- {
- startplane = thatbrush_start->planes + nplane2;
- endplane = thatbrush_end->planes + nplane2;
- }
- d1 = nearestplanedist_double(startplane->normal, thisbrush_start->points, thisbrush_start->numpoints) - furthestplanedist_double(startplane->normal, thatbrush_start->points, thatbrush_start->numpoints);
- d2 = nearestplanedist_double(endplane->normal, thisbrush_end->points, thisbrush_end->numpoints) - furthestplanedist_double(endplane->normal, thatbrush_end->points, thatbrush_end->numpoints) - COLLISIONEPSILON2;
- //Con_Printf("%c%i: d1 = %f, d2 = %f, d1 / (d1 - d2) = %f\n", nplane2 != nplane ? 'b' : 'a', nplane2, d1, d2, d1 / (d1 - d2));
-
- f = d1 - d2;
- if (f >= 0)
- {
- // moving into brush
- if (d2 > 0)
- return;
- if (d1 < 0)
- continue;
- // enter
- fstartsolid = false;
- f = (d1 - COLLISIONEPSILON) / f;
- f = bound(0, f, 1);
- if (enterfrac < f)
- {
- enterfrac = f;
- VectorBlend(startplane->normal, endplane->normal, enterfrac, newimpactnormal);
- }
- }
- else if (f < 0)
- {
- // moving out of brush
- if (d1 > 0)
- return;
- if (d2 < 0)
- continue;
- // leave
- fendsolid = false;
- f = (d1 + COLLISIONEPSILON) / f;
- f = bound(0, f, 1);
- if (leavefrac > f)
- leavefrac = f;
- }
- }
-
- if (fstartsolid)
- {
- trace->startsolid = true;
- if (fendsolid)
- trace->allsolid = true;
- }
-
- // LordHavoc: we need an epsilon nudge here because for a point trace the
- // penetrating line segment is normally zero length if this brush was
- // generated from a polygon (infinitely thin), and could even be slightly
- // positive or negative due to rounding errors in that case.
- if (enterfrac > -1 && enterfrac < trace->fraction && enterfrac - (1.0f / 1024.0f) <= leavefrac)
- {
- trace->fraction = bound(0, enterfrac, 1);
- VectorCopy(newimpactnormal, trace->plane.normal);
- }
-}
-
-static colplaned_t polyd_planes[256 + 2];
-static colbrushd_t polyd_brush;
-void Collision_TraceBrushPolygonDouble(trace_t *trace, const colbrushd_t *thisbrush_start, const colbrushd_t *thisbrush_end, int numpoints, const double *points)
-{
- if (numpoints > 256)
- {
- Con_Printf("Polygon with more than 256 points not supported yet (fixme!)\n");
- return;
- }
- polyd_brush.numpoints = numpoints;
- polyd_brush.numplanes = numpoints + 2;
- polyd_brush.points = (colpointd_t *)points;
- polyd_brush.planes = polyd_planes;
- Collision_CalcPlanesForPolygonBrushDouble(&polyd_brush);
- Collision_TraceBrushBrushDouble(trace, thisbrush_start, thisbrush_end, &polyd_brush, &polyd_brush);
-}
-
-
-
-
-typedef struct colbrushbmodelinfo_s
-{
- model_t *model;
- trace_t *trace;
- const matrix4x4_t *modelmatrixstart;
- const matrix4x4_t *modelmatrixend;
- const colbrushf_t *thisbrush_start;
- const colbrushf_t *thisbrush_end;
-}
-colbrushbmodelinfo_t;
-
-static int colframecount = 1;
-
-void Collision_RecursiveTraceBrushNode(colbrushbmodelinfo_t *info, mnode_t *node)
-{
- if (node->contents)
- {
- // collide with surfaces marked by this leaf
- int i, *mark;
- mleaf_t *leaf = (mleaf_t *)node;
- msurface_t *surf;
- for (i = 0, mark = leaf->firstmarksurface;i < leaf->nummarksurfaces;i++, mark++)
- {
- surf = info->model->brushq1.surfaces + *mark;
- // don't check a surface twice
- if (surf->colframe != colframecount)
- {
- surf->colframe = colframecount;
- if (surf->flags & SURF_SOLIDCLIP)
- {
- Collision_TraceBrushPolygonFloat(info->trace, info->thisbrush_start, info->thisbrush_end, surf->poly_numverts, surf->poly_verts);
- //Collision_TraceBrushPolygonTransformFloat(info->trace, info->thisbrush_start, info->thisbrush_end, surf->poly_numverts, surf->poly_verts, info->modelmatrixstart, info->modelmatrixend);
- }
- }
- }
- }
- else
- {
- // recurse down node sides
- int i;
- float dist;
- colpointf_t *ps, *pe;
- // FIXME? if TraceBrushPolygonTransform were to be made usable, the
- // node planes would need to be transformed too
- dist = node->plane->dist - (1.0f / 8.0f);
- for (i = 0, ps = info->thisbrush_start->points, pe = info->thisbrush_end->points;i < info->thisbrush_start->numpoints;i++, ps++, pe++)
- {
- if (DotProduct(ps->v, node->plane->normal) > dist || DotProduct(pe->v, node->plane->normal) > dist)
- {
- Collision_RecursiveTraceBrushNode(info, node->children[0]);
- break;
- }
- }
- dist = node->plane->dist + (1.0f / 8.0f);
- for (i = 0, ps = info->thisbrush_start->points, pe = info->thisbrush_end->points;i < info->thisbrush_start->numpoints;i++, ps++, pe++)
- {
- if (DotProduct(ps->v, node->plane->normal) < dist || DotProduct(pe->v, node->plane->normal) < dist)
- {
- Collision_RecursiveTraceBrushNode(info, node->children[1]);
- break;
- }
- }
- }
-}
-
-void Collision_TraceBrushBModel(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model)
-{
- colbrushbmodelinfo_t info;
- colframecount++;
- memset(trace, 0, sizeof(*trace));
- trace->fraction = 1;
- info.trace = trace;
- info.model = model;
- info.thisbrush_start = thisbrush_start;
- info.thisbrush_end = thisbrush_end;
- Collision_RecursiveTraceBrushNode(&info, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode);
-}
-
-void Collision_TraceBrushBModelTransform(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model, const matrix4x4_t *modelmatrixstart, const matrix4x4_t *modelmatrixend)
-{
- colbrushbmodelinfo_t info;
- colframecount++;
- memset(trace, 0, sizeof(*trace));
- trace->fraction = 1;
- info.trace = trace;
- info.model = model;
- info.modelmatrixstart = modelmatrixstart;
- info.modelmatrixend = modelmatrixend;
- info.thisbrush_start = thisbrush_start;
- info.thisbrush_end = thisbrush_end;
- Collision_RecursiveTraceBrushNode(&info, model->brushq1.nodes + model->brushq1.hulls[0].firstclipnode);
-}
-
#define MAX_BRUSHFORBOX 16
return brush;
}
-void Collision_PolygonClipTrace (trace_t *trace, const void *cent, model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end)
-{
- vec3_t impactnormal;
- //vec3_t mins2, maxs2;
- matrix4x4_t cmatrix, cimatrix, startmatrix, endmatrix;
- matrix4x4_t mstartmatrix, mendmatrix, identitymatrix;
- colbrushf_t *thisbrush_start, *thisbrush_end, *cbrush;
-
- Matrix4x4_CreateFromQuakeEntity(&cmatrix, corigin[0], corigin[1], corigin[2], cangles[0], cangles[1], cangles[2], 1);
- Matrix4x4_Invert_Simple(&cimatrix, &cmatrix);
- Matrix4x4_CreateTranslate(&startmatrix, start[0], start[1], start[2]);
- Matrix4x4_CreateTranslate(&endmatrix, end[0], end[1], end[2]);
-
- Matrix4x4_CreateIdentity(&identitymatrix);
- Matrix4x4_Concat(&mstartmatrix, &cimatrix, &startmatrix);
- Matrix4x4_Concat(&mendmatrix, &cimatrix, &endmatrix);
- thisbrush_start = Collision_BrushForBox(&mstartmatrix, mins, maxs);
- //mins2[0] = mins[0] - 0.0625;mins2[1] = mins[1] - 0.0625;mins2[2] = mins[2] - 0.0625;
- //maxs2[0] = maxs[0] + 0.0625;maxs2[1] = maxs[1] + 0.0625;maxs2[2] = maxs[2] + 0.0625;
- thisbrush_end = Collision_BrushForBox(&mendmatrix, mins, maxs);
-
- //Collision_PrintBrushAsQHull(thisbrush_start, "thisbrush_start");
- //Collision_PrintBrushAsQHull(thisbrush_end, "thisbrush_end");
- memset (trace, 0, sizeof(trace_t));
- if (cmodel && cmodel->type == mod_brush)
- {
- // brush model
- Collision_TraceBrushBModel(trace, thisbrush_start, thisbrush_end, cmodel);
- //Collision_TraceBrushBModelTransform(trace, thisbrush_start, thisbrush_end, cmodel, &cmatrix, &cmatrix);
- }
- else
- {
- // bounding box
- cbrush = Collision_BrushForBox(&identitymatrix, cmins, cmaxs);
- Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, cbrush, cbrush);
- //cbrush = Collision_BrushForBox(&cmatrix, cmins, cmaxs);
- //trace->fraction = Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, cbrush, cbrush);
- }
-
- if (trace->fraction < 0 || trace->fraction > 1)
- Con_Printf("fraction out of bounds %f %s:%d\n", trace->fraction, __FILE__, __LINE__);
-
- VectorBlend(start, end, trace->fraction, trace->endpos);
- if (trace->fraction < 1)
- {
- trace->ent = (void *) cent;
- VectorCopy(trace->plane.normal, impactnormal);
- Matrix4x4_Transform(&cmatrix, impactnormal, trace->plane.normal);
- VectorNormalize(trace->plane.normal);
- //Con_Printf("fraction %f normal %f %f %f\n", trace->fraction, trace->plane.normal[0], trace->plane.normal[1], trace->plane.normal[2]);
- }
-}
-
-
// LordHavoc: currently unused and not yet tested
// note: this can be used for tracing a moving sphere vs a stationary sphere,
// by simply adding the moving sphere's radius to the sphereradius parameter,
}
trace_t;
-void Collision_RoundUpToHullSize(const model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs);
void Collision_Init(void);
void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
void Collision_TraceBrushPolygonFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int numpoints, const float *points);
void Collision_TraceBrushPolygonTransformFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, int numpoints, const float *points, const matrix4x4_t *polygonmatrixstart, const matrix4x4_t *polygonmatrixend);
-typedef struct colpointd_s
-{
- double v[3];
-}
-colpointd_t;
-
-typedef struct colplaned_s
-{
- double normal[3];
- double dist;
-}
-colplaned_t;
-
-typedef struct colbrushd_s
-{
- int numplanes;
- int numpoints;
- colplaned_t *planes;
- colpointd_t *points;
-}
-colbrushd_t;
-
-colbrushd_t *Collision_AllocBrushDouble(mempool_t *mempool, int numpoints, int numplanes);
-void Collision_CalcPlanesForPolygonBrushDouble(colbrushd_t *brush);
-colbrushd_t *Collision_AllocBrushFromPermanentPolygonDouble(mempool_t *mempool, int numpoints, double *points);
-void Collision_TraceBrushBrushDouble(trace_t *trace, const colbrushd_t *thisbrush_start, const colbrushd_t *thisbrush_end, const colbrushd_t *thatbrush_start, const colbrushd_t *thatbrush_end);
-void Collision_TraceBrushPolygonDouble(trace_t *trace, const colbrushd_t *thisbrush_start, const colbrushd_t *thisbrush_end, int numpoints, const double *points);
-
-void Collision_TraceBrushBModel(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model);
-void Collision_TraceBrushBModelTransform(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model, const matrix4x4_t *modelmatrixstart, const matrix4x4_t *modelmatrixend);
-
-void Collision_PolygonClipTrace(trace_t *trace, const void *cent, model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
-
colbrushf_t *Collision_BrushForBox(const matrix4x4_t *matrix, const vec3_t mins, const vec3_t maxs);
#endif
// used for dlight push checking and other things
int r_framecount;
+// used for visibility checking
+qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
+
mplane_t frustum[4];
matrix4x4_t r_identitymatrix;
return false;
}
-int PVS_CullBox(const vec3_t mins, const vec3_t maxs)
-{
- int stackpos, sides;
- mnode_t *node, *stack[4096];
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->pvsframe == cl.worldmodel->brushq1.pvsframecount)
- return false;
- }
- else
- {
- sides = BoxOnPlaneSide(mins, maxs, node->plane);
- if (sides & 2 && stackpos < 4096)
- stack[stackpos++] = node->children[1];
- if (sides & 1 && stackpos < 4096)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-int VIS_CullBox(const vec3_t mins, const vec3_t maxs)
-{
- int stackpos, sides;
- mnode_t *node, *stack[4096];
- if (R_CullBox(mins, maxs))
- return true;
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->visframe == r_framecount)
- return false;
- }
- else
- {
- sides = BoxOnPlaneSide(mins, maxs, node->plane);
- if (sides & 2 && stackpos < 4096)
- stack[stackpos++] = node->children[1];
- if (sides & 1 && stackpos < 4096)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-int R_CullSphere(const vec3_t origin, vec_t radius)
-{
- return (DotProduct(frustum[0].normal, origin) + radius < frustum[0].dist
- || DotProduct(frustum[1].normal, origin) + radius < frustum[1].dist
- || DotProduct(frustum[2].normal, origin) + radius < frustum[2].dist
- || DotProduct(frustum[3].normal, origin) + radius < frustum[3].dist);
-}
-
-int PVS_CullSphere(const vec3_t origin, vec_t radius)
-{
- int stackpos;
- mnode_t *node, *stack[4096];
- float dist;
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->pvsframe == cl.worldmodel->brushq1.pvsframecount)
- return false;
- }
- else
- {
- dist = PlaneDiff(origin, node->plane);
- if (dist <= radius)
- stack[stackpos++] = node->children[1];
- if (dist >= -radius)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-int VIS_CullSphere(const vec3_t origin, vec_t radius)
-{
- int stackpos;
- mnode_t *node, *stack[4096];
- float dist;
- if (R_CullSphere(origin, radius))
- return true;
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->visframe == r_framecount)
- return false;
- }
- else
- {
- dist = PlaneDiff(origin, node->plane);
- if (dist <= radius)
- stack[stackpos++] = node->children[1];
- if (dist >= -radius)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
+#define VIS_CullBox(mins,maxs) (R_CullBox((mins), (maxs)) || (cl.worldmodel && cl.worldmodel->brush.BoxTouchingPVS && !cl.worldmodel->brush.BoxTouchingPVS(cl.worldmodel, r_pvsbits, (mins), (maxs))))
//==================================================================================
R_LerpAnimation(ent);
R_UpdateEntLights(ent);
if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL))
- && !VIS_CullSphere(ent->origin, (ent->model != NULL ? ent->model->radius : 16) * ent->scale)
&& !VIS_CullBox(ent->mins, ent->maxs))
{
ent->visframe = r_framecount;
int shadowframecount = 0;
-int Light_CullBox(const vec3_t mins, const vec3_t maxs)
-{
- int stackpos, sides;
- mnode_t *node, *stack[4096];
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->worldnodeframe == shadowframecount)
- return false;
- }
- else
- {
- sides = BoxOnPlaneSide(mins, maxs, node->plane);
- if (sides & 2 && stackpos < 4096)
- stack[stackpos++] = node->children[1];
- if (sides & 1 && stackpos < 4096)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-int LightAndVis_CullBox(const vec3_t mins, const vec3_t maxs)
-{
- int stackpos, sides;
- mnode_t *node, *stack[4096];
- if (R_CullBox(mins, maxs))
- return true;
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
- return false;
- }
- else
- {
- sides = BoxOnPlaneSide(mins, maxs, node->plane);
- if (sides & 2 && stackpos < 4096)
- stack[stackpos++] = node->children[1];
- if (sides & 1 && stackpos < 4096)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-int LightAndVis_CullPointCloud(int numpoints, const float *points)
-{
- int i;
- const float *p;
- int stackpos, sides;
- mnode_t *node, *stack[4096];
- //if (R_CullBox(mins, maxs))
- // return true;
- if (cl.worldmodel == NULL)
- return false;
- stackpos = 0;
- stack[stackpos++] = cl.worldmodel->brushq1.nodes;
- while (stackpos)
- {
- node = stack[--stackpos];
- if (node->contents < 0)
- {
- if (((mleaf_t *)node)->visframe == r_framecount && ((mleaf_t *)node)->worldnodeframe == shadowframecount)
- return false;
- }
- else
- {
- sides = 0;
- for (i = 0, p = points;i < numpoints && sides != 3;i++, p += 3)
- {
- if (DotProduct(p, node->plane->normal) < node->plane->dist)
- sides |= 1;
- else
- sides |= 2;
- }
- if (sides & 2 && stackpos < 4096)
- stack[stackpos++] = node->children[1];
- if (sides & 1 && stackpos < 4096)
- stack[stackpos++] = node->children[0];
- }
- }
- return true;
-}
-
-
void R_TestAndDrawShadowVolume(entity_render_t *ent, vec3_t lightorigin, float cullradius, float lightradius, vec3_t lightmins, vec3_t lightmaxs, vec3_t clipmins, vec3_t clipmaxs, int lightmarked)
{
vec3_t relativelightorigin;
- #if 0
- int i;
- vec3_t temp;
- float dist, projectdistance;
- float points[16][3];
- #endif
// rough checks
- if (!(ent->flags & RENDER_SHADOW) || ent->model == NULL || ent->model->DrawShadowVolume == NULL)
- return;
- if (r_shadow_cull.integer)
+ if ((ent->flags & RENDER_SHADOW) && ent->model && ent->model->DrawShadowVolume && !(r_shadow_cull.integer && (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0] || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1] || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2])))
{
- if (ent->maxs[0] < lightmins[0] || ent->mins[0] > lightmaxs[0]
- || ent->maxs[1] < lightmins[1] || ent->mins[1] > lightmaxs[1]
- || ent->maxs[2] < lightmins[2] || ent->mins[2] > lightmaxs[2]
- || (lightmarked && Light_CullBox(ent->mins, ent->maxs)))
- return;
+ Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
+ ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
}
- #if 0
- if (r_shadow_cull.integer)
- {
- projectdistance = cullradius;
- // calculate projected bounding box and decide if it is on-screen
- for (i = 0;i < 8;i++)
- {
- temp[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
- temp[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
- temp[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
- Matrix4x4_Transform(&ent->matrix, temp, points[i]);
- VectorSubtract(points[i], lightorigin, temp);
- dist = projectdistance / sqrt(DotProduct(temp, temp));
- VectorMA(lightorigin, dist, temp, points[i+8]);
- }
- if (LightAndVis_CullPointCloud(16, points[0]))
- return;
- /*
- for (i = 0;i < 8;i++)
- {
- p2[0] = i & 1 ? ent->model->normalmaxs[0] : ent->model->normalmins[0];
- p2[1] = i & 2 ? ent->model->normalmaxs[1] : ent->model->normalmins[1];
- p2[2] = i & 4 ? ent->model->normalmaxs[2] : ent->model->normalmins[2];
- Matrix4x4_Transform(&ent->matrix, p2, p);
- VectorSubtract(p, lightorigin, temp);
- dist = projectdistance / sqrt(DotProduct(temp, temp));
- VectorMA(p, dist, temp, p2);
- if (i)
- {
- if (mins[0] > p[0]) mins[0] = p[0];if (maxs[0] < p[0]) maxs[0] = p[0];
- if (mins[1] > p[1]) mins[1] = p[1];if (maxs[1] < p[1]) maxs[1] = p[1];
- if (mins[2] > p[2]) mins[2] = p[2];if (maxs[2] < p[2]) maxs[2] = p[2];
- }
- else
- {
- VectorCopy(p, mins);
- VectorCopy(p, maxs);
- }
- if (mins[0] > p2[0]) mins[0] = p2[0];if (maxs[0] < p2[0]) maxs[0] = p2[0];
- if (mins[1] > p2[1]) mins[1] = p2[1];if (maxs[1] < p2[1]) maxs[1] = p2[1];
- if (mins[2] > p2[2]) mins[2] = p2[2];if (maxs[2] < p2[2]) maxs[2] = p2[2];
- }
- if (mins[0] >= clipmaxs[0] || maxs[0] <= clipmins[0]
- || mins[1] >= clipmaxs[1] || maxs[1] <= clipmins[1]
- || mins[2] >= clipmaxs[2] || maxs[2] <= clipmins[2]
- || LightAndVis_CullBox(mins, maxs))
- return;
- */
- }
- #endif
- Matrix4x4_Transform(&ent->inversematrix, lightorigin, relativelightorigin);
- ent->model->DrawShadowVolume (ent, relativelightorigin, lightradius);
}
void R_Shadow_DrawWorldLightShadowVolume(matrix4x4_t *matrix, worldlight_t *light);
extern void R_Model_Brush_DrawLightForSurfaceList(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, msurface_t **surflist, int numsurfaces, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
-void R_ShadowVolumeLighting (int visiblevolumes)
+void R_ShadowVolumeLighting(int visiblevolumes)
{
int i;
entity_render_t *ent;
worldlight_t *wl;
rdlight_t *rd;
rmeshstate_t m;
- mleaf_t *leaf;
matrix4x4_t matrix;
matrix4x4_t matrix_worldtofilter, matrix_worldtoattenuationxyz, matrix_worldtoattenuationz;
matrix4x4_t matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz;
{
if (d_lightstylevalue[wl->style] <= 0)
continue;
- if (R_CullBox(wl->mins, wl->maxs))
- //if (R_CullSphere(wl->origin, cullradius))
+ if (VIS_CullBox(wl->mins, wl->maxs))
continue;
- //if (R_CullBox(wl->mins, wl->maxs) || R_CullSphere(wl->origin, lightradius))
- // continue;
- //if (VIS_CullBox(wl->mins, wl->maxs) || VIS_CullSphere(wl->origin, lightradius))
- // continue;
if (r_shadow_debuglight.integer >= 0 && lnum != r_shadow_debuglight.integer)
continue;
+ if (R_Shadow_ScissorForBBox(wl->mins, wl->maxs))
+ continue;
cullradius = wl->cullradius;
lightradius = wl->lightradius;
-
- if (cl.worldmodel != NULL)
- {
- for (i = 0;i < wl->numleafs;i++)
- if (wl->leafs[i]->visframe == r_framecount)
- break;
- if (i == wl->numleafs)
- continue;
- leaf = wl->leafs[i++];
- VectorCopy(leaf->mins, clipmins);
- VectorCopy(leaf->maxs, clipmaxs);
- for (;i < wl->numleafs;i++)
- {
- leaf = wl->leafs[i];
- if (leaf->visframe == r_framecount)
- {
- if (clipmins[0] > leaf->mins[0]) clipmins[0] = leaf->mins[0];
- if (clipmaxs[0] < leaf->maxs[0]) clipmaxs[0] = leaf->maxs[0];
- if (clipmins[1] > leaf->mins[1]) clipmins[1] = leaf->mins[1];
- if (clipmaxs[1] < leaf->maxs[1]) clipmaxs[1] = leaf->maxs[1];
- if (clipmins[2] > leaf->mins[2]) clipmins[2] = leaf->mins[2];
- if (clipmaxs[2] < leaf->maxs[2]) clipmaxs[2] = leaf->maxs[2];
- }
- }
- if (clipmins[0] < wl->mins[0]) clipmins[0] = wl->mins[0];
- if (clipmaxs[0] > wl->maxs[0]) clipmaxs[0] = wl->maxs[0];
- if (clipmins[1] < wl->mins[1]) clipmins[1] = wl->mins[1];
- if (clipmaxs[1] > wl->maxs[1]) clipmaxs[1] = wl->maxs[1];
- if (clipmins[2] < wl->mins[2]) clipmins[2] = wl->mins[2];
- if (clipmaxs[2] > wl->maxs[2]) clipmaxs[2] = wl->maxs[2];
- }
- else
- {
- VectorCopy(wl->mins, clipmins);
- VectorCopy(wl->maxs, clipmaxs);
- }
-
- //if (R_Shadow_ScissorForBBoxAndSphere(clipmins, clipmaxs, wl->origin, wl->cullradius))
- if (R_CullBox(clipmins, clipmaxs) || R_Shadow_ScissorForBBox(clipmins, clipmaxs))
- continue;
-
- // mark the leafs we care about so only things in those leafs will matter
- if (cl.worldmodel != NULL)
- for (i = 0;i < wl->numleafs;i++)
- wl->leafs[i]->worldnodeframe = shadowframecount;
+ VectorCopy(wl->mins, clipmins);
+ VectorCopy(wl->maxs, clipmaxs);
f = d_lightstylevalue[wl->style] * (1.0f / 256.0f);
VectorScale(wl->light, f, lightcolor);
R_BuildLightList();
R_TimeReport("setup");
+ if (cl.worldmodel && cl.worldmodel->brush.FatPVS)
+ cl.worldmodel->brush.FatPVS(cl.worldmodel, r_origin, 2, r_pvsbits, sizeof(r_pvsbits));
+
R_WorldVisibility(world);
R_TimeReport("worldvis");
rmeshstate_t m;
// LordHavoc: HalfLife maps have freaky skypolys...
- if (ent->model->brushq1.ishlbsp)
+ if (ent->model->brush.ishlbsp)
return;
if (skyrendernow)
R_Mesh_Draw(portal->numpoints, portal->numpoints - 2, polygonelements);
}
+// LordHavoc: this is just a nice debugging tool, very slow
static void R_DrawPortals(entity_render_t *ent)
{
int i;
return;
for (portal = ent->model->brushq1.portals, endportal = portal + ent->model->brushq1.numportals;portal < endportal;portal++)
{
- if ((portal->here->pvsframe == ent->model->brushq1.pvsframecount || portal->past->pvsframe == ent->model->brushq1.pvsframecount) && portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
+ if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
{
VectorClear(temp);
for (i = 0;i < portal->numpoints;i++)
static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
{
- int c, leafstackpos, *mark, *surfacevisframes;
+ int c, leafstackpos, *mark, *surfacevisframes, bitnum;
#if WORLDNODECULLBACKFACES
int n;
msurface_t *surf;
{
leaf->worldnodeframe = r_framecount;
// FIXME: R_CullBox is absolute, should be done relative
- if (leaf->pvsframe == ent->model->brushq1.pvsframecount && !R_CullBox(leaf->mins, leaf->maxs))
+ bitnum = (leaf - ent->model->brushq1.leafs) - 1;
+ if ((r_pvsbits[bitnum >> 3] & (1 << (bitnum & 7))) && !R_CullBox(leaf->mins, leaf->maxs))
leafstack[leafstackpos++] = leaf;
}
}
{
int j, c, *surfacepvsframes, *mark;
mleaf_t *leaf;
- qbyte *pvs;
model_t *model;
model = ent->model;
model->brushq1.pvssurflistlength = 0;
if (viewleaf)
{
- pvs = viewleaf->pvsdata;
surfacepvsframes = model->brushq1.surfacepvsframes;
- for (j = 0;j < model->brushq1.numleafs-1;j++)
+ for (j = 0;j < model->brushq1.visleafs;j++)
{
- if (pvs[j >> 3] & (1 << (j & 7)))
+ if (r_pvsbits[j >> 3] & (1 << (j & 7)))
{
leaf = model->brushq1.leafs + j + 1;
leaf->pvsframe = model->brushq1.pvsframecount;
}
}
+/*
+void R_Q3BSP_DrawSky(entity_render_t *ent)
+{
+}
+*/
+
+void R_Q3BSP_Draw(entity_render_t *ent)
+{
+}
+
+/*
+void R_Q3BSP_DrawFakeShadow(entity_render_t *ent)
+{
+}
+*/
+
+/*
+void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
+{
+}
+*/
+
+/*
+void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz)
+{
+}
+*/
+
static void gl_surf_start(void)
{
}
return (mleaf_t *)node;
}
+static void Mod_Q1BSP_AmbientSoundLevelsForPoint(model_t *model, const vec3_t p, qbyte *out, int outsize)
+{
+ int i;
+ mleaf_t *leaf;
+ leaf = Mod_Q1BSP_PointInLeaf(model, p);
+ if (leaf)
+ {
+ i = min(outsize, (int)sizeof(leaf->ambient_sound_level));;
+ if (i)
+ {
+ memcpy(out, leaf->ambient_sound_level, i);
+ out += i;
+ outsize -= i;
+ }
+ }
+ if (outsize)
+ memset(out, 0, outsize);
+}
+
static int Mod_Q1BSP_BoxTouchingPVS_RecursiveBSPNode(const model_t *model, const mnode_t *node, const qbyte *pvs, const vec3_t mins, const vec3_t maxs)
{
VectorSubtract(boxstartmaxs, boxstartmins, boxsize);
if (boxsize[0] < 3)
rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
- else if (model->brushq1.ishlbsp)
+ else if (model->brush.ishlbsp)
{
if (boxsize[0] <= 32)
{
}
// LordHavoc: HL sky textures are entirely different than quake
- if (!loadmodel->brushq1.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
+ if (!loadmodel->brush.ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
{
if (loadmodel->isworldmodel)
{
if (!Mod_LoadSkinFrame(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true))
{
// did not find external texture, load it from the bsp or wad3
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
// internal texture overrides wad
qbyte *pixels, *freepixels, *fogpixels;
qbyte *in, *out, *data, d;
char litfilename[1024];
loadmodel->brushq1.lightdata = NULL;
- if (loadmodel->brushq1.ishlbsp) // LordHavoc: load the colored lighting data straight
+ if (loadmodel->brush.ishlbsp) // LordHavoc: load the colored lighting data straight
{
loadmodel->brushq1.lightdata = Mem_Alloc(loadmodel->mempool, l->filelen);
memcpy(loadmodel->brushq1.lightdata, mod_base + l->fileofs, l->filelen);
}
}
-/*
-static int castshadowcount = 0;
-static void Mod_Q1BSP_ProcessLightList(void)
-{
- int j, k, l, *mark, lnum;
- mlight_t *e;
- msurface_t *surf;
- float dist;
- mleaf_t *leaf;
- qbyte *pvs;
- vec3_t temp;
- float *v, radius2;
- for (lnum = 0, e = loadmodel->brushq1.lights;lnum < loadmodel->brushq1.numlights;lnum++, e++)
- {
- e->cullradius2 = DotProduct(e->light, e->light) / (e->falloff * e->falloff * 8192.0f * 8192.0f * 2.0f * 2.0f);// + 4096.0f;
- if (e->cullradius2 > 4096.0f * 4096.0f)
- e->cullradius2 = 4096.0f * 4096.0f;
- e->cullradius = e->lightradius = sqrt(e->cullradius2);
- leaf = Mod_Q1BSP_PointInLeaf(e->origin, loadmodel);
- if (leaf->compressed_vis)
- pvs = Mod_Q1BSP_DecompressVis(leaf->compressed_vis, loadmodel);
- else
- pvs = mod_q1bsp_novis;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- loadmodel->brushq1.surfacevisframes[j] = -1;
- for (j = 0, leaf = loadmodel->brushq1.leafs + 1;j < loadmodel->brushq1.numleafs - 1;j++, leaf++)
- {
- if (pvs[j >> 3] & (1 << (j & 7)))
- {
- for (k = 0, mark = leaf->firstmarksurface;k < leaf->nummarksurfaces;k++, mark++)
- {
- surf = loadmodel->brushq1.surfaces + *mark;
- if (surf->number != *mark)
- Con_Printf("%d != %d\n", surf->number, *mark);
- dist = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
- if (surf->flags & SURF_PLANEBACK)
- dist = -dist;
- if (dist > 0 && dist < e->cullradius)
- {
- temp[0] = bound(surf->poly_mins[0], e->origin[0], surf->poly_maxs[0]) - e->origin[0];
- temp[1] = bound(surf->poly_mins[1], e->origin[1], surf->poly_maxs[1]) - e->origin[1];
- temp[2] = bound(surf->poly_mins[2], e->origin[2], surf->poly_maxs[2]) - e->origin[2];
- if (DotProduct(temp, temp) < lightradius2)
- loadmodel->brushq1.surfacevisframes[*mark] = -2;
- }
- }
- }
- }
- // build list of light receiving surfaces
- e->numsurfaces = 0;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- if (loadmodel->brushq1.surfacevisframes[j] == -2)
- e->numsurfaces++;
- e->surfaces = NULL;
- if (e->numsurfaces > 0)
- {
- e->surfaces = Mem_Alloc(loadmodel->mempool, sizeof(msurface_t *) * e->numsurfaces);
- e->numsurfaces = 0;
- for (j = 0;j < loadmodel->brushq1.numsurfaces;j++)
- if (loadmodel->brushq1.surfacevisframes[j] == -2)
- e->surfaces[e->numsurfaces++] = loadmodel->brushq1.surfaces + j;
- }
- // find bounding box and sphere of lit surfaces
- // (these will be used for creating a shape to clip the light)
- radius2 = 0;
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (j == 0)
- {
- VectorCopy(surf->poly_verts, e->mins);
- VectorCopy(surf->poly_verts, e->maxs);
- }
- for (k = 0, v = surf->poly_verts;k < surf->poly_numverts;k++, v += 3)
- {
- if (e->mins[0] > v[0]) e->mins[0] = v[0];if (e->maxs[0] < v[0]) e->maxs[0] = v[0];
- if (e->mins[1] > v[1]) e->mins[1] = v[1];if (e->maxs[1] < v[1]) e->maxs[1] = v[1];
- if (e->mins[2] > v[2]) e->mins[2] = v[2];if (e->maxs[2] < v[2]) e->maxs[2] = v[2];
- VectorSubtract(v, e->origin, temp);
- dist = DotProduct(temp, temp);
- if (radius2 < dist)
- radius2 = dist;
- }
- }
- if (e->cullradius2 > radius2)
- {
- e->cullradius2 = radius2;
- e->cullradius = sqrt(e->cullradius2);
- }
- if (e->mins[0] < e->origin[0] - e->lightradius) e->mins[0] = e->origin[0] - e->lightradius;
- if (e->maxs[0] > e->origin[0] + e->lightradius) e->maxs[0] = e->origin[0] + e->lightradius;
- if (e->mins[1] < e->origin[1] - e->lightradius) e->mins[1] = e->origin[1] - e->lightradius;
- if (e->maxs[1] > e->origin[1] + e->lightradius) e->maxs[1] = e->origin[1] + e->lightradius;
- if (e->mins[2] < e->origin[2] - e->lightradius) e->mins[2] = e->origin[2] - e->lightradius;
- if (e->maxs[2] > e->origin[2] + e->lightradius) e->maxs[2] = e->origin[2] + e->lightradius;
- // clip shadow volumes against eachother to remove unnecessary
- // polygons(and sections of polygons)
- {
- //vec3_t polymins, polymaxs;
- int maxverts = 4;
- float *verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- float f, *v0, *v1, projectdistance;
-
- e->shadowvolume = Mod_ShadowMesh_Begin(loadmodel->mempool, 1024);
-#if 0
- {
- vec3_t outermins, outermaxs, innermins, innermaxs;
- innermins[0] = e->mins[0] - 1;
- innermins[1] = e->mins[1] - 1;
- innermins[2] = e->mins[2] - 1;
- innermaxs[0] = e->maxs[0] + 1;
- innermaxs[1] = e->maxs[1] + 1;
- innermaxs[2] = e->maxs[2] + 1;
- outermins[0] = loadmodel->normalmins[0] - 1;
- outermins[1] = loadmodel->normalmins[1] - 1;
- outermins[2] = loadmodel->normalmins[2] - 1;
- outermaxs[0] = loadmodel->normalmaxs[0] + 1;
- outermaxs[1] = loadmodel->normalmaxs[1] + 1;
- outermaxs[2] = loadmodel->normalmaxs[2] + 1;
- // add bounding box around the whole shadow volume set,
- // facing inward to limit light area, with an outer bounding box
- // facing outward (this is needed by the shadow rendering method)
- // X major
- verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermaxs[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
- verts[ 9] = innermaxs[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermaxs[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
- verts[ 9] = outermaxs[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // X minor
- verts[ 0] = innermins[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermins[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermins[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermins[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Y major
- verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermins[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermins[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermaxs[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermaxs[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Y minor
- verts[ 0] = innermins[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermins[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermaxs[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermaxs[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Z major
- verts[ 0] = innermaxs[0];verts[ 1] = innermins[1];verts[ 2] = innermaxs[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermaxs[1];verts[ 5] = innermaxs[2];
- verts[ 6] = innermins[0];verts[ 7] = innermaxs[1];verts[ 8] = innermaxs[2];
- verts[ 9] = innermins[0];verts[10] = innermins[1];verts[11] = innermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermaxs[1];verts[ 2] = outermaxs[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermins[1];verts[ 5] = outermaxs[2];
- verts[ 6] = outermins[0];verts[ 7] = outermins[1];verts[ 8] = outermaxs[2];
- verts[ 9] = outermins[0];verts[10] = outermaxs[1];verts[11] = outermaxs[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- // Z minor
- verts[ 0] = innermaxs[0];verts[ 1] = innermaxs[1];verts[ 2] = innermins[2];
- verts[ 3] = innermaxs[0];verts[ 4] = innermins[1];verts[ 5] = innermins[2];
- verts[ 6] = innermins[0];verts[ 7] = innermins[1];verts[ 8] = innermins[2];
- verts[ 9] = innermins[0];verts[10] = innermaxs[1];verts[11] = innermins[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- verts[ 0] = outermaxs[0];verts[ 1] = outermins[1];verts[ 2] = outermins[2];
- verts[ 3] = outermaxs[0];verts[ 4] = outermaxs[1];verts[ 5] = outermins[2];
- verts[ 6] = outermins[0];verts[ 7] = outermaxs[1];verts[ 8] = outermins[2];
- verts[ 9] = outermins[0];verts[10] = outermins[1];verts[11] = outermins[2];
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- }
-#endif
- castshadowcount++;
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (surf->flags & SURF_SHADOWCAST)
- surf->castshadow = castshadowcount;
- }
- for (j = 0;j < e->numsurfaces;j++)
- {
- surf = e->surfaces[j];
- if (surf->castshadow != castshadowcount)
- continue;
- f = DotProduct(e->origin, surf->plane->normal) - surf->plane->dist;
- if (surf->flags & SURF_PLANEBACK)
- f = -f;
- projectdistance = e->lightradius;
- if (maxverts < surf->poly_numverts)
- {
- maxverts = surf->poly_numverts;
- if (verts)
- Mem_Free(verts);
- verts = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- }
- // copy the original polygon, for the front cap of the volume
- for (k = 0, v0 = surf->poly_verts, v1 = verts;k < surf->poly_numverts;k++, v0 += 3, v1 += 3)
- VectorCopy(v0, v1);
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, surf->poly_numverts, verts);
- // project the original polygon, reversed, for the back cap of the volume
- for (k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = verts;k < surf->poly_numverts;k++, v0 -= 3, v1 += 3)
- {
- VectorSubtract(v0, e->origin, temp);
- VectorNormalize(temp);
- VectorMA(v0, projectdistance, temp, v1);
- }
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, surf->poly_numverts, verts);
- // project the shadow volume sides
- for (l = surf->poly_numverts - 1, k = 0, v0 = surf->poly_verts + (surf->poly_numverts - 1) * 3, v1 = surf->poly_verts;k < surf->poly_numverts;l = k, k++, v0 = v1, v1 += 3)
- {
- if (!surf->neighborsurfaces[l] || surf->neighborsurfaces[l]->castshadow != castshadowcount)
- {
- VectorCopy(v1, &verts[0]);
- VectorCopy(v0, &verts[3]);
- VectorCopy(v0, &verts[6]);
- VectorCopy(v1, &verts[9]);
- VectorSubtract(&verts[6], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[6], projectdistance, temp, &verts[6]);
- VectorSubtract(&verts[9], e->origin, temp);
- VectorNormalize(temp);
- VectorMA(&verts[9], projectdistance, temp, &verts[9]);
- Mod_ShadowMesh_AddPolygon(loadmodel->mempool, e->shadowvolume, 4, verts);
- }
- }
- }
- // build the triangle mesh
- e->shadowvolume = Mod_ShadowMesh_Finish(loadmodel->mempool, e->shadowvolume);
- {
- shadowmesh_t *mesh;
- l = 0;
- for (mesh = e->shadowvolume;mesh;mesh = mesh->next)
- l += mesh->numtriangles;
- Con_Printf("light %i shadow volume built containing %i triangles\n", lnum, l);
- }
- }
- }
-}
-*/
-
-
static void Mod_Q1BSP_LoadVisibility(lump_t *l)
{
loadmodel->brushq1.num_compressedpvs = 0;
strcpy(value, com_token);
if (!strcmp("wad", key)) // for HalfLife maps
{
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
j = 0;
for (i = 0;i < 4096;i++)
return;
loadmodel->brush.entities = Mem_Alloc(loadmodel->mempool, l->filelen);
memcpy(loadmodel->brush.entities, mod_base + l->fileofs, l->filelen);
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
Mod_Q1BSP_ParseWadsFromEntityLump(loadmodel->brush.entities);
}
out = Mem_Alloc(loadmodel->mempool, count*sizeof(*out));
loadmodel->brushq1.submodels = out;
- loadmodel->brushq1.numsubmodels = count;
+ loadmodel->brush.numsubmodels = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
i = LittleLong(in->lightofs);
if (i == -1)
surf->samples = NULL;
- else if (loadmodel->brushq1.ishlbsp) // LordHavoc: HalfLife map (bsp version 30)
+ else if (loadmodel->brush.ishlbsp) // LordHavoc: HalfLife map (bsp version 30)
surf->samples = loadmodel->brushq1.lightdata + i;
else // LordHavoc: white lighting (bsp version 29)
surf->samples = loadmodel->brushq1.lightdata + (i * 3);
loadmodel->brushq1.leafs = out;
loadmodel->brushq1.numleafs = count;
- pvschainbytes = ((loadmodel->brushq1.num_leafs - 1)+7)>>3;
+ pvschainbytes = ((loadmodel->brushq1.numleafs - 1)+7)>>3;
loadmodel->brushq1.data_decompressedpvs = pvs = Mem_Alloc(loadmodel->mempool, loadmodel->brushq1.numleafs * pvschainbytes);
for ( i=0 ; i<count ; i++, in++, out++)
loadmodel->brushq1.clipnodes = out;
loadmodel->brushq1.numclipnodes = count;
- if (loadmodel->brushq1.ishlbsp)
+ if (loadmodel->brush.ishlbsp)
{
hull = &loadmodel->brushq1.hulls[1];
hull->clipnodes = out;
//of the given point.
int Mod_Q1BSP_FatPVS(model_t *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength)
{
- int bytes = ((model->brushq1.num_leafs - 1) + 7) >> 3;
+ int bytes = ((model->brushq1.numleafs - 1) + 7) >> 3;
bytes = min(bytes, pvsbufferlength);
memset(pvsbuffer, 0, bytes);
Mod_Q1BSP_FatPVS_RecursiveBSPNode(model, org, radius, pvsbuffer, bytes, sv.worldmodel->brushq1.nodes);
return bytes;
}
+static void Mod_Q1BSP_RoundUpToHullSize(model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
+{
+ vec3_t size;
+ const hull_t *hull;
+
+ VectorSubtract(inmaxs, inmins, size);
+ if (cmodel->brush.ishlbsp)
+ {
+ if (size[0] < 3)
+ hull = &cmodel->brushq1.hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ {
+ if (size[2] < 54) // pick the nearest of 36 or 72
+ hull = &cmodel->brushq1.hulls[3]; // 32x32x36
+ else
+ hull = &cmodel->brushq1.hulls[1]; // 32x32x72
+ }
+ else
+ hull = &cmodel->brushq1.hulls[2]; // 64x64x64
+ }
+ else
+ {
+ if (size[0] < 3)
+ hull = &cmodel->brushq1.hulls[0]; // 0x0x0
+ else if (size[0] <= 32)
+ hull = &cmodel->brushq1.hulls[1]; // 32x32x56
+ else
+ hull = &cmodel->brushq1.hulls[2]; // 64x64x88
+ }
+ VectorCopy(inmins, outmins);
+ VectorAdd(inmins, hull->clip_size, outmaxs);
+}
+
extern void R_Model_Brush_DrawSky(entity_render_t *ent);
extern void R_Model_Brush_Draw(entity_render_t *ent);
extern void R_Model_Brush_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
i = LittleLong(header->version);
if (i != BSPVERSION && i != 30)
Host_Error("Mod_Q1BSP_Load: %s has wrong version number(%i should be %i(Quake) or 30(HalfLife))", mod->name, i, BSPVERSION);
- mod->brushq1.ishlbsp = i == 30;
+ mod->brush.ishlbsp = i == 30;
+ mod->brush.AmbientSoundLevelsForPoint = Mod_Q1BSP_AmbientSoundLevelsForPoint;
mod->brush.FatPVS = Mod_Q1BSP_FatPVS;
mod->brush.BoxTouchingPVS = Mod_Q1BSP_BoxTouchingPVS;
mod->brush.LightPoint = Mod_Q1BSP_LightPoint;
mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
mod->brush.TraceBox = Mod_Q1BSP_TraceBox;
+ mod->brush.RoundUpToHullSize = Mod_Q1BSP_RoundUpToHullSize;
mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
if (loadmodel->isworldmodel)
{
- Cvar_SetValue("halflifebsp", mod->brushq1.ishlbsp);
+ Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
// until we get a texture for it...
R_ResetQuakeSky();
}
Mod_Q1BSP_MakePortals();
if (developer.integer)
- Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.numleafs, loadmodel->brushq1.num_leafs - 1, loadmodel->brushq1.numportals);
+ Con_Printf("Some stats for q1bsp model \"%s\": %i faces, %i nodes, %i leafs, %i visleafs, %i visleafportals\n", loadmodel->name, loadmodel->brushq1.numsurfaces, loadmodel->brushq1.numnodes, loadmodel->brushq1.numleafs, loadmodel->brushq1.numleafs - 1, loadmodel->brushq1.numportals);
mod->numframes = 2; // regular and alternate animation
//
// set up the submodels(FIXME: this is confusing)
//
- for (i = 0;i < mod->brushq1.numsubmodels;i++)
+ for (i = 0;i < mod->brush.numsubmodels;i++)
{
bm = &mod->brushq1.submodels[i];
if (surf->texinfo->texture->shader == &Cshader_sky)
mod->DrawSky = R_Model_Brush_DrawSky;
// LordHavoc: submodels always clip, even if water
- if (mod->brushq1.numsubmodels - 1)
+ if (mod->brush.numsubmodels - 1)
surf->flags |= SURF_SOLIDCLIP;
// calculate bounding shapes
for (mesh = surf->mesh;mesh;mesh = mesh->chain)
}
Mod_Q1BSP_BuildSurfaceNeighbors(mod->brushq1.surfaces + mod->brushq1.firstmodelsurface, mod->brushq1.nummodelsurfaces, originalloadmodel->mempool);
- mod->brushq1.numleafs = bm->visleafs;
+ mod->brushq1.visleafs = bm->visleafs;
// LordHavoc: only register submodels if it is the world
// (prevents bsp models from replacing world submodels)
- if (loadmodel->isworldmodel && i < (mod->brushq1.numsubmodels - 1))
+ if (loadmodel->isworldmodel && i < (mod->brush.numsubmodels - 1))
{
char name[10];
// duplicate the basic information
i = LittleLong(header->version);
if (i != Q2BSPVERSION)
Host_Error("Mod_Q2BSP_Load: %s has wrong version number (%i, should be %i)", mod->name, i, Q2BSPVERSION);
- mod->brushq1.ishlbsp = false;
+ mod->brush.ishlbsp = false;
if (loadmodel->isworldmodel)
{
- Cvar_SetValue("halflifebsp", mod->brushq1.ishlbsp);
+ Cvar_SetValue("halflifebsp", mod->brush.ishlbsp);
// until we get a texture for it...
R_ResetQuakeSky();
}
return pvsbufferlength;
}
+//extern void R_Q3BSP_DrawSky(struct entity_render_s *ent);
+extern void R_Q3BSP_Draw(struct entity_render_s *ent);
+//extern void R_Q3BSP_DrawFakeShadow(struct entity_render_s *ent);
+//extern void R_Q3BSP_DrawShadowVolume(struct entity_render_s *ent, vec3_t relativelightorigin, float lightradius);
+//extern void R_Q3BSP_DrawLight(struct entity_render_s *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
void Mod_Q3BSP_Load(model_t *mod, void *buffer)
{
int i;
mod->brush.LightPoint = Mod_Q3BSP_LightPoint;
mod->brush.FindNonSolidLocation = Mod_Q3BSP_FindNonSolidLocation;
mod->brush.TraceBox = Mod_Q3BSP_TraceBox;
- //mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
- //mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
+ //mod->DrawSky = R_Q3BSP_DrawSky;
+ mod->Draw = R_Q3BSP_Draw;
+ //mod->DrawFakeShadow = R_Q3BSP_DrawFakeShadow;
+ //mod->DrawShadowVolume = R_Q3BSP_DrawShadowVolume;
+ //mod->DrawLight = R_Q3BSP_DrawLight;
mod_base = (qbyte *)header;
typedef struct model_brush_s
{
+ // true if this model is a HalfLife .bsp file
+ qboolean ishlbsp;
+ // string of entity definitions (.map format)
char *entities;
+ // number of submodels in this map (just used by server to know how many
+ // submodels to load)
+ int numsubmodels;
+ // common functions
+ void (*AmbientSoundLevelsForPoint)(struct model_s *model, const vec3_t p, qbyte *out, int outsize);
int (*FatPVS)(struct model_s *model, const vec3_t org, vec_t radius, qbyte *pvsbuffer, int pvsbufferlength);
int (*BoxTouchingPVS)(struct model_s *model, const qbyte *pvs, const vec3_t mins, const vec3_t maxs);
void (*LightPoint)(struct model_s *model, const vec3_t p, vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal);
void (*FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius);
void (*TraceBox)(struct model_s *model, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs);
+ // this is actually only found on brushq1, but NULL is handled gracefully
+ void (*RoundUpToHullSize)(struct model_s *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs);
}
model_brush_t;
typedef struct model_brushq1_s
{
- // true if this model is a HalfLife .bsp file
- qboolean ishlbsp;
-
int firstmodelsurface, nummodelsurfaces;
// lightmap format, set to r_lightmaprgba when model is loaded
int lightmaprgba;
- int numsubmodels;
dmodel_t *submodels;
int numplanes;
mplane_t *planes;
- // number of visible leafs, not counting 0 (solid)
+ // number of actual leafs (including 0 which is solid)
int numleafs;
+ // visible leafs, not counting 0 (solid)
+ int visleafs;
mleaf_t *leafs;
int numvertexes;
Host_Error ("PF_Precache_*: Precache can only be done in spawn functions");
s = G_STRING(OFS_PARM0);
- if (sv.worldmodel->brushq1.ishlbsp && ((!s) || (!s[0])))
+ if (sv.worldmodel->brush.ishlbsp && ((!s) || (!s[0])))
return;
G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
PR_CheckEmptyString (s);
lightpvsbytes = 0;
if (r_vismarklights.integer && ent->model->brush.FatPVS)
lightpvsbytes = ent->model->brush.FatPVS(ent->model, lightorigin, 0, lightpvs, sizeof(lightpvs));
- R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.num_leafs - 1));
+ R_RecursiveMarkLights(ent, lightorigin, rd, bit, bitindex, ent->model->brushq1.nodes + ent->model->brushq1.hulls[0].firstclipnode, lightpvs, min(lightpvsbytes * 8, ent->model->brushq1.visleafs));
}
}
}
else
VectorSet(ambientcolor, 1, 1, 1);
- /*
- if (leaf == NULL && cl.worldmodel != NULL)
- leaf = cl.worldmodel->brushq1.PointInLeaf(cl.worldmodel, p);
- if (!leaf || leaf->contents == CONTENTS_SOLID || !cl.worldmodel->brushq1.lightdata)
- {
- VectorSet(ambientcolor, 1, 1, 1);
- return;
- }
- */
-
// FIXME: this .lights related stuff needs to be ported into the Mod_Q1BSP code
if (cl.worldmodel->brushq1.numlights)
{
if (r_shadow_texture3d.integer && !gl_texture3d)
Cvar_SetValueQuick(&r_shadow_texture3d, 0);
- //cl.worldmodel->brushq1.numlights = min(cl.worldmodel->brushq1.numlights, 1);
if (!r_shadow_attenuation2dtexture
|| (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
|| r_shadow_lightattenuationpower.value != r_shadow_attenpower
r_shadowstage = SHADOWSTAGE_NONE;
}
-#if 0
-int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const float *origin, float radius)
-{
- int i, ix1, iy1, ix2, iy2;
- float x1, y1, x2, y2, x, y;
- vec3_t smins, smaxs;
- vec4_t v, v2;
- if (!r_shadow_scissor.integer)
- return false;
- // if view is inside the box, just say yes it's visible
- if (r_origin[0] >= mins[0] && r_origin[0] <= maxs[0]
- && r_origin[1] >= mins[1] && r_origin[1] <= maxs[1]
- && r_origin[2] >= mins[2] && r_origin[2] <= maxs[2])
- {
- qglDisable(GL_SCISSOR_TEST);
- return false;
- }
- VectorSubtract(r_origin, origin, v);
- if (DotProduct(v, v) < radius * radius)
- {
- qglDisable(GL_SCISSOR_TEST);
- return false;
- }
- // create viewspace bbox
- for (i = 0;i < 8;i++)
- {
- v[0] = ((i & 1) ? mins[0] : maxs[0]) - r_origin[0];
- v[1] = ((i & 2) ? mins[1] : maxs[1]) - r_origin[1];
- v[2] = ((i & 4) ? mins[2] : maxs[2]) - r_origin[2];
- v2[0] = DotProduct(v, vright);
- v2[1] = DotProduct(v, vup);
- v2[2] = DotProduct(v, vpn);
- if (i)
- {
- if (smins[0] > v2[0]) smins[0] = v2[0];
- if (smaxs[0] < v2[0]) smaxs[0] = v2[0];
- if (smins[1] > v2[1]) smins[1] = v2[1];
- if (smaxs[1] < v2[1]) smaxs[1] = v2[1];
- if (smins[2] > v2[2]) smins[2] = v2[2];
- if (smaxs[2] < v2[2]) smaxs[2] = v2[2];
- }
- else
- {
- smins[0] = smaxs[0] = v2[0];
- smins[1] = smaxs[1] = v2[1];
- smins[2] = smaxs[2] = v2[2];
- }
- }
- // now we have a bbox in viewspace
- // clip it to the viewspace version of the sphere
- v[0] = origin[0] - r_origin[0];
- v[1] = origin[1] - r_origin[1];
- v[2] = origin[2] - r_origin[2];
- v2[0] = DotProduct(v, vright);
- v2[1] = DotProduct(v, vup);
- v2[2] = DotProduct(v, vpn);
- if (smins[0] < v2[0] - radius) smins[0] = v2[0] - radius;
- if (smaxs[0] < v2[0] - radius) smaxs[0] = v2[0] + radius;
- if (smins[1] < v2[1] - radius) smins[1] = v2[1] - radius;
- if (smaxs[1] < v2[1] - radius) smaxs[1] = v2[1] + radius;
- if (smins[2] < v2[2] - radius) smins[2] = v2[2] - radius;
- if (smaxs[2] < v2[2] - radius) smaxs[2] = v2[2] + radius;
- // clip it to the view plane
- if (smins[2] < 1)
- smins[2] = 1;
- // return true if that culled the box
- if (smins[2] >= smaxs[2])
- return true;
- // ok some of it is infront of the view, transform each corner back to
- // worldspace and then to screenspace and make screen rect
- // initialize these variables just to avoid compiler warnings
- x1 = y1 = x2 = y2 = 0;
- for (i = 0;i < 8;i++)
- {
- v2[0] = (i & 1) ? smins[0] : smaxs[0];
- v2[1] = (i & 2) ? smins[1] : smaxs[1];
- v2[2] = (i & 4) ? smins[2] : smaxs[2];
- v[0] = v2[0] * vright[0] + v2[1] * vup[0] + v2[2] * vpn[0] + r_origin[0];
- v[1] = v2[0] * vright[1] + v2[1] * vup[1] + v2[2] * vpn[1] + r_origin[1];
- v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_origin[2];
- v[3] = 1.0f;
- GL_TransformToScreen(v, v2);
- //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
- x = v2[0];
- y = v2[1];
- if (i)
- {
- if (x1 > x) x1 = x;
- if (x2 < x) x2 = x;
- if (y1 > y) y1 = y;
- if (y2 < y) y2 = y;
- }
- else
- {
- x1 = x2 = x;
- y1 = y2 = y;
- }
- }
- /*
- // this code doesn't handle boxes with any points behind view properly
- x1 = 1000;x2 = -1000;
- y1 = 1000;y2 = -1000;
- for (i = 0;i < 8;i++)
- {
- v[0] = (i & 1) ? mins[0] : maxs[0];
- v[1] = (i & 2) ? mins[1] : maxs[1];
- v[2] = (i & 4) ? mins[2] : maxs[2];
- v[3] = 1.0f;
- GL_TransformToScreen(v, v2);
- //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
- if (v2[2] > 0)
- {
- x = v2[0];
- y = v2[1];
-
- if (x1 > x) x1 = x;
- if (x2 < x) x2 = x;
- if (y1 > y) y1 = y;
- if (y2 < y) y2 = y;
- }
- }
- */
- ix1 = x1 - 1.0f;
- iy1 = y1 - 1.0f;
- ix2 = x2 + 1.0f;
- iy2 = y2 + 1.0f;
- //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
- if (ix1 < r_refdef.x) ix1 = r_refdef.x;
- if (iy1 < r_refdef.y) iy1 = r_refdef.y;
- if (ix2 > r_refdef.x + r_refdef.width) ix2 = r_refdef.x + r_refdef.width;
- if (iy2 > r_refdef.y + r_refdef.height) iy2 = r_refdef.y + r_refdef.height;
- if (ix2 <= ix1 || iy2 <= iy1)
- return true;
- // set up the scissor rectangle
- qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1);
- qglEnable(GL_SCISSOR_TEST);
- c_rt_scissored++;
- return false;
-}
-#endif
-
int R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
{
int i, ix1, iy1, ix2, iy2;
static int castshadowcount = 1;
void R_Shadow_NewWorldLight(vec3_t origin, float radius, vec3_t color, int style, const char *cubemapname, int castshadow)
{
- int i, j, k, l, maxverts = 256, *mark, tris;
- float *vertex3f = NULL;
+ int i, j, k, l, maxverts = 256, *mark, tris, numsurfaces;
+ float *vertex3f = NULL, mins[3], maxs[3];
worldlight_t *e;
shadowmesh_t *mesh, *castmesh;
mleaf_t *leaf;
e->cullradius = e->lightradius;
for (k = 0;k < 3;k++)
{
- e->mins[k] = e->origin[k] - e->lightradius;
- e->maxs[k] = e->origin[k] + e->lightradius;
+ mins[k] = e->origin[k] - e->lightradius;
+ maxs[k] = e->origin[k] + e->lightradius;
}
e->next = r_shadow_worldlightchain;
if (cl.worldmodel)
{
castshadowcount++;
+ VectorCopy(e->origin, e->mins);
+ VectorCopy(e->origin, e->maxs);
i = CL_PointContents(e->origin);
if (r_shadow_portallight.integer && i != CONTENTS_SOLID && i != CONTENTS_SKY)
{
Portal_Visibility(cl.worldmodel, e->origin, byteleafpvs, bytesurfacepvs, NULL, 0, true, RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin));
for (i = 0, leaf = cl.worldmodel->brushq1.leafs;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
- if (byteleafpvs[i] && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
- leaf->worldnodeframe = castshadowcount;
+ {
+ if (byteleafpvs[i] && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
+ {
+ for (k = 0;k < 3;k++)
+ {
+ if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
+ if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
+ }
+ }
+ }
for (i = 0, surf = cl.worldmodel->brushq1.surfaces;i < cl.worldmodel->brushq1.numsurfaces;i++, surf++)
- if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs))
+ if (bytesurfacepvs[i] && BoxesOverlap(surf->poly_mins, surf->poly_maxs, mins, maxs))
surf->castshadow = castshadowcount;
Mem_Free(byteleafpvs);
else
{
lightpvsbytes = cl.worldmodel->brush.FatPVS(cl.worldmodel, origin, 0, lightpvs, sizeof(lightpvs));
- for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs - 1;i++, leaf++)
+ for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.visleafs;i++, leaf++)
{
- if (lightpvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, e->mins, e->maxs))
+ if (lightpvs[i >> 3] & (1 << (i & 7)) && BoxesOverlap(leaf->mins, leaf->maxs, mins, maxs))
{
- leaf->worldnodeframe = castshadowcount;
+ for (k = 0;k < 3;k++)
+ {
+ if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
+ if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
+ }
for (j = 0, mark = leaf->firstmarksurface;j < leaf->nummarksurfaces;j++, mark++)
{
surf = cl.worldmodel->brushq1.surfaces + *mark;
- if (surf->castshadow != castshadowcount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, e->mins, e->maxs))
+ if (surf->castshadow != castshadowcount && BoxesOverlap(surf->poly_mins, surf->poly_maxs, mins, maxs))
surf->castshadow = castshadowcount;
}
}
}
}
- e->numleafs = 0;
- for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
- if (leaf->worldnodeframe == castshadowcount)
- e->numleafs++;
- e->numsurfaces = 0;
- for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
- if (surf->castshadow == castshadowcount)
- e->numsurfaces++;
-
- if (e->numleafs)
- e->leafs = Mem_Alloc(r_shadow_mempool, e->numleafs * sizeof(mleaf_t *));
- if (e->numsurfaces)
- e->surfaces = Mem_Alloc(r_shadow_mempool, e->numsurfaces * sizeof(msurface_t *));
- e->numleafs = 0;
- for (i = 0, leaf = cl.worldmodel->brushq1.leafs + 1;i < cl.worldmodel->brushq1.numleafs;i++, leaf++)
- if (leaf->worldnodeframe == castshadowcount)
- e->leafs[e->numleafs++] = leaf;
- e->numsurfaces = 0;
- for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
- if (surf->castshadow == castshadowcount)
- e->surfaces[e->numsurfaces++] = surf;
-
- // find bounding box of lit leafs
- VectorCopy(e->origin, e->mins);
- VectorCopy(e->origin, e->maxs);
- for (j = 0;j < e->numleafs;j++)
- {
- leaf = e->leafs[j];
- for (k = 0;k < 3;k++)
- {
- if (e->mins[k] > leaf->mins[k]) e->mins[k] = leaf->mins[k];
- if (e->maxs[k] < leaf->maxs[k]) e->maxs[k] = leaf->maxs[k];
- }
- }
-
for (k = 0;k < 3;k++)
{
if (e->mins[k] < e->origin[k] - e->lightradius) e->mins[k] = e->origin[k] - e->lightradius;
}
e->cullradius = RadiusFromBoundsAndOrigin(e->mins, e->maxs, e->origin);
+ numsurfaces = 0;
+ for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
+ if (surf->castshadow == castshadowcount)
+ numsurfaces++;
+ if (numsurfaces)
+ e->surfaces = Mem_Alloc(r_shadow_mempool, numsurfaces * sizeof(msurface_t *));
+ e->numsurfaces = 0;
+ for (i = 0, surf = cl.worldmodel->brushq1.surfaces + cl.worldmodel->brushq1.firstmodelsurface;i < cl.worldmodel->brushq1.nummodelsurfaces;i++, surf++)
+ if (surf->castshadow == castshadowcount)
+ e->surfaces[e->numsurfaces++] = surf;
+
if (e->castshadows)
{
castshadowcount++;
Con_Printf("static shadow volume built containing %i triangles\n", l);
}
}
- Con_Printf("%f %f %f, %f %f %f, %f, %f, %d, %d\n", e->mins[0], e->mins[1], e->mins[2], e->maxs[0], e->maxs[1], e->maxs[2], e->cullradius, e->lightradius, e->numleafs, e->numsurfaces);
+ Con_Printf("%f %f %f, %f %f %f, %f, %f, %d\n", e->mins[0], e->mins[1], e->mins[2], e->maxs[0], e->maxs[1], e->maxs[2], e->cullradius, e->lightradius, e->numsurfaces);
}
void R_Shadow_FreeWorldLight(worldlight_t *light)
Mod_ShadowMesh_Free(light->shadowvolume);
if (light->surfaces)
Mem_Free(light->surfaces);
- if (light->leafs)
- Mem_Free(light->leafs);
Mem_Free(light);
}
void R_Shadow_Stage_LightWithShadows(void);
void R_Shadow_Stage_LightWithoutShadows(void);
void R_Shadow_Stage_End(void);
-//int R_Shadow_ScissorForBBoxAndSphere(const float *mins, const float *maxs, const float *origin, float radius);
int R_Shadow_ScissorForBBox(const float *mins, const float *maxs);
typedef struct worldlight_s
struct worldlight_s *next;
msurface_t **surfaces;
int numsurfaces;
- mleaf_t **leafs;
- int numleafs;
rtexture_t *cubemap;
int style;
shadowmesh_t *shadowvolume;
#ifndef RENDER_H
#define RENDER_H
+extern qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3];
+
extern matrix4x4_t r_identitymatrix;
// 1.0f / N table
//#define PARANOID 1
int R_CullBox(const vec3_t mins, const vec3_t maxs);
-int PVS_CullBox(const vec3_t mins, const vec3_t maxs);
-int R_CullSphere(const vec3_t origin, vec_t radius);
-int PVS_CullSphere(const vec3_t origin, vec_t radius);
extern qboolean fogenabled;
extern vec3_t fogcolor;
*/
void S_UpdateAmbientSounds (void)
{
- mleaf_t *l;
float vol;
int ambient_channel;
channel_t *chan;
+ qbyte ambientlevels[NUM_AMBIENTS];
// LordHavoc: kill ambient sounds until proven otherwise
for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++)
channels[ambient_channel].sfx = NULL;
- if (!snd_ambient || ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brushq1.PointInLeaf || (l = cl.worldmodel->brushq1.PointInLeaf(cl.worldmodel, listener_origin)) == NULL)
+ if (!snd_ambient || ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint)
return;
+ cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels));
+
// calc ambient sound levels
for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
{
chan->forceloop = true;
chan->sfx = ambient_sfx[ambient_channel];
- vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
+ vol = ambient_level.value * ambientlevels[ambient_channel];
if (vol < 8)
vol = 0;
// sv_main.c -- server main program
#include "quakedef.h"
-#include "portals.h"
static cvar_t sv_cullentities_pvs = {0, "sv_cullentities_pvs", "0"}; // fast but loose
-static cvar_t sv_cullentities_portal = {0, "sv_cullentities_portal", "0"}; // extremely accurate visibility checking, but too slow
static cvar_t sv_cullentities_trace = {0, "sv_cullentities_trace", "1"}; // tends to get false negatives, uses a timeout to keep entities visible a short time after becoming hidden
static cvar_t sv_cullentities_stats = {0, "sv_cullentities_stats", "0"};
static cvar_t sv_entpatch = {0, "sv_entpatch", "1"};
Cvar_RegisterVariable (&sv_nostep);
Cvar_RegisterVariable (&sv_deltacompress);
Cvar_RegisterVariable (&sv_cullentities_pvs);
- Cvar_RegisterVariable (&sv_cullentities_portal);
Cvar_RegisterVariable (&sv_cullentities_trace);
Cvar_RegisterVariable (&sv_cullentities_stats);
Cvar_RegisterVariable (&sv_entpatch);
void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
{
int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects, lightsize;
- int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities;
+ int culled_pvs, culled_trace, visibleentities, totalentities;
qbyte *pvs;
vec3_t origin, angles, entmins, entmaxs, testorigin, testeye;
float nextfullupdate, alphaf;
fatbytes = sv.worldmodel->brush.FatPVS(sv.worldmodel, testeye, 8, sv_writeentitiestoclient_pvs, sizeof(sv_writeentitiestoclient_pvs));
culled_pvs = 0;
- culled_portal = 0;
culled_trace = 0;
visibleentities = 0;
totalentities = 0;
continue;
}
- // or not visible through the portals
- if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, testeye, entmins, entmaxs))
- {
- culled_portal++;
- continue;
- }
-
// don't try to cull embedded brush models with this, they're sometimes huge (spanning several rooms)
if (sv_cullentities_trace.integer && (model == NULL || model->type != mod_brush || model->name[0] != '*'))
{
}
if (sv_cullentities_stats.integer)
- Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_portal + culled_trace, culled_pvs, culled_portal, culled_trace);
+ Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_trace, culled_pvs, culled_trace);
}
#else
static int numsendentities;
static int sententities[MAX_EDICTS];
static int sententitiesconsideration[MAX_EDICTS];
static int sv_writeentitiestoclient_culled_pvs;
-static int sv_writeentitiestoclient_culled_portal;
static int sv_writeentitiestoclient_culled_trace;
static int sv_writeentitiestoclient_visibleentities;
static int sv_writeentitiestoclient_totalentities;
sv_writeentitiestoclient_culled_pvs++;
return;
}
- // or not visible through the portals
- if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, sv_writeentitiestoclient_testeye, lightmins, lightmaxs))
- {
- sv_writeentitiestoclient_culled_portal++;
- return;
- }
// or not seen by random tracelines
if (sv_cullentities_trace.integer)
{
sv_writeentitiestoclient_client = client;
sv_writeentitiestoclient_culled_pvs = 0;
- sv_writeentitiestoclient_culled_portal = 0;
sv_writeentitiestoclient_culled_trace = 0;
sv_writeentitiestoclient_visibleentities = 0;
sv_writeentitiestoclient_totalentities = 0;
d->currentcommit = NULL;
if (sv_cullentities_stats.integer)
- Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_portal + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_portal, sv_writeentitiestoclient_culled_trace);
+ Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
}
#endif
sv.model_precache[0] = "";
sv.model_precache[1] = sv.modelname;
- for (i = 1;i < sv.worldmodel->brushq1.numsubmodels;i++)
+ for (i = 1;i < sv.worldmodel->brush.numsubmodels;i++)
{
sv.model_precache[i+1] = localmodels[i];
sv.models[i+1] = Mod_ForName (localmodels[i], false, false, false);
- todo: difficulty ratings are: 0 = trivial, 1 = easy, 2 = easy-moderate, 3 = moderate, 4 = moderate-hard, 5 = hard, 6 = hard++, 7 = nightmare, d = done, -n = done but have not notified the people who asked for it, f = failed
-d darkplaces: finish the partial update support in protocol.[ch] and reduce packet size to 1k to fix NAT routers (yummyluv, Vermeulen, Elric)
-d darkplaces: fix server crashing from client timeouts (Moz)
-d darkplaces: fix server list only querying the master to reply (Rick)
-d darkplaces: fix sounds not following entities (yummyluv, SeienAbunae)
+-n darkplaces: revert noclip movement to match nq for compatibility with mods that trap movement as input (MauveBib)
-n dpmod: make grapple off-hand (joe hill)
-0 dpmod: add a "monsterwander" cvar and default it off, this would enable the spawnwanderpath code (Zombie13)
-0 darkplaces: stuttering movement when walking over steps or monsters (romi)
-0 darkplaces: bullets don't hit walls at steep angles in id1
-0 darkplaces: hack PF_nextent to skip inaccessible client slots depending on maxplayers - but always report ones that are active at the time (FrikaC)
-0 darkplaces: client colors being reset to "15 15" each level in prydon gate (FrikaC)
-0 darkplaces: make lightning work without bolt models persent (Vermeulen)
-0 darkplaces: make the WriteEntitiesToClient code call TraceBox directly instead of SV_Move because checking all the entities is far too slow in helm18 (banshee21)
-0 darkplaces: add te_flamejet builtin and add extension (Supajoe)
-0 darkplaces: pointcontents crash when building harvester in gvb2? (yummyluv)
-0 darkplaces: integrate zinx's psycho.c gamma hack as an easteregg
-0 dpmod: crash when dog attacks you in dpdm2 deathmatch 7 with bots present (Zombie13)
-0 dpmod: identify what could cause huge angles values (1187488512.0000) on a dog entity, may be related to anglemod, FacingIdeal, ai_run, or dog_run2 (Zombie13)
-0 dpmod: modify anglemod to be able to recover from extremely large angles numbers (Zombie13)
-0 darkplaces: add error messages to LHNET_OpenSocket_Connectionless or its callers (Zombie13)
-0 dpmod: find a way to make deathmatch 7 get more difficulty as kills increase? (Zombie13)
-0 darkplaces: can't move when stuck in a monster (SeienAbunae)
-0 dpmod: monsters falling out of level? (SeienAbunae)
-0 dpmod: add killing spree reporting; how many kills since spawn when you die, as well as announcing when you hit certain numbers of kills (SeienAbunae)
-0 dpmod: add combo kill detection; rapid burst of kills (SeienAbunae)
-0 darkplaces: may be reading md3 tag matrices wrong (Electro)
-d dpmod: add back charge-up on plasma rifle alt-fire and increase the max charge to 50 cells
-0 darkplaces: make sure that disappearing entities are removed on the client in quake demos, they aren't currently
-0 darkplaces: scrags frequently fly through ceilings - this needs to be fixed
-0 dpmod: set oldorigin when spawning to prevent being stuck at the spawn from causing an instant teleport back to where you died (SeienAbunae)
-0 darkplaces: model interpolation off crashes? (SeienAbunae)
-0 dpmod: impulse 102 isn't removing the bots (SeienAbunae)
-d dpmod: make enforcers drop more cells for plasma gun (SeienAbunae)
-d dpmod: make tarbabies easier to kill? (SeienAbunae)
-f dpmod: make tarbabies have a self.resist_explosive = 3; like zombies (SeienAbunae)
-d dpmod: make tarbabies explode larger (SeienAbunae)
-0 darkplaces: make sure that sound engine does not remove sounds when volume drops to 0 due to going out of range (SeienAbunae)
-0 darkplaces: crashes if you type too long a command line in the console (SeienAbunae)
-0 darkplaces: fix 'wall hugging' stuttering (romi)
-0 darkplaces: fix intermission failing to move view to intermission camera (romi, Zombie_13)
-0 darkplaces: fix key based turning being affected by slowmo - it should not be
-0 darkplaces: add view height to chase_active again (yummyluv)
-0 darkplaces: examine the surface rendering code to make sure it has no bugs regarding texture selection for any of the passes (sublim3)
-1 darkplaces: add rate command (and _cl_rate cvar to save to config) to control client rate (send to server on connect as a command, like other properties) (Transfusion)
-3 darkplaces: add sv_rate cvar (limits total rate of the server - rather complicated rules to distribute rate between clients on the server, honoring their requests as best as possible) (Transfusion)
0 darkplaces: ability to disable fopen builtin access to read /, read data/, write data/, or disable fopen builtin entirely
0 darkplaces: add DP_GFX_QUAKE3MODELTAGS, DP_GFX_SKINFILES, and any other new extensions to the wiki
0 darkplaces: add DP_LITSUPPORT extension
0 darkplaces: add bullet hole decals to the particlefont (Vermeulen)
0 darkplaces: add cl_particles_quality cvar (1-10) which would scale count of particles and inversely scale alpha of particles (TheBeast)
0 darkplaces: add cvars for sbar alpha (background and foreground) (Throvold@uboot.com)
+0 darkplaces: add error messages to LHNET_OpenSocket_Connectionless or its callers (Zombie13)
0 darkplaces: add lightning beam settings to menu (romi)
0 darkplaces: add svc_setanglefloat and DP_SVC_SETANGLEFLOAT extension (FrikaC, SeienAbunae)
+0 darkplaces: add te_flamejet builtin and add extension (Supajoe)
+0 darkplaces: add view height to chase_active again (yummyluv)
+0 darkplaces: bullets don't hit walls at steep angles in id1
+0 darkplaces: can't move when stuck in a monster (SeienAbunae)
0 darkplaces: change particle() macro in cl_particles.c to have a do{}while(0) to eat the ;
0 darkplaces: check out qe1 textures and make sure they load in all the e1 maps, report of crashing in most but not all maps (Linny Amore)
0 darkplaces: cl_particles_maximum cvar (default 32768) which would change number of particles allowed at once (TheBeast)
+0 darkplaces: client colors being reset to "15 15" each level in prydon gate (FrikaC)
+0 darkplaces: crashes if you type too long a command line in the console (SeienAbunae)
0 darkplaces: darkplaces-glx -path transfusion crashes, fix the crash even though it's not going to work anyway (Todd)
0 darkplaces: default to 32bit color
0 darkplaces: delay "connect" and "playdemo" and "timedemo" until after video init to cause quicker video startup (KrimZon)
0 darkplaces: document how polygon collision works in the code (KrimZon)
0 darkplaces: document the TEI stuff used in Nexuiz? check telejano site first (SeienAbunae)
+0 darkplaces: examine the surface rendering code to make sure it has no bugs regarding texture selection for any of the passes (sublim3)
0 darkplaces: figure out and fix the 'rubbing against a moving door causes block' bug (Static_Fiend)
0 darkplaces: figure out random crashes on map changes (Uffe, QorpsE)
0 darkplaces: figure out what's wrong with gloss rendering vertex calculations, which may be GF2 related (QorpsE)
0 darkplaces: figure out why monsters keep making fall pain sound after they've landed in dpmod (Cruaich)
+0 darkplaces: fix 'wall hugging' stuttering (romi)
0 darkplaces: fix a crash when changing level while using qe1 textures (Todd)
0 darkplaces: fix con_notify (should control number of lines)
+0 darkplaces: fix intermission failing to move view to intermission camera (romi, Zombie_13)
+0 darkplaces: fix key based turning being affected by slowmo - it should not be
0 darkplaces: fix skybox geometry (SeienAbunae)
0 darkplaces: fix the fact singleplayer is using maxplayers 8
0 darkplaces: fix view blends slightly lingering as time goes on, they should go away completely (Cruaich)
-2 darkplaces: frikbot scores don't update - discovered this is because of the fact they have no client (Todd)
0 darkplaces: get rid of stencil options and make 32bit color automatically use stencil
+0 darkplaces: hack PF_nextent to skip inaccessible client slots depending on maxplayers - but always report ones that are active at the time (FrikaC)
0 darkplaces: identify weird lightmap texturing bug on TNT cards - goes away in r_textureunits 1 (NotoriousRay, Uffe)
+0 darkplaces: integrate zinx's psycho.c gamma hack as an easteregg
0 darkplaces: make Com_HexDumpToConsole not use color
0 darkplaces: make DP_EF_FULLBRIGHT extension (FrikaC)
0 darkplaces: make S_Update take a matrix4x4_t *
0 darkplaces: make a flag for rtlights that makes them appear in normal mode (not just r_shadow_realtime_world mode) (Vermeulen)
0 darkplaces: make dedicated server not load images (maybe all fail?)
0 darkplaces: make fopen builtin check / as well as data/ when reading (writing would always go in data/)
+0 darkplaces: make lightning work without bolt models persent (Vermeulen)
0 darkplaces: make memory pools have a flag to print them as temporary pools (I.E. consider them leaks if anything is in them) (Vicious)
0 darkplaces: make server queries use a queue to avoid flooding out queries too fast, and then change the reply receive code drop packets from servers not in the list (Willis)
0 darkplaces: make sure EF_FULLBRIGHT works on bmodels (FrikaC)
0 darkplaces: make sure PR_SetString points NULL strings at pr_strings (which would be an offset of 0) (Fuh)
0 darkplaces: make sure QuakeDoneQuick works (Chris Kemp)
0 darkplaces: make sure r_fullbright works - need to fix maxplayers checking
+0 darkplaces: make sure that disappearing entities are removed on the client in quake demos, they aren't currently
0 darkplaces: make sure that sky works without a valid size (just treat it as single layer clouds or non-animated) (tell Vermeulen)
+0 darkplaces: make sure that sound engine does not remove sounds when volume drops to 0 due to going out of range (SeienAbunae)
+0 darkplaces: make the WriteEntitiesToClient code call TraceBox directly instead of SV_Move because checking all the entities is far too slow in helm18 (banshee21)
+0 darkplaces: may be reading md3 tag matrices wrong (Electro)
+0 darkplaces: model interpolation off crashes? (SeienAbunae)
+0 darkplaces: pointcontents crash when building harvester in gvb2? (yummyluv)
0 darkplaces: r_shadow should load .ent when importing light entities
0 darkplaces: r_skyscroll1 and r_skyscroll2 cvars (SeienAbunae)
0 darkplaces: rename r_picmip and r_max_size and such to glquake names
0 darkplaces: reset zoom on connect (Rick)
--n darkplaces: revert noclip movement to match nq for compatibility with mods that trap movement as input (MauveBib)
+0 darkplaces: scrags frequently fly through ceilings - this needs to be fixed
0 darkplaces: segfault reading memory in windows when starting a new server from menu (yummyluv)
+0 darkplaces: stuttering movement when walking over steps or monsters (romi)
0 darkplaces: test TecnoX and find the frikbot crash in SV_Physics (KrimZon)
0 darkplaces: test zlib support with entirely pk3'd id1 data (should crash because of zlib not being setup early enough - fix this) (Mabus)
0 darkplaces: the new sound engine should have a cvar for random variations of pitch on sounds like in doom (RenegadeC)
0 darkplaces: try not adding gravity when onground to see if it gets rid of ramp sliding (Midgar)
0 darkplaces: tweak the blood decals in the particlefont to make them look more like the q2e_blood.avi video (Vermeulen)
+0 dpmod: add a "monsterwander" cvar and default it off, this would enable the spawnwanderpath code (Zombie13)
+0 dpmod: add combo kill detection; rapid burst of kills (SeienAbunae)
0 dpmod: add flame thrower enforcers back (scar3crow)
0 dpmod: add flame thrower weapon, and make its altfire drop a canister of fuel (10 fuel units?), which can be ignited to set off as a bomb about the size of a rocket blast, plus some fireballs raining down (scar3crow)
+0 dpmod: add killing spree reporting; how many kills since spawn when you die, as well as announcing when you hit certain numbers of kills (SeienAbunae)
+0 dpmod: crash when dog attacks you in dpdm2 deathmatch 7 with bots present (Zombie13)
+0 dpmod: find a way to make deathmatch 7 get more difficulty as kills increase? (Zombie13)
+0 dpmod: identify what could cause huge angles values (1187488512.0000) on a dog entity, may be related to anglemod, FacingIdeal, ai_run, or dog_run2 (Zombie13)
+0 dpmod: impulse 102 isn't removing the bots (SeienAbunae)
0 dpmod: impulse 154 should cycle to deathmatch 7 (Rick)
0 dpmod: items aren't respawning in coop, they should
+0 dpmod: modify anglemod to be able to recover from extremely large angles numbers (Zombie13)
+0 dpmod: monsters falling out of level? (SeienAbunae)
+0 dpmod: set oldorigin when spawning to prevent being stuck at the spawn from causing an instant teleport back to where you died (SeienAbunae)
0 dpmod: try making ball lightning mortar shamblers (scar3crow)
0 dpmod: up nail limit to 500 (scar3crow)
0 dpzoo: colored lighting
1 darkplaces: add log cvar to set console logging target (default "", or default "qconsole.log" if -condebug is used)
1 darkplaces: add r_displayrefresh cvar for windows video refresh settings (Willis)
1 darkplaces: add r_waterwarp to allow disabling view squishing underwater
+1 darkplaces: add rate command (and _cl_rate cvar to save to config) to control client rate (send to server on connect as a command, like other properties) (Transfusion)
1 darkplaces: add some particles to teleportsplash (Uffe)
1 darkplaces: check out QMB lightning and lava effects (jeremy janzen)
1 darkplaces: clear stainmaps on map restart/change based on cl_stainmapsclearonload cvar (John Truex, Electro)
2 darkplaces: add stats to slist menu displaying how many masters/servers have been queried and replied (tell yummyluv)
2 darkplaces: figure out how to prevent "alias a a" - infinite loop when executed, this should be detected when executing it (Vicious)
2 darkplaces: figure out why -sndspeed 22050, 44100 and 16000 are choppy in windows? (cheapalert)
+2 darkplaces: frikbot scores don't update - discovered this is because of the fact they have no client (Todd)
2 darkplaces: implement menu_clearkeyconfig and menu_keyconfig and the corresponding menu (diGGer)
2 darkplaces: lerp lightstyles (Mitchell)
2 darkplaces: locked console scrollback (sublim3)
3 darkplaces: add back r_waterripple (Vermeulen)
3 darkplaces: add ogg music playback using optional library after adding wav music playback (Joseph Caporale, Static_Fiend)
3 darkplaces: add stainmaps to realtime lighting mode
+3 darkplaces: add sv_rate cvar (limits total rate of the server - rather complicated rules to distribute rate between clients on the server, honoring their requests as best as possible) (Transfusion)
3 darkplaces: call checkvelocity (to clear NaNs) every time velocity is set in physics, to fix frikbot (tell FrikaC)
3 darkplaces: dpshaders (when supported) should have support for envmaps, and should support being lit by diffuse lighting as a fake gloss effect for normal mode (Vermeulen)
3 darkplaces: dsound broken, needs to be managed as part of video system (jeremy janzen)
d darkplaces: figure out why disconnections are showing up as " disconnected"
d darkplaces: figure out why quad is creating two coronas, one at player and one at 0 0 0 - answer: viewmodel dlight (Tomaz)
d darkplaces: finish new udp networking code (yummyluv)
+d darkplaces: finish the partial update support in protocol.[ch] and reduce packet size to 1k to fix NAT routers (yummyluv, Vermeulen, Elric)
d darkplaces: fix PF_substring's mishandling of the end variable (Fuh)
d darkplaces: fix Short format entity origins to fix shell casings sitting in floor/above floor (Tomaz)
d darkplaces: fix bounding box bugs with viewmodelforclient (diGGer)
d darkplaces: fix network timeouts
d darkplaces: fix non-polygonal lightning beam model pitch (it was backwards) (thanks Eksess for reporting this)
d darkplaces: fix particle trails (I think trail start is identical to trail end) (Supajoe, SeienAbunae)
+d darkplaces: fix server crashing from client timeouts (Moz)
d darkplaces: fix server list not working until you set maxplayers above 1 (Rick)
+d darkplaces: fix server list only querying the master to reply (Rick)
+d darkplaces: fix sounds not following entities (yummyluv, SeienAbunae)
d darkplaces: fix starting non-existent maps. (drops to console with an error like it should)
d darkplaces: fix startup on multiplayer games so they don't start a game when executing startdemos unless -listen or -dedicated was used (yummyluv)
d darkplaces: fix toggling decals in menu
d darkplaces: release new hqbsp with -wadpath support (also searchs in map's directory and map's parent directory)
d darkplaces: remove frags per hour rating from scoreboard because it depends on cl.scores[i]->entertime (which is never set)
d darkplaces: tags support on md3 (Electro needs this urgently)
+d dpmod: add back charge-up on plasma rifle alt-fire and increase the max charge to 50 cells
d dpmod: add back tarbaby gibs (scar3crow)
d dpmod: add frags for killing monsters in dpmod (scar3crow)
d dpmod: change weapons 8-10 to lightning, plasma, plasma wave (joe hill)
d dpmod: fix backpacks (giving no ammo)
+d dpmod: make enforcers drop more cells for plasma gun (SeienAbunae)
+d dpmod: make tarbabies easier to kill? (SeienAbunae)
+d dpmod: make tarbabies explode larger (SeienAbunae)
d dpmod: post new dpmod build.
d dpmod: switch to new Tomaz weapon models
d dpmod: why can't I pick up nails when I have no nailguns? and other similar pickup problems with weapons
f darkplaces: add _0.tga support (per texture) to bsp/md2/md3 loaders
f darkplaces: examine proquake code to find nat fix and implement similar in darkplaces
f darkplaces: look at and integrate Vic's updated zone.[ch] (Vic)
+f dpmod: make tarbabies have a self.resist_explosive = 3; like zombies (SeienAbunae)
*/
cvar_t sv_debugmove = {CVAR_NOTIFY, "sv_debugmove", "0"};
-cvar_t sv_polygoncollisions = {CVAR_NOTIFY, "sv_polygoncollisions", "0"};
cvar_t sv_areagrid_mingridsize = {CVAR_NOTIFY, "sv_areagrid_mingridsize", "64"};
void SV_AreaStats_f(void);
void SV_World_Init(void)
{
Cvar_RegisterVariable(&sv_debugmove);
- Cvar_RegisterVariable(&sv_polygoncollisions);
Cvar_RegisterVariable(&sv_areagrid_mingridsize);
Cmd_AddCommand("sv_areastats", SV_AreaStats_f);
Collision_Init();
VectorAdd(starttransformed, mins, starttransformedmins);
VectorAdd(endtransformed, mins, endtransformedmins);
- // FIXME: the PolygonClipTrace should go away (should all be done in model code)
- if (sv_polygoncollisions.integer == 1)
- Collision_PolygonClipTrace(&trace, ent, model, vec3_origin, vec3_origin, ent->v->mins, ent->v->maxs, starttransformed, mins, maxs, endtransformed);
- else if (model && model->brush.TraceBox)
+ if (model && model->brush.TraceBox)
model->brush.TraceBox(model, &trace, starttransformedmins, starttransformedmaxs, endtransformedmins, endtransformedmaxs);
else
Collision_ClipTrace_Box(&trace, ent->v->mins, ent->v->maxs, starttransformed, mins, maxs, endtransformed);
clip.type = type;
clip.passedict = passedict;
- Collision_RoundUpToHullSize(sv.worldmodel, clip.mins, clip.maxs, clip.hullmins, clip.hullmaxs);
+ if (sv.worldmodel && sv.worldmodel->brush.RoundUpToHullSize)
+ sv.worldmodel->brush.RoundUpToHullSize(sv.worldmodel, clip.mins, clip.maxs, clip.hullmins, clip.hullmaxs);
// clip to world
clip.trace = SV_ClipMoveToEntity(sv.edicts, clip.start, clip.hullmins, clip.hullmaxs, clip.end);