[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);
void AngleQuat (const vec3_t angles, quat_t q);
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,
const plane_t *plane) __attribute__((pure));
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,
const vec3_t point, float degrees);
// NOTE expects plane distance is -p.n
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \
( \
((p)->dist <= (emins)[(p)->type])? \
(-(p)->dist <= (emins)[(p)->type])? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type])? \
(-(p)->dist >= (emaxs)[(p)->type])? \
2 \
: \
3 \
@ -185,6 +187,7 @@ R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs)
int i;
for (i=0 ; i < 4 ; i++) {
// NOTE frustum distance is -p.n
if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2) {
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++)
{
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)
return true;
}

View file

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

View file

@ -74,7 +74,8 @@ struct entity_s;
struct animation_s;
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 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_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_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
@ -308,8 +308,8 @@ void R_SetupFrame (void);
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_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin,
struct dlight_s *light, int bit, mnode_t *node);
void R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin,
struct dlight_s *light, int bit, int node_id);
void R_LoadSkys (const char *);
//void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx);

View file

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

View file

@ -57,8 +57,8 @@ static mleaf_t empty_leafs[] = {
},
};
static mnode_t *empty_leaf_parents[] = {
[1] = 0,
static int empty_leaf_parents[] = {
[1] = -1,
};
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
sides = 0;
if (dist1 >= p->dist)
if (dist1 >= -p->dist)
sides = 1;
if (dist2 < p->dist)
if (dist2 < -p->dist)
sides |= 2;
#ifdef PARANOID

View file

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

View file

@ -173,7 +173,7 @@ gl_R_NewScene (scene_t *scene)
brush->leafs[i].efrags = NULL;
// Force a vis update
R_MarkLeaves (0);
R_MarkLeaves (0, 0);
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
if (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
vec3_t lightorigin;
for (unsigned k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime)
|| (!r_dlights[k].radius))
continue;
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin);
lightorigin[3] = 1;
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)
{
// find which side of the node we are on
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position;
if (plane->type < 3)
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
return dotf (org, node->plane)[0] < 0;
}
static inline void
@ -630,12 +627,13 @@ visit_node (glbspctx_t *bctx, mnode_t *node, int side)
}
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;
if (node->visframe != r_visframecount)
if (r_node_visframes[node_id] != r_visframecount)
return 0;
mnode_t *node = bctx->brush->nodes + node_id;
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
return 0;
return 1;
@ -645,45 +643,55 @@ static void
R_VisitWorldNodes (glbspctx_t *bctx)
{
typedef struct {
mnode_t *node;
int node_id;
int side;
} rstack_t;
mod_brush_t *brush = bctx->brush;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int node_id;
int front;
int side;
node = brush->nodes;
node_id = 0;
// +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
while (1) {
while (test_node (node)) {
while (test_node (bctx, node_id)) {
mnode_t *node = bctx->brush->nodes + node_id;
side = get_side (node);
front = node->children[side];
if (test_node (front)) {
node_ptr->node = node;
if (test_node (bctx, front)) {
node_ptr->node_id = node_id;
node_ptr->side = side;
node_ptr++;
node = front;
node_id = front;
continue;
}
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) front);
if (front < 0) {
mleaf_t *leaf = bctx->brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
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) {
node_ptr--;
node = node_ptr->node;
node_id = node_ptr->node_id;
mnode_t *node = bctx->brush->nodes + node_id;
side = node_ptr->side;
visit_node (bctx, node, side);
node = node->children[!side];
node_id = node->children[side ^ 1];
continue;
}
break;

View file

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

View file

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

View file

@ -47,12 +47,11 @@ static mleaf_t *r_oldviewleaf;
static set_t *solid;
void
R_MarkLeaves (mleaf_t *viewleaf)
R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes)
{
set_t *vis;
int c;
mleaf_t *leaf;
mnode_t *node;
msurface_t **mark;
mod_brush_t *brush = &r_refdef.worldmodel->brush;
@ -86,12 +85,12 @@ R_MarkLeaves (mleaf_t *viewleaf)
} while (--c);
}
leaf->visframe = r_visframecount;
node = brush->leaf_parents[leaf - brush->leafs];
while (node) {
if (node->visframe == r_visframecount)
int node_id = brush->leaf_parents[leaf - brush->leafs];
while (node_id >= 0) {
if (node_visframes[node_id] == r_visframecount)
break;
node->visframe = r_visframecount;
node = brush->node_parents[node - brush->nodes];
node_visframes[node_id] = r_visframecount;
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;
int sides;
efrag_t **lastlink;
mnode_t **node_stack;
mnode_t **node_ptr;
mnode_t *node = brush->nodes;
int *node_stack;
int *node_ptr;
node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *));
node_ptr = node_stack;
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
if (__builtin_expect (node->contents < 0, 0)) {
if (!ent->visibility.topnode) {
ent->visibility.topnode = node;
if (__builtin_expect (node_id < 0, 0)) {
if (ent->visibility.topnode_id == -1) {
ent->visibility.topnode_id = node_id;
}
leaf = (mleaf_t *) node;
leaf = brush->leafs + ~node_id;
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;
leaf->efrags = ef;
node = *--node_ptr;
node_id = *--node_ptr;
} else {
mnode_t *node = brush->nodes + node_id;
// NODE_MIXED
splitplane = node->plane;
splitplane = (plane_t *) &node->plane;
sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane);
if (sides == 3) {
// split on this plane
// if this is the first splitter of this bmodel, remember it
if (!ent->visibility.topnode) {
ent->visibility.topnode = node;
if (ent->visibility.topnode_id == -1) {
ent->visibility.topnode_id = node_id;
}
}
// recurse down the contacted sides
if (sides & 1 && node->children[0]->contents != CONTENTS_SOLID) {
if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID)
if (sides & 1) {
if (sides & 2)
*node_ptr++ = node->children[1];
node = node->children[0];
node_id = node->children[0];
} else {
if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID)
node = node->children[1];
if (sides & 2)
node_id = node->children[1];
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->maxs, emaxs);
ent->visibility.topnode = 0;
ent->visibility.topnode_id = -1; // leaf 0 (solid space)
R_SplitEntityOnNode (brush, ent, emins, emaxs);
}

View file

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

View file

@ -111,7 +111,7 @@ R_SetFrustum (plane_t *frustum, const refframe_t *frame,
vec4f_t origin = frame->position;
for (i = 0; i < 4; i++) {
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]);
}
}

