mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
[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:
parent
8633ffe9d2
commit
7240d2dc80
36 changed files with 397 additions and 350 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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);
|
||||
visit_node (bctx, node, side);
|
||||
node = node->children[!side];
|
||||
if (front < 0) {
|
||||
mleaf_t *leaf = bctx->brush->leafs + ~front;
|
||||
if (leaf->contents != CONTENTS_SOLID) {
|
||||
visit_leaf (leaf);
|
||||
}
|
||||
}
|
||||
visit_node (bctx, node, 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;
|
||||
|
|
|
@ -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);
|
||||
visit_node (bctx, node, side);
|
||||
node = node->children[!side];
|
||||
if (front < 0) {
|
||||
mleaf_t *leaf = bctx->brush->leafs + ~front;
|
||||
if (leaf->contents != CONTENTS_SOLID) {
|
||||
visit_leaf (leaf);
|
||||
}
|
||||
}
|
||||
visit_node (bctx, node, 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
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 {
|
||||
R_RecursiveClipBPoly (ent, psideedges[i],
|
||||
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
|
||||
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);
|
||||
visit_node (bctx, node, side, clipflags);
|
||||
node = node->children[!side];
|
||||
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_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;
|
||||
|
|
|
@ -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) {
|
||||
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, topnode);
|
||||
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
|
||||
R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode);
|
||||
}
|
||||
mleaf_t *leaf = brush->leafs + ~topnode_id;
|
||||
R_DrawSubmodelPolygons (ent, clmodel, clipflags, leaf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
visit_node (brush, node, side, ctx);
|
||||
node = node->children[!side];
|
||||
if (front < 0) {
|
||||
mleaf_t *leaf = brush->leafs + ~front;
|
||||
if (leaf->contents != CONTENTS_SOLID) {
|
||||
visit_leaf (leaf);
|
||||
}
|
||||
}
|
||||
visit_node (brush, node, side, ctx);
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -410,20 +410,18 @@ 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)
|
||||
// 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;
|
||||
|
||||
// add an efrag if the node is a leaf
|
||||
if (node->contents < 0) {
|
||||
leaf = (mleaf_t *) node;
|
||||
|
||||
edict_leaf = alloc_edict_leaf ();
|
||||
edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1;
|
||||
edict_leaf->next = SVdata (ent)->leafs;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
// add an efrag if the node is a leaf
|
||||
if (node_id < 0) {
|
||||
mleaf_t *leaf = sv->worldmodel->brush.leafs + ~node_id;
|
||||
if (leaf->contents == CONTENTS_SOLID) {
|
||||
return;
|
||||
}
|
||||
// add an efrag if the node is a leaf
|
||||
if (node->contents < 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
// add an efrag if the node is a leaf
|
||||
if (node_id < 0) {
|
||||
mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id;
|
||||
if (leaf->contents == CONTENTS_SOLID)
|
||||
return;
|
||||
|
||||
// add an efrag if the node is a leaf
|
||||
if (node->contents < 0) {
|
||||
leaf = (mleaf_t *) node;
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue