[model] Move plane info into mnode_t, and visframe out

The main goal was to get visframe out of mnode_t to make it thread-safe
(each thread can have its own visframe array), but moving the plane info
into mnode_t made for better data access patters when traversing the bsp
tree as the plane is right there with the child indices. Nicely, the
size of mnode_t is the same as before (64 bytes due to alignment), with
4 bytes wasted.

Performance-wise, there seems to be very little difference. Maybe
slightly slower.

The unfortunate thing about the change is the plane distance is negated,
possibly leading to some confusion, particularly since the box and
sphere culling functions were affected. However, this is so point-plane
distance calculations can be done with a single 4d dot product.
This commit is contained in:
Bill Currie 2022-05-22 11:18:32 +09:00
parent 8633ffe9d2
commit 7240d2dc80
36 changed files with 397 additions and 350 deletions

View file

@ -136,6 +136,7 @@ void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right,
vec3_t up); vec3_t up);
void AngleQuat (const vec3_t angles, quat_t q); void AngleQuat (const vec3_t angles, quat_t q);
void VectorVectors (const vec3_t forward, vec3_t right, vec3_t up); void VectorVectors (const vec3_t forward, vec3_t right, vec3_t up);
// NOTE expects plane distance is -p.n
int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs,
const plane_t *plane) __attribute__((pure)); const plane_t *plane) __attribute__((pure));
float anglemod (float a) __attribute__((const)); float anglemod (float a) __attribute__((const));
@ -143,14 +144,15 @@ float anglemod (float a) __attribute__((const));
void RotatePointAroundVector (vec3_t dst, const vec3_t axis, void RotatePointAroundVector (vec3_t dst, const vec3_t axis,
const vec3_t point, float degrees); const vec3_t point, float degrees);
// NOTE expects plane distance is -p.n
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ #define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \ (((p)->type < 3)? \
( \ ( \
((p)->dist <= (emins)[(p)->type])? \ (-(p)->dist <= (emins)[(p)->type])? \
1 \ 1 \
: \ : \
( \ ( \
((p)->dist >= (emaxs)[(p)->type])? \ (-(p)->dist >= (emaxs)[(p)->type])? \
2 \ 2 \
: \ : \
3 \ 3 \
@ -185,6 +187,7 @@ R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs)
int i; int i;
for (i=0 ; i < 4 ; i++) { for (i=0 ; i < 4 ; i++) {
// NOTE frustum distance is -p.n
if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2) { if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2) {
return true; return true;
} }
@ -205,7 +208,8 @@ R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
r = DotProduct (origin, frustum[i].normal) - frustum[i].dist; // NOTE frustum distance is -p.n
r = DotProduct (origin, frustum[i].normal) + frustum[i].dist;
if (r <= -radius) if (r <= -radius)
return true; return true;
} }

View file

@ -34,6 +34,8 @@
#include "QF/modelgen.h" #include "QF/modelgen.h"
#include "QF/zone.h" #include "QF/zone.h"
#include "QF/simd/types.h"
extern struct vid_model_funcs_s *mod_funcs; extern struct vid_model_funcs_s *mod_funcs;
/* /*
@ -174,18 +176,18 @@ typedef struct msurface_s {
} msurface_t; } msurface_t;
typedef struct mnode_s { typedef struct mnode_s {
// common with leaf /// Vector representation of the plane.
int contents; // 0, to differentiate from leafs /// \note the 4th component is the negative of the plane distance. This
int visframe; // node needs to be traversed if current /// makes it so a 4d dot product with a point vector (4th component = 1)
/// gives the distance of the point from the plane.
float minmaxs[6]; // for bounding box culling vec4f_t plane;
byte type;
// node specific byte signbits;
plane_t *plane; byte pad[2];
struct mnode_s *children[2]; int32_t children[2]; ///< Negative values = ~(leaf number)
float minmaxs[6];
unsigned int firstsurface; uint32_t firstsurface;
unsigned int numsurfaces; uint32_t numsurfaces;
} mnode_t; } mnode_t;
typedef struct mleaf_s { typedef struct mleaf_s {
@ -267,8 +269,8 @@ typedef struct mod_brush_s {
byte *lightdata; byte *lightdata;
char *entities; //FIXME should not be here char *entities; //FIXME should not be here
mnode_t **node_parents; int32_t *node_parents;
mnode_t **leaf_parents; int32_t *leaf_parents;
int *leaf_flags; // union of surf flags for surfs in leaf int *leaf_flags; // union of surf flags for surfs in leaf
unsigned int checksum; unsigned int checksum;
@ -437,7 +439,7 @@ model_t *Mod_ForName (const char *name, qboolean crash);
void Mod_TouchModel (const char *name); void Mod_TouchModel (const char *name);
void Mod_UnloadModel (model_t *model); void Mod_UnloadModel (model_t *model);
// brush specific // brush specific
mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); mleaf_t *Mod_PointInLeaf (vec4f_t p, model_t *model) __attribute__((pure));
struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);
void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis,

View file

@ -59,7 +59,7 @@ typedef struct animation_s {
typedef struct visibility_s { typedef struct visibility_s {
struct entity_s *entity; // owning entity struct entity_s *entity; // owning entity
struct efrag_s *efrag; // linked list of efrags struct efrag_s *efrag; // linked list of efrags
struct mnode_s *topnode; // bmodels, first world node that int topnode_id; // bmodels, first world node that
// splits bmodel, or NULL if not split // splits bmodel, or NULL if not split
// applies to other models, too // applies to other models, too
// found in an active leaf // found in an active leaf

View file

@ -74,7 +74,8 @@ struct entity_s;
struct animation_s; struct animation_s;
void R_DrawAliasModel (struct entity_s *e); void R_DrawAliasModel (struct entity_s *e);
void R_MarkLeaves (struct mleaf_s *viewleaf); void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes);
extern int *r_node_visframes;
void GL_SetPalette (void *data, const byte *palette); void GL_SetPalette (void *data, const byte *palette);
void GLSL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette);

View file

@ -159,7 +159,7 @@ texture_t *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf)
void R_GenSkyTile (void *pdest); void R_GenSkyTile (void *pdest);
void R_SurfPatch (void); void R_SurfPatch (void);
void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mnode_s *topnode); void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf);
void R_DrawSolidClippedSubmodelPolygons (struct entity_s *ent, model_t *pmodel, struct mnode_s *topnode); void R_DrawSolidClippedSubmodelPolygons (struct entity_s *ent, model_t *pmodel, struct mnode_s *topnode);
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
@ -308,8 +308,8 @@ void R_SetupFrame (void);
void R_cshift_f (void); void R_cshift_f (void);
void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1);
void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip);
void R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, void R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin,
struct dlight_s *light, int bit, mnode_t *node); struct dlight_s *light, int bit, int node_id);
void R_LoadSkys (const char *); void R_LoadSkys (const char *);
//void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx); //void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx);

View file

@ -52,6 +52,7 @@
#include "QF/va.h" #include "QF/va.h"
#include "QF/plugin/vid_render.h" #include "QF/plugin/vid_render.h"
#include "QF/simd/vec4f.h"
#include "compat.h" #include "compat.h"
#include "mod_internal.h" #include "mod_internal.h"
@ -60,25 +61,20 @@ VISIBLE int mod_sky_divide; //FIXME visibility?
VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible?
VISIBLE mleaf_t * VISIBLE mleaf_t *
Mod_PointInLeaf (const vec3_t p, model_t *model) Mod_PointInLeaf (vec4f_t p, model_t *model)
{ {
float d; float d;
mnode_t *node;
plane_t *plane;
if (!model || !model->brush.nodes) if (!model || !model->brush.nodes)
Sys_Error ("Mod_PointInLeaf: bad model"); Sys_Error ("Mod_PointInLeaf: bad model");
node = model->brush.nodes; int node_id = 0;
while (1) { while (1) {
if (node->contents < 0) if (node_id < 0)
return (mleaf_t *) node; return model->brush.leafs + ~node_id;
plane = node->plane; mnode_t *node = model->brush.nodes + node_id;
d = DotProduct (p, plane->normal) - plane->dist; d = dotf (p, node->plane)[0];
if (d >= 0) node_id = node->children[d < 0];
node = node->children[0];
else
node = node->children[1];
} }
return NULL; // never reached return NULL; // never reached
@ -668,15 +664,16 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp)
} }
static void static void
Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) Mod_SetParent (mod_brush_t *brush, int node_id, int parent_id)
{ {
if (node->contents < 0) { if (node_id < 0) {
brush->leaf_parents[(mleaf_t *)node - brush->leafs] = parent; brush->leaf_parents[~node_id] = parent_id;
return; return;
} }
brush->node_parents[node - brush->nodes] = parent; brush->node_parents[node_id] = parent_id;
Mod_SetParent (brush, node->children[0], node); mnode_t *node = brush->nodes + node_id;
Mod_SetParent (brush, node->children[1], node); Mod_SetParent (brush, node->children[0], node_id);
Mod_SetParent (brush, node->children[1], node_id);
} }
static void static void
@ -720,8 +717,11 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp)
out->minmaxs[3 + j] = in->maxs[j]; out->minmaxs[3 + j] = in->maxs[j];
} }
p = in->planenum; plane_t *plane = brush->planes + in->planenum;
out->plane = brush->planes + p; out->plane = loadvec3f (plane->normal);
out->plane[3] = -plane->dist;
out->type = plane->type;
out->signbits = plane->signbits;
out->firstsurface = in->firstface; out->firstsurface = in->firstface;
out->numsurfaces = in->numfaces; out->numsurfaces = in->numfaces;
@ -730,28 +730,27 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp)
p = in->children[j]; p = in->children[j];
// this check is for extended bsp 29 files // this check is for extended bsp 29 files
if (p >= 0) { if (p >= 0) {
out->children[j] = brush->nodes + p; out->children[j] = p;
} else { } else {
p = ~p; if ((unsigned) ~p < brush->modleafs) {
if ((unsigned) p < brush->modleafs) { out->children[j] = p;
out->children[j] = (mnode_t *) (brush->leafs + p);
} else { } else {
Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " Sys_Printf ("Mod_LoadNodes: invalid leaf index %i "
"(file has only %i leafs)\n", p, "(file has only %i leafs)\n", ~p,
brush->modleafs); brush->modleafs);
//map it to the solid leaf //map it to the solid leaf
out->children[j] = (mnode_t *)(brush->leafs); out->children[j] = ~0;
} }
} }
} }
} }
size_t size = (brush->modleafs + brush->numnodes) * sizeof (mnode_t *); size_t size = (brush->modleafs + brush->numnodes) * sizeof (int32_t);
size += brush->modleafs * sizeof (int); size += brush->modleafs * sizeof (int);
brush->node_parents = Hunk_AllocName (0, size, mod->name); brush->node_parents = Hunk_AllocName (0, size, mod->name);
brush->leaf_parents = brush->node_parents + brush->numnodes; brush->leaf_parents = brush->node_parents + brush->numnodes;
brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs); brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs);
Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs Mod_SetParent (brush, 0, -1); // sets nodes and leafs
Mod_SetLeafFlags (brush); Mod_SetLeafFlags (brush);
} }
@ -889,12 +888,12 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp)
Replicate the drawing hull structure as a clipping hull Replicate the drawing hull structure as a clipping hull
*/ */
static void static void
Mod_MakeHull0 (model_t *mod) Mod_MakeHull0 (model_t *mod, bsp_t *bsp)
{ {
dclipnode_t *out; dclipnode_t *out;
hull_t *hull; hull_t *hull;
int count, i, j; int count, i, j;
mnode_t *in, *child; mnode_t *in;
mod_brush_t *brush = &mod->brush; mod_brush_t *brush = &mod->brush;
hull = &brush->hulls[0]; hull = &brush->hulls[0];
@ -910,13 +909,14 @@ Mod_MakeHull0 (model_t *mod)
hull->planes = brush->planes; hull->planes = brush->planes;
for (i = 0; i < count; i++, out++, in++) { for (i = 0; i < count; i++, out++, in++) {
out->planenum = in->plane - brush->planes; out->planenum = bsp->nodes[i].planenum;
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
child = in->children[j]; int child_id = in->children[j];
if (child->contents < 0) if (child_id < 0) {
out->children[j] = child->contents; out->children[j] = bsp->leafs[~child_id].contents;
else } else {
out->children[j] = child - brush->nodes; out->children[j] = child_id;
}
} }
} }
} }
@ -1026,13 +1026,14 @@ do_checksums (const bsp_t *bsp, void *_mod)
} }
static void static void
recurse_draw_tree (mod_brush_t *brush, mnode_t *node, int depth) recurse_draw_tree (mod_brush_t *brush, int node_id, int depth)
{ {
if (!node || node->contents < 0) { if (node_id < 0) {
if (depth > brush->depth) if (depth > brush->depth)
brush->depth = depth; brush->depth = depth;
return; return;
} }
mnode_t *node = &brush->nodes[node_id];
recurse_draw_tree (brush, node->children[0], depth + 1); recurse_draw_tree (brush, node->children[0], depth + 1);
recurse_draw_tree (brush, node->children[1], depth + 1); recurse_draw_tree (brush, node->children[1], depth + 1);
} }
@ -1041,7 +1042,7 @@ static void
Mod_FindDrawDepth (mod_brush_t *brush) Mod_FindDrawDepth (mod_brush_t *brush)
{ {
brush->depth = 0; brush->depth = 0;
recurse_draw_tree (brush, brush->nodes, 1); recurse_draw_tree (brush, 0, 1);
} }
void void
@ -1074,9 +1075,9 @@ Mod_LoadBrushModel (model_t *mod, void *buffer)
Mod_LoadEntities (mod, bsp); Mod_LoadEntities (mod, bsp);
Mod_LoadSubmodels (mod, bsp); Mod_LoadSubmodels (mod, bsp);
BSP_Free(bsp); Mod_MakeHull0 (mod, bsp);
Mod_MakeHull0 (mod); BSP_Free(bsp);
Mod_FindDrawDepth (&mod->brush); Mod_FindDrawDepth (&mod->brush);
for (i = 0; i < MAX_MAP_HULLS; i++) for (i = 0; i < MAX_MAP_HULLS; i++)

