[renderer] Support multiple entity queues

While there's currently only the one still, this will allow the entities
to be multiply queued for multi-pass rendering (eg, shadows). As the
avoidance of putting an entity in the same queue more than once relies
on the entity id, all entities now come from the scene (which is stored
in cl_world in the client code for nq and qw), thus the extensive
changes in the clients.
This commit is contained in:
Bill Currie 2022-03-05 01:48:10 +09:00
parent 6573acbc74
commit d69355f521
53 changed files with 741 additions and 618 deletions

View file

@ -119,7 +119,6 @@ typedef struct vid_render_funcs_s {
void (*R_RemoveEfrags) (entity_t *ent);
void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height);
dlight_t *(*R_AllocDlight) (int key);
entity_t *(*R_AllocEntity) (void);
void (*R_MaxDlightsCheck) (struct cvar_s *var);
void (*R_DecayLights) (double frametime);

View file

@ -155,7 +155,6 @@ typedef struct visibility_s {
struct mnode_s *topnode; // bmodels, first world node that
// splits bmodel, or NULL if not split
// applies to other models, too
int visframe; // last frame this entity was
// found in an active leaf
int trivial_accept; // view clipping (frustum and depth)
} visibility_t;

View file

@ -33,6 +33,7 @@
#include "QF/darray.h"
#include "QF/qtypes.h"
#include "QF/set.h"
#include "QF/simd/vec4f.h"
#include "QF/simd/mat4f.h"
@ -46,6 +47,38 @@
#include "QF/render.h" //FIXME move entity_t here
typedef struct entqueue_s {
set_t *queued_ents;
entityset_t *ent_queues;
int num_queues;
} entqueue_t;
#define ENTINLINE GNU89INLINE inline
entqueue_t *EntQueue_New (int num_queues);
void EntQueue_Delete (entqueue_t *queue);
ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent,
int queue_num);
void EntQueue_Clear (entqueue_t *queue);
#undef ENTINLINE
#ifndef IMPLEMENT_ENTITY_Funcs
#define ENTINLINE GNU89INLINE inline
#else
#define ENTINLINE VISIBLE
#endif
ENTINLINE
void
EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num)
{
if (!set_is_member (queue->queued_ents, ent->id)) {
// entity ids are negative (ones-complement)
set_add (queue->queued_ents, -ent->id);//FIXME use ~
DARRAY_APPEND (&queue->ent_queues[queue_num], ent);
}
}
///@}
#endif//__QF_scene_entity_h

View file

@ -31,9 +31,16 @@
#ifndef __client_entities_h
#define __client_entities_h
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/qtypes.h"
#include "QF/simd/types.h"
typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s)
entitystateset_t;
extern entitystateset_t cl_static_entities;
// entity_state_t is the information conveyed from the server
// in an update message
typedef struct entity_state_s {

View file

@ -96,15 +96,12 @@ typedef enum TE_qwEffect {
//FIXME find a better way to get this info from the parser
typedef struct TEntContext_s {
vec4f_t simorg;
struct model_s *worldModel;
int playerEntity;
} TEntContext_t;
struct msg_s;
struct entity_s;
extern struct scene_s *cl_scene;
void CL_TEnts_Init (void);
void CL_Init_Entity (struct entity_s *ent);
void CL_ClearTEnts (void);

70
include/client/world.h Normal file
View file

@ -0,0 +1,70 @@
/*
world.h
Client world scene management
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2022/3/4
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifndef __client_world_h
#define __client_world_h
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/qtypes.h"
#include "QF/simd/types.h"
typedef struct modelset_s DARRAY_TYPE (struct model_s *) modelset_t;
typedef struct worldscene_s {
struct scene_s *scene;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
struct model_s *worldmodel;
modelset_t models;
} worldscene_t;
extern worldscene_t cl_world;
struct msg_s;
struct entity_state_s;
void CL_World_Init (void);
// PROTOCOL_FITZQUAKE -- flags for entity baseline messages
#define B_LARGEMODEL (1<<0) // modelindex is short instead of byte
#define B_LARGEFRAME (1<<1) // frame is short instead of byte
#define B_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT
void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline,
int version);
/*
Static entities are non-interactive world objects like torches
*/
void CL_ParseStatic (struct msg_s *msg, int version);
void CL_MapCfg (const char *mapname);
void CL_World_NewMap (const char *mapname, const char *skyname);
#endif//__client_world_h

View file

@ -81,10 +81,6 @@ void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj);
void R_LoadSkys (const char *);
void R_ClearEfrags (void);
void R_ClearEnts (void);
void R_EnqueueEntity (struct entity_s *ent);
entity_t *R_AllocEntity (void);
void R_FreeAllEntities (void);
void R_FindNearLights (const vec3_t pos, int count, dlight_t **lights);
dlight_t *R_AllocDlight (int key);

View file

@ -292,7 +292,7 @@ extern mleaf_t *r_viewleaf;
extern int r_clipflags;
extern int r_dlightframecount;
extern struct entity_s *r_ent_queue[mod_num_types];
extern struct entqueue_s *r_ent_queue;
struct dlight_s;
extern vec3_t lightspot;

View file

@ -10,6 +10,7 @@ libs_client_libQFclient_la_SOURCES= \
libs/client/cl_particles.c \
libs/client/cl_temp_entities.c \
libs/client/cl_view.c \
libs/client/cl_world.c \
libs/client/hud.c \
libs/client/locs.c \
libs/client/old_keys.c

View file

@ -31,11 +31,18 @@
# include "config.h"
#endif
#include "QF/render.h" //FIXME for entity_t
#include "QF/msg.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "client/entities.h"
#include "client/temp_entities.h"
entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32);
/* QW has a max of 512 entities and wants 64 frames of data per entity, plus
the baseline data (512 * (64 + 1) = 33280), but NQ has a max of 32000

View file

@ -52,10 +52,11 @@
#include "client/entities.h"
#include "client/particles.h"
#include "client/temp_entities.h"
#include "client/world.h"
typedef struct tent_s {
struct tent_s *next;
entity_t ent;
entity_t *ent;
} tent_t;
typedef struct {
@ -86,7 +87,6 @@ typedef struct tent_obj_s {
static PR_RESMAP (tent_t) temp_entities;
static PR_RESMAP (tent_obj_t) tent_objects;
scene_t *cl_scene;
static tent_obj_t *cl_beams;
static tent_obj_t *cl_explosions;
@ -137,8 +137,6 @@ CL_TEnts_Precache (int phase)
void
CL_TEnts_Init (void)
{
cl_scene = Scene_NewScene ();
QFS_GamedirCallback (CL_TEnts_Precache);
CL_TEnts_Precache (1);
for (int i = 0; i < 360; i++) {
@ -150,12 +148,12 @@ CL_TEnts_Init (void)
void
CL_Init_Entity (entity_t *ent)
{
if (ent->transform) {
Transform_Delete (ent->transform);
}
memset (ent, 0, sizeof (*ent));
memset (&ent->animation, 0, sizeof (ent->animation));
memset (&ent->visibility, 0, sizeof (ent->visibility));
memset (&ent->renderer, 0, sizeof (ent->renderer));
ent->active = 1;
ent->old_origin = (vec4f_t) {};
ent->transform = Transform_New (cl_scene, 0);
ent->renderer.skin = 0;
QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod);
ent->animation.pose1 = ent->animation.pose2 = -1;
@ -165,9 +163,9 @@ static tent_t *
new_temp_entity (void)
{
tent_t *tent = PR_RESNEW_NC (temp_entities);
tent->ent.transform = 0;
tent->ent = Scene_CreateEntity (cl_world.scene);
tent->next = 0;
CL_Init_Entity (&tent->ent);
CL_Init_Entity (tent->ent);
return tent;
}
@ -177,7 +175,7 @@ free_temp_entities (tent_t *tents)
tent_t **t = &tents;
while (*t) {
Transform_Delete ((*t)->ent.transform);//FIXME reuse?
Scene_DestroyEntity (cl_world.scene, (*t)->ent);//FIXME reuse?
t = &(*t)->next;
}
*t = temp_entities._free;
@ -215,8 +213,8 @@ beam_clear (beam_t *b)
tent_t *t;
for (t = b->tents; t; t = t->next) {
r_funcs->R_RemoveEfrags (&t->ent);
t->ent.visibility.efrag = 0;
r_funcs->R_RemoveEfrags (t->ent);
t->ent->visibility.efrag = 0;
}
free_temp_entities (b->tents);
b->tents = 0;
@ -263,17 +261,17 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx)
vec4f_t position = org + d * dist;
d += 1.0;
tent->ent.renderer.model = b->model;
tent->ent->renderer.model = b->model;
if (transform) {
seed = seed * BEAM_SEED_PRIME;
Transform_SetLocalTransform (tent->ent.transform, scale,
Transform_SetLocalTransform (tent->ent->transform, scale,
qmulf (rotation,
beam_rolls[seed % 360]),
position);
} else {
Transform_SetLocalPosition (tent->ent.transform, position);
Transform_SetLocalPosition (tent->ent->transform, position);
}
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
}
}
@ -377,8 +375,8 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
if (!cl_spr_explod->cache.data) {
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
}
ex->tent->ent.renderer.model = cl_spr_explod;
Transform_SetLocalPosition (ex->tent->ent.transform,//FIXME
ex->tent->ent->renderer.model = cl_spr_explod;
Transform_SetLocalPosition (ex->tent->ent->transform,//FIXME
(vec4f_t) {VectorExpand (position), 1});
break;
case TE_Explosion2:
@ -601,7 +599,7 @@ CL_UpdateBeams (double time, TEntContext_t *ctx)
// add new entities for the lightning
for (t = b->tents; t; t = t->next) {
seed = seed * BEAM_SEED_PRIME;
Transform_SetLocalRotation (t->ent.transform,
Transform_SetLocalRotation (t->ent->transform,
qmulf (b->rotation,
beam_rolls[seed % 360]));
}
@ -618,7 +616,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
for (to = &cl_explosions; *to; ) {
ex = &(*to)->to.ex;
ent = &ex->tent->ent;
ent = ex->tent->ent;
f = 10 * (time - ex->start);
if (f >= ent->renderer.model->numframes) {
tent_obj_t *_to;
@ -634,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
ent->animation.frame = f;
if (!ent->visibility.efrag) {
r_funcs->R_AddEfrags (&ctx->worldModel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
}
}
@ -675,8 +673,8 @@ CL_ClearProjectiles (void)
tent_t *tent;
for (tent = cl_projectiles; tent; tent = tent->next) {
r_funcs->R_RemoveEfrags (&tent->ent);
tent->ent.visibility.efrag = 0;
r_funcs->R_RemoveEfrags (tent->ent);
tent->ent->visibility.efrag = 0;
}
free_temp_entities (cl_projectiles);
cl_projectiles = 0;
@ -712,7 +710,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
*tail = tent;
tail = &tent->next;
pr = &tent->ent;
pr = tent->ent;
pr->renderer.model = cl_spike;
pr->renderer.skin = 0;
position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096;
@ -721,9 +719,9 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
angles[0] = (bits[4] >> 4) * (360.0 / 16.0);
angles[1] = bits[5] * (360.0 / 256.0);
angles[2] = 0;
CL_TransformEntity (&tent->ent, 1, angles, position);
CL_TransformEntity (tent->ent, 1, angles, position);
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
}
*tail = cl_projectiles;

View file

@ -43,8 +43,8 @@
#include "client/entities.h"
#include "client/hud.h"
#include "client/input.h"
#include "client/temp_entities.h"//FIXME for cl_scene
#include "client/view.h"
#include "client/world.h"
/*
The view is allowed to move slightly from it's true position for bobbing,
@ -763,7 +763,7 @@ V_Init (viewstate_t *viewstate)
"Used when you are underwater, hit, have the Ring of "
"Shadows, or Quad Damage. (v_cshift r g b intensity)");
viewstate->camera_transform = Transform_New (cl_scene, 0);
viewstate->camera_transform = Transform_New (cl_world.scene, 0);
}
void

224
libs/client/cl_world.c Normal file
View file

@ -0,0 +1,224 @@
/*
cl_entities.c
Client side entity management
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
Date: 2012/6/28
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/cbuf.h"
#include "QF/cmd.h"
#include "QF/idparse.h"
#include "QF/quakefs.h"
#include "QF/plist.h"
#include "QF/progs.h"
#include "QF/msg.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "QF/simd/vec4f.h"
#include "QF/plugin/vid_render.h" //FIXME
#include "client/entities.h"
#include "client/temp_entities.h"
#include "client/world.h"
worldscene_t cl_world = {
.models = DARRAY_STATIC_INIT (32),
};
void
CL_World_Init (void)
{
cl_world.scene = Scene_NewScene ();
}
void
CL_ParseBaseline (qmsg_t *msg, entity_state_t *baseline, int version)
{
int bits = 0;
if (version == 2)
bits = MSG_ReadByte (msg);
if (bits & B_LARGEMODEL)
baseline->modelindex = MSG_ReadShort (msg);
else
baseline->modelindex = MSG_ReadByte (msg);
if (bits & B_LARGEFRAME)
baseline->frame = MSG_ReadShort (msg);
else
baseline->frame = MSG_ReadByte (msg);
baseline->colormap = MSG_ReadByte (msg);
baseline->skinnum = MSG_ReadByte (msg);
MSG_ReadCoordAngleV (msg, &baseline->origin[0], baseline->angles);
baseline->origin[3] = 1;//FIXME
if (bits & B_ALPHA)
baseline->alpha = MSG_ReadByte (msg);
else
baseline->alpha = 255;//FIXME alpha
baseline->scale = 16;
baseline->glow_size = 0;
baseline->glow_color = 254;
baseline->colormod = 255;
}
void
CL_ParseStatic (qmsg_t *msg, int version)
{
entity_t *ent;
entity_state_t es;
ent = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (ent);
CL_ParseBaseline (msg, &es, version);
DARRAY_APPEND (&cl_static_entities, es);
// copy it to the current state
ent->renderer.model = cl_world.models.a[es.modelindex];
ent->animation.frame = es.frame;
ent->renderer.skinnum = es.skinnum;
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
static void
map_cfg (const char *mapname, int all)
{
char *name = malloc (strlen (mapname) + 4 + 1);
cbuf_t *cbuf = Cbuf_New (&id_interp);
QFile *f;
QFS_StripExtension (mapname, name);
strcat (name, ".cfg");
f = QFS_FOpenFile (name);
if (f) {
Qclose (f);
Cmd_Exec_File (cbuf, name, 1);
} else {
Cmd_Exec_File (cbuf, "maps_default.cfg", 1);
}
if (all) {
Cbuf_Execute_Stack (cbuf);
} else {
Cbuf_Execute_Sets (cbuf);
}
free (name);
Cbuf_Delete (cbuf);
}
void
CL_MapCfg (const char *mapname)
{
map_cfg (mapname, 0);
}
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl_world.models.a[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl_world.models.a[1]->brush.entities);
}
free (name);
return edicts;
}
static void
CL_LoadSky (const char *name)
{
plitem_t *worldspawn = cl_world.worldspawn;
plitem_t *item;
static const char *sky_keys[] = {
"sky", // Q2/DarkPlaces
"skyname", // old QF
"qlsky", // QuakeLives
0
};
if (!name) {
if (!worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
for (const char **key = sky_keys; *key; key++) {
if ((item = PL_ObjectForKey (cl_world.worldspawn, *key))) {
name = PL_String (item);
break;
}
}
}
r_funcs->R_LoadSkys (name);
}
void
CL_World_NewMap (const char *mapname, const char *skyname)
{
cl_static_entities.size = 0;
r_funcs->R_NewMap (cl_world.worldmodel,
cl_world.models.a, cl_world.models.size);
if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) {
if (cl_world.edicts) {
PL_Free (cl_world.edicts);
}
cl_world.edicts = map_ent (mapname);
if (cl_world.edicts) {
cl_world.worldspawn = PL_ObjectAtIndex (cl_world.edicts, 0);
CL_LoadSky (skyname);
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl_world.worldspawn);
}
}
map_cfg (mapname, 1);
}

View file

@ -9,6 +9,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps)
libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps)
libs_scene_libQFscene_la_SOURCES= \
libs/scene/camera.c \
libs/scene/entity.c \
libs/scene/hierarchy.c \
libs/scene/scene.c \
libs/scene/transform.c

71
libs/scene/entity.c Normal file
View file

@ -0,0 +1,71 @@
/*
entity.c
Entity management
Copyright (C) 2022 Bill Currke
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/set.h"
#define IMPLEMENT_ENTITY_Funcs
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "scn_internal.h"
entqueue_t *
EntQueue_New (int num_queues)
{
int size = sizeof (entqueue_t) + num_queues * sizeof (entityset_t);
entqueue_t *queue = calloc (1, size);
queue->queued_ents = set_new ();
queue->ent_queues = (entityset_t *) (queue + 1);
queue->num_queues = num_queues;
for (int i = 0; i < num_queues; i++) {
queue->ent_queues[i].grow = 64;
}
return queue;
}
void
EntQueue_Delete (entqueue_t *queue)
{
for (int i = 0; i < queue->num_queues; i++) {
DARRAY_CLEAR (&queue->ent_queues[i]);
}
set_delete (queue->queued_ents);
free (queue);
}
void
EntQueue_Clear (entqueue_t *queue)
{
for (int i = 0; i < queue->num_queues; i++) {
queue->ent_queues[i].size = 0;
}
set_empty (queue->queued_ents);
}

View file

@ -551,7 +551,6 @@ gl_overbright_f (cvar_t *var)
{
int num;
model_t *m;
entity_t *ent;
mod_brush_t *brush;
if (!var)
@ -598,7 +597,8 @@ gl_overbright_f (cvar_t *var)
if (!gl_R_BuildLightMap)
return;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \
m = ent->renderer.model;
if (m->path[0] == '*')
continue;

View file

@ -193,8 +193,6 @@ gl_R_RotateForEntity (entity_t *e)
static void
R_DrawEntitiesOnList (void)
{
entity_t *ent;
if (!r_drawentities->int_val)
return;
@ -220,7 +218,8 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_NORMALIZE);
}
for (ent = r_ent_queue[mod_alias]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_alias].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_alias].a[i]; \
gl_R_DrawAliasModel (ent);
}
qfglColor3ubv (color_white);
@ -248,7 +247,8 @@ R_DrawEntitiesOnList (void)
qglActiveTexture (gl_mtex_enum + 0);
}
for (ent = r_ent_queue[mod_iqm]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_iqm].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_iqm].a[i]; \
gl_R_DrawIQMModel (ent);
}
qfglColor3ubv (color_white);
@ -257,7 +257,8 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_ALPHA_TEST);
if (gl_va_capable)
qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray);
for (ent = r_ent_queue[mod_sprite]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_sprite].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_sprite].a[i]; \
R_DrawSpriteModel (ent);
}
qfglDisable (GL_ALPHA_TEST);
@ -328,7 +329,7 @@ void
gl_R_SetupFrame (void)
{
R_AnimateLight ();
R_ClearEnts ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
gl_Fog_SetupFrame ();

View file

@ -61,6 +61,8 @@
#include "QF/GL/qf_textures.h"
#include "QF/GL/qf_vid.h"
#include "QF/scene/entity.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "varrays.h"
@ -140,6 +142,7 @@ gl_R_LoadSky_f (void)
void
gl_R_Init (void)
{
r_ent_queue = EntQueue_New (mod_num_types);
R_Init_Cvars ();
gl_R_Particles_Init_Cvars ();
@ -191,8 +194,6 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
r_worldentity.renderer.model = worldmodel;
brush = &worldmodel->brush;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL;

View file

@ -740,8 +740,8 @@ gl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \
gl_R_DrawBrushModel (ent);
}
}

View file

@ -1149,8 +1149,8 @@ glsl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
R_DrawBrushModel (ent);
}
}

View file

@ -48,6 +48,8 @@
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/GLSL/defines.h"
#include "QF/GLSL/funcs.h"
#include "QF/GLSL/qf_alias.h"
@ -95,7 +97,7 @@ void
glsl_R_SetupFrame (void)
{
R_AnimateLight ();
R_ClearEnts ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
VectorCopy (r_refdef.viewposition, r_origin);
@ -141,7 +143,6 @@ R_SetupView (void)
static void
R_RenderEntities (void)
{
entity_t *ent;
int begun;
if (!r_drawentities->int_val)
@ -149,7 +150,9 @@ R_RenderEntities (void)
#define RE_LOOP(type_name, Type) \
do { \
begun = 0; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
if (!begun) { \
glsl_R_##Type##Begin (); \
begun = 1; \
@ -237,6 +240,7 @@ glsl_R_RenderView (void)
void
glsl_R_Init (void)
{
r_ent_queue = EntQueue_New (mod_num_types);
Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f,
"Test the current refresh rate for the current location.");
R_Init_Cvars ();
@ -267,7 +271,6 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
r_viewleaf = NULL;
R_MarkLeaves ();
R_FreeAllEntities ();
R_ClearParticles ();
glsl_R_RegisterTextures (models, num_models);
glsl_R_BuildLightmaps (models, num_models);

View file

@ -235,11 +235,7 @@ R_StoreEfrags (const efrag_t *efrag)
case mod_brush:
case mod_sprite:
case mod_iqm:
if (ent->visibility.visframe != r_framecount) {
R_EnqueueEntity (ent);
// mark that we've recorded this entity for this frame
ent->visibility.visframe = r_framecount;
}
EntQueue_AddEntity (r_ent_queue, ent, model->type);
efrag = efrag->leafnext;
break;

View file

@ -48,100 +48,7 @@
#include "r_internal.h"
#define ENT_POOL_SIZE 32
typedef struct entity_pool_s {
struct entity_pool_s *next;
entity_t entities[ENT_POOL_SIZE];
} entity_pool_t;
entity_t *r_ent_queue[mod_num_types];
static entity_t **vis_tail[mod_num_types] = {
[mod_brush] &r_ent_queue[mod_brush],
[mod_sprite] &r_ent_queue[mod_sprite],
[mod_alias] &r_ent_queue[mod_alias],
[mod_iqm] &r_ent_queue[mod_iqm],
};
static entity_pool_t *entity_pools = 0;
static entity_pool_t **entpool_tail = &entity_pools;
static entity_t *free_entities;
entity_t *
R_AllocEntity (void)
{
entity_pool_t *pool;
entity_t *ent;
int i;
if ((ent = free_entities)) {
free_entities = ent->next;
ent->next = 0;
ent->transform = 0;
return ent;
}
pool = malloc (sizeof (entity_pool_t));
pool->next = 0;
*entpool_tail = pool;
entpool_tail = &pool->next;
for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) {
ent->next = ent + 1;
ent->transform = 0;
}
ent->next = 0;
ent->transform = 0;
free_entities = pool->entities;
return R_AllocEntity ();
}
void
R_FreeAllEntities (void)
{
entity_pool_t *pool;
entity_t *ent;
int i;
for (pool = entity_pools; pool; pool = pool->next) {
for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) {
ent->next = ent + 1;
if (ent->transform) {
Transform_Delete (ent->transform);
ent->transform = 0;
}
}
ent->next = pool->next ? pool->next->entities : 0;
if (ent->transform) {
Transform_Delete (ent->transform);
ent->transform = 0;
}
}
free_entities = entity_pools ? entity_pools->entities : 0;
}
void
R_ClearEnts (void)
{
for (int i = 0; i < mod_num_types; i++) {
r_ent_queue[i] = 0;
vis_tail[i] = &r_ent_queue[i];
}
}
void
R_EnqueueEntity (entity_t *ent)
{
modtype_t type = ent->renderer.model->type;
if (type < 0 || type >= mod_num_types) {
Sys_Error ("R_EnqueueEntity: Bad entity model type %d", type);
}
ent->next = 0;
*vis_tail[type] = ent;
vis_tail[type] = &ent->next;
}
entqueue_t *r_ent_queue;
float
R_EntityBlend (animation_t *animation, int pose, float interval)

View file

@ -117,6 +117,8 @@ sw_R_Init (void)
{
int dummy;
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow
r_stack_start = (byte *) & dummy;
@ -167,8 +169,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
memset (&r_worldentity, 0, sizeof (r_worldentity));
r_worldentity.renderer.model = worldmodel;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL;
@ -418,14 +418,14 @@ draw_iqm_entity (entity_t *ent)
static void
R_DrawEntitiesOnList (void)
{
entity_t *ent;
if (!r_drawentities->int_val)
return;
#define RE_LOOP(type_name) \
do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
currententity = ent; \
@ -566,7 +566,6 @@ R_DrawBEntitiesOnList (void)
vec3_t origin;
model_t *clmodel;
float minmaxs[6];
entity_t *ent;
if (!r_drawentities->int_val)
return;
@ -574,12 +573,12 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform),
origin);
clmodel = currententity->renderer.model;
VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
clmodel = ent->renderer.model;
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
@ -626,8 +625,8 @@ R_DrawBEntitiesOnList (void)
if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode;
if (ent->visibility.topnode) {
mnode_t *topnode = ent->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world

View file

@ -35,6 +35,8 @@
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
@ -224,7 +226,7 @@ R_SetupFrame (void)
R_CheckVariables ();
R_AnimateLight ();
R_ClearEnts ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
numbtofpolys = 0;

View file

@ -142,6 +142,8 @@ sw32_R_Init (void)
{
int dummy;
r_ent_queue = EntQueue_New (mod_num_types);
// get stack position so we can guess if we are going to overflow
r_stack_start = (byte *) & dummy;
@ -182,8 +184,6 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
memset (&r_worldentity, 0, sizeof (r_worldentity));
r_worldentity.renderer.model = worldmodel;
R_FreeAllEntities ();
// clear out efrags in case the level hasn't been reloaded
for (unsigned i = 0; i < brush->modleafs; i++)
brush->leafs[i].efrags = NULL;
@ -425,14 +425,14 @@ draw_iqm_entity (entity_t *ent)
static void
R_DrawEntitiesOnList (void)
{
entity_t *ent;
if (!r_drawentities->int_val)
return;
#define RE_LOOP(type_name) \
do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
currententity = ent; \
@ -572,7 +572,6 @@ R_DrawBEntitiesOnList (void)
vec3_t origin;
model_t *clmodel;
float minmaxs[6];
entity_t *ent;
if (!r_drawentities->int_val)
return;
@ -580,12 +579,12 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform),
origin);
clmodel = currententity->renderer.model;
VectorCopy (Transform_GetWorldPosition (ent->transform), origin);
clmodel = ent->renderer.model;
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
@ -632,8 +631,8 @@ R_DrawBEntitiesOnList (void)
if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
sw32_R_ZDrawSubmodelPolys (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode;
if (ent->visibility.topnode) {
mnode_t *topnode = ent->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world

View file

@ -38,6 +38,8 @@
#include "QF/sys.h"
#include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "compat.h"
#include "r_internal.h"
#include "vid_internal.h"
@ -220,7 +222,7 @@ sw32_R_SetupFrame (void)
R_CheckVariables ();
R_AnimateLight ();
R_ClearEnts ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
sw32_numbtofpolys = 0;

View file

@ -152,7 +152,6 @@ vid_render_funcs_t gl_vid_render_funcs = {
R_RemoveEfrags,
gl_R_LineGraph,
R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck,
R_DecayLights,
gl_R_ViewChanged,

View file

@ -151,7 +151,6 @@ vid_render_funcs_t glsl_vid_render_funcs = {
R_RemoveEfrags,
glsl_R_LineGraph,
R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck,
R_DecayLights,
glsl_R_ViewChanged,

View file

@ -148,7 +148,6 @@ vid_render_funcs_t sw_vid_render_funcs = {
R_RemoveEfrags,
R_LineGraph,
R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck,
R_DecayLights,
R_ViewChanged,

View file

@ -153,7 +153,6 @@ vid_render_funcs_t sw32_vid_render_funcs = {
R_RemoveEfrags,
sw32_R_LineGraph,
R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck,
R_DecayLights,
sw32_R_ViewChanged,

View file

@ -61,6 +61,8 @@
#include "QF/Vulkan/swapchain.h"
#include "QF/ui/view.h"
#include "QF/scene/entity.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "vid_internal.h"
@ -100,6 +102,7 @@ vulkan_ParticleSystem (void)
static void
vulkan_R_Init (void)
{
r_ent_queue = EntQueue_New (mod_num_types);
Vulkan_CreateStagingBuffers (vulkan_ctx);
Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateFrames (vulkan_ctx);
@ -679,7 +682,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
R_RemoveEfrags,
vulkan_R_LineGraph,
R_AllocDlight,
R_AllocEntity,
R_MaxDlightsCheck,
R_DecayLights,
vulkan_R_ViewChanged,

View file

@ -1039,8 +1039,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
R_VisitWorldNodes (brush, ctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i];
R_DrawBrushModel (ent, ctx);
}
}

View file

@ -45,6 +45,8 @@
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_bsp.h"
@ -65,7 +67,7 @@ static void
setup_frame (vulkan_ctx_t *ctx)
{
R_AnimateLight ();
R_ClearEnts ();
EntQueue_Clear (r_ent_queue);
r_framecount++;
VectorCopy (r_refdef.viewposition, r_origin);
@ -85,9 +87,10 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame)
return;
#define RE_LOOP(type_name, Type) \
do { \
entity_t *ent; \
int begun = 0; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \
i++) { \
entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \
if (!begun) { \
Vulkan_##Type##Begin (rFrame); \
begun = 1; \
@ -122,7 +125,7 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx)
|| !ent->renderer.model)
return;
R_EnqueueEntity (ent);
EntQueue_AddEntity (r_ent_queue, ent, ent->renderer.model->type);
}
void
@ -195,7 +198,6 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models,
r_viewleaf = NULL;
R_MarkLeaves ();
R_FreeAllEntities ();
R_ClearParticles ();
Vulkan_RegisterTextures (models, num_models, ctx);
//Vulkan_BuildLightmaps (models, num_models, ctx);

View file

@ -180,14 +180,9 @@ typedef struct client_state_s {
/* information that is static for the entire time connected to a server */
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
int nummodels;
int numsounds;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
char levelname[40]; // for display on solo scoreboard
int spectator;
int playernum;
@ -205,9 +200,7 @@ typedef struct client_state_s {
int fbskins;
// refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
int num_entities; // held in cl_entities array
entity_t viewent; // the weapon model
int cdtrack; // cd audio
@ -240,10 +233,9 @@ extern struct cvar_s *noskins;
extern client_state_t cl;
// FIXME, allocate dynamically
extern entity_t cl_entities[MAX_EDICTS];
extern entity_t *cl_entities[MAX_EDICTS];
extern double cl_msgtime[MAX_EDICTS];
extern byte cl_forcelink[MAX_EDICTS];
extern struct set_s cl_forcelink;
extern int fps_count;
@ -299,6 +291,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin);
void CL_SignonReply (void);
void CL_RelinkEntities (void);
void CL_ClearEnts (void);
entity_t *CL_GetEntity (int num);
extern double realtime;