View file

@ -61,6 +61,7 @@
int scr_copytop;
byte *draw_chars; // 8*8 graphic characters FIXME location
qboolean r_cache_thrash; // set if surface cache is thrashing
int *r_node_visframes; //FIXME per renderer
qboolean scr_skipupdate;
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) {
scr_scene->viewleaf = 0;
vec4f_t position = refdef->frame.position;
scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position,
scr_scene->worldmodel);//FIXME
scr_scene->viewleaf = Mod_PointInLeaf (position, scr_scene->worldmodel);
r_dowarpold = r_dowarp;
if (r_waterwarp) {
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,
r_data->vid->height);
}
R_MarkLeaves (scr_scene->viewleaf);
R_MarkLeaves (scr_scene->viewleaf, r_node_visframes);
}
R_PushDlights (vec3_origin);
@ -514,6 +514,9 @@ SCR_NewScene (scene_t *scene)
{
scr_scene = 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->R_NewScene (scene);
} 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
// FIXME: cache these?
splitplane = pnode->plane;
tplane.dist = splitplane->dist -
splitplane = (plane_t *) &pnode->plane;
tplane.dist = splitplane->dist +
DotProduct (r_entorigin, splitplane->normal);
tplane.normal[0] = DotProduct (entity_rotation[0], 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
// FIXME: cache this stuff somehow?
plastvert = pedges->v[0];
lastdist = DotProduct (plastvert->position, tplane.normal) -
lastdist = DotProduct (plastvert->position, tplane.normal) +
tplane.dist;
if (lastdist > 0)
@ -142,7 +142,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
pvert = pedges->v[1];
dist = DotProduct (pvert->position, tplane.normal) - tplane.dist;
dist = DotProduct (pvert->position, tplane.normal) + tplane.dist;
if (dist > 0)
side = 0;
@ -228,18 +228,20 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode,
if (psideedges[i]) {
// 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
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
if (pn->visframe == r_visframecount) {
if (pn->contents < 0) {
if (pn->contents != CONTENTS_SOLID) {
r_currentbkey = ((mleaf_t *) pn)->key;
R_RenderBmodelFace (ent, psideedges[i], psurf);
}
} else {
R_RecursiveClipBPoly (ent, psideedges[i],
pnode->children[i], psurf);
if (child_id < 0) {
mleaf_t *leaf = r_refdef.worldmodel->brush.leafs + ~child_id;
if (leaf->visframe == r_visframecount
&& leaf->contents != CONTENTS_SOLID) {
r_currentbkey = leaf->key;
R_RenderBmodelFace (ent, psideedges[i], psurf);
}
} else {
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
R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags,
mnode_t *topnode)
mleaf_t *topleaf)
{
int i;
vec_t dot;
@ -343,7 +345,7 @@ R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags,
// draw the polygon
if (((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?
R_RenderFace (ent, psurf, clipflags);
@ -365,12 +367,9 @@ static inline int
get_side (mnode_t *node)
{
// find which side of the node we are on
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position;
if (plane->type < 3)
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
return dotf (org, node->plane)[0] < 0;
}
static void
@ -414,20 +413,21 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags)
}
static inline int
test_node (mnode_t *node, int *clipflags)
test_node (swbspctx_t *bctx, int node_id, int *clipflags)
{
int i, *pindex;
vec3_t acceptpt, rejectpt;
double d;
if (node->contents < 0)
if (node_id < 0)
return 0;
if (node->visframe != r_visframecount)
if (r_node_visframes[node_id] != r_visframecount)
return 0;
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (*clipflags) {
mnode_t *node = bctx->brush->nodes + node_id;
for (i = 0; i < 4; i++) {
if (!(*clipflags & (1 << i)))
continue; // don't need to clip against it
@ -465,50 +465,60 @@ static void
R_VisitWorldNodes (swbspctx_t *bctx, int clipflags)
{
typedef struct {
mnode_t *node;
int node_id;
int side, clipflags;
} rstack_t;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int front;
int side, cf;
int node_id;
mod_brush_t *brush = &bctx->entity->renderer.model->brush;
node = brush->nodes;
// +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
node_id = 0;
cf = clipflags;
while (1) {
while (test_node (node, &cf)) {
while (test_node (bctx, node_id, &cf)) {
mnode_t *node = bctx->brush->nodes + node_id;
cf = clipflags;
side = get_side (node);
front = node->children[side];
if (test_node (front, &cf)) {
node_ptr->node = node;
if (test_node (bctx, front, &cf)) {
node_ptr->node_id = node_id;
node_ptr->side = side;
node_ptr->clipflags = clipflags;
node_ptr++;
clipflags = cf;
node = front;
node_id = front;
continue;
}
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) front);
if (front < 0) {
mleaf_t *leaf = bctx->brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
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) {
node_ptr--;
node = node_ptr->node;
node_id = node_ptr->node_id;
mnode_t *node = bctx->brush->nodes + node_id;
side = node_ptr->side;
clipflags = node_ptr->clipflags;
visit_node (bctx, node, side, clipflags);
node = node->children[!side];
node_id = node->children[side ^ 1];
continue;
}
break;

View file

@ -167,7 +167,7 @@ R_NewScene (scene_t *scene)
R_InitSky (brush->skytexture);
// Force a vis update
R_MarkLeaves (0);
R_MarkLeaves (0, 0);
R_ClearParticles ();
@ -303,8 +303,7 @@ R_DrawEntitiesOnList (entqueue_t *queue)
for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
r_entorigin = Transform_GetWorldPosition (ent->transform); \
draw_##type_name##_entity (ent); \
} \
} while (0)
@ -473,19 +472,18 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) {
continue;
}
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
brush->hulls[0].firstclipnode);
}
}
// if the driver wants polygons, deliver those.
@ -494,20 +492,21 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (ent, clmodel);
} else {
if (ent->visibility.topnode) {
mnode_t *topnode = ent->visibility.topnode;
int topnode_id = ent->visibility.topnode_id;
mod_brush_t *brush = &r_refdef.worldmodel->brush;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
r_clipflags = clipflags;
R_DrawSolidClippedSubmodelPolygons (ent, clmodel, topnode);
} else {
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode);
}
if (topnode_id >= 0) {
// not a leaf; has to be clipped to the world
// BSP
mnode_t *node = brush->nodes + topnode_id;
r_clipflags = clipflags;
R_DrawSolidClippedSubmodelPolygons (ent, clmodel, node);
} else {
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// 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)
{
// find the node side on which we are
plane_t *plane = node->plane;
vec4f_t org = r_refdef.frame.position;
if (plane->type < 3)
return (org[plane->type] - plane->dist) < 0;
return (DotProduct (org, plane->normal) - plane->dist) < 0;
return dotf (org, node->plane)[0] < 0;
}
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
test_node (mnode_t *node)
test_node (mod_brush_t *brush, int node_id)
{
if (node->contents < 0)
if (node_id < 0)
return 0;
if (node->visframe != r_visframecount)
if (r_node_visframes[node_id] != r_visframecount)
return 0;
mnode_t *node = brush->nodes + node_id;
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
return 0;
return 1;
@ -700,48 +698,58 @@ static void
R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx)
{
typedef struct {
mnode_t *node;
int node_id;
int side;
} rstack_t;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int node_id;
int front;
int side;
node = brush->nodes;
node_id = 0;
// +2 for paranoia
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
while (1) {
while (test_node (node)) {
while (test_node (brush, node_id)) {
mnode_t *node = brush->nodes + node_id;
side = get_side (node);
front = node->children[side];
if (test_node (front)) {
node_ptr->node = node;
if (test_node (brush, front)) {
node_ptr->node_id = node_id;
node_ptr->side = side;
node_ptr++;
node = front;
node_id = front;
continue;
}
// 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
// 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
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
visit_leaf ((mleaf_t *) front);
if (front < 0) {
mleaf_t *leaf = brush->leafs + ~front;
if (leaf->contents != CONTENTS_SOLID) {
visit_leaf (leaf);
}
}
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) {
node_ptr--;
node = node_ptr->node;
node_id = node_ptr->node_id;
side = node_ptr->side;
mnode_t *node = brush->nodes + node_id;
visit_node (brush, node, side, ctx);
node = node->children[!side];
node_id = node->children[side ^ 1];
continue;
}
break;

View file

@ -142,7 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx)
r_refdef.worldmodel = scene->worldmodel;
// Force a vis update
R_MarkLeaves (0);
R_MarkLeaves (0, 0);
R_ClearParticles ();
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) {
vec4f_t origin;
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;
}
V_SetContentsColor (&cl.viewstate, contents);

View file

@ -757,7 +757,7 @@ Host_ClientFrame (void)
vec4f_t origin;
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)
asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl);

View file

@ -372,30 +372,29 @@ SV_ClearDatagram (void)
static set_t *fatpvs;
static void
SV_AddToFatPVS (vec3_t org, mnode_t *node)
SV_AddToFatPVS (vec4f_t org, int node_id)
{
float d;
plane_t *plane;
while (1) {
// if this is a leaf, accumulate the pvs bits
if (node->contents < 0) {
if (node->contents != CONTENTS_SOLID) {
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node,
sv.worldmodel));
if (node_id < 0) {
mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel));
}
return;
}
mnode_t *node = sv.worldmodel->brush.nodes + node_id;
plane = node->plane;
d = DotProduct (org, plane->normal) - plane->dist;
d = dotf (node->plane, org)[0];
if (d > 8)
node = node->children[0];
node_id = node->children[0];
else if (d < -8)
node = node->children[1];
node_id = node->children[1];
else { // go down both
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.
*/
static set_t *
SV_FatPVS (vec3_t org)
SV_FatPVS (vec4f_t org)
{
if (!fatpvs) {
fatpvs = set_new_size (sv.worldmodel->brush.visleafs);
}
set_expand (fatpvs, sv.worldmodel->brush.visleafs);
set_empty (fatpvs);
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes);
SV_AddToFatPVS (org, 0);
return fatpvs;
}
@ -426,13 +425,14 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
pr_uint_t bits, e;
set_t *pvs;
float miss;
vec3_t org;
vec4f_t org;
edict_t *ent;
entity_state_t *baseline;
edict_leaf_t *el;
// find the client's PVS
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
org[3] = 1;
pvs = SV_FatPVS (org);
// 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;
unsigned i;
mleaf_t *leaf;
vec3_t org;
// cycle to the next one
if (check < 1)
@ -582,7 +581,9 @@ PF_newcheckclient (progs_t *pr, unsigned check)
}
// get the PVS for the entity
vec4f_t org;
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
org[3] = 1;
leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (!checkpvs) {
checkpvs = set_new_size (sv.worldmodel->brush.visleafs);
@ -615,7 +616,6 @@ PF_checkclient (progs_t *pr, void *data)
edict_t *ent, *self;
int l;
mleaf_t *leaf;
vec3_t view;
// find a new check if on a new frame
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
self = PROG_TO_EDICT (pr, *sv_globals.self);
vec4f_t view;
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
view[3] = 1;
leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->brush.leafs) - 1;
if (!set_is_member (checkpvs, l)) {

View file

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

View file

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

View file

@ -116,15 +116,16 @@ sv_unlink_entity (server_t *sv, qtv_entity_t *ent)
}
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
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 ();
ent_leaf->num = (mleaf_t *) node - sv->worldmodel->brush.leafs - 1;
ent_leaf->num = ~node_id - 1;
ent_leaf->next = ent->leafs;
ent->leafs = ent_leaf;
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->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);
if (sides & 1) {
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);
}
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;
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)
asl = l->ambient_sound_level;
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) {
vec4f_t origin;
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;
}
V_SetContentsColor (&cl.viewstate, contents);