View file

@ -78,7 +78,7 @@ Light_AddLight (lightingdata_t *ldata, const light_t *light, int style)
int visleaf = -1; // directional light int visleaf = -1; // directional light
if (light->position[3]) { if (light->position[3]) {
// positional light // positional light
mleaf_t *leaf = Mod_PointInLeaf (&light->position[0], model); mleaf_t *leaf = Mod_PointInLeaf (light->position, model);
visleaf = leaf - model->brush.leafs - 1; visleaf = leaf - model->brush.leafs - 1;
} else if (!DotProduct (light->direction, light->direction)) { } else if (!DotProduct (light->direction, light->direction)) {
// ambient light // ambient light

View file

@ -57,8 +57,8 @@ static mleaf_t empty_leafs[] = {
}, },
}; };
static mnode_t *empty_leaf_parents[] = { static int empty_leaf_parents[] = {
[1] = 0, [1] = -1,
}; };
static int empty_leaf_flags[] = { static int empty_leaf_flags[] = {

View file

@ -486,9 +486,9 @@ BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, const plane_t *p)
#endif #endif
sides = 0; sides = 0;
if (dist1 >= p->dist) if (dist1 >= -p->dist)
sides = 1; sides = 1;
if (dist2 < p->dist) if (dist2 < -p->dist)
sides |= 2; sides |= 2;
#ifdef PARANOID #ifdef PARANOID

View file

@ -122,8 +122,8 @@ gl_R_RenderEntities (entqueue_t *queue)
qfglEnable (GL_NORMALIZE); qfglEnable (GL_NORMALIZE);
} }
for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { \ for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) {
entity_t *ent = queue->ent_queues[mod_alias].a[i]; \ entity_t *ent = queue->ent_queues[mod_alias].a[i];
gl_R_DrawAliasModel (ent); gl_R_DrawAliasModel (ent);
} }
qfglColor3ubv (color_white); qfglColor3ubv (color_white);

View file

@ -173,7 +173,7 @@ gl_R_NewScene (scene_t *scene)
brush->leafs[i].efrags = NULL; brush->leafs[i].efrags = NULL;
// Force a vis update // Force a vis update
R_MarkLeaves (0); R_MarkLeaves (0, 0);
R_ClearParticles (); R_ClearParticles ();

View file

