mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-25 22:01:33 +00:00
[scene] Move visibility management into scene code
Well, sort of: it's still really in the renderer, but now calling R_AddEfrags automatically updates the visibility structure as necessary, and deleting an entity cleans up the efrags automatically. I wanted this over twenty years ago.
This commit is contained in:
parent
88e59e72c4
commit
0e64f959e2
8 changed files with 80 additions and 127 deletions
|
@ -146,7 +146,7 @@ Entity_Transform (entity_t ent)
|
|||
|
||||
struct mod_brush_s;
|
||||
void R_AddEfrags (struct mod_brush_s *, entity_t ent);
|
||||
void R_RemoveEfrags (entity_t ent);
|
||||
void R_ClearEfragChain (efrag_t *ef);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
@ -157,12 +157,10 @@ void
|
|||
CL_Init_Entity (entity_t ent)
|
||||
{
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg);
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg);
|
||||
byte *active = Ent_GetComponent (ent.id, scene_active, cl_world.scene->reg);
|
||||
vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg);
|
||||
memset (animation, 0, sizeof (*animation));
|
||||
memset (visibility, 0, sizeof (*visibility));
|
||||
memset (renderer, 0, sizeof (*renderer));
|
||||
*active = 1;
|
||||
*old_origin = (vec4f_t) {0, 0, 0, 1};
|
||||
|
@ -223,11 +221,6 @@ static inline void
|
|||
beam_clear (beam_t *b)
|
||||
{
|
||||
if (b->tents) {
|
||||
tent_t *t;
|
||||
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
R_RemoveEfrags (t->ent);
|
||||
}
|
||||
free_temp_entities (b->tents);
|
||||
b->tents = 0;
|
||||
}
|
||||
|
@ -635,11 +628,9 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
|
|||
ent = ex->tent->ent;
|
||||
f = 10 * (time - ex->start);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg);
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg);
|
||||
if (f >= renderer->model->numframes) {
|
||||
tent_obj_t *_to;
|
||||
R_RemoveEfrags (ent);
|
||||
free_temp_entities (ex->tent);
|
||||
_to = *to;
|
||||
*to = _to->next;
|
||||
|
@ -649,10 +640,8 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
|
|||
to = &(*to)->next;
|
||||
|
||||
animation->frame = f;
|
||||
if (!visibility->efrag) {
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -688,11 +677,6 @@ CL_ParseParticleEffect (qmsg_t *net_message)
|
|||
void
|
||||
CL_ClearProjectiles (void)
|
||||
{
|
||||
tent_t *tent;
|
||||
|
||||
for (tent = cl_projectiles; tent; tent = tent->next) {
|
||||
R_RemoveEfrags (tent->ent);
|
||||
}
|
||||
free_temp_entities (cl_projectiles);
|
||||
cl_projectiles = 0;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,6 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res)
|
|||
pr_ulong_t scene_id = id & 0xffffffff;
|
||||
rua_scene_t *scene = rua_scene_get (res, scene_id);
|
||||
|
||||
R_RemoveEfrags (ent);
|
||||
// bad scene caught above
|
||||
Scene_DestroyEntity (scene->scene, ent);
|
||||
}
|
||||
|
@ -301,8 +300,7 @@ bi_Entity_SetModel (progs_t *pr, void *_res)
|
|||
// bad scene caught above
|
||||
rua_scene_t *scene = rua_scene_get (res, scene_id);
|
||||
|
||||
R_RemoveEfrags (ent);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, scene->scene->reg);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
renderer->model = model;
|
||||
R_AddEfrags (&scene->scene->worldmodel->brush, ent);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,15 @@ create_old_origin (void *_old_origin)
|
|||
*old_origin = (vec4f_t) {0, 0, 0, 1};
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_visibility (void *_visibility)
|
||||
{
|
||||
visibility_t *visibility = _visibility;
|
||||
if (visibility->efrag) {
|
||||
R_ClearEfragChain (visibility->efrag);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sw_identity_matrix (void *_mat)
|
||||
{
|
||||
|
@ -94,6 +103,7 @@ static const component_t scene_components[] = {
|
|||
[scene_visibility] = {
|
||||
.size = sizeof (visibility_t),
|
||||
.create = 0,//create_visibility,
|
||||
.destroy = destroy_visibility,
|
||||
.name = "visibility",
|
||||
},
|
||||
[scene_renderer] = {
|
||||
|
@ -219,7 +229,6 @@ Scene_CreateEntity (scene_t *scene)
|
|||
uint32_t id = trans.id;
|
||||
|
||||
Ent_SetComponent (id, scene_animation, scene->reg, 0);
|
||||
Ent_SetComponent (id, scene_visibility, scene->reg, 0);
|
||||
Ent_SetComponent (id, scene_renderer, scene->reg, 0);
|
||||
Ent_SetComponent (id, scene_active, scene->reg, 0);
|
||||
Ent_SetComponent (id, scene_old_origin, scene->reg, 0);
|
||||
|
|
|
@ -95,18 +95,10 @@ R_ClearEfrags (void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
R_RemoveEfrags
|
||||
|
||||
Call when removing an object from the world or moving it to another position
|
||||
*/
|
||||
void
|
||||
R_RemoveEfrags (entity_t ent)
|
||||
R_ClearEfragChain (efrag_t *ef)
|
||||
{
|
||||
efrag_t *ef, *old, *walk, **prev;
|
||||
visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg);
|
||||
|
||||
ef = vis->efrag;
|
||||
efrag_t *old, *walk, **prev;
|
||||
|
||||
while (ef) {
|
||||
prev = &ef->leaf->efrags;
|
||||
|
@ -128,8 +120,6 @@ R_RemoveEfrags (entity_t ent)
|
|||
old->entnext = r_free_efrags;
|
||||
r_free_efrags = old;
|
||||
}
|
||||
|
||||
vis->efrag = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -210,11 +200,19 @@ R_AddEfrags (mod_brush_t *brush, entity_t ent)
|
|||
vec3_t emins, emaxs;
|
||||
transform_t transform = Entity_Transform (ent);
|
||||
renderer_t *rend = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg);
|
||||
|
||||
if (!rend->model) {
|
||||
Ent_RemoveComponent (ent.id, scene_visibility, ent.reg);
|
||||
return;
|
||||
}
|
||||
visibility_t *vis;
|
||||
if (Ent_HasComponent (ent.id, scene_visibility, ent.reg)) {
|
||||
vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg);
|
||||
R_ClearEfragChain (vis->efrag);
|
||||
} else {
|
||||
vis = Ent_AddComponent (ent.id, scene_visibility, ent.reg);
|
||||
}
|
||||
vis->efrag = 0;
|
||||
|
||||
entmodel = rend->model;
|
||||
|
||||
|
|
|
@ -147,8 +147,8 @@ static void
|
|||
set_entity_model (int ent_ind, int modelindex)
|
||||
{
|
||||
entity_t ent = cl_entities[ent_ind];
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, ent.reg);
|
||||
renderer->model = cl_world.models.a[modelindex];
|
||||
// automatic animation (torches, etc) can be either all together
|
||||
// or randomized
|
||||
|
@ -158,10 +158,10 @@ set_entity_model (int ent_ind, int modelindex)
|
|||
} else {
|
||||
animation->syncbase = 0.0;
|
||||
}
|
||||
} else {
|
||||
// hack to make null model players work
|
||||
SET_ADD (&cl_forcelink, ent_ind);
|
||||
}
|
||||
// Changing the model can change the visibility of the entity and even
|
||||
// the model type
|
||||
SET_ADD (&cl_forcelink, ent_ind);
|
||||
animation->nolerp = 1; // don't try to lerp when the model has changed
|
||||
if (ent_ind <= cl.maxclients) {
|
||||
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, ent_ind);
|
||||
|
@ -175,7 +175,6 @@ CL_RelinkEntities (void)
|
|||
entity_state_t *new, *old;
|
||||
float bobjrotate, frac, f;
|
||||
int i, j;
|
||||
int entvalid;
|
||||
int model_flags;
|
||||
|
||||
// determine partial update time
|
||||
|
@ -207,31 +206,23 @@ CL_RelinkEntities (void)
|
|||
new = &nq_entstates.frame[0 + cl.frameIndex][i];
|
||||
old = &nq_entstates.frame[1 - cl.frameIndex][i];
|
||||
|
||||
// if the object wasn't included in the last packet, remove it
|
||||
entvalid = cl_msgtime[i] == cl.mtime[0];
|
||||
if (entvalid && !new->modelindex) {
|
||||
ent = CL_GetEntity (i);
|
||||
CL_TransformEntity (ent, new->scale / 16.0, new->angles,
|
||||
new->origin);
|
||||
entvalid = 0;
|
||||
}
|
||||
if (!entvalid) {
|
||||
ent = CL_GetInvalidEntity (i);
|
||||
// if the object wasn't included in the last packet, or the model
|
||||
// has been removed, remove the entity
|
||||
if (cl_msgtime[i] != cl.mtime[0] || !new->modelindex) {
|
||||
if (Entity_Valid (ent)) {
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg);
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent); // just became empty
|
||||
}
|
||||
Scene_DestroyEntity (cl_world.scene, ent);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entity_Valid (ent)) {
|
||||
ent = CL_GetEntity (i);
|
||||
SET_ADD (&cl_forcelink, i);
|
||||
}
|
||||
transform_t transform = Entity_Transform (ent);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, ent.reg);
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg);
|
||||
vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, ent.reg);
|
||||
|
||||
if (SET_TEST_MEMBER (&cl_forcelink, i)) {
|
||||
|
@ -242,9 +233,6 @@ CL_RelinkEntities (void)
|
|||
|| new->modelindex != old->modelindex) {
|
||||
old->modelindex = new->modelindex;
|
||||
set_entity_model (i, new->modelindex);
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent);
|
||||
}
|
||||
}
|
||||
animation->frame = new->frame;
|
||||
if (SET_TEST_MEMBER (&cl_forcelink, i)
|
||||
|
@ -280,9 +268,6 @@ CL_RelinkEntities (void)
|
|||
CL_TransformEntity (ent, new->scale / 16.0, new->angles,
|
||||
new->origin);
|
||||
if (i != cl.viewentity || chase_active) {
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent);
|
||||
}
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
*old_origin = new->origin;
|
||||
|
@ -315,12 +300,7 @@ CL_RelinkEntities (void)
|
|||
}
|
||||
if (i != cl.viewentity || chase_active) {
|
||||
vec4f_t org = Transform_GetWorldPosition (transform);
|
||||
if (visibility->efrag) {
|
||||
if (!VectorCompare (org, *old_origin)) {//FIXME
|
||||
R_RemoveEfrags (ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
} else {
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,10 +234,9 @@ CL_ClearMemory (void)
|
|||
cl.viewstate.demoplayback = cls.demoplayback;
|
||||
|
||||
CL_ClearTEnts ();
|
||||
CL_ClearEnts ();
|
||||
|
||||
SCR_NewScene (0);
|
||||
|
||||
CL_ClearEnts ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -89,6 +89,12 @@ CL_ClearEnts (void)
|
|||
memset (cl_entity_valid, 0, sizeof (cl_entity_valid));
|
||||
}
|
||||
|
||||
static entity_t
|
||||
CL_GetInvalidEntity (int num)
|
||||
{
|
||||
return cl_entities[num];
|
||||
}
|
||||
|
||||
entity_t
|
||||
CL_GetEntity (int num)
|
||||
{
|
||||
|
@ -163,42 +169,37 @@ CL_LinkPacketEntities (void)
|
|||
for (i = MAX_CLIENTS + 1; i < 512; i++) {
|
||||
new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i];
|
||||
old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i];
|
||||
ent = CL_GetEntity (i);
|
||||
transform_t transform = Entity_Transform (ent);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer,
|
||||
cl_world.scene->reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation,
|
||||
cl_world.scene->reg);
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility,
|
||||
cl_world.scene->reg);
|
||||
vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin,
|
||||
cl_world.scene->reg);
|
||||
|
||||
ent = CL_GetInvalidEntity (i);
|
||||
forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i];
|
||||
cl_entity_valid[1][i] = cl_entity_valid[0][i];
|
||||
// if the object wasn't included in the last packet, remove it
|
||||
if (!cl_entity_valid[0][i]) {
|
||||
renderer->model = NULL;
|
||||
animation->pose1 = animation->pose2 = -1;
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent); // just became empty
|
||||
// if the object wasn't included in the last packet, or set
|
||||
// to invisible, remove it
|
||||
if (!cl_entity_valid[0][i]
|
||||
|| !new->modelindex
|
||||
|| (cl_deadbodyfilter && is_dead_body (new))
|
||||
|| (cl_gibfilter && is_gib (new))) {
|
||||
if (Entity_Valid (ent)) {
|
||||
Scene_DestroyEntity (cl_world.scene, ent);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!Entity_Valid (ent)) {
|
||||
ent = CL_GetEntity (i);
|
||||
forcelink = true;
|
||||
}
|
||||
transform_t transform = Entity_Transform (ent);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer,
|
||||
ent.reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation,
|
||||
ent.reg);
|
||||
vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin,
|
||||
ent.reg);
|
||||
|
||||
// spawn light flashes, even ones coming from invisible objects
|
||||
CL_NewDlight (i, new->origin, new->effects, new->glow_size,
|
||||
new->glow_color, cl.time);
|
||||
|
||||
// if set to invisible, skip
|
||||
if (!new->modelindex
|
||||
|| (cl_deadbodyfilter && is_dead_body (new))
|
||||
|| (cl_gibfilter && is_gib (new))) {
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (forcelink)
|
||||
*old = *new;
|
||||
|
||||
|
@ -246,9 +247,6 @@ CL_LinkPacketEntities (void)
|
|||
CL_TransformEntity (ent, new->scale / 16, new->angles,
|
||||
new->origin);
|
||||
if (i != cl.viewentity || chase_active) {
|
||||
if (visibility->efrag) {
|
||||
R_RemoveEfrags (ent);
|
||||
}
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
} else {
|
||||
|
@ -277,19 +275,11 @@ CL_LinkPacketEntities (void)
|
|||
}
|
||||
if (i != cl.viewentity || chase_active) {
|
||||
vec4f_t org = Transform_GetWorldPosition (transform);
|
||||
if (visibility->efrag) {
|
||||
if (!VectorCompare (org, *old_origin)) {//FIXME
|
||||
R_RemoveEfrags (ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
} else {
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!visibility->efrag) {
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
|
||||
// rotate binary objects locally
|
||||
if (renderer->model->flags & EF_ROTATE) {
|
||||
|
@ -420,28 +410,23 @@ CL_LinkPlayers (void)
|
|||
|
||||
for (j = 0, player = cl.players, state = frame->playerstate;
|
||||
j < MAX_CLIENTS; j++, player++, state++) {
|
||||
ent = CL_GetInvalidEntity (j + 1);
|
||||
if (state->messagenum != cl.parsecount
|
||||
|| !player->name || !player->name->value[0]) {
|
||||
// not present this frame
|
||||
if (Entity_Valid (ent)) {
|
||||
Scene_DestroyEntity (cl_world.scene, ent);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Entity_Valid (ent)) {
|
||||
ent = CL_GetEntity (j + 1);
|
||||
visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility,
|
||||
cl_world.scene->reg);
|
||||
}
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer,
|
||||
cl_world.scene->reg);
|
||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation,
|
||||
cl_world.scene->reg);
|
||||
if (visibility->efrag)
|
||||
R_RemoveEfrags (ent);
|
||||
if (Entity_Valid (player->flag_ent)) {
|
||||
visibility_t *fvis = Ent_GetComponent (player->flag_ent.id,
|
||||
scene_visibility,
|
||||
cl_world.scene->reg);
|
||||
if (fvis->efrag) {
|
||||
R_RemoveEfrags (player->flag_ent);
|
||||
}
|
||||
}
|
||||
if (state->messagenum != cl.parsecount)
|
||||
continue; // not present this frame
|
||||
|
||||
if (!player->name || !player->name->value[0])
|
||||
continue;
|
||||
|
||||
// spawn light flashes, even ones coming from invisible objects
|
||||
if (j == cl.playernum) {
|
||||
|
|
Loading…
Reference in a new issue