View file

@ -48,6 +48,8 @@
#include "compat.h"
#include "client/world.h"
#include "nq/include/client.h"
#include "nq/include/host.h"
@ -338,8 +340,8 @@ demo_default_name (const char *argv1)
time (&tim);
strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim));
// the leading path-name is to be removed from cl.worldmodel->name
mapname = QFS_SkipPath (cl.worldmodel->path);
// the leading path-name is to be removed from cl_world.worldmodel->name
mapname = QFS_SkipPath (cl_world.worldmodel->path);
// the map name is cut off after any "." because this would prevent
// an extension being appended

View file

@ -44,11 +44,13 @@
#include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h"
#include "client/effects.h"
#include "client/temp_entities.h"
#include "client/world.h"
#include "client/chase.h"
@ -57,9 +59,12 @@
#include "nq/include/host.h"
#include "nq/include/server.h"
entity_t cl_entities[MAX_EDICTS];
double cl_msgtime[MAX_EDICTS];
byte cl_forcelink[MAX_EDICTS];
entity_t *cl_entities[MAX_EDICTS];
double cl_msgtime[MAX_EDICTS];
static byte forcelink_bytes[SET_SIZE(MAX_EDICTS)];
#define alloc_forcelink(s) (set_bits_t *)forcelink_bytes
set_t cl_forcelink = SET_STATIC_INIT (MAX_EDICTS, alloc_forcelink);
#undef alloc_forcelink
void
CL_ClearEnts (void)
@ -67,14 +72,27 @@ CL_ClearEnts (void)
size_t i;
for (i = 0; i < MAX_EDICTS; i++) {
CL_Init_Entity (cl_entities + i);
if (cl_entities[i]) {
Scene_DestroyEntity (cl_world.scene, cl_entities[i]);
cl_entities[i] = 0;
}
}
// clear other arrays
i = nq_entstates.num_frames * nq_entstates.num_entities;
memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t));
memset (cl_msgtime, 0, sizeof (cl_msgtime));
memset (cl_forcelink, 0, sizeof (cl_forcelink));
set_empty (&cl_forcelink);
}
entity_t *
CL_GetEntity (int num)
{
if (!cl_entities[num]) {
cl_entities[num] = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl_entities[num]);
}
return cl_entities[num];
}
/*
@ -115,12 +133,12 @@ CL_LerpPoint (void)
}
static void
set_entity_model (entity_t *ent, int modelindex)
set_entity_model (int ent_ind, int modelindex)
{
int i = ent - cl_entities;
entity_t *ent = cl_entities[ent_ind];
renderer_t *renderer = &ent->renderer;
animation_t *animation = &ent->animation;
renderer->model = cl.model_precache[modelindex];
renderer->model = cl_world.models.a[modelindex];
// automatic animation (torches, etc) can be either all together
// or randomized
if (renderer->model) {
@ -130,11 +148,12 @@ set_entity_model (entity_t *ent, int modelindex)
animation->syncbase = 0.0;
}
} else {
cl_forcelink[i] = true; // hack to make null model players work
// hack to make null model players work
SET_ADD (&cl_forcelink, ent_ind);
}
animation->nolerp = 1; // don't try to lerp when the model has changed
if (i <= cl.maxclients) {
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i);
if (ent_ind <= cl.maxclients) {
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, ent_ind);
}
}
@ -150,8 +169,6 @@ CL_RelinkEntities (void)
int entvalid;
int model_flags;
r_data->player_entity = &cl_entities[cl.viewentity];
// determine partial update time
frac = CL_LerpPoint ();
@ -180,7 +197,7 @@ CL_RelinkEntities (void)
for (i = 1; i < cl.num_entities; i++) {
new = &nq_entstates.frame[0 + cl.frameIndex][i];
old = &nq_entstates.frame[1 - cl.frameIndex][i];
ent = &cl_entities[i];
ent = CL_GetEntity (i);
renderer = &ent->renderer;
animation = &ent->animation;
@ -200,20 +217,24 @@ CL_RelinkEntities (void)
continue;
}
if (cl_forcelink[i])
if (SET_TEST_MEMBER (&cl_forcelink, i)) {
*old = *new;
}
if (cl_forcelink[i] || new->modelindex != old->modelindex) {
if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->modelindex != old->modelindex) {
old->modelindex = new->modelindex;
set_entity_model (ent, new->modelindex);
set_entity_model (i, new->modelindex);
}
animation->frame = new->frame;
if (cl_forcelink[i] || new->colormap != old->colormap) {
if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->colormap != old->colormap) {
old->colormap = new->colormap;
renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin,
new->colormap);
}
if (cl_forcelink[i] || new->skinnum != old->skinnum) {
if (SET_TEST_MEMBER (&cl_forcelink, i)
|| new->skinnum != old->skinnum) {
old->skinnum = new->skinnum;
renderer->skinnum = new->skinnum;
if (i <= cl.maxclients) {
@ -232,7 +253,7 @@ CL_RelinkEntities (void)
model_flags = renderer->model->flags;
}
if (cl_forcelink[i]) {
if (SET_TEST_MEMBER (&cl_forcelink, i)) {
// The entity was not updated in the last message so move to the
// final spot
animation->pose1 = animation->pose2 = -1;
@ -242,7 +263,7 @@ CL_RelinkEntities (void)
if (ent->visibility.efrag) {
r_funcs->R_RemoveEfrags (ent);
}
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
ent->old_origin = new->origin;
} else {
@ -278,10 +299,10 @@ CL_RelinkEntities (void)
= Transform_GetWorldPosition (ent->transform);
if (!VectorCompare (org, ent->old_origin)) {//FIXME
r_funcs->R_RemoveEfrags (ent);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
} else {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
}
}
@ -303,8 +324,10 @@ CL_RelinkEntities (void)
if (model_flags & ~EF_ROTATE)
CL_ModelEffects (ent, i, new->glow_color, cl.time);
cl_forcelink[i] = false;
SET_REMOVE (&cl_forcelink, i);
}
r_data->player_entity = CL_GetEntity (cl.viewentity);
cl.viewstate.player_entity = CL_GetEntity (cl.viewentity);
cl.viewstate.player_origin
= Transform_GetWorldPosition (cl_entities[cl.viewentity].transform);
= Transform_GetWorldPosition (cl.viewstate.player_entity->transform);
}

View file

@ -48,14 +48,16 @@
#include "QF/plugin/console.h"
#include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h"
#include "sbar.h"
#include "client/chase.h"
#include "client/particles.h"
#include "client/temp_entities.h"
#include "client/world.h"
#include "client/chase.h"
#include "nq/include/cl_skin.h"
#include "nq/include/client.h"
#include "nq/include/host.h"
@ -188,9 +190,9 @@ CL_ClearState (void)
if (!sv.active)
Host_ClearMemory ();
if (cl.edicts)
PL_Free (cl.edicts);
if (cl.viewstate.weapon_entity) {
Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity);
}
if (cl.players) {
int i;
@ -202,6 +204,7 @@ CL_ClearState (void)
__auto_type cam = cl.viewstate.camera_transform;
memset (&cl, 0, sizeof (cl));
cl.viewstate.camera_transform = cam;
cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1};
cl.viewstate.chase = 1;
cl.viewstate.chasestate = &cl.chasestate;
@ -210,10 +213,6 @@ CL_ClearState (void)
r_data->force_fullscreen = 0;
r_data->lightstyle = cl.lightstyle;
CL_Init_Entity (&cl.viewent);
cl.viewstate.weapon_entity = &cl.viewent;
r_data->view_model = &cl.viewent;
SZ_Clear (&cls.message);
CL_ClearTEnts ();
@ -221,6 +220,10 @@ CL_ClearState (void)
r_funcs->R_ClearState ();
CL_ClearEnts ();
cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl.viewstate.weapon_entity);
r_data->view_model = cl.viewstate.weapon_entity;
}
/*
@ -276,7 +279,7 @@ CL_Disconnect (void)
Host_ShutdownServer (false);
}
cl.worldmodel = NULL;
cl_world.worldmodel = NULL;
cl.intermission = 0;
cl.viewstate.intermission = 0;
}
@ -389,18 +392,18 @@ CL_NextDemo (void)
static void
pointfile_f (void)
{
CL_LoadPointFile (cl.worldmodel);
CL_LoadPointFile (cl_world.worldmodel);
}
static void
CL_PrintEntities_f (void)
{
entity_t *ent;
int i;
for (i = 0, ent = cl_entities; i < cl.num_entities; i++, ent++) {
for (i = 0; i < cl.num_entities; i++) {
entity_t *ent = cl_entities[i];
Sys_Printf ("%3i:", i);
if (!ent->renderer.model) {
if (!ent || !ent->renderer.model) {
Sys_Printf ("EMPTY\n");
continue;
}
@ -422,8 +425,8 @@ CL_ReadFromServer (void)
{
int ret;
TEntContext_t tentCtx = {
Transform_GetWorldPosition (cl_entities[cl.viewentity].transform),
cl.worldmodel, cl.viewentity
cl.viewstate.player_origin,
cl.viewentity
};
cl.oldtime = cl.time;
@ -571,6 +574,7 @@ CL_Init (cbuf_t *cbuf)
CL_Init_Input (cbuf);
CL_Particles_Init ();
CL_TEnts_Init ();
CL_World_Init ();
CL_ClearState ();
V_Init (&cl.viewstate);

View file

@ -51,10 +51,13 @@
#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_*
#include "QF/va.h"
#include "QF/scene/scene.h"
#include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h"
#include "client/temp_entities.h"
#include "client/world.h"
#include "compat.h"
#include "sbar.h"
@ -125,24 +128,6 @@ const char *svc_strings[] = {
dstring_t *centerprint;
static void
CL_LoadSky (void)
{
plitem_t *item;
const char *name = 0;
if (!cl.worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
if ((item = PL_ObjectForKey (cl.worldspawn, "sky")) // Q2/DarkPlaces
|| (item = PL_ObjectForKey (cl.worldspawn, "skyname")) // old QF
|| (item = PL_ObjectForKey (cl.worldspawn, "qlsky"))) /* QuakeLives */ {
name = PL_String (item);
}
r_funcs->R_LoadSkys (name);
}
/*
CL_EntityNum
@ -263,72 +248,13 @@ CL_KeepaliveMessage (void)
SZ_Clear (&cls.message);
}
static void
map_cfg (const char *mapname, int all)
{
char *name = malloc (strlen (mapname) + 4 + 1);
cbuf_t *cbuf = Cbuf_New (&id_interp);
QFile *f;
QFS_StripExtension (mapname, name);
strcat (name, ".cfg");
f = QFS_FOpenFile (name);
if (f) {
Qclose (f);
Cmd_Exec_File (cbuf, name, 1);
} else {
Cmd_Exec_File (cbuf, "maps_default.cfg", 1);
}
if (all) {
Cbuf_Execute_Stack (cbuf);
} else {
Cbuf_Execute_Sets (cbuf);
}
free (name);
Cbuf_Delete (cbuf);
}
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities);
}
free (name);
return edicts;
}
static void
CL_NewMap (const char *mapname)
{
r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels);
Con_NewMap ();
Hunk_Check (0); // make sure nothing is hurt
Sbar_CenterPrint (0);
if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) {
cl.edicts = map_ent (mapname);
if (cl.edicts) {
cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0);
CL_LoadSky ();
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl.worldspawn);
}
}
map_cfg (mapname, 1);
CL_World_NewMap (mapname, 0);
}
static void
@ -338,6 +264,7 @@ CL_ParseServerInfo (void)
char sound_precache[MAX_SOUNDS][MAX_QPATH];
const char *str;
int i;
int nummodels;
Sys_MaskPrintf (SYS_dev, "Serverinfo packet received.\n");
@ -394,16 +321,17 @@ CL_ParseServerInfo (void)
// needlessly purge it
// precache models
memset (cl.model_precache, 0, sizeof (cl.model_precache));
for (cl.nummodels = 1;; cl.nummodels++) {
cl_world.models.size = 0;
DARRAY_APPEND (&cl_world.models, 0); // ind 0 is null model
for (nummodels = 1;; nummodels++) {
str = MSG_ReadString (net_message);
if (!str[0])
break;
if (cl.nummodels >= MAX_MODELS) {
if (nummodels >= MAX_MODELS) {
Sys_Printf ("Server sent too many model precaches\n");
goto done;
}
strcpy (model_precache[cl.nummodels], str);
strcpy (model_precache[nummodels], str);
Mod_TouchModel (str);
}
@ -421,12 +349,12 @@ CL_ParseServerInfo (void)
}
// now we try to load everything else until a cache allocation fails
if (model_precache[1])
map_cfg (model_precache[1], 0);
CL_MapCfg (model_precache[1]);
for (i = 1; i < cl.nummodels; i++) {
cl.model_precache[i] = Mod_ForName (model_precache[i], false);
if (cl.model_precache[i] == NULL) {
for (i = 1; i < nummodels; i++) {
DARRAY_APPEND (&cl_world.models,
Mod_ForName (model_precache[i], false));
if (cl_world.models.a[i] == NULL) {
Sys_Printf ("Model %s not found\n", model_precache[i]);
goto done;
}
@ -439,8 +367,8 @@ CL_ParseServerInfo (void)
}
// local state
cl_entities[0].renderer.model = cl.worldmodel = cl.model_precache[1];
cl.chasestate.worldmodel = cl.worldmodel;
cl_world.worldmodel = cl_world.models.a[1];
cl.chasestate.worldmodel = cl_world.worldmodel;
if (!centerprint)
centerprint = dstring_newstr ();
else
@ -600,44 +528,10 @@ CL_ParseUpdate (int bits)
//VectorCopy (state->msg_angles[0], state->msg_angles[1]);
//CL_TransformEntity (ent, state->msg_angles[0]);
//state->forcelink = true;
cl_forcelink[num] = true;
SET_ADD (&cl_forcelink, num);
}
}
static void
CL_ParseBaseline (entity_state_t *baseline, int version)
{
int bits = 0;
if (version == 2)
bits = MSG_ReadByte (net_message);
if (bits & B_LARGEMODEL)
baseline->modelindex = MSG_ReadShort (net_message);
else
baseline->modelindex = MSG_ReadByte (net_message);
if (bits & B_LARGEFRAME)
baseline->frame = MSG_ReadShort (net_message);
else
baseline->frame = MSG_ReadByte (net_message);
baseline->colormap = MSG_ReadByte (net_message);
baseline->skinnum = MSG_ReadByte (net_message);
MSG_ReadCoordAngleV (net_message, &baseline->origin[0], baseline->angles);
baseline->origin[3] = 1;//FIXME
if (bits & B_ALPHA)
baseline->alpha = MSG_ReadByte (net_message);
else
baseline->alpha = 255;//FIXME alpha
baseline->scale = 16;
baseline->glow_size = 0;
baseline->glow_color = 254;
baseline->colormod = 255;
}
/*
CL_ParseClientdata
@ -723,7 +617,7 @@ CL_ParseClientdata (void)
if (cl.stats[STAT_WEAPON] != i) {
cl.stats[STAT_WEAPON] = i;
Sbar_Changed ();
cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]];
cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]];
}
i = (short) MSG_ReadShort (net_message);
@ -779,38 +673,13 @@ CL_ParseClientdata (void)
cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8;
if (bits & SU_WEAPONALPHA) {
byte alpha = MSG_ReadByte (net_message);
cl.viewent.renderer.colormod[3] = ENTALPHA_DECODE (alpha);
float a = ENTALPHA_DECODE (alpha);
cl.viewstate.weapon_entity->renderer.colormod[3] = a;
} else {
cl.viewent.renderer.colormod[3] = 1.0;
cl.viewstate.weapon_entity->renderer.colormod[3] = 1;
}
}
static void
CL_ParseStatic (int version)
{
entity_state_t baseline;
entity_t *ent;
ent = r_funcs->R_AllocEntity ();
CL_Init_Entity (ent);
CL_ParseBaseline (&baseline, version);
// copy it to the current state
//FIXME alpha & lerp
ent->renderer.model = cl.model_precache[baseline.modelindex];
ent->animation.frame = baseline.frame;
ent->renderer.skin = 0;
ent->renderer.skinnum = baseline.skinnum;
VectorCopy (ent_colormod[baseline.colormod], ent->renderer.colormod);
ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha);
CL_TransformEntity (ent, baseline.scale / 16.0, baseline.angles,
baseline.origin);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
}
static void
CL_ParseStaticSound (int version)
{
@ -850,8 +719,8 @@ CL_ParseServerMessage (void)
cl.last_servermessage = realtime;
TEntContext_t tentCtx = {
Transform_GetWorldPosition (cl_entities[cl.viewentity].transform),
cl.worldmodel, cl.viewentity
cl.viewstate.player_origin,
cl.viewentity
};
// if recording demos, copy the message out
@ -921,7 +790,6 @@ CL_ParseServerMessage (void)
case svc_setview:
cl.viewentity = MSG_ReadShort (net_message);
cl.viewstate.player_entity = &cl_entities[cl.viewentity];
break;
case svc_sound:
@ -1035,7 +903,7 @@ CL_ParseServerMessage (void)
Host_Error ("CL_ParseServerMessage: svc_updatecolors > "
"MAX_SCOREBOARD");
} else {
entity_t *ent = &cl_entities[i+1];
entity_t *ent = CL_GetEntity (i + 1);
byte col = MSG_ReadByte (net_message);
byte top = col >> 4;
byte bot = col & 0xf;
@ -1061,7 +929,7 @@ CL_ParseServerMessage (void)
break;
case svc_spawnstatic:
CL_ParseStatic (1);
CL_ParseStatic (net_message, 1);
break;
// svc_spawnbinary
@ -1069,7 +937,7 @@ CL_ParseServerMessage (void)
case svc_spawnbaseline:
i = MSG_ReadShort (net_message);
// must use CL_EntityNum () to force cl.num_entities up
CL_ParseBaseline (CL_EntityNum (i), 1);
CL_ParseBaseline (net_message, CL_EntityNum (i), 1);
break;
case svc_temp_entity:
@ -1205,10 +1073,10 @@ CL_ParseServerMessage (void)
case svc_spawnbaseline2:
i = MSG_ReadShort (net_message);
// must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline (CL_EntityNum(i), 2);
CL_ParseBaseline (net_message, CL_EntityNum(i), 2);
break;
case svc_spawnstatic2:
CL_ParseStatic (2);
CL_ParseStatic (net_message, 2);
break;
case svc_spawnstaticsound2:
CL_ParseStaticSound (2);

View file

@ -51,6 +51,8 @@
#include "sbar.h"
#include "client/world.h"
#include "nq/include/client.h"
static view_t *net_view;
@ -75,11 +77,11 @@ SCR_CShift (void)
mleaf_t *leaf;
int contents = CONTENTS_EMPTY;
if (cls.state == ca_active && cl.worldmodel) {
if (cls.state == ca_active && cl_world.worldmodel) {
vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
//FIXME
leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel);
leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);
contents = leaf->contents;
}
V_SetContentsColor (&cl.viewstate, contents);

View file

@ -60,6 +60,7 @@
#include "compat.h"
#include "client/chase.h"
#include "client/world.h"
#include "nq/include/host.h"
#include "nq/include/server.h"
@ -612,7 +613,7 @@ Host_ClientFrame (void)
vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME
l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME
if (l)
asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl);

View file

@ -50,6 +50,8 @@
#include "QF/sys.h"
#include "QF/va.h"
#include "client/world.h"
#include "compat.h"
#include "world.h"
@ -1320,7 +1322,7 @@ Host_Viewmodel_f (void)
}
SVfloat (e, frame) = 0;
cl.model_precache[(int) SVfloat (e, modelindex)] = m;
cl_world.models.a[(int) SVfloat (e, modelindex)] = m;
}
static void
@ -1333,7 +1335,7 @@ Host_Viewframe_f (void)
e = FindViewthing ();
if (!e)
return;
m = cl.model_precache[(int) SVfloat (e, modelindex)];
m = cl_world.models.a[(int) SVfloat (e, modelindex)];
f = atoi (Cmd_Argv (1));
if (f >= m->numframes)
@ -1366,7 +1368,7 @@ Host_Viewnext_f (void)
e = FindViewthing ();
if (!e)
return;
m = cl.model_precache[(int) SVfloat (e, modelindex)];
m = cl_world.models.a[(int) SVfloat (e, modelindex)];
SVfloat (e, frame) = SVfloat (e, frame) + 1;
if (SVfloat (e, frame) >= m->numframes)
@ -1385,7 +1387,7 @@ Host_Viewprev_f (void)
if (!e)
return;
m = cl.model_precache[(int) SVfloat (e, modelindex)];
m = cl_world.models.a[(int) SVfloat (e, modelindex)];
SVfloat (e, frame) = SVfloat (e, frame) - 1;
if (SVfloat (e, frame) < 0)

View file

@ -36,12 +36,16 @@
#include "QF/plugin/vid_render.h"
#include "client/world.h"
#include "nq/include/host.h"
#include "nq/include/server.h"
client_state_t cl;
client_static_t cls;
worldscene_t cl_world;
cvar_t *cl_name;
cvar_t *cl_writecfg;
cvar_t *demo_speed;

View file

@ -41,12 +41,9 @@ void CL_ParsePacketEntities (qboolean delta);
void CL_SetSolidEntities (void);
void CL_ParsePlayerinfo (void);
void CL_Ents_Init (void);
entity_t *CL_GetEntity (int num);
extern struct cvar_s *cl_deadbodyfilter;
extern struct cvar_s *cl_gibfilter;
extern entity_t cl_player_ents[];
extern entity_t cl_flag_ents[];
extern entity_t cl_packet_ents[];
#endif

View file

@ -222,14 +222,10 @@ typedef struct client_state_s {
char model_name[MAX_MODELS][MAX_QPATH];
char sound_name[MAX_SOUNDS][MAX_QPATH];
struct model_s *model_precache[MAX_MODELS];
struct sfx_s *sound_precache[MAX_SOUNDS];
int nummodels;
int numsounds;
struct plitem_s *edicts;
struct plitem_s *worldspawn;
char levelname[40]; // for display on solo scoreboard
int spectator;
int playernum;
@ -247,9 +243,7 @@ typedef struct client_state_s {
int fbskins;
// refresh related state
struct model_s *worldmodel; // cl_entitites[0].model
int num_entities; // held in cl_entities array
entity_t viewent; // the weapon model
int cdtrack; // cd audio
@ -288,10 +282,7 @@ extern struct cvar_s *cl_fb_players;
extern client_state_t cl;
typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s)
entitystateset_t;
extern entitystateset_t cl_static_entities;
extern entity_t cl_entities[512];
extern entity_t *cl_entities[512];
extern byte cl_entity_valid[2][512];
extern qboolean nomaster;

View file

@ -56,6 +56,8 @@
#include "compat.h"
#include "client/world.h"
#include "qw/include/cl_cam.h"
#include "qw/include/cl_demo.h"
#include "qw/include/cl_ents.h"
@ -633,8 +635,8 @@ demo_default_name (const char *argv1)
time (&tim);
strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim));
// the leading path-name is to be removed from cl.worldmodel->name
mapname = QFS_SkipPath (cl.worldmodel->path);
// the leading path-name is to be removed from cl_world.worldmodel->name
mapname = QFS_SkipPath (cl_world.worldmodel->path);
// the map name is cut off after any "." because this would prevent
// an extension being appended

View file

@ -45,6 +45,7 @@
#include "client/temp_entities.h"
#include "client/view.h"
#include "client/world.h"
#include "qw/msg_ucmd.h"
#include "qw/pmove.h"
@ -481,7 +482,7 @@ CL_ParsePlayerinfo (void)
byte val;
entity_t *ent;
ent = &cl_player_ents[num];
ent = CL_GetEntity (num + 1);
bits = MSG_ReadByte (net_message);
if (bits & PF_ALPHA) {
val = MSG_ReadByte (net_message);
@ -529,7 +530,7 @@ CL_SetSolidEntities (void)
frame_t *frame;
packet_entities_t *pak;
pmove.physents[0].model = cl.worldmodel;
pmove.physents[0].model = cl_world.worldmodel;
VectorZero (pmove.physents[0].origin);
VectorZero (pmove.physents[0].angles);
pmove.physents[0].info = 0;
@ -543,17 +544,17 @@ CL_SetSolidEntities (void)
if (!state->modelindex)
continue;
if (!cl.model_precache[state->modelindex])
if (!cl_world.models.a[state->modelindex])
continue;
if (cl.model_precache[state->modelindex]->brush.hulls[1].firstclipnode
|| cl.model_precache[state->modelindex]->clipbox) {
if (cl_world.models.a[state->modelindex]->brush.hulls[1].firstclipnode
|| cl_world.models.a[state->modelindex]->clipbox) {
if (pmove.numphysent == MAX_PHYSENTS) {
Sys_Printf ("WARNING: entity physent overflow, email "
"quakeforge-devel@lists.quakeforge.net\n");
break;
}
pmove.physents[pmove.numphysent].model =
cl.model_precache[state->modelindex];
cl_world.models.a[state->modelindex];
VectorCopy (state->origin,
pmove.physents[pmove.numphysent].origin);
VectorCopy (state->angles,

View file

@ -42,6 +42,7 @@
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/scene/scene.h"
#include "compat.h"
#include "d_iface.h"
@ -50,6 +51,7 @@
#include "client/locs.h"
#include "client/temp_entities.h"
#include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h"
#include "qw/msg_ucmd.h"
@ -62,9 +64,8 @@
#include "qw/include/cl_pred.h"
#include "qw/include/host.h"
entity_t cl_player_ents[MAX_CLIENTS];
entity_t cl_flag_ents[MAX_CLIENTS];
entity_t cl_entities[512]; // FIXME: magic number
entity_t *cl_flag_ents[MAX_CLIENTS];
entity_t *cl_entities[512]; // FIXME: magic number
byte cl_entity_valid[2][512];
void
@ -72,15 +73,32 @@ CL_ClearEnts (void)
{
size_t i;
for (i = 0; i < MAX_CLIENTS; i++) {
if (cl_flag_ents[i]) {
Scene_DestroyEntity (cl_world.scene, cl_flag_ents[i]);
cl_flag_ents[i] = 0;
}
}
for (i = 0; i < 512; i++) {
if (cl_entities[i]) {
Scene_DestroyEntity (cl_world.scene, cl_entities[i]);
cl_entities[i] = 0;
}
}
i = qw_entstates.num_frames * qw_entstates.num_entities;
memset (qw_entstates.frame[0], 0, i * sizeof (entity_state_t));
memset (cl_entity_valid, 0, sizeof (cl_entity_valid));
for (i = 0; i < sizeof (cl_entities) / sizeof (cl_entities[0]); i++)
CL_Init_Entity (&cl_entities[i]);
for (i = 0; i < sizeof (cl_flag_ents) / sizeof (cl_flag_ents[0]); i++)
CL_Init_Entity (&cl_flag_ents[i]);
for (i = 0; i < sizeof (cl_player_ents) / sizeof (cl_player_ents[0]); i++)
CL_Init_Entity (&cl_player_ents[i]);
}
entity_t *
CL_GetEntity (int num)
{
if (!cl_entities[num]) {
cl_entities[num] = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl_entities[num]);
}
return cl_entities[num];
}
// Hack hack hack
@ -110,7 +128,7 @@ set_entity_model (entity_t *ent, int modelindex)
{
renderer_t *renderer = &ent->renderer;
animation_t *animation = &ent->animation;
renderer->model = cl.model_precache[modelindex];
renderer->model = cl_world.models.a[modelindex];
// automatic animation (torches, etc) can be either all together
// or randomized
if (renderer->model) {
@ -134,10 +152,10 @@ CL_LinkPacketEntities (void)
animation_t *animation;
frac = 1;
for (i = 0; i < 512; i++) {
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_entities[i];
ent = CL_GetEntity (i);
renderer = &ent->renderer;
animation = &ent->animation;
forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i];
@ -216,7 +234,7 @@ CL_LinkPacketEntities (void)
if (ent->visibility.efrag) {
r_funcs->R_RemoveEfrags (ent);
}
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
} else {
vec4f_t delta = new->origin - old->origin;
@ -248,15 +266,15 @@ CL_LinkPacketEntities (void)
= Transform_GetWorldPosition (ent->transform);
if (!VectorCompare (org, ent->old_origin)) {//FIXME
r_funcs->R_RemoveEfrags (ent);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
} else {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
}
}
if (!ent->visibility.efrag) {
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
}
// rotate binary objects locally
@ -288,7 +306,7 @@ CL_UpdateFlagModels (entity_t *ent, int key)
float f;
entity_t *fent;
fent = &cl_flag_ents[key];
fent = cl_flag_ents[key];
if (!fent->active) {
return;
@ -322,7 +340,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
{
entity_t *fent;
fent = &cl_flag_ents[key];
fent = cl_flag_ents[key];
if (cl_flagindex == -1) {
fent->active = 0;
@ -336,7 +354,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
}
CL_UpdateFlagModels (ent, key);
fent->renderer.model = cl.model_precache[cl_flagindex];
fent->renderer.model = cl_world.models.a[cl_flagindex];
fent->renderer.skinnum = team;
return fent;
@ -347,7 +365,7 @@ CL_RemoveFlagModels (int key)
{
entity_t *fent;
fent = &cl_flag_ents[key];
fent = cl_flag_ents[key];
fent->active = 0;
Transform_SetParent (fent->transform, 0);
}
@ -380,7 +398,7 @@ CL_LinkPlayers (void)
for (j = 0, player = cl.players, state = frame->playerstate;
j < MAX_CLIENTS; j++, player++, state++) {
ent = &cl_player_ents[j];
ent = CL_GetEntity (j + 1);
if (ent->visibility.efrag)
r_funcs->R_RemoveEfrags (ent);
if (player->flag_ent && player->flag_ent->visibility.efrag) {
@ -395,7 +413,8 @@ CL_LinkPlayers (void)
// spawn light flashes, even ones coming from invisible objects
if (j == cl.playernum) {
org = cl.viewstate.player_origin;
r_data->player_entity = &cl_player_ents[j];
r_data->player_entity = ent;
cl.viewstate.player_entity = ent;
clientplayer = true;
} else {
org = state->pls.es.origin;
@ -453,8 +472,8 @@ CL_LinkPlayers (void)
ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0;
if (ent->renderer.model
!= cl.model_precache[state->pls.es.modelindex]) {
ent->renderer.model = cl.model_precache[state->pls.es.modelindex];
!= cl_world.models.a[state->pls.es.modelindex]) {
ent->renderer.model = cl_world.models.a[state->pls.es.modelindex];
ent->animation.nolerp = 1;
}
ent->animation.frame = state->pls.es.frame;
@ -492,10 +511,10 @@ CL_LinkPlayers (void)
}
// stuff entity in map
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent);
if (player->flag_ent) {
CL_UpdateFlagModels (ent, j);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, player->flag_ent);
r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent);
}
}
}
@ -516,7 +535,7 @@ CL_EmitEntities (void)
return;
TEntContext_t tentCtx = {
cl.viewstate.player_origin, cl.worldmodel, cl.viewentity
cl.viewstate.player_origin, cl.viewentity
};
CL_LinkPlayers ();
@ -530,5 +549,4 @@ CL_EmitEntities (void)
void
CL_Ents_Init (void)
{
r_data->view_model = &cl.viewent;
}

View file

@ -91,6 +91,7 @@
#include "QF/plugin/console.h"
#include "QF/scene/transform.h"
#include "QF/scene/scene.h"
#include "buildnum.h"
#include "compat.h"
@ -99,6 +100,7 @@
#include "client/particles.h"
#include "client/temp_entities.h"
#include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h"
#include "qw/pmove.h"
@ -229,7 +231,7 @@ CL_Quit_f (void)
static void
pointfile_f (void)
{
CL_LoadPointFile (cl.worldmodel);
CL_LoadPointFile (cl_world.worldmodel);
}
static void
@ -385,6 +387,9 @@ CL_ClearState (void)
S_StopAllSounds ();
if (cl.viewstate.weapon_entity) {
Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity);
}
// wipe the entire cl structure
if (cl.serverinfo)
Info_Destroy (cl.serverinfo);
@ -402,7 +407,6 @@ CL_ClearState (void)
cl.chasestate.viewstate = &cl.viewstate;
cl.viewstate.punchangle = (vec4f_t) {0, 0, 0, 1};
// Note: we should probably hack around this and give diff values for
// diff gamedirs
cl.fpd = FPD_DEFAULT;
@ -412,9 +416,6 @@ CL_ClearState (void)
cl.frames[i].packet_entities.entities = qw_entstates.frame[i];
cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0);
CL_Init_Entity (&cl.viewent);
cl.viewstate.weapon_entity = &cl.viewent;
Sys_MaskPrintf (SYS_dev, "Clearing memory\n");
VID_ClearMemory ();
Mod_ClearAll ();
@ -424,6 +425,10 @@ CL_ClearState (void)
CL_ClearEnts ();
CL_ClearTEnts ();
cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene);
CL_Init_Entity (cl.viewstate.weapon_entity);
r_data->view_model = cl.viewstate.weapon_entity;
r_funcs->R_ClearState ();
SZ_Clear (&cls.netchan.message);
@ -519,7 +524,7 @@ CL_Disconnect (void)
Info_Destroy (cl.players[i].userinfo);
memset (&cl.players[i], 0, sizeof (cl.players[i]));
}
cl.worldmodel = NULL;
cl_world.worldmodel = NULL;
cl.validsequence = 0;
}
@ -1216,6 +1221,7 @@ CL_Init (void)
CL_Ents_Init ();
CL_Particles_Init ();
CL_TEnts_Init ();
CL_World_Init ();
CL_ClearState ();
Pmove_Init ();
@ -1725,7 +1731,7 @@ Host_Frame (float time)
vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME
l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME
if (l)
asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl);

View file

@ -61,12 +61,15 @@
#include "QF/teamplay.h"
#include "QF/va.h"
#include "QF/scene/scene.h"
#include "compat.h"
#include "sbar.h"
#include "client/effects.h"
#include "client/temp_entities.h"
#include "client/view.h"
#include "client/world.h"
#include "qw/bothdefs.h"
#include "qw/pmove.h"
@ -170,40 +173,6 @@ int packet_latency[NET_TIMINGS];
extern cvar_t *hud_scoreboard_uid;
entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32);
static void
CL_LoadSky (void)
{
plitem_t *item;
const char *name = 0;
static const char *sky_keys[] = {
"sky", // Q2/DarkPlaces
"skyname", // old QF
"qlsky", // QuakeLives
0
};
// R_LoadSkys does the right thing with null pointers.
if (cl.serverinfo) {
name = Info_ValueForKey (cl.serverinfo, "sky");
}
if (!name) {
if (!cl.worldspawn) {
r_funcs->R_LoadSkys (0);
return;
}
for (const char **key = sky_keys; *key; key++) {
if ((item = PL_ObjectForKey (cl.worldspawn, *key))) {
name = PL_String (item);
break;
}
}
}
r_funcs->R_LoadSkys (name);
}
int
CL_CalcNet (void)
{
@ -290,49 +259,20 @@ CL_CheckOrDownloadFile (const char *filename)
return false;
}
static plitem_t *
map_ent (const char *mapname)
{
static progs_t edpr;
char *name = malloc (strlen (mapname) + 4 + 1);
char *buf;
plitem_t *edicts = 0;
QFile *ent_file;
QFS_StripExtension (mapname, name);
strcat (name, ".ent");
ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath);
if ((buf = (char *) QFS_LoadFile (ent_file, 0))) {
edicts = ED_Parse (&edpr, buf);
free (buf);
} else {
edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities);
}
free (name);
return edicts;
}
static void
CL_NewMap (const char *mapname)
{
cl_static_entities.size = 0;
r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels);
Team_NewMap ();
Con_NewMap ();
Hunk_Check (0); // make sure nothing is hurt
Sbar_CenterPrint (0);
if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) {
cl.edicts = map_ent (mapname);
if (cl.edicts) {
cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0);
CL_LoadSky ();
if (r_funcs->Fog_ParseWorldspawn)
r_funcs->Fog_ParseWorldspawn (cl.worldspawn);
}
const char *skyname = 0;
// R_LoadSkys does the right thing with null pointers.
if (cl.serverinfo) {
skyname = Info_ValueForKey (cl.serverinfo, "sky");
}
map_cfg (mapname, 1);
CL_World_NewMap (mapname, skyname);
}
static void
@ -357,7 +297,7 @@ Model_NextDownload (void)
}
if (cl.model_name[1])
map_cfg (cl.model_name[1], 0);
CL_MapCfg (cl.model_name[1]);
for (i = 1; i < cl.nummodels; i++) {
const char *info_key = 0;
@ -365,9 +305,10 @@ Model_NextDownload (void)
if (!cl.model_name[i][0])
break;
cl.model_precache[i] = Mod_ForName (cl.model_name[i], false);
DARRAY_APPEND (&cl_world.models,
Mod_ForName (cl.model_name[i], false));
if (!cl.model_precache[i]) {
if (!cl_world.models.a[i]) {
Sys_Printf ("\nThe required model file '%s' could not be found or "
"downloaded.\n\n", cl.model_name[i]);
Sys_Printf ("You may need to download or purchase a %s client "
@ -378,18 +319,18 @@ Model_NextDownload (void)
}
if (strequal (cl.model_name[i], "progs/player.mdl")
&& cl.model_precache[i]->type == mod_alias) {
&& cl_world.models.a[i]->type == mod_alias) {
info_key = pmodel_name;
//XXX mod_funcs->Skin_Player_Model (cl.model_precache[i]);
//XXX mod_funcs->Skin_Player_Model (cl_world.models.a[i]);
}
if (strequal (cl.model_name[i], "progs/eyes.mdl")
&& cl.model_precache[i]->type == mod_alias)
&& cl_world.models.a[i]->type == mod_alias)
info_key = emodel_name;
if (info_key && cl_model_crcs->int_val) {
aliashdr_t *ahdr = cl.model_precache[i]->aliashdr;
aliashdr_t *ahdr = cl_world.models.a[i]->aliashdr;
if (!ahdr)
ahdr = Cache_Get (&cl.model_precache[i]->cache);
ahdr = Cache_Get (&cl_world.models.a[i]->cache);
Info_SetValueForKey (cls.userinfo, info_key, va (0, "%d",
ahdr->crc),
0);
@ -398,14 +339,14 @@ Model_NextDownload (void)
SZ_Print (&cls.netchan.message, va (0, "setinfo %s %d",
info_key, ahdr->crc));
}
if (!cl.model_precache[i]->aliashdr)
Cache_Release (&cl.model_precache[i]->cache);
if (!cl_world.models.a[i]->aliashdr)
Cache_Release (&cl_world.models.a[i]->cache);
}
}
// Something went wrong (probably in the server, probably a TF server)
// We need to disconnect gracefully.
if (!cl.model_precache[1]) {
if (!cl_world.models.a[1]) {
Sys_Printf ("\nThe server has failed to provide the map name.\n\n");
Sys_Printf ("Disconnecting to prevent a crash.\n\n");
CL_Disconnect ();
@ -413,8 +354,8 @@ Model_NextDownload (void)
}
// all done
cl.worldmodel = cl.model_precache[1];
cl.chasestate.worldmodel = cl.worldmodel;
cl_world.worldmodel = cl_world.models.a[1];
cl.chasestate.worldmodel = cl_world.worldmodel;
CL_NewMap (cl.model_name[1]);
// done with modellist, request first of static signon messages
@ -422,7 +363,7 @@ Model_NextDownload (void)
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
MSG_WriteString (&cls.netchan.message,
va (0, prespawn_name, cl.servercount,
cl.worldmodel->brush.checksum2));
cl_world.worldmodel->brush.checksum2));
}
}
@ -453,7 +394,8 @@ Sound_NextDownload (void)
}
// done with sounds, request models now
memset (cl.model_precache, 0, sizeof (cl.model_precache));
cl_world.models.size = 0;
DARRAY_APPEND (&cl_world.models, 0);// ind 0 is null model
cl_playerindex = -1;
cl_flagindex = -1;
cl_h_playerindex = -1;
@ -832,7 +774,6 @@ CL_ParseServerData (void)
}
cl.viewentity = cl.playernum + 1;
cl.viewstate.player_entity = &cl_entities[cl.viewentity];
cl.viewstate.bob_enabled = !cl.spectator;
// get the full level name
@ -957,54 +898,6 @@ CL_ParseModellist (void)
Model_NextDownload ();
}
static void
CL_ParseBaseline (entity_state_t *es)
{
es->modelindex = MSG_ReadByte (net_message);
es->frame = MSG_ReadByte (net_message);
es->colormap = MSG_ReadByte (net_message);
es->skinnum = MSG_ReadByte (net_message);
MSG_ReadCoordAngleV (net_message, &es->origin[0], es->angles);//FIXME
es->origin[3] = 1;
// LordHavoc: set up baseline to for new effects (alpha, colormod, etc)
es->colormod = 255;
es->alpha = 255;
es->scale = 16;
es->glow_size = 0;
es->glow_color = 254;
}
/*
CL_ParseStatic
Static entities are non-interactive world objects
like torches
*/
static void
CL_ParseStatic (void)
{
entity_t *ent;
entity_state_t es;
CL_ParseBaseline (&es);
ent = r_funcs->R_AllocEntity ();
CL_Init_Entity (ent);
DARRAY_APPEND (&cl_static_entities, es);
// copy it to the current state
ent->renderer.model = cl.model_precache[es.modelindex];
ent->animation.frame = es.frame;
ent->renderer.skinnum = es.skinnum;
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
}
static void
CL_ParseStaticSound (void)
{
@ -1275,7 +1168,7 @@ CL_SetStat (int stat, int value)
break;
}
cl.stats[stat] = value;
cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]];
cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]];
}
static void
@ -1318,7 +1211,7 @@ CL_ParseServerMessage (void)
const char *str;
static dstring_t *stuffbuf;
TEntContext_t tentCtx = {
cl.viewstate.player_origin, cl.worldmodel, cl.viewentity
cl.viewstate.player_origin, cl.viewentity
};
received_framecount = host_framecount;
@ -1513,14 +1406,14 @@ CL_ParseServerMessage (void)
break;
case svc_spawnstatic:
CL_ParseStatic ();
CL_ParseStatic (net_message, 1);
break;
// svc_spawnbinary
case svc_spawnbaseline:
i = MSG_ReadShort (net_message);
CL_ParseBaseline (&qw_entstates.baseline[i]);
CL_ParseBaseline (net_message, &qw_entstates.baseline[i], 1);
break;
case svc_temp_entity:

View file

@ -51,6 +51,7 @@
#include "client/hud.h"
#include "client/view.h"
#include "client/world.h"
#include "qw/include/client.h"
#include "qw/include/cl_parse.h"
@ -77,11 +78,11 @@ SCR_CShift (void)
mleaf_t *leaf;
int contents = CONTENTS_EMPTY;
if (cls.state == ca_active && cl.worldmodel) {
if (cls.state == ca_active && cl_world.worldmodel) {
vec4f_t origin;
origin = Transform_GetWorldPosition (cl.viewstate.camera_transform);
//FIXME
leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel);
leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);
contents = leaf->contents;
}
V_SetContentsColor (&cl.viewstate, contents);

View file

@ -58,6 +58,7 @@
#include "compat.h"
#include "client/hud.h"
#include "client/world.h"
#include "qw/bothdefs.h"
#include "qw/include/cl_cam.h"
@ -1109,8 +1110,8 @@ Sbar_LogFrags (void)
if (t)
Qwrite (file, t, strlen (t));
Qprintf (file, "%s\n%s %s\n", cls.servername->str, cl.worldmodel->path,
cl.levelname);
Qprintf (file, "%s\n%s %s\n", cls.servername->str,
cl_world.worldmodel->path, cl.levelname);
// scores
Sbar_SortFrags (true);