@ -548,16 +548,16 @@ gl_R_DrawBrushModel (entity_t *e)
// calculate dynamic lighting for bmodel if it's not an instanced model // calculate dynamic lighting for bmodel if it's not an instanced model
if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { if (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
vec3_t lightorigin;
for (unsigned k = 0; k < r_maxdlights; k++) { for (unsigned k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) if ((r_dlights[k].die < vr_data.realtime)
|| (!r_dlights[k].radius)) || (!r_dlights[k].radius))
continue; continue;
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin); VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k,
brush->nodes + brush->hulls[0].firstclipnode); brush->hulls[0].firstclipnode);
} }
} }
@ -597,12 +597,9 @@ static inline int
get_side (mnode_t *node) get_side (mnode_t *node)
{ {
// find which side of the node we are on // find which side of the node we are on
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position; vec4f_t org = r_refdef.frame.position;
if (plane->type < 3) return dotf (org, node->plane)[0] < 0;
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
} }
static inline void static inline void
@ -630,12 +627,13 @@ visit_node (glbspctx_t *bctx, mnode_t *node, int side)
} }
static inline int static inline int
test_node (mnode_t *node) test_node (glbspctx_t *bctx, int node_id)
{ {
if (node->contents < 0) if (node_id < 0)
return 0; return 0;
if (node->visframe != r_visframecount) if (r_node_visframes[node_id] != r_visframecount)
return 0; return 0;
mnode_t *node = bctx->brush->nodes + node_id;
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
return 0; return 0;
return 1; return 1;
@ -645,45 +643,55 @@ static void
R_VisitWorldNodes (glbspctx_t *bctx) R_VisitWorldNodes (glbspctx_t *bctx)
{ {
typedef struct { typedef struct {
mnode_t *node; int node_id;
int side; int side;
} rstack_t; } rstack_t;
mod_brush_t *brush = bctx->brush; mod_brush_t *brush = bctx->brush;
rstack_t *node_ptr; rstack_t *node_ptr;
rstack_t *node_stack; rstack_t *node_stack;
mnode_t *node; int node_id;
mnode_t *front; int front;
int side; int side;
node = brush->nodes; node_id = 0;
// +2 for paranoia // +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack; node_ptr = node_stack;
while (1) { while (1) {
while (test_node (node)) { while (test_node (bctx, node_id)) {
mnode_t *node = bctx->brush->nodes + node_id;
side = get_side (node); side = get_side (node);
front = node->children[side]; front = node->children[side];
if (test_node (front)) { if (test_node (bctx, front)) {
node_ptr->node = node; node_ptr->node_id = node_id;
node_ptr->side = side; node_ptr->side = side;
node_ptr++; node_ptr++;
node = front; node_id = front;
continue; continue;
} }
if (front->contents < 0 && front->contents != CONTENTS_SOLID) if (front < 0) {
visit_leaf ((mleaf_t *) front); mleaf_t *leaf = bctx->brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
visit_node (bctx, node, side); visit_node (bctx, node, side);
node = node->children[!side]; node_id = node->children[side ^ 1];
}
if (node_id < 0) {
mleaf_t *leaf = bctx->brush->leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
} }
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
if (node_ptr != node_stack) { if (node_ptr != node_stack) {
node_ptr--; node_ptr--;
node = node_ptr->node; node_id = node_ptr->node_id;
mnode_t *node = bctx->brush->nodes + node_id;
side = node_ptr->side; side = node_ptr->side;
visit_node (bctx, node, side); visit_node (bctx, node, side);
node = node->children[!side]; node_id = node->children[side ^ 1];
continue; continue;
} }
break; break;

View file

@ -694,16 +694,16 @@ R_DrawBrushModel (entity_t *e)
// calculate dynamic lighting for bmodel if it's not an instanced model // calculate dynamic lighting for bmodel if it's not an instanced model
if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { if (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) { for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) if ((r_dlights[k].die < vr_data.realtime)
|| (!r_dlights[k].radius)) || (!r_dlights[k].radius))
continue; continue;
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, mat[3], lightorigin); VectorSubtract (r_dlights[k].origin, mat[3], lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k,
brush->nodes + brush->hulls[0].firstclipnode); brush->hulls[0].firstclipnode);
} }
} }
@ -736,12 +736,9 @@ static inline int
get_side (mnode_t *node) get_side (mnode_t *node)
{ {
// find the node side on which we are // find the node side on which we are
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position; vec4f_t org = r_refdef.frame.position;
if (plane->type < 3) return dotf (org, node->plane)[0] < 0;
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
} }
static inline void static inline void
@ -773,12 +770,13 @@ visit_node (glslbspctx_t *bctx, mnode_t *node, int side)
} }
static inline int static inline int
test_node (mnode_t *node) test_node (glslbspctx_t *bctx, int node_id)
{ {
if (node->contents < 0) if (node_id < 0)
return 0; return 0;
if (node->visframe != r_visframecount) if (r_node_visframes[node_id] != r_visframecount)
return 0; return 0;
mnode_t *node = bctx->brush->nodes + node_id;
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
return 0; return 0;
return 1; return 1;
@ -788,45 +786,55 @@ static void
R_VisitWorldNodes (glslbspctx_t *bctx) R_VisitWorldNodes (glslbspctx_t *bctx)
{ {
typedef struct { typedef struct {
mnode_t *node; int node_id;
int side; int side;
} rstack_t; } rstack_t;
mod_brush_t *brush = bctx->brush; mod_brush_t *brush = bctx->brush;
rstack_t *node_ptr; rstack_t *node_ptr;
rstack_t *node_stack; rstack_t *node_stack;
mnode_t *node; int node_id;
mnode_t *front; int front;
int side; int side;
node = brush->nodes; node_id = 0;
// +2 for paranoia // +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack; node_ptr = node_stack;
while (1) { while (1) {
while (test_node (node)) { while (test_node (bctx, node_id)) {
mnode_t *node = bctx->brush->nodes + node_id;
side = get_side (node); side = get_side (node);
front = node->children[side]; front = node->children[side];
if (test_node (front)) { if (test_node (bctx, front)) {
node_ptr->node = node; node_ptr->node_id = node_id;
node_ptr->side = side; node_ptr->side = side;
node_ptr++; node_ptr++;
node = front; node_id = front;
continue; continue;
} }
if (front->contents < 0 && front->contents != CONTENTS_SOLID) if (front < 0) {
visit_leaf ((mleaf_t *) front); mleaf_t *leaf = bctx->brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
visit_node (bctx, node, side); visit_node (bctx, node, side);
node = node->children[!side]; node_id = node->children[side ^ 1];
}
if (node_id < 0) {
mleaf_t *leaf = bctx->brush->leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
} }
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
if (node_ptr != node_stack) { if (node_ptr != node_stack) {
node_ptr--; node_ptr--;
node = node_ptr->node; node_id = node_ptr->node_id;
side = node_ptr->side; side = node_ptr->side;
mnode_t *node = bctx->brush->nodes + node_id;
visit_node (bctx, node, side); visit_node (bctx, node, side);
node = node->children[!side]; node_id = node->children[side ^ 1];
continue; continue;
} }
break; break;

View file

@ -199,7 +199,7 @@ glsl_R_NewScene (scene_t *scene)
r_refdef.worldmodel = scene->worldmodel; r_refdef.worldmodel = scene->worldmodel;
// Force a vis update // Force a vis update
R_MarkLeaves (0); R_MarkLeaves (0, 0);
R_ClearParticles (); R_ClearParticles ();
glsl_R_RegisterTextures (scene->models, scene->num_models); glsl_R_RegisterTextures (scene->models, scene->num_models);

View file

@ -47,12 +47,11 @@ static mleaf_t *r_oldviewleaf;
static set_t *solid; static set_t *solid;
void void
R_MarkLeaves (mleaf_t *viewleaf) R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes)
{ {
set_t *vis; set_t *vis;
int c; int c;
mleaf_t *leaf; mleaf_t *leaf;
mnode_t *node;
msurface_t **mark; msurface_t **mark;
mod_brush_t *brush = &r_refdef.worldmodel->brush; mod_brush_t *brush = &r_refdef.worldmodel->brush;
@ -86,12 +85,12 @@ R_MarkLeaves (mleaf_t *viewleaf)
} while (--c); } while (--c);
} }
leaf->visframe = r_visframecount; leaf->visframe = r_visframecount;
node = brush->leaf_parents[leaf - brush->leafs]; int node_id = brush->leaf_parents[leaf - brush->leafs];
while (node) { while (node_id >= 0) {
if (node->visframe == r_visframecount) if (node_visframes[node_id] == r_visframecount)
break; break;
node->visframe = r_visframecount; node_visframes[node_id] = r_visframecount;
node = brush->node_parents[node - brush->nodes]; node_id = brush->node_parents[node_id];
} }
} }
} }

View file

