mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Use a linked list for the leafs in which the entity is positioned.
This allows the pvs to be used on an antity no matter how many leafs the entity is touching. Seems to work nicely, but it will leak memory every time a map is loaded.
This commit is contained in:
parent
a0828ddd06
commit
31cf4b0d78
5 changed files with 107 additions and 33 deletions
|
@ -214,13 +214,16 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type);
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
#define MAX_ENT_LEAFS 16
|
typedef struct edict_leaf_s {
|
||||||
|
struct edict_leaf_s *next;
|
||||||
|
struct mleaf_s *leaf;
|
||||||
|
} edict_leaf_t;
|
||||||
|
|
||||||
struct edict_s {
|
struct edict_s {
|
||||||
qboolean free;
|
qboolean free;
|
||||||
link_t area; ///< linked to a division node or leaf
|
link_t area; ///< linked to a division node or leaf
|
||||||
|
|
||||||
int num_leafs;
|
edict_leaf_t *leafs;
|
||||||
short leafnums[MAX_ENT_LEAFS];
|
|
||||||
|
|
||||||
float freetime; ///< sv.time when the object was freed
|
float freetime; ///< sv.time when the object was freed
|
||||||
void *data; ///< external per-edict data
|
void *data; ///< external per-edict data
|
||||||
|
|
|
@ -443,6 +443,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
||||||
vec3_t org;
|
vec3_t org;
|
||||||
edict_t *ent;
|
edict_t *ent;
|
||||||
entity_state_t *baseline;
|
entity_state_t *baseline;
|
||||||
|
edict_leaf_t *el;
|
||||||
|
|
||||||
// find the client's PVS
|
// find the client's PVS
|
||||||
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
|
VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org);
|
||||||
|
@ -465,11 +466,13 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg)
|
||||||
&& (int) SVfloat (ent, modelindex) & 0xFF00)
|
&& (int) SVfloat (ent, modelindex) & 0xFF00)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < ent->num_leafs; i++)
|
for (el = ent->leafs; el; el = el->next) {
|
||||||
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7)))
|
unsigned leafnum = el->leaf - sv.worldmodel->leafs - 1;
|
||||||
|
if (pvs[leafnum >> 3] & (1 << (leafnum & 7)))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (i == ent->num_leafs)
|
if (!el)
|
||||||
continue; // not visible
|
continue; // not visible
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,39 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
#include "sv_progs.h"
|
#include "sv_progs.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
|
#define EDICT_LEAFS 32
|
||||||
|
static edict_leaf_t *free_edict_leaf_list;
|
||||||
|
|
||||||
|
static edict_leaf_t *
|
||||||
|
alloc_edict_leaf (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
edict_leaf_t *edict_leaf;
|
||||||
|
|
||||||
|
if (!free_edict_leaf_list) {
|
||||||
|
free_edict_leaf_list = malloc (EDICT_LEAFS * sizeof (edict_leaf_t));
|
||||||
|
for (i = 0; i < EDICT_LEAFS - 1; i++)
|
||||||
|
free_edict_leaf_list[i].next = &free_edict_leaf_list[i + 1];
|
||||||
|
free_edict_leaf_list[i].next = 0;
|
||||||
|
}
|
||||||
|
edict_leaf = free_edict_leaf_list;
|
||||||
|
free_edict_leaf_list = free_edict_leaf_list->next;
|
||||||
|
edict_leaf->next = 0;
|
||||||
|
return edict_leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_edict_leafs (edict_leaf_t **edict_leafs)
|
||||||
|
{
|
||||||
|
edict_leaf_t **el;
|
||||||
|
|
||||||
|
for (el = edict_leafs; *el; el = &(*el)->next)
|
||||||
|
;
|
||||||
|
*el = free_edict_leaf_list;
|
||||||
|
free_edict_leaf_list = *edict_leafs;
|
||||||
|
*edict_leafs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
entities never clip against themselves, or their owner
|
entities never clip against themselves, or their owner
|
||||||
line of sight checks trace->crosscontent, but bullets don't
|
line of sight checks trace->crosscontent, but bullets don't
|
||||||
|
@ -328,23 +361,22 @@ SV_TouchLinks (edict_t *ent, areanode_t *node)
|
||||||
static void
|
static void
|
||||||
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
|
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
|
||||||
{
|
{
|
||||||
int leafnum, sides;
|
int sides;
|
||||||
mleaf_t *leaf;
|
mleaf_t *leaf;
|
||||||
mplane_t *splitplane;
|
mplane_t *splitplane;
|
||||||
|
edict_leaf_t *edict_leaf;
|
||||||
|
|
||||||
if (node->contents == CONTENTS_SOLID)
|
if (node->contents == CONTENTS_SOLID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// add an efrag if the node is a leaf
|
// add an efrag if the node is a leaf
|
||||||
if (node->contents < 0) {
|
if (node->contents < 0) {
|
||||||
if (ent->num_leafs == MAX_ENT_LEAFS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
leaf = (mleaf_t *) node;
|
leaf = (mleaf_t *) node;
|
||||||
leafnum = leaf - sv.worldmodel->leafs - 1;
|
|
||||||
|
|
||||||
ent->leafnums[ent->num_leafs] = leafnum;
|
edict_leaf = alloc_edict_leaf ();
|
||||||
ent->num_leafs++;
|
edict_leaf->leaf = leaf;
|
||||||
|
edict_leaf->next = ent->leafs;
|
||||||
|
ent->leafs = edict_leaf;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +430,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// link to PVS leafs
|
// link to PVS leafs
|
||||||
ent->num_leafs = 0;
|
free_edict_leafs (&ent->leafs);
|
||||||
if (SVfloat (ent, modelindex))
|
if (SVfloat (ent, modelindex))
|
||||||
SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
|
SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
|
||||||
|
|
||||||
|
|
|
@ -553,12 +553,13 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to,
|
||||||
static void
|
static void
|
||||||
SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int j, k;
|
||||||
client_t *cl;
|
client_t *cl;
|
||||||
edict_t *clent = 0;
|
edict_t *clent = 0;
|
||||||
int spec_track = 0;
|
int spec_track = 0;
|
||||||
int stdver = 2, full = stdver;
|
int stdver = 2, full = stdver;
|
||||||
edict_t *ent;
|
edict_t *ent;
|
||||||
|
edict_leaf_t *el;
|
||||||
packet_players_t *pack;
|
packet_players_t *pack;
|
||||||
client_frame_t *frame = &delta->frames[delta->in_frame];
|
client_frame_t *frame = &delta->frames[delta->in_frame];
|
||||||
packet_players_t *from_pack = 0;
|
packet_players_t *from_pack = 0;
|
||||||
|
@ -614,11 +615,12 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg)
|
||||||
|
|
||||||
if (pvs) {
|
if (pvs) {
|
||||||
// ignore if not touching a PV leaf
|
// ignore if not touching a PV leaf
|
||||||
for (i = 0; i < ent->num_leafs; i++)
|
for (el = ent->leafs; el; el = el->next) {
|
||||||
if (pvs[ent->leafnums[i] >> 3]
|
unsigned leafnum = el->leaf - sv.worldmodel->leafs - 1;
|
||||||
& (1 << (ent->leafnums[i] & 7)))
|
if (pvs[leafnum >> 3] & (1 << (leafnum & 7)))
|
||||||
break;
|
break;
|
||||||
if (i == ent->num_leafs)
|
}
|
||||||
|
if (!el)
|
||||||
continue; // not visible
|
continue; // not visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -759,11 +761,12 @@ void
|
||||||
SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg)
|
SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg)
|
||||||
{
|
{
|
||||||
byte *pvs = 0;
|
byte *pvs = 0;
|
||||||
int e, i, num_edicts;
|
int e, num_edicts;
|
||||||
int max_packet_entities = MAX_DEMO_PACKET_ENTITIES;
|
int max_packet_entities = MAX_DEMO_PACKET_ENTITIES;
|
||||||
int stdver = 1;
|
int stdver = 1;
|
||||||
client_frame_t *frame;
|
client_frame_t *frame;
|
||||||
edict_t *ent;
|
edict_t *ent;
|
||||||
|
edict_leaf_t *el;
|
||||||
entity_state_t *state;
|
entity_state_t *state;
|
||||||
packet_entities_t *pack;
|
packet_entities_t *pack;
|
||||||
|
|
||||||
|
@ -801,12 +804,13 @@ SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg)
|
||||||
|
|
||||||
if (pvs) {
|
if (pvs) {
|
||||||
// ignore if not touching a PV leaf
|
// ignore if not touching a PV leaf
|
||||||
for (i = 0; i < ent->num_leafs; i++)
|
for (el = ent->leafs; el; el = el->next) {
|
||||||
if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7)))
|
unsigned leafnum = el->leaf - sv.worldmodel->leafs - 1;
|
||||||
|
if (pvs[leafnum >> 3] & (1 << (leafnum & 7)))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (i == ent->num_leafs)
|
if (!el)
|
||||||
continue; // not visible
|
continue; // not visible
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SV_AddNailUpdate (ent))
|
if (SV_AddNailUpdate (ent))
|
||||||
|
|
|
@ -50,6 +50,39 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
#include "sv_progs.h"
|
#include "sv_progs.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
|
#define EDICT_LEAFS 32
|
||||||
|
static edict_leaf_t *free_edict_leaf_list;
|
||||||
|
|
||||||
|
static edict_leaf_t *
|
||||||
|
alloc_edict_leaf (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
edict_leaf_t *edict_leaf;
|
||||||
|
|
||||||
|
if (!free_edict_leaf_list) {
|
||||||
|
free_edict_leaf_list = malloc (EDICT_LEAFS * sizeof (edict_leaf_t));
|
||||||
|
for (i = 0; i < EDICT_LEAFS - 1; i++)
|
||||||
|
free_edict_leaf_list[i].next = &free_edict_leaf_list[i + 1];
|
||||||
|
free_edict_leaf_list[i].next = 0;
|
||||||
|
}
|
||||||
|
edict_leaf = free_edict_leaf_list;
|
||||||
|
free_edict_leaf_list = free_edict_leaf_list->next;
|
||||||
|
edict_leaf->next = 0;
|
||||||
|
return edict_leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_edict_leafs (edict_leaf_t **edict_leafs)
|
||||||
|
{
|
||||||
|
edict_leaf_t **el;
|
||||||
|
|
||||||
|
for (el = edict_leafs; *el; el = &(*el)->next)
|
||||||
|
;
|
||||||
|
*el = free_edict_leaf_list;
|
||||||
|
free_edict_leaf_list = *edict_leafs;
|
||||||
|
*edict_leafs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
entities never clip against themselves, or their owner
|
entities never clip against themselves, or their owner
|
||||||
line of sight checks trace->crosscontent, but bullets don't
|
line of sight checks trace->crosscontent, but bullets don't
|
||||||
|
@ -316,23 +349,22 @@ SV_TouchLinks (edict_t *ent, areanode_t *node)
|
||||||
static void
|
static void
|
||||||
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
|
SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
|
||||||
{
|
{
|
||||||
int leafnum, sides;
|
int sides;
|
||||||
mleaf_t *leaf;
|
mleaf_t *leaf;
|
||||||
mplane_t *splitplane;
|
mplane_t *splitplane;
|
||||||
|
edict_leaf_t *edict_leaf;
|
||||||
|
|
||||||
if (node->contents == CONTENTS_SOLID)
|
if (node->contents == CONTENTS_SOLID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// add an efrag if the node is a leaf
|
// add an efrag if the node is a leaf
|
||||||
if (node->contents < 0) {
|
if (node->contents < 0) {
|
||||||
if (ent->num_leafs == MAX_ENT_LEAFS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
leaf = (mleaf_t *) node;
|
leaf = (mleaf_t *) node;
|
||||||
leafnum = leaf - sv.worldmodel->leafs - 1;
|
|
||||||
|
|
||||||
ent->leafnums[ent->num_leafs] = leafnum;
|
edict_leaf = alloc_edict_leaf ();
|
||||||
ent->num_leafs++;
|
edict_leaf->leaf = leaf;
|
||||||
|
edict_leaf->next = ent->leafs;
|
||||||
|
ent->leafs = edict_leaf;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +418,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// link to PVS leafs
|
// link to PVS leafs
|
||||||
ent->num_leafs = 0;
|
free_edict_leafs (&ent->leafs);
|
||||||
if (SVfloat (ent, modelindex))
|
if (SVfloat (ent, modelindex))
|
||||||
SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
|
SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue