diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index ab5bdd74b..a5ff97101 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -45,6 +45,7 @@ extern int nanmask; #define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];} #define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];} #define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];} +#define VectorMA(a,s,b,c) {(c)[0]=(a)[0]+(s)*(b)[0];(c)[1]=(a)[1]+(s)*(b)[1];(c)[2]=(a)[2]+(s)*(b)[2];} /* * VectorDistance, the distance between two points. @@ -66,7 +67,7 @@ extern int nanmask; // fall over #define ROLL 2 -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); +void _VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); vec_t _DotProduct (vec3_t v1, vec3_t v2); void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out); @@ -113,6 +114,10 @@ void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, : \ BoxOnPlaneSide( (emins), (emaxs), (p))) +#define PlaneDist(point,plane) ((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) +#define PlaneDiff(point,plane) (((plane)->type < 3 ? (point)[(plane)->type] : DotProduct((point), (plane)->normal)) - (plane)->dist) + + extern mplane_t frustum[4]; #ifndef IMPLEMENT_R_CullBox diff --git a/include/QF/model.h b/include/QF/model.h index 5f4d4cd9c..d4f20524a 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -194,6 +194,9 @@ typedef struct mleaf_s struct mnode_s *parent; // leaf specific + int dlightbits; + int dlightframe; + byte *compressed_vis; efrag_t *efrags; diff --git a/include/r_local.h b/include/r_local.h index 0eb8e113b..67dfbf94a 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -335,7 +335,7 @@ void R_cshift_f (void); void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); void R_SplitEntityOnNode2 (mnode_t *node); -void R_MarkLights (vec3_t lightorigin, struct dlight_s *light, int bit, mnode_t *node); +void R_MarkLights (vec3_t lightorigin, struct dlight_s *light, int bit, model_t *model); void R_LoadSkys (const char *); diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 88c01b8c3..093977460 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -388,7 +388,7 @@ VectorCompare (vec3_t v1, vec3_t v2) } void -VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) +_VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) { vecc[0] = veca[0] + scale * vecb[0]; vecc[1] = veca[1] + scale * vecb[1]; diff --git a/libs/video/renderer/gl/gl_rlight.c b/libs/video/renderer/gl/gl_rlight.c index 9ee86f708..c4ab26067 100644 --- a/libs/video/renderer/gl/gl_rlight.c +++ b/libs/video/renderer/gl/gl_rlight.c @@ -44,6 +44,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "r_local.h" #include "r_shared.h" #include "r_cvar.h" @@ -193,7 +194,8 @@ R_RenderDlights (void) // LordHavoc: heavily modified, to eliminate unnecessary texture uploads, // and support bmodel lighting better void -R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node) +R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit, + mnode_t *node) { mplane_t *splitplane; float ndist, maxdist; @@ -272,7 +274,7 @@ loc0: if (node->children[0]->contents >= 0) { if (node->children[1]->contents >= 0) - R_MarkLights (lightorigin, light, bit, node->children[1]); + R_RecursiveMarkLights (lightorigin, light, bit, node->children[1]); node = node->children[0]; goto loc0; @@ -282,13 +284,127 @@ loc0: } } +static void +mark_surfaces (msurface_t *surf, vec3_t lightorigin, dlight_t *light, + int bit) +{ + float dist, dist2, d; + float maxdist = light->radius * light->radius; + vec3_t impact; + + surf->dlightframe = r_framecount; + dist = PlaneDiff(lightorigin, surf->plane); + if (surf->flags & SURF_PLANEBACK) + dist = -dist; +#if 0 +//FIXME SURF_LIGHTBOTHSIDES seems to be a darkplaces thing. need to investigate + if ((dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES)) + || dist > radius) + return; +#else + if (dist < -0.25f || dist > light->radius) + return; +#endif + dist2 = dist * dist; + dist = -dist; + VectorMA (light->origin, dist, surf->plane->normal, impact); + + d = DotProduct (impact, surf->texinfo->vecs[0]) + + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + if (d < 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } else { + d -= surf->extents[0] + 16; + if (d > 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } + } + d = DotProduct (impact, surf->texinfo->vecs[1]) + + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + if (d < 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } else { + d -= surf->extents[1] + 16; + if (d > 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } + } + + if (surf->dlightframe != r_framecount) { + surf->dlightbits = 0; + surf->dlightframe = r_framecount; + } + surf->dlightbits |= bit; +} + +void +R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model) +{ + mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); + + if (!pvsleaf->compressed_vis) { + R_RecursiveMarkLights (lightorigin, light, bit, model->nodes); + } else { + float radius = light->radius; + vec3_t mins, maxs; + int leafnum = 0; + byte *in = pvsleaf->compressed_vis; + byte vis_bits; + + mins[0] = lightorigin[0] - radius; + mins[1] = lightorigin[1] - radius; + mins[2] = lightorigin[2] - radius; + maxs[0] = lightorigin[0] + radius; + maxs[1] = lightorigin[1] + radius; + maxs[2] = lightorigin[2] + radius; + while (leafnum < model->numleafs) { + int i; + if (!(vis_bits = *in++)) { + leafnum += (*in++) * 8; + continue; + } + for (i = 0; i < 8 && leafnum < model->numleafs; i++, leafnum++) { + int m; + mleaf_t *leaf = &model->leafs[leafnum]; + if (!(vis_bits & (1 << i))) + continue; + if (leaf->visframe != r_visframecount) + continue; + if (leaf->mins[0] > maxs[0] || leaf->maxs[0] < mins[0] + || leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1] + || leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2]) + continue; + if (leaf->dlightframe != r_framecount) { + leaf->dlightbits = 0; + leaf->dlightframe = r_framecount; + } + leaf->dlightbits |= bit; + for (m = 0; m < leaf->nummarksurfaces; m++) { + msurface_t *surf = leaf->firstmarksurface[m]; + if (surf->visframe != r_visframecount + || surf->dlightframe == r_framecount) + continue; + mark_surfaces (surf, lightorigin, light, bit); + } + } + } + } +} + void R_PushDlights (vec3_t entorigin) { int i; dlight_t *l; - vec3_t lightorigin; if (!gl_dlight_lightmap->int_val) return; @@ -298,8 +414,7 @@ R_PushDlights (vec3_t entorigin) for (i = 0; i < MAX_DLIGHTS; i++, l++) { if (l->die < r_realtime || !l->radius) continue; - VectorSubtract (l->origin, entorigin, lightorigin); - R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model->nodes); + R_MarkLights (l->origin, l, 1 << i, r_worldentity.model); } } diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 7e87e52f0..323b4be32 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -1058,10 +1058,10 @@ R_RenderScene (void) R_SetupGL (); - R_PushDlights (vec3_origin); - R_MarkLeaves (); // done here so we know if we're in water + R_PushDlights (vec3_origin); + R_DrawWorld (); // adds static entities to the list S_ExtraUpdate (); // don't let sound get messed up if going slow diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 55ac5a420..c29ce6145 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -727,8 +727,7 @@ R_DrawBrushModel (entity_t *e) continue; VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); - R_MarkLights (lightorigin, &r_dlights[k], 1 << k, - clmodel->nodes + clmodel->hulls[0].firstclipnode); + R_MarkLights (lightorigin, &r_dlights[k], 1 << k, clmodel); } } @@ -807,7 +806,7 @@ R_RecursiveWorldNode (mnode_t *node) if ((c = pleaf->nummarksurfaces)) { mark = pleaf->firstmarksurface; do { - (*mark)->visframe = r_framecount; + (*mark)->visframe = r_visframecount; mark++; } while (--c); } @@ -857,7 +856,7 @@ R_RecursiveWorldNode (mnode_t *node) side = 0; for (; c; c--, surf++) { - if (surf->visframe != r_framecount) + if (surf->visframe != r_visframecount) continue; if ((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) diff --git a/libs/video/renderer/sw/sw_rlight.c b/libs/video/renderer/sw/sw_rlight.c index acdabe1e6..4f8233ff4 100644 --- a/libs/video/renderer/sw/sw_rlight.c +++ b/libs/video/renderer/sw/sw_rlight.c @@ -64,8 +64,9 @@ R_AnimateLight (void) void -R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node) +R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model) { + mnode_t *node = (mnode_t *)model;//FIXME evilness mplane_t *splitplane; float dist; msurface_t *surf; @@ -78,11 +79,11 @@ R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node) dist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist; if (dist > light->radius) { - R_MarkLights (lightorigin, light, bit, node->children[0]); + R_MarkLights (lightorigin, light, bit, (model_t*)node->children[0]); return; } if (dist < -light->radius) { - R_MarkLights (lightorigin, light, bit, node->children[1]); + R_MarkLights (lightorigin, light, bit, (model_t*)node->children[1]); return; } // mark the polygons @@ -95,8 +96,8 @@ R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node) surf->dlightbits |= bit; } - R_MarkLights (lightorigin, light, bit, node->children[0]); - R_MarkLights (lightorigin, light, bit, node->children[1]); + R_MarkLights (lightorigin, light, bit, (model_t*)node->children[0]); + R_MarkLights (lightorigin, light, bit, (model_t*)node->children[1]); } @@ -115,7 +116,7 @@ R_PushDlights (vec3_t entorigin) if (l->die < r_realtime || !l->radius) continue; VectorSubtract (l->origin, entorigin, lightorigin); - R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model->nodes); + R_MarkLights (lightorigin, l, 1 << i, (model_t*)r_worldentity.model->nodes); } } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 625d38d52..35b5573b4 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -714,8 +714,9 @@ R_DrawBEntitiesOnList (void) VectorSubtract (r_dlights[k].origin, currententity->origin, lightorigin); R_MarkLights (lightorigin, &r_dlights[k], 1 << k, + (model_t*)(//FIXME this is so evil clmodel->nodes + - clmodel->hulls[0].firstclipnode); + clmodel->hulls[0].firstclipnode)); } } // if the driver wants polygons, deliver those.