@ -140,25 +140,25 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent,
mleaf_t *leaf; mleaf_t *leaf;
int sides; int sides;
efrag_t **lastlink; efrag_t **lastlink;
mnode_t **node_stack; int *node_stack;
mnode_t **node_ptr; int *node_ptr;
mnode_t *node = brush->nodes;
node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *));
node_ptr = node_stack; node_ptr = node_stack;
lastlink = &ent->visibility.efrag; lastlink = &ent->visibility.efrag;
*node_ptr++ = 0; *node_ptr++ = brush->numnodes;
while (node) { int node_id = 0;
while (node_id != (int) brush->numnodes) {
// add an efrag if the node is a leaf // add an efrag if the node is a leaf
if (__builtin_expect (node->contents < 0, 0)) { if (__builtin_expect (node_id < 0, 0)) {
if (!ent->visibility.topnode) { if (ent->visibility.topnode_id == -1) {
ent->visibility.topnode = node; ent->visibility.topnode_id = node_id;
} }
leaf = (mleaf_t *) node; leaf = brush->leafs + ~node_id;
ef = new_efrag (); // ensures ef->entnext is 0 ef = new_efrag (); // ensures ef->entnext is 0
@ -172,29 +172,30 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent,
ef->leafnext = leaf->efrags; ef->leafnext = leaf->efrags;
leaf->efrags = ef; leaf->efrags = ef;
node = *--node_ptr; node_id = *--node_ptr;
} else { } else {
mnode_t *node = brush->nodes + node_id;
// NODE_MIXED // NODE_MIXED
splitplane = node->plane; splitplane = (plane_t *) &node->plane;
sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane);
if (sides == 3) { if (sides == 3) {
// split on this plane // split on this plane
// if this is the first splitter of this bmodel, remember it // if this is the first splitter of this bmodel, remember it
if (!ent->visibility.topnode) { if (ent->visibility.topnode_id == -1) {
ent->visibility.topnode = node; ent->visibility.topnode_id = node_id;
} }
} }
// recurse down the contacted sides // recurse down the contacted sides
if (sides & 1 && node->children[0]->contents != CONTENTS_SOLID) { if (sides & 1) {
if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) if (sides & 2)
*node_ptr++ = node->children[1]; *node_ptr++ = node->children[1];
node = node->children[0]; node_id = node->children[0];
} else { } else {
if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) if (sides & 2)
node = node->children[1]; node_id = node->children[1];
else else
node = *--node_ptr; node_id = *--node_ptr;
} }
} }
} }
@ -216,7 +217,7 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent)
VectorAdd (org, entmodel->mins, emins); VectorAdd (org, entmodel->mins, emins);
VectorAdd (org, entmodel->maxs, emaxs); VectorAdd (org, entmodel->maxs, emaxs);
ent->visibility.topnode = 0; ent->visibility.topnode_id = -1; // leaf 0 (solid space)
R_SplitEntityOnNode (brush, ent, emins, emaxs); R_SplitEntityOnNode (brush, ent, emins, emaxs);
} }

View file

@ -152,7 +152,7 @@ R_AnimateLight (void)
} }
static inline void static inline void
real_mark_surfaces (float dist, msurface_t *surf, const vec3_t lightorigin, real_mark_surfaces (float dist, msurface_t *surf, vec4f_t lightorigin,
dlight_t *light, unsigned lightnum) dlight_t *light, unsigned lightnum)
{ {
float dist2, is, it; float dist2, is, it;
@ -190,7 +190,7 @@ real_mark_surfaces (float dist, msurface_t *surf, const vec3_t lightorigin,
} }
static inline void static inline void
mark_surfaces (msurface_t *surf, const vec3_t lightorigin, dlight_t *light, mark_surfaces (msurface_t *surf, vec4f_t lightorigin, dlight_t *light,
int lightnum) int lightnum)
{ {
float dist; float dist;
@ -208,35 +208,33 @@ mark_surfaces (msurface_t *surf, const vec3_t lightorigin, dlight_t *light,
// LordHavoc: heavily modified, to eliminate unnecessary texture uploads, // LordHavoc: heavily modified, to eliminate unnecessary texture uploads,
// and support bmodel lighting better // and support bmodel lighting better
void void
R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin,
dlight_t *light, int lightnum, mnode_t *node) dlight_t *light, int lightnum, int node_id)
{ {
unsigned i; unsigned i;
float ndist, maxdist; float ndist, maxdist;
plane_t *splitplane;
msurface_t *surf; msurface_t *surf;
maxdist = light->radius; maxdist = light->radius;
loc0: loc0:
if (node->contents < 0) if (node_id < 0)
return; return;
splitplane = node->plane; mnode_t *node = brush->nodes + node_id;
ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist; ndist = dotf (lightorigin, node->plane)[0];
if (ndist > maxdist * maxdist) { if (ndist > maxdist * maxdist) {
// Save time by not pushing another stack frame. // Save time by not pushing another stack frame.
if (node->children[0]->contents >= 0) { if (node->children[0] >= 0) {
node = node->children[0]; node_id = node->children[0];
goto loc0; goto loc0;
} }
return; return;
} }
if (ndist < -maxdist * maxdist) { if (ndist < -maxdist * maxdist) {
// Save time by not pushing another stack frame. if (node->children[1] >= 0) {
if (node->children[1]->contents >= 0) { node_id = node->children[1];
node = node->children[1];
goto loc0; goto loc0;
} }
return; return;
@ -248,29 +246,29 @@ loc0:
mark_surfaces (surf, lightorigin, light, lightnum); mark_surfaces (surf, lightorigin, light, lightnum);
} }
if (node->children[0]->contents >= 0) { if (node->children[0] >= 0) {
if (node->children[1]->contents >= 0) if (node->children[1] >= 0)
R_RecursiveMarkLights (brush, lightorigin, light, lightnum, R_RecursiveMarkLights (brush, lightorigin, light, lightnum,
node->children[1]); node->children[1]);
node = node->children[0]; node_id = node->children[0];
goto loc0; goto loc0;
} else if (node->children[1]->contents >= 0) { } else if (node->children[1] >= 0) {
node = node->children[1]; node_id = node->children[1];
goto loc0; goto loc0;
} }
} }
static void static void
R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum,
model_t *model) model_t *model)
{ {
mod_brush_t *brush = &model->brush; mod_brush_t *brush = &model->brush;
mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
if (!pvsleaf->compressed_vis) { if (!pvsleaf->compressed_vis) {
mnode_t *node = brush->nodes + brush->hulls[0].firstclipnode; int node_id = brush->hulls[0].firstclipnode;
R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node); R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node_id);
} else { } else {
float radius = light->radius; float radius = light->radius;
vec3_t mins, maxs; vec3_t mins, maxs;
@ -321,7 +319,6 @@ R_PushDlights (const vec3_t entorigin)
{ {
unsigned int i; unsigned int i;
dlight_t *l; dlight_t *l;
vec3_t lightorigin;
// because the count hasn't advanced yet for this frame // because the count hasn't advanced yet for this frame
r_dlightframecount = r_framecount + 1; r_dlightframecount = r_framecount + 1;
@ -334,14 +331,15 @@ R_PushDlights (const vec3_t entorigin)
for (i = 0; i < r_maxdlights; i++, l++) { for (i = 0; i < r_maxdlights; i++, l++) {
if (l->die < r_data->realtime || !l->radius) if (l->die < r_data->realtime || !l->radius)
continue; continue;
vec4f_t lightorigin;
VectorSubtract (l->origin, entorigin, lightorigin); VectorSubtract (l->origin, entorigin, lightorigin);
lightorigin[3] = 1;
R_MarkLights (lightorigin, l, i, r_refdef.worldmodel); R_MarkLights (lightorigin, l, i, r_refdef.worldmodel);
} }
} }
/* LIGHT SAMPLING */ /* LIGHT SAMPLING */
plane_t *lightplane;
vec3_t lightspot; vec3_t lightspot;
static int static int
@ -408,27 +406,26 @@ calc_lighting_3 (msurface_t *surf, int ds, int dt)
} }
static int static int
RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, vec4f_t start, RecursiveLightPoint (mod_brush_t *brush, int node_id, vec4f_t start,
vec4f_t end) vec4f_t end)
{ {
unsigned i; unsigned i;
int r, s, t, ds, dt, side; int r, s, t, ds, dt, side;
float front, back, frac; float front, back, frac;
plane_t *plane;
msurface_t *surf; msurface_t *surf;
mtexinfo_t *tex; mtexinfo_t *tex;
loop: loop:
if (node->contents < 0) if (node_id < 0)
return -1; // didn't hit anything return -1; // didn't hit anything
// calculate mid point // calculate mid point
plane = node->plane; mnode_t *node = brush->nodes + node_id;
front = DotProduct (start, plane->normal) - plane->dist; front = dotf (start, node->plane)[0];
back = DotProduct (end, plane->normal) - plane->dist; back = dotf (end, node->plane)[0];
side = front < 0; side = front < 0;
if ((back < 0) == side) { if ((back < 0) == side) {
node = node->children[side]; node_id = node->children[side];
goto loop; goto loop;
} }
@ -445,7 +442,6 @@ loop:
// check for impact on this node // check for impact on this node
VectorCopy (mid, lightspot); VectorCopy (mid, lightspot);
lightplane = plane;
surf = brush->surfaces + node->firstsurface; surf = brush->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) { for (i = 0; i < node->numsurfaces; i++, surf++) {
@ -478,7 +474,7 @@ loop:
} }
// go down back side // go down back side
return RecursiveLightPoint (brush, node->children[!side], mid, end); return RecursiveLightPoint (brush, node->children[side ^ 1], mid, end);
} }
int int
@ -491,7 +487,7 @@ R_LightPoint (mod_brush_t *brush, vec4f_t p)
} }
vec4f_t end = p - (vec4f_t) { 0, 0, 2048, 0 }; vec4f_t end = p - (vec4f_t) { 0, 0, 2048, 0 };
int r = RecursiveLightPoint (brush, brush->nodes, p, end); int r = RecursiveLightPoint (brush, 0, p, end);
if (r == -1) if (r == -1)
r = 0; r = 0;

View file

@ -111,7 +111,7 @@ R_SetFrustum (plane_t *frustum, const refframe_t *frame,
vec4f_t origin = frame->position; vec4f_t origin = frame->position;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
frustum[i].type = PLANE_ANYZ; frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct (origin, frustum[i].normal); frustum[i].dist = -DotProduct (origin, frustum[i].normal);
frustum[i].signbits = SignbitsForPlane (&frustum[i]); frustum[i].signbits = SignbitsForPlane (&frustum[i]);
} }
} }

View file

@ -61,6 +61,7 @@
int scr_copytop; int scr_copytop;
byte *draw_chars; // 8*8 graphic characters FIXME location byte *draw_chars; // 8*8 graphic characters FIXME location
qboolean r_cache_thrash; // set if surface cache is thrashing qboolean r_cache_thrash; // set if surface cache is thrashing
int *r_node_visframes; //FIXME per renderer
qboolean scr_skipupdate; qboolean scr_skipupdate;
static qboolean scr_initialized;// ready to draw static qboolean scr_initialized;// ready to draw
@ -273,8 +274,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
if (scr_scene && scr_scene->worldmodel) { if (scr_scene && scr_scene->worldmodel) {
scr_scene->viewleaf = 0; scr_scene->viewleaf = 0;
vec4f_t position = refdef->frame.position; vec4f_t position = refdef->frame.position;
scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position, scr_scene->viewleaf = Mod_PointInLeaf (position, scr_scene->worldmodel);
scr_scene->worldmodel);//FIXME
r_dowarpold = r_dowarp; r_dowarpold = r_dowarp;
if (r_waterwarp) { if (r_waterwarp) {
r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER; r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER;
@ -283,7 +283,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width,
r_data->vid->height); r_data->vid->height);
} }
R_MarkLeaves (scr_scene->viewleaf); R_MarkLeaves (scr_scene->viewleaf, r_node_visframes);
} }
R_PushDlights (vec3_origin); R_PushDlights (vec3_origin);
@ -514,6 +514,9 @@ SCR_NewScene (scene_t *scene)
{ {
scr_scene = scene; scr_scene = scene;
if (scene) { if (scene) {
mod_brush_t *brush = &scr_scene->worldmodel->brush;
int size = brush->numnodes * sizeof (int);
r_node_visframes = Hunk_AllocName (0, size, "visframes");
r_funcs->set_fov (tan_fov_x, tan_fov_y); r_funcs->set_fov (tan_fov_x, tan_fov_y);
r_funcs->R_NewScene (scene); r_funcs->R_NewScene (scene);
} else { } else {

View file

@ -118,8 +118,8 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
// transform the BSP plane into model space // transform the BSP plane into model space
// FIXME: cache these? // FIXME: cache these?
splitplane = pnode->plane; splitplane = (plane_t *) &pnode->plane;
tplane.dist = splitplane->dist - tplane.dist = splitplane->dist +
DotProduct (r_entorigin, splitplane->normal); DotProduct (r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal);
tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal);
@ -132,7 +132,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
// set the status for the last point as the previous point // set the status for the last point as the previous point
// FIXME: cache this stuff somehow? // FIXME: cache this stuff somehow?
plastvert = pedges->v[0]; plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) - lastdist = DotProduct (plastvert->position, tplane.normal) +
tplane.dist; tplane.dist;
if (lastdist > 0) if (lastdist > 0)
@ -142,7 +142,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
pvert = pedges->v[1]; pvert = pedges->v[1];
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; dist = DotProduct (pvert->position, tplane.normal) + tplane.dist;
if (dist > 0) if (dist > 0)
side = 0; side = 0;
@ -228,18 +228,20 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
if (psideedges[i]) { if (psideedges[i]) {
// draw if we've reached a non-solid leaf, done if all that's left // draw if we've reached a non-solid leaf, done if all that's left
// is a solid leaf, and continue down the tree if it's not a leaf // is a solid leaf, and continue down the tree if it's not a leaf
pn = pnode->children[i]; int child_id = pnode->children[i];
pn = r_refdef.worldmodel->brush.nodes + child_id;
// we're done with this branch if the node or leaf isn't in the PVS // we're done with this branch if the node or leaf isn't in the PVS
if (pn->visframe == r_visframecount) { if (child_id < 0) {
if (pn->contents < 0) { mleaf_t *leaf = r_refdef.worldmodel->brush.leafs + ~child_id;
if (pn->contents != CONTENTS_SOLID) { if (leaf->visframe == r_visframecount
r_currentbkey = ((mleaf_t *) pn)->key; && leaf->contents != CONTENTS_SOLID) {
R_RenderBmodelFace (ent, psideedges[i], psurf); r_currentbkey = leaf->key;
} R_RenderBmodelFace (ent, psideedges[i], psurf);
} else { }
R_RecursiveClipBPoly (ent, psideedges[i], } else {
pnode->children[i], psurf); if (r_node_visframes[child_id] == r_visframecount) {
R_RecursiveClipBPoly (ent, psideedges[i], pn, psurf);
} }
} }
} }
@ -320,7 +322,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *model,
void void
R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags, R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags,
mnode_t *topnode) mleaf_t *topleaf)
{ {
int i; int i;
vec_t dot; vec_t dot;
@ -343,7 +345,7 @@ R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags,
// draw the polygon // draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
r_currentkey = ((mleaf_t *) topnode)->key; r_currentkey = topleaf->key;
// FIXME: use bounding-box-based frustum clipping info? // FIXME: use bounding-box-based frustum clipping info?
R_RenderFace (ent, psurf, clipflags); R_RenderFace (ent, psurf, clipflags);
@ -365,12 +367,9 @@ static inline int
get_side (mnode_t *node) get_side (mnode_t *node)
{ {
// find which side of the node we are on // find which side of the node we are on
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position; vec4f_t org = r_refdef.frame.position;
if (plane->type < 3) return dotf (org, node->plane)[0] < 0;
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
} }
static void static void
@ -414,20 +413,21 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags)
} }
static inline int static inline int
test_node (mnode_t *node, int *clipflags) test_node (swbspctx_t *bctx, int node_id, int *clipflags)
{ {
int i, *pindex; int i, *pindex;
vec3_t acceptpt, rejectpt; vec3_t acceptpt, rejectpt;
double d; double d;
if (node->contents < 0) if (node_id < 0)
return 0; return 0;
if (node->visframe != r_visframecount) if (r_node_visframes[node_id] != r_visframecount)
return 0; return 0;
// cull the clipping planes if not trivial accept // cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be // FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM // twice as fast in ASM
if (*clipflags) { if (*clipflags) {
mnode_t *node = bctx->brush->nodes + node_id;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (!(*clipflags & (1 << i))) if (!(*clipflags & (1 << i)))
continue; // don't need to clip against it continue; // don't need to clip against it
@ -465,50 +465,60 @@ static void
R_VisitWorldNodes (swbspctx_t *bctx, int clipflags) R_VisitWorldNodes (swbspctx_t *bctx, int clipflags)
{ {
typedef struct { typedef struct {
mnode_t *node; int node_id;
int side, clipflags; int side, clipflags;
} rstack_t; } rstack_t;
rstack_t *node_ptr; rstack_t *node_ptr;
rstack_t *node_stack; rstack_t *node_stack;
mnode_t *node; int front;
mnode_t *front;
int side, cf; int side, cf;
int node_id;
mod_brush_t *brush = &bctx->entity->renderer.model->brush; mod_brush_t *brush = &bctx->entity->renderer.model->brush;
node = brush->nodes;
// +2 for paranoia // +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack; node_ptr = node_stack;
node_id = 0;
cf = clipflags; cf = clipflags;
while (1) { while (1) {
while (test_node (node, &cf)) { while (test_node (bctx, node_id, &cf)) {
mnode_t *node = bctx->brush->nodes + node_id;
cf = clipflags; cf = clipflags;
side = get_side (node); side = get_side (node);
front = node->children[side]; front = node->children[side];
if (test_node (front, &cf)) { if (test_node (bctx, front, &cf)) {
node_ptr->node = node; node_ptr->node_id = node_id;
node_ptr->side = side; node_ptr->side = side;
node_ptr->clipflags = clipflags; node_ptr->clipflags = clipflags;
node_ptr++; node_ptr++;
clipflags = cf; clipflags = cf;
node = front; node_id = front;
continue; continue;
} }
if (front->contents < 0 && front->contents != CONTENTS_SOLID) if (front < 0) {
visit_leaf ((mleaf_t *) front); mleaf_t *leaf = bctx->brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
visit_node (bctx, node, side, clipflags); visit_node (bctx, node, side, clipflags);
node = node->children[!side]; node_id = node->children[side ^ 1];
}
if (node_id < 0) {
mleaf_t *leaf = bctx->brush->leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
} }
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
if (node_ptr != node_stack) { if (node_ptr != node_stack) {
node_ptr--; node_ptr--;
node = node_ptr->node; node_id = node_ptr->node_id;
mnode_t *node = bctx->brush->nodes + node_id;
side = node_ptr->side; side = node_ptr->side;
clipflags = node_ptr->clipflags; clipflags = node_ptr->clipflags;
visit_node (bctx, node, side, clipflags); visit_node (bctx, node, side, clipflags);
node = node->children[!side]; node_id = node->children[side ^ 1];
continue; continue;
} }
break; break;

View file

@ -167,7 +167,7 @@ R_NewScene (scene_t *scene)
R_InitSky (brush->skytexture); R_InitSky (brush->skytexture);
// Force a vis update // Force a vis update
R_MarkLeaves (0); R_MarkLeaves (0, 0);
R_ClearParticles (); R_ClearParticles ();
@ -303,8 +303,7 @@ R_DrawEntitiesOnList (entqueue_t *queue)
for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \
i++) { \ i++) { \
entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \ r_entorigin = Transform_GetWorldPosition (ent->transform); \
r_entorigin); \
draw_##type_name##_entity (ent); \ draw_##type_name##_entity (ent); \
} \ } \
} while (0) } while (0)
@ -473,19 +472,18 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
// calculate dynamic lighting for bmodel if it's not an // calculate dynamic lighting for bmodel if it's not an
// instanced model // instanced model
if (brush->firstmodelsurface != 0) { if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) { for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) || if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) { (!r_dlights[k].radius)) {
continue; continue;
} }
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, origin, lightorigin); VectorSubtract (r_dlights[k].origin, origin, lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin, R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k, &r_dlights[k], k,
brush->nodes brush->hulls[0].firstclipnode);
+ brush->hulls[0].firstclipnode);
} }
} }
// if the driver wants polygons, deliver those. // if the driver wants polygons, deliver those.
@ -494,20 +492,21 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
if (r_drawpolys | r_drawculledpolys) { if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (ent, clmodel); R_ZDrawSubmodelPolys (ent, clmodel);
} else { } else {
if (ent->visibility.topnode) { int topnode_id = ent->visibility.topnode_id;
mnode_t *topnode = ent->visibility.topnode; mod_brush_t *brush = &r_refdef.worldmodel->brush;
if (topnode->contents >= 0) { if (topnode_id >= 0) {
// not a leaf; has to be clipped to the world // not a leaf; has to be clipped to the world
// BSP // BSP
r_clipflags = clipflags; mnode_t *node = brush->nodes + topnode_id;
R_DrawSolidClippedSubmodelPolygons (ent, clmodel, topnode); r_clipflags = clipflags;
} else { R_DrawSolidClippedSubmodelPolygons (ent, clmodel, node);
// falls entirely in one leaf, so we just put } else {
// all the edges in the edge list and let 1/z // falls entirely in one leaf, so we just put
// sorting handle drawing order // all the edges in the edge list and let 1/z
R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode); // sorting handle drawing order
} mleaf_t *leaf = brush->leafs + ~topnode_id;
R_DrawSubmodelPolygons (ent, clmodel, clipflags, leaf);
} }
} }