View file

@ -52,6 +52,7 @@
#include "compat.h"
#include "client/locs.h"
#include "client/world.h"
#include "qw/bothdefs.h"
#include "qw/include/cl_input.h"
@ -289,8 +290,8 @@ Team_NewMap (void)
died = false;
recorded_location = false;
mapname = strdup (cl.worldmodel->path);
t2 = malloc (sizeof (cl.worldmodel->path));
mapname = strdup (cl_world.worldmodel->path);
t2 = malloc (sizeof (cl_world.worldmodel->path));
if (!mapname || !t2)
Sys_Error ("Can't duplicate mapname!");
map_to_loc (mapname,t2);
@ -340,16 +341,16 @@ locs_loc (void)
"parameter\n");
return;
}
if (!cl.worldmodel) {
if (!cl_world.worldmodel) {
Sys_Printf ("No map loaded. Unable to work with location markers.\n");
return;
}
if (Cmd_Argc () >= 3)
desc = Cmd_Args (2);
mapname = malloc (sizeof (cl.worldmodel->path));
mapname = malloc (sizeof (cl_world.worldmodel->path));
if (!mapname)
Sys_Error ("Can't duplicate mapname!");
map_to_loc (cl.worldmodel->path, mapname);
map_to_loc (cl_world.worldmodel->path, mapname);
snprintf (locfile, sizeof (locfile), "%s/%s",
qfs_gamedir->dir.def, mapname);
free (mapname);