View file

@ -40,6 +40,8 @@
#include "QF/set.h"
#include "QF/sys.h"
#include "QF/simd/vec4f.h"
#include "compat.h"
#include "qw/msg_ucmd.h"
@ -59,30 +61,29 @@ static set_t *fatpvs;
static void
SV_AddToFatPVS (vec3_t org, mnode_t *node)
SV_AddToFatPVS (vec4f_t org, int node_id)
{
float d;
plane_t *plane;
while (1) {
// if this is a leaf, accumulate the pvs bits
if (node->contents < 0) {
if (node->contents != CONTENTS_SOLID) {
set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node,
sv.worldmodel));
if (node_id < 0) {
mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
if (leaf->contents != CONTENTS_SOLID) {
set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel));
}
return;
}
plane = node->plane;
d = DotProduct (org, plane->normal) - plane->dist;
mnode_t *node = sv.worldmodel->brush.nodes + node_id;
d = dotf (org, node->plane)[0];
if (d > 8)
node = node->children[0];
node_id = node->children[0];
else if (d < -8)
node = node->children[1];
node_id = node->children[1];
else { // go down both
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.
*/
static set_t *
SV_FatPVS (vec3_t org)
SV_FatPVS (vec4f_t org)
{
if (!fatpvs) {
fatpvs = set_new_size (sv.worldmodel->brush.visleafs);
}
set_expand (fatpvs, sv.worldmodel->brush.visleafs);
set_empty (fatpvs);
SV_AddToFatPVS (org, sv.worldmodel->brush.nodes);
SV_AddToFatPVS (org, 0);
return fatpvs;
}
@ -710,12 +711,13 @@ static inline set_t *
calc_pvs (delta_t *delta)
{
set_t *pvs = 0;
vec3_t org;
vec4f_t org = {};
// find the client's PVS
if (delta->pvs == dt_pvs_normal) {
edict_t *clent = delta->client->edict;
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
org[3] = 1;
pvs = SV_FatPVS (org);
} else if (delta->pvs == dt_pvs_fat) {
// 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),
SVvector (cl->edict, view_ofs), org);
org[3] = 1;
if (pvs == NULL) {
pvs = SV_FatPVS (org);
} 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;
int i;
mleaf_t *leaf;
vec3_t org;
// cycle to the next one
if (check < 1)
@ -503,7 +502,9 @@ PF_newcheckclient (progs_t *pr, int check)
}
// get the PVS for the entity
vec4f_t org;
VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org);
org[3] = 1;
leaf = Mod_PointInLeaf (org, sv.worldmodel);
if (!checkpvs) {
checkpvs = set_new_size (sv.worldmodel->brush.visleafs);
@ -536,7 +537,6 @@ PF_checkclient (progs_t *pr, void *data)
edict_t *ent, *self;
int l;
mleaf_t *leaf;
vec3_t view;
// find a new check if on a new frame
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
self = PROG_TO_EDICT (pr, *sv_globals.self);
vec4f_t view;
VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view);
view[3] = 1;
leaf = Mod_PointInLeaf (view, sv.worldmodel);
l = (leaf - sv.worldmodel->brush.leafs) - 1;
if (!set_is_member (checkpvs, l)) {

View file

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

View file

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