View file

@ -648,12 +648,9 @@ static inline int
get_side (mnode_t *node) get_side (mnode_t *node)
{ {
// find the node side on which we are // find the node side on which we are
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position; vec4f_t org = r_refdef.frame.position;
if (plane->type < 3) return dotf (org, node->plane)[0] < 0;
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
} }
static inline void static inline void
@ -685,12 +682,13 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx)
} }
static inline int static inline int
test_node (mnode_t *node) test_node (mod_brush_t *brush, int node_id)
{ {
if (node->contents < 0) if (node_id < 0)
return 0; return 0;
if (node->visframe != r_visframecount) if (r_node_visframes[node_id] != r_visframecount)
return 0; return 0;
mnode_t *node = brush->nodes + node_id;
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
return 0; return 0;
return 1; return 1;
@ -700,48 +698,58 @@ static void
R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
{ {
typedef struct { typedef struct {
mnode_t *node; int node_id;
int side; int side;
} rstack_t; } rstack_t;
rstack_t *node_ptr; rstack_t *node_ptr;
rstack_t *node_stack; rstack_t *node_stack;
mnode_t *node; int node_id;
mnode_t *front; int front;
int side; int side;
node = brush->nodes; node_id = 0;
// +2 for paranoia // +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack; node_ptr = node_stack;
while (1) { while (1) {
while (test_node (node)) { while (test_node (brush, node_id)) {
mnode_t *node = brush->nodes + node_id;
side = get_side (node); side = get_side (node);
front = node->children[side]; front = node->children[side];
if (test_node (front)) { if (test_node (brush, front)) {
node_ptr->node = node; node_ptr->node_id = node_id;
node_ptr->side = side; node_ptr->side = side;
node_ptr++; node_ptr++;
node = front; node_id = front;
continue; continue;
} }
// front is either not a node (ie, is a leaf) or is not visible // front is either not a node (ie, is a leaf) or is not visible
// if node is visible, then at least one of its child nodes // if node is visible, then at least one of its child nodes
// must also be visible, and a leaf child in front of the node // must also be visible, and a leaf child in front of the node
// will be visible, so no need for vis checks on a leaf // will be visible, so no need for vis checks on a leaf
if (front->contents < 0 && front->contents != CONTENTS_SOLID) if (front < 0) {
visit_leaf ((mleaf_t *) front); mleaf_t *leaf = brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
visit_node (brush, node, side, ctx); visit_node (brush, node, side, ctx);
node = node->children[!side]; node_id = node->children[side ^ 1];
}
if (node_id < 0) {
mleaf_t *leaf = brush->leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
} }
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) node);
if (node_ptr != node_stack) { if (node_ptr != node_stack) {
node_ptr--; node_ptr--;
node = node_ptr->node; node_id = node_ptr->node_id;
side = node_ptr->side; side = node_ptr->side;
mnode_t *node = brush->nodes + node_id;
visit_node (brush, node, side, ctx); visit_node (brush, node, side, ctx);
node = node->children[!side]; node_id = node->children[side ^ 1];
continue; continue;
} }
break; break;

View file

@ -142,7 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx)
r_refdef.worldmodel = scene->worldmodel; r_refdef.worldmodel = scene->worldmodel;
// Force a vis update // Force a vis update
R_MarkLeaves (0); R_MarkLeaves (0, 0);
R_ClearParticles (); R_ClearParticles ();
Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx);

View file

@ -83,7 +83,7 @@ SCR_CShift (void)
if (cls.state == ca_active && cl_world.scene->worldmodel) { if (cls.state == ca_active && cl_world.scene->worldmodel) {
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel);
contents = leaf->contents; contents = leaf->contents;
} }
V_SetContentsColor (&cl.viewstate, contents); V_SetContentsColor (&cl.viewstate, contents);

View file

@ -757,7 +757,7 @@ Host_ClientFrame (void)
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel);
if (l) if (l)
asl = l->ambient_sound_level; asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl); S_Update (cl.viewstate.camera_transform, asl);

View file

@ -372,30 +372,29 @@ SV_ClearDatagram (void)
static set_t *fatpvs; static set_t *fatpvs;
static void static void
SV_AddToFatPVS (vec3_t org, mnode_t *node) SV_AddToFatPVS (vec4f_t org, int node_id)
{ {
float d; float d;
plane_t *plane;
while (1) { while (1) {
// if this is a leaf, accumulate the pvs bits // if this is a leaf, accumulate the pvs bits
if (node->contents < 0) { if (node_id < 0) {
if (node->contents != CONTENTS_SOLID) { mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, if (leaf->contents != CONTENTS_SOLID) {
sv.worldmodel)); set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel));
} }
return; return;
} }
mnode_t *node = sv.worldmodel->brush.nodes + node_id;
plane = node->plane; d = dotf (node->plane, org)[0];
d = DotProduct (org, plane->normal) - plane->dist;
if (d > 8) if (d > 8)
node = node->children[0]; node_id = node->children[0];
else if (d < -8) else if (d < -8)
node = node->children[1]; node_id = node->children[1];
else { // go down both else { // go down both
SV_AddToFatPVS (org, node->children[0]); SV_AddToFatPVS (org, node->children[0]);
node = node->children[1]; node_id = node->children[1];
} }
} }
} }
@ -407,14 +406,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node)
given point. given point.
*/ */
static set_t * static set_t *
SV_FatPVS (vec3_t org) SV_FatPVS (vec4f_t org)
{ {
if (!fatpvs) { if (!fatpvs) {
fatpvs = set_new_size (sv.worldmodel->brush.visleafs); fatpvs = set_new_size (sv.worldmodel->brush.visleafs);
} }
set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_expand (fatpvs, sv.worldmodel->brush.visleafs);
set_empty (fatpvs); set_empty (fatpvs);
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); SV_AddToFatPVS (org, 0);
return fatpvs; return fatpvs;
} }
@ -426,13 +425,14 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
pr_uint_t bits, e; pr_uint_t bits, e;
set_t *pvs; set_t *pvs;
float miss; float miss;
vec3_t org; vec4f_t org;
edict_t *ent; edict_t *ent;
entity_state_t *baseline; entity_state_t *baseline;
edict_leaf_t *el; edict_leaf_t *el;
// find the client's PVS // find the client's PVS
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org); VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
org[3] = 1;
pvs = SV_FatPVS (org); pvs = SV_FatPVS (org);
// send over all entities (excpet the client) that touch the pvs // send over all entities (excpet the client) that touch the pvs

View file

@ -548,7 +548,6 @@ PF_newcheckclient (progs_t *pr, unsigned check)
edict_t *ent; edict_t *ent;
unsigned i; unsigned i;
mleaf_t *leaf; mleaf_t *leaf;
vec3_t org;
// cycle to the next one // cycle to the next one
if (check < 1) if (check < 1)
@ -582,7 +581,9 @@ PF_newcheckclient (progs_t *pr, unsigned check)
} }
// get the PVS for the entity // get the PVS for the entity
vec4f_t org;
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
org[3] = 1;
leaf = Mod_PointInLeaf (org, sv.worldmodel); leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (!checkpvs) { if (!checkpvs) {
checkpvs = set_new_size (sv.worldmodel->brush.visleafs); checkpvs = set_new_size (sv.worldmodel->brush.visleafs);
@ -615,7 +616,6 @@ PF_checkclient (progs_t *pr, void *data)
edict_t *ent, *self; edict_t *ent, *self;
int l; int l;
mleaf_t *leaf; mleaf_t *leaf;
vec3_t view;
// find a new check if on a new frame // find a new check if on a new frame
if (sv.time - sv.lastchecktime >= 0.1) { if (sv.time - sv.lastchecktime >= 0.1) {
@ -630,7 +630,9 @@ PF_checkclient (progs_t *pr, void *data)
} }
// if current entity can't possibly see the check entity, return 0 // if current entity can't possibly see the check entity, return 0
self = PROG_TO_EDICT (pr, *sv_globals.self); self = PROG_TO_EDICT (pr, *sv_globals.self);
vec4f_t view;
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
view[3] = 1;
leaf = Mod_PointInLeaf (view, sv.worldmodel); leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->brush.leafs) - 1; l = (leaf - sv.worldmodel->brush.leafs) - 1;
if (!set_is_member (checkpvs, l)) { if (!set_is_member (checkpvs, l)) {

View file

@ -410,19 +410,17 @@ SV_TouchLinks (edict_t *ent, areanode_t *node)
} }
static void static void
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) SV_FindTouchedLeafs (edict_t *ent, int node_id)
{ {
int sides; int sides;
mleaf_t *leaf;
plane_t *splitplane; plane_t *splitplane;
edict_leaf_t *edict_leaf; edict_leaf_t *edict_leaf;
if (node->contents == CONTENTS_SOLID) // add an efrag if the node is a non-solid leaf
return; if (node_id < 0) {
mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
// add an efrag if the node is a leaf if (leaf->contents == CONTENTS_SOLID)
if (node->contents < 0) { return;
leaf = (mleaf_t *) node;
edict_leaf = alloc_edict_leaf (); edict_leaf = alloc_edict_leaf ();
edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1;
@ -431,8 +429,9 @@ SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
return; return;
} }
mnode_t *node = sv.worldmodel->brush.nodes + node_id;
// NODE_MIXED // NODE_MIXED
splitplane = node->plane; splitplane = (plane_t *) &node->plane;
sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin), sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin),
SVvector (ent, absmax), splitplane); SVvector (ent, absmax), splitplane);
@ -497,7 +496,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
// link to PVS leafs // link to PVS leafs
free_edict_leafs (&SVdata (ent)->leafs); free_edict_leafs (&SVdata (ent)->leafs);
if (SVfloat (ent, modelindex)) if (SVfloat (ent, modelindex))
SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); SV_FindTouchedLeafs (ent, 0);
if (SVfloat (ent, solid) == SOLID_NOT) if (SVfloat (ent, solid) == SOLID_NOT)
return; return;

View file

@ -52,6 +52,8 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/va.h" #include "QF/va.h"
#include "QF/simd/vec4f.h"
#include "qw/bothdefs.h" #include "qw/bothdefs.h"
#include "qw/msg_ucmd.h" #include "qw/msg_ucmd.h"
#include "qw/protocol.h" #include "qw/protocol.h"
@ -978,30 +980,27 @@ emit_entities (client_t *client, packet_entities_t *to, sizebuf_t *msg)
} }
static void static void
add_to_fat_pvs (vec4f_t org, mnode_t *node, server_t *sv) add_to_fat_pvs (vec4f_t org, int node_id, server_t *sv)
{ {
float d;
plane_t *plane;
while (1) { while (1) {
// if this is a leaf, accumulate the pvs bits // if this is a leaf, accumulate the pvs bits
if (node->contents < 0) { if (node_id < 0) {
if (node->contents != CONTENTS_SOLID) { mleaf_t *leaf = sv->worldmodel->brush.leafs + ~node_id;
set_union (sv->fatpvs, Mod_LeafPVS ((mleaf_t *) node, if (leaf->contents != CONTENTS_SOLID) {
sv->worldmodel)); set_union (sv->fatpvs, Mod_LeafPVS (leaf, sv->worldmodel));
} }
return; return;
} }
plane = node->plane; mnode_t *node = sv->worldmodel->brush.nodes + node_id;
d = DotProduct (org, plane->normal) - plane->dist; float d = dotf (node->plane, org)[0];
if (d > 8) if (d > 8)
node = node->children[0]; node_id = node->children[0];
else if (d < -8) else if (d < -8)
node = node->children[1]; node_id = node->children[1];
else { // go down both else { // go down both
add_to_fat_pvs (org, node->children[0], sv); add_to_fat_pvs (org, node->children[0], sv);
node = node->children[1]; node_id = node->children[1];
} }
} }
} }
@ -1015,7 +1014,7 @@ fat_pvs (vec4f_t org, server_t *sv)
set_expand (sv->fatpvs, sv->worldmodel->brush.visleafs); set_expand (sv->fatpvs, sv->worldmodel->brush.visleafs);
set_empty (sv->fatpvs); set_empty (sv->fatpvs);
add_to_fat_pvs (org, sv->worldmodel->brush.nodes, sv); add_to_fat_pvs (org, 0, sv);
return sv->fatpvs; return sv->fatpvs;
} }

View file

@ -116,15 +116,16 @@ sv_unlink_entity (server_t *sv, qtv_entity_t *ent)
} }
static void static void
sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node) sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, int node_id)
{ {
if (node->contents == CONTENTS_SOLID) {
return;
}
// add an efrag if the node is a leaf // add an efrag if the node is a leaf
if (node->contents < 0) { if (node_id < 0) {
mleaf_t *leaf = sv->worldmodel->brush.leafs + ~node_id;
if (leaf->contents == CONTENTS_SOLID) {
return;
}
qtv_leaf_t *ent_leaf = alloc_qtv_leaf (); qtv_leaf_t *ent_leaf = alloc_qtv_leaf ();
ent_leaf->num = (mleaf_t *) node - sv->worldmodel->brush.leafs - 1; ent_leaf->num = ~node_id - 1;
ent_leaf->next = ent->leafs; ent_leaf->next = ent->leafs;
ent->leafs = ent_leaf; ent->leafs = ent_leaf;
return; return;
@ -134,7 +135,8 @@ sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node)
VectorAdd (ent->e.origin, ent->model->mins, emins); VectorAdd (ent->e.origin, ent->model->mins, emins);
VectorAdd (ent->e.origin, ent->model->maxs, emaxs); VectorAdd (ent->e.origin, ent->model->maxs, emaxs);
plane_t *splitplane = node->plane; mnode_t *node = sv->worldmodel->brush.nodes + node_id;
plane_t *splitplane = (plane_t *) &node->plane;
int sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); int sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane);
if (sides & 1) { if (sides & 1) {
sv_find_touched_leafs (sv, ent, node->children[0]); sv_find_touched_leafs (sv, ent, node->children[0]);
@ -153,7 +155,7 @@ sv_link_entity (server_t *sv, qtv_entity_t *ent)
ent->model = Mod_ForName (sv->modellist[ent->model_index - 1], false); ent->model = Mod_ForName (sv->modellist[ent->model_index - 1], false);
} }
if (ent->model) { if (ent->model) {
sv_find_touched_leafs (sv, ent, sv->worldmodel->brush.nodes); sv_find_touched_leafs (sv, ent, 0);
} }
} }

View file

@ -1995,7 +1995,7 @@ Host_Frame (float time)
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel);
if (l) if (l)
asl = l->ambient_sound_level; asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl); S_Update (cl.viewstate.camera_transform, asl);

View file

@ -82,7 +82,7 @@ SCR_CShift (void)
if (cls.state == ca_active && cl_world.scene->worldmodel) { if (cls.state == ca_active && cl_world.scene->worldmodel) {
vec4f_t origin; vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel);
contents = leaf->contents; contents = leaf->contents;
} }
V_SetContentsColor (&cl.viewstate, contents); V_SetContentsColor (&cl.viewstate, contents);

View file

@ -40,6 +40,8 @@
#include "QF/set.h" #include "QF/set.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/simd/vec4f.h"
#include "compat.h" #include "compat.h"
#include "qw/msg_ucmd.h" #include "qw/msg_ucmd.h"
@ -59,30 +61,29 @@ static set_t *fatpvs;
static void static void
SV_AddToFatPVS (vec3_t org, mnode_t *node) SV_AddToFatPVS (vec4f_t org, int node_id)
{ {
float d; float d;
plane_t *plane;
while (1) { while (1) {
// if this is a leaf, accumulate the pvs bits // if this is a leaf, accumulate the pvs bits
if (node->contents < 0) { if (node_id < 0) {
if (node->contents != CONTENTS_SOLID) { mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, if (leaf->contents != CONTENTS_SOLID) {
sv.worldmodel)); set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel));
} }
return; return;
} }
plane = node->plane; mnode_t *node = sv.worldmodel->brush.nodes + node_id;
d = DotProduct (org, plane->normal) - plane->dist; d = dotf (org, node->plane)[0];
if (d > 8) if (d > 8)
node = node->children[0]; node_id = node->children[0];
else if (d < -8) else if (d < -8)
node = node->children[1]; node_id = node->children[1];
else { // go down both else { // go down both
SV_AddToFatPVS (org, node->children[0]); SV_AddToFatPVS (org, node->children[0]);
node = node->children[1]; node_id = node->children[1];
} }
} }
} }
@ -94,14 +95,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node)
of the given point. of the given point.
*/ */
static set_t * static set_t *
SV_FatPVS (vec3_t org) SV_FatPVS (vec4f_t org)
{ {
if (!fatpvs) { if (!fatpvs) {
fatpvs = set_new_size (sv.worldmodel->brush.visleafs); fatpvs = set_new_size (sv.worldmodel->brush.visleafs);
} }
set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_expand (fatpvs, sv.worldmodel->brush.visleafs);
set_empty (fatpvs); set_empty (fatpvs);
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); SV_AddToFatPVS (org, 0);
return fatpvs; return fatpvs;
} }
@ -710,12 +711,13 @@ static inline set_t *
calc_pvs (delta_t *delta) calc_pvs (delta_t *delta)
{ {
set_t *pvs = 0; set_t *pvs = 0;
vec3_t org; vec4f_t org = {};
// find the client's PVS // find the client's PVS
if (delta->pvs == dt_pvs_normal) { if (delta->pvs == dt_pvs_normal) {
edict_t *clent = delta->client->edict; edict_t *clent = delta->client->edict;
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org); VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
org[3] = 1;
pvs = SV_FatPVS (org); pvs = SV_FatPVS (org);
} else if (delta->pvs == dt_pvs_fat) { } else if (delta->pvs == dt_pvs_fat) {
// when recording a demo, send only entities that can be seen. Can help // when recording a demo, send only entities that can be seen. Can help
@ -735,10 +737,11 @@ calc_pvs (delta_t *delta)
VectorAdd (SVvector (cl->edict, origin), VectorAdd (SVvector (cl->edict, origin),
SVvector (cl->edict, view_ofs), org); SVvector (cl->edict, view_ofs), org);
org[3] = 1;
if (pvs == NULL) { if (pvs == NULL) {
pvs = SV_FatPVS (org); pvs = SV_FatPVS (org);
} else { } else {
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); SV_AddToFatPVS (org, 0);
} }
} }
} }

View file

@ -469,7 +469,6 @@ PF_newcheckclient (progs_t *pr, int check)
edict_t *ent; edict_t *ent;
int i; int i;
mleaf_t *leaf; mleaf_t *leaf;
vec3_t org;
// cycle to the next one // cycle to the next one
if (check < 1) if (check < 1)
@ -503,7 +502,9 @@ PF_newcheckclient (progs_t *pr, int check)
} }
// get the PVS for the entity // get the PVS for the entity
vec4f_t org;
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
org[3] = 1;
leaf = Mod_PointInLeaf (org, sv.worldmodel); leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (!checkpvs) { if (!checkpvs) {
checkpvs = set_new_size (sv.worldmodel->brush.visleafs); checkpvs = set_new_size (sv.worldmodel->brush.visleafs);
@ -536,7 +537,6 @@ PF_checkclient (progs_t *pr, void *data)
edict_t *ent, *self; edict_t *ent, *self;
int l; int l;
mleaf_t *leaf; mleaf_t *leaf;
vec3_t view;
// find a new check if on a new frame // find a new check if on a new frame
if (sv.time - sv.lastchecktime >= 0.1) { if (sv.time - sv.lastchecktime >= 0.1) {
@ -551,7 +551,9 @@ PF_checkclient (progs_t *pr, void *data)
} }
// if current entity can't possibly see the check entity, return 0 // if current entity can't possibly see the check entity, return 0
self = PROG_TO_EDICT (pr, *sv_globals.self); self = PROG_TO_EDICT (pr, *sv_globals.self);
vec4f_t view;
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
view[3] = 1;
leaf = Mod_PointInLeaf (view, sv.worldmodel); leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->brush.leafs) - 1; l = (leaf - sv.worldmodel->brush.leafs) - 1;
if (!set_is_member (checkpvs, l)) { if (!set_is_member (checkpvs, l)) {

View file

@ -302,7 +302,8 @@ SV_Multicast (const vec3_t origin, int to)
qboolean reliable; qboolean reliable;
mod_brush_t *brush = &sv.worldmodel->brush; mod_brush_t *brush = &sv.worldmodel->brush;
leaf = Mod_PointInLeaf (origin, sv.worldmodel); vec4f_t org = { VectorExpand (origin), 1 };
leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (!leaf) if (!leaf)
leafnum = 0; leafnum = 0;
else else
@ -346,8 +347,8 @@ SV_Multicast (const vec3_t origin, int to)
goto inrange; goto inrange;
} }
leaf = Mod_PointInLeaf (SVvector (client->edict, origin), org = (vec4f_t) {VectorExpand (SVvector (client->edict, origin)), 1};
sv.worldmodel); leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (leaf) { if (leaf) {
// -1 is because pvs rows are 1 based, not 0 based like leafs // -1 is because pvs rows are 1 based, not 0 based like leafs
leafnum = leaf - brush->leafs - 1; leafnum = leaf - brush->leafs - 1;

View file

@ -410,29 +410,28 @@ SV_TouchLinks (edict_t *ent, areanode_t *node)
} }
static void static void
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) SV_FindTouchedLeafs (edict_t *ent, int node_id)
{ {
int sides; int sides;
mleaf_t *leaf;
plane_t *splitplane; plane_t *splitplane;
edict_leaf_t *edict_leaf; edict_leaf_t *edict_leaf;
if (node->contents == CONTENTS_SOLID)
return;
// add an efrag if the node is a leaf // add an efrag if the node is a leaf
if (node->contents < 0) { if (node_id < 0) {
leaf = (mleaf_t *) node; mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
if (leaf->contents == CONTENTS_SOLID)
return;
edict_leaf = alloc_edict_leaf (); edict_leaf = alloc_edict_leaf ();
edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; edict_leaf->leafnum = ~node_id - 1;
edict_leaf->next = SVdata (ent)->leafs; edict_leaf->next = SVdata (ent)->leafs;
SVdata (ent)->leafs = edict_leaf; SVdata (ent)->leafs = edict_leaf;
return; return;
} }
mnode_t *node = sv.worldmodel->brush.nodes + node_id;
// NODE_MIXED // NODE_MIXED
splitplane = node->plane; splitplane = (plane_t *) &node->plane;
sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin), sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin),
SVvector (ent, absmax), splitplane); SVvector (ent, absmax), splitplane);
@ -497,7 +496,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
// link to PVS leafs // link to PVS leafs
free_edict_leafs (&SVdata (ent)->leafs); free_edict_leafs (&SVdata (ent)->leafs);
if (SVfloat (ent, modelindex)) if (SVfloat (ent, modelindex))
SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); SV_FindTouchedLeafs (ent, 0);
if (SVfloat (ent, solid) == SOLID_NOT) if (SVfloat (ent, solid) == SOLID_NOT)
return; return;