mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Move the entity transform setup into the clients.
This has several benifits: o The silly issue with alias model pitches being backwards is kept out of the renderer (it's a quakec thing: entites do their pitch backwards, but originally, only alias models were rotated. Hipnotic did brush entity rotations in the correct direction). o Angle to frame vector conversions are done only when the entity's angles vector changes, rather than every frame. This avoids a lot of unnecessary trig function calls. o Once transformed, an entity's frame vectors are always available. However, the vectors are left handed rather than right handed (ie, forward/left/up instead of forward/right/up): just a matter of watching the sign. This avoids even more trig calls (flag models in qw). o This paves the way for merging brush entity surface rendering with the world model surface rendering (the actual goal of this patch). o This also paves the way for using quaternions to represent entity orientation, as that would be a protocol change.
This commit is contained in:
parent
f6ebb78140
commit
3eb859a88f
24 changed files with 205 additions and 223 deletions
|
@ -250,7 +250,7 @@ QFGL_DONT_NEED (void, glMaterialiv, (GLenum face, GLenum pname, const GLint * pa
|
|||
QFGL_NEED (void, glMatrixMode, (GLenum mode))
|
||||
QFGL_DONT_NEED (void, glMinmax, (GLenum target, GLenum internalformat, GLboolean sink))
|
||||
QFGL_DONT_NEED (void, glMultMatrixd, (const GLdouble * m))
|
||||
QFGL_DONT_NEED (void, glMultMatrixf, (const GLfloat * m))
|
||||
QFGL_NEED (void, glMultMatrixf, (const GLfloat * m))
|
||||
QFGL_NEED (void, glNewList, (GLuint list, GLenum mode))
|
||||
QFGL_DONT_NEED (void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz))
|
||||
QFGL_NEED (void, glNormal3bv, (const GLbyte * v))
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct entity_s {
|
|||
vec3_t origin;
|
||||
vec3_t old_origin;
|
||||
vec3_t angles;
|
||||
vec_t transform[4 * 4];
|
||||
struct model_s *model; // NULL = no model
|
||||
int frame;
|
||||
byte *colormap;
|
||||
|
|
|
@ -110,16 +110,15 @@ R_DrawSpriteModel_f (entity_t *e)
|
|||
float *up, *right;
|
||||
msprite_t *psprite;
|
||||
mspriteframe_t *frame;
|
||||
vec3_t point, point1, point2, v_forward, v_right, v_up;
|
||||
vec3_t point, point1, point2, v_up;
|
||||
|
||||
// don't bother culling, it's just a single polygon without a surface cache
|
||||
frame = R_GetSpriteFrame (e);
|
||||
psprite = e->model->cache.data;
|
||||
|
||||
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
||||
AngleVectors (e->angles, v_forward, v_right, v_up);
|
||||
up = v_up;
|
||||
right = v_right;
|
||||
up = e->transform + 2 * 4;
|
||||
right = e->transform + 1 * 4;
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||
v_up[0] = 0;
|
||||
v_up[1] = 0;
|
||||
|
@ -179,7 +178,7 @@ R_DrawSpriteModel_VA_f (entity_t *e)
|
|||
// unsigned int vacount;
|
||||
msprite_t *psprite;
|
||||
mspriteframe_t *frame;
|
||||
vec3_t point1, point2, v_forward, v_right, v_up;
|
||||
vec3_t point1, point2, v_up;
|
||||
varray_t2f_c4ub_v3f_t *VA;
|
||||
|
||||
VA = spriteVertexArray; // FIXME: Despair
|
||||
|
@ -191,9 +190,8 @@ R_DrawSpriteModel_VA_f (entity_t *e)
|
|||
qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR
|
||||
|
||||
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
||||
AngleVectors (e->angles, v_forward, v_right, v_up);
|
||||
up = v_up;
|
||||
right = v_right;
|
||||
up = e->transform + 2 * 4;
|
||||
right = e->transform + 1 * 4;
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||
v_up[0] = 0;
|
||||
v_up[1] = 0;
|
||||
|
|
|
@ -203,11 +203,7 @@ glrmain_init (void)
|
|||
void
|
||||
R_RotateForEntity (entity_t *e)
|
||||
{
|
||||
qfglTranslatef (e->origin[0], e->origin[1], e->origin[2]);
|
||||
|
||||
qfglRotatef ( e->angles[YAW], 0, 0, 1);
|
||||
qfglRotatef (-e->angles[PITCH], 0, 1, 0);
|
||||
qfglRotatef ( e->angles[ROLL], 1, 0, 0);
|
||||
qfglMultMatrixf (e->transform);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -388,7 +388,7 @@ R_DrawBrushModel (entity_t *e)
|
|||
|
||||
model = e->model;
|
||||
|
||||
if (e->angles[0] || e->angles[1] || e->angles[2]) {
|
||||
if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) {
|
||||
rotated = true;
|
||||
radius = model->radius;
|
||||
#if 0 //QSG FIXME
|
||||
|
@ -423,13 +423,12 @@ R_DrawBrushModel (entity_t *e)
|
|||
|
||||
VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
|
||||
if (rotated) {
|
||||
vec3_t temp, forward, right, up;
|
||||
vec3_t temp;
|
||||
|
||||
VectorCopy (modelorg, temp);
|
||||
AngleVectors (e->angles, forward, right, up);
|
||||
modelorg[0] = DotProduct (temp, forward);
|
||||
modelorg[1] = -DotProduct (temp, right);
|
||||
modelorg[2] = DotProduct (temp, up);
|
||||
modelorg[0] = DotProduct (temp, e->transform + 0);
|
||||
modelorg[1] = DotProduct (temp, e->transform + 4);
|
||||
modelorg[2] = DotProduct (temp, e->transform + 8);
|
||||
}
|
||||
|
||||
psurf = &model->surfaces[model->firstmodelsurface];
|
||||
|
@ -449,9 +448,7 @@ R_DrawBrushModel (entity_t *e)
|
|||
}
|
||||
|
||||
qfglPushMatrix ();
|
||||
e->angles[0] = -e->angles[0]; // stupid quake bug
|
||||
R_RotateForEntity (e);
|
||||
e->angles[0] = -e->angles[0]; // stupid quake bug
|
||||
|
||||
// Build lightmap chains
|
||||
for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
|
||||
|
|
|
@ -360,16 +360,10 @@ R_AliasSetUpTransform (int trivial_accept)
|
|||
float rotationmatrix[3][4], t2matrix[3][4];
|
||||
static float tmatrix[3][4];
|
||||
static float viewmatrix[3][4];
|
||||
vec3_t angles;
|
||||
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: should use a look-up table
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
|
||||
angles[ROLL] = currententity->angles[ROLL];
|
||||
angles[PITCH] = -currententity->angles[PITCH];
|
||||
angles[YAW] = currententity->angles[YAW];
|
||||
AngleVectors (angles, alias_forward, alias_right, alias_up);
|
||||
VectorCopy (currententity->transform + 0, alias_forward);
|
||||
VectorNegate (currententity->transform + 4, alias_right);
|
||||
VectorCopy (currententity->transform + 8, alias_up);
|
||||
|
||||
tmatrix[0][0] = pmdl->scale[0];
|
||||
tmatrix[1][1] = pmdl->scale[1];
|
||||
|
|
|
@ -80,64 +80,9 @@ R_EntityRotate (vec3_t vec)
|
|||
void
|
||||
R_RotateBmodel (void)
|
||||
{
|
||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
||||
|
||||
// TODO: should use a look-up table
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
// TODO: share work with R_SetUpAliasTransform
|
||||
|
||||
// yaw
|
||||
angle = currententity->angles[YAW];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp1[0][0] = c;
|
||||
temp1[0][1] = s;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = -s;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = 0;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = 0;
|
||||
temp1[2][2] = 1;
|
||||
|
||||
// pitch
|
||||
angle = currententity->angles[PITCH];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp2[0][0] = c;
|
||||
temp2[0][1] = 0;
|
||||
temp2[0][2] = -s;
|
||||
temp2[1][0] = 0;
|
||||
temp2[1][1] = 1;
|
||||
temp2[1][2] = 0;
|
||||
temp2[2][0] = s;
|
||||
temp2[2][1] = 0;
|
||||
temp2[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp2, temp1, temp3);
|
||||
|
||||
// roll
|
||||
angle = currententity->angles[ROLL];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp1[0][0] = 1;
|
||||
temp1[0][1] = 0;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = 0;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = s;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = -s;
|
||||
temp1[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp1, temp3, entity_rotation);
|
||||
VectorCopy (currententity->transform + 0, entity_rotation[0]);
|
||||
VectorCopy (currententity->transform + 4, entity_rotation[1]);
|
||||
VectorCopy (currententity->transform + 8, entity_rotation[2]);
|
||||
|
||||
// rotate modelorg and the transformation matrix
|
||||
R_EntityRotate (modelorg);
|
||||
|
|
|
@ -550,8 +550,8 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
|
|||
|
||||
clipflags = 0;
|
||||
|
||||
if (currententity->angles[0] || currententity->angles[1]
|
||||
|| currententity->angles[2]) {
|
||||
if (currententity->transform[0] != 1 || currententity->transform[5] != 1
|
||||
|| currententity->transform[10] != 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
|
|
@ -364,8 +364,9 @@ R_DrawSprite (void)
|
|||
} else if (psprite->type == SPR_ORIENTED) {
|
||||
// generate the sprite's axes, according to the sprite's world
|
||||
// orientation
|
||||
AngleVectors (currententity->angles, r_spritedesc.vpn,
|
||||
r_spritedesc.vright, r_spritedesc.vup);
|
||||
VectorCopy (currententity->transform + 0, r_spritedesc.vpn);
|
||||
VectorNegate (currententity->transform + 4, r_spritedesc.vright);
|
||||
VectorCopy (currententity->transform + 8, r_spritedesc.vup);
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
||||
// generate the sprite's axes, parallel to the viewplane, but rotated
|
||||
// in that plane around the center according to the sprite entity's
|
||||
|
|
|
@ -363,16 +363,10 @@ R_AliasSetUpTransform (int trivial_accept)
|
|||
float rotationmatrix[3][4], t2matrix[3][4];
|
||||
static float tmatrix[3][4];
|
||||
static float viewmatrix[3][4];
|
||||
vec3_t angles;
|
||||
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: should use a look-up table
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
|
||||
angles[ROLL] = currententity->angles[ROLL];
|
||||
angles[PITCH] = -currententity->angles[PITCH];
|
||||
angles[YAW] = currententity->angles[YAW];
|
||||
AngleVectors (angles, alias_forward, alias_right, alias_up);
|
||||
VectorCopy (currententity->transform + 0, alias_forward);
|
||||
VectorNegate (currententity->transform + 4, alias_right);
|
||||
VectorCopy (currententity->transform + 8, alias_up);
|
||||
|
||||
tmatrix[0][0] = pmdl->scale[0];
|
||||
tmatrix[1][1] = pmdl->scale[1];
|
||||
|
|
|
@ -80,64 +80,9 @@ R_EntityRotate (vec3_t vec)
|
|||
void
|
||||
R_RotateBmodel (void)
|
||||
{
|
||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
||||
|
||||
// TODO: should use a look-up table
|
||||
// TODO: should really be stored with the entity instead of being reconstructed
|
||||
// TODO: could cache lazily, stored in the entity
|
||||
// TODO: share work with R_SetUpAliasTransform
|
||||
|
||||
// yaw
|
||||
angle = currententity->angles[YAW];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp1[0][0] = c;
|
||||
temp1[0][1] = s;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = -s;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = 0;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = 0;
|
||||
temp1[2][2] = 1;
|
||||
|
||||
// pitch
|
||||
angle = currententity->angles[PITCH];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp2[0][0] = c;
|
||||
temp2[0][1] = 0;
|
||||
temp2[0][2] = -s;
|
||||
temp2[1][0] = 0;
|
||||
temp2[1][1] = 1;
|
||||
temp2[1][2] = 0;
|
||||
temp2[2][0] = s;
|
||||
temp2[2][1] = 0;
|
||||
temp2[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp2, temp1, temp3);
|
||||
|
||||
// roll
|
||||
angle = currententity->angles[ROLL];
|
||||
angle = angle * M_PI * 2 / 360;
|
||||
s = sin (angle);
|
||||
c = cos (angle);
|
||||
|
||||
temp1[0][0] = 1;
|
||||
temp1[0][1] = 0;
|
||||
temp1[0][2] = 0;
|
||||
temp1[1][0] = 0;
|
||||
temp1[1][1] = c;
|
||||
temp1[1][2] = s;
|
||||
temp1[2][0] = 0;
|
||||
temp1[2][1] = -s;
|
||||
temp1[2][2] = c;
|
||||
|
||||
R_ConcatRotations (temp1, temp3, entity_rotation);
|
||||
VectorCopy (currententity->transform + 0, entity_rotation[0]);
|
||||
VectorCopy (currententity->transform + 4, entity_rotation[1]);
|
||||
VectorCopy (currententity->transform + 8, entity_rotation[2]);
|
||||
|
||||
// rotate modelorg and the transformation matrix
|
||||
R_EntityRotate (modelorg);
|
||||
|
|
|
@ -569,8 +569,8 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
|
|||
|
||||
clipflags = 0;
|
||||
|
||||
if (currententity->angles[0] || currententity->angles[1]
|
||||
|| currententity->angles[2]) {
|
||||
if (currententity->transform[0] != 1 || currententity->transform[5] != 1
|
||||
|| currententity->transform[10] != 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
|
|
@ -357,8 +357,9 @@ R_DrawSprite (void)
|
|||
} else if (psprite->type == SPR_ORIENTED) {
|
||||
// generate the sprite's axes, according to the sprite's world
|
||||
// orientation
|
||||
AngleVectors (currententity->angles, r_spritedesc.vpn,
|
||||
r_spritedesc.vright, r_spritedesc.vup);
|
||||
VectorCopy (currententity->transform + 0, r_spritedesc.vpn);
|
||||
VectorNegate (currententity->transform + 4, r_spritedesc.vright);
|
||||
VectorCopy (currententity->transform + 8, r_spritedesc.vup);
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
||||
// generate the sprite's axes, parallel to the viewplane, but rotated
|
||||
// in that plane around the center according to the sprite entity's
|
||||
|
|
|
@ -380,6 +380,8 @@ void CL_ClearTEnts (void);
|
|||
void CL_Init_Entity (struct entity_s *ent);
|
||||
void CL_ParseTEnt (void);
|
||||
void CL_SignonReply (void);
|
||||
void CL_TransformEntity (struct entity_s *ent, const vec3_t
|
||||
angles, qboolean force);
|
||||
void CL_RelinkEntities (void);
|
||||
void CL_ClearEnts (void);
|
||||
|
||||
|
|
|
@ -179,6 +179,38 @@ CL_LerpPoint (void)
|
|||
return frac;
|
||||
}
|
||||
|
||||
void
|
||||
CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force)
|
||||
{
|
||||
vec3_t ang;
|
||||
vec_t *forward, *left, *up;
|
||||
|
||||
if (VectorIsZero (angles)) {
|
||||
VectorSet (1, 0, 0, ent->transform + 0);
|
||||
VectorSet (0, 1, 0, ent->transform + 4);
|
||||
VectorSet (0, 0, 1, ent->transform + 8);
|
||||
} else if (force || !VectorCompare (angles, ent->angles)) {
|
||||
forward = ent->transform + 0;
|
||||
left = ent->transform + 4;
|
||||
up = ent->transform + 8;
|
||||
VectorCopy (angles, ang);
|
||||
if (ent->model && ent->model->type == mod_alias) {
|
||||
// stupid quake bug
|
||||
// why, oh, why, do alias models pitch in the opposite direction
|
||||
// to everything else?
|
||||
ang[PITCH] = -ang[PITCH];
|
||||
}
|
||||
AngleVectors (ang, forward, left, up);
|
||||
VectorNegate (left, left); // AngleVectors is right-handed
|
||||
}
|
||||
VectorCopy (angles, ent->angles);
|
||||
ent->transform[3] = 0;
|
||||
ent->transform[7] = 0;
|
||||
ent->transform[11] = 0;
|
||||
VectorCopy (ent->origin, ent->transform + 12);
|
||||
ent->transform[15] = 1;
|
||||
}
|
||||
|
||||
void
|
||||
CL_RelinkEntities (void)
|
||||
{
|
||||
|
@ -251,18 +283,24 @@ CL_RelinkEntities (void)
|
|||
|| fabs (delta[2]) > 100) {
|
||||
// assume a teleportation, not a motion
|
||||
VectorCopy (state->msg_origins[0], ent->origin);
|
||||
VectorCopy (state->msg_angles[0], ent->angles);
|
||||
if (!(ent->model->flags & EF_ROTATE))
|
||||
CL_TransformEntity (ent, state->msg_angles[0], true);
|
||||
ent->pose1 = ent->pose2 = -1;
|
||||
} else {
|
||||
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
|
||||
vec3_t angles, d;
|
||||
// interpolate the origin and angles
|
||||
for (j = 0; j < 3; j++) {
|
||||
d = state->msg_angles[0][j] - state->msg_angles[1][j];
|
||||
if (d > 180)
|
||||
d -= 360;
|
||||
else if (d < -180)
|
||||
d += 360;
|
||||
ent->angles[j] = state->msg_angles[1][j] + f * d;
|
||||
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
|
||||
if (!(ent->model->flags & EF_ROTATE)) {
|
||||
VectorSubtract (state->msg_angles[0],
|
||||
state->msg_angles[1], d);
|
||||
for (j = 0; j < 3; j++) {
|
||||
if (d[j] > 180)
|
||||
d[j] -= 360;
|
||||
else if (d[j] < -180)
|
||||
d[j] += 360;
|
||||
}
|
||||
VectorMultAdd (state->msg_angles[1], f, d, angles);
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
}
|
||||
}
|
||||
if (i != cl.viewentity || chase_active->int_val) {
|
||||
|
@ -278,18 +316,20 @@ CL_RelinkEntities (void)
|
|||
}
|
||||
|
||||
// rotate binary objects locally
|
||||
if (ent->model->flags & EF_ROTATE)
|
||||
ent->angles[1] = bobjrotate;
|
||||
if (ent->model->flags & EF_ROTATE) {
|
||||
vec3_t angles;
|
||||
VectorCopy (state->msg_angles[0], angles);
|
||||
angles[YAW] = bobjrotate;
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
}
|
||||
|
||||
if (state->effects & EF_BRIGHTFIELD)
|
||||
R_EntityParticles (ent);
|
||||
if (state->effects & EF_MUZZLEFLASH) {
|
||||
vec3_t fv, rv, uv;
|
||||
vec_t *fv = ent->transform;
|
||||
|
||||
dl = R_AllocDlight (i);
|
||||
if (dl) {
|
||||
AngleVectors (ent->angles, fv, rv, uv);
|
||||
|
||||
VectorMultAdd (ent->origin, 18, fv, dl->origin);
|
||||
dl->origin[2] += 16;
|
||||
dl->radius = 200 + (rand () & 31);
|
||||
|
|
|
@ -344,9 +344,8 @@ CL_PrintEntities_f (void)
|
|||
continue;
|
||||
}
|
||||
Sys_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n",
|
||||
ent->model->name, ent->frame, ent->origin[0],
|
||||
ent->origin[1], ent->origin[2], ent->angles[0],
|
||||
ent->angles[1], ent->angles[2]);
|
||||
ent->model->name, ent->frame, VectorExpand (ent->origin),
|
||||
VectorExpand (ent->angles));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -628,7 +628,7 @@ CL_ParseUpdate (int bits)
|
|||
VectorCopy (state->msg_origins[0], state->msg_origins[1]);
|
||||
VectorCopy (state->msg_origins[0], ent->origin);
|
||||
VectorCopy (state->msg_angles[0], state->msg_angles[1]);
|
||||
VectorCopy (state->msg_angles[0], ent->angles);
|
||||
CL_TransformEntity (ent, state->msg_angles[0], true);
|
||||
state->forcelink = true;
|
||||
}
|
||||
}
|
||||
|
@ -821,8 +821,6 @@ CL_ParseStatic (int version)
|
|||
CL_ParseBaseline (&state, version);
|
||||
|
||||
// copy it to the current state
|
||||
VectorCopy (state.baseline.origin, ent->origin);
|
||||
VectorCopy (state.baseline.angles, ent->angles);
|
||||
//FIXME alpha & lerp
|
||||
ent->model = cl.model_precache[state.baseline.modelindex];
|
||||
ent->frame = state.baseline.frame;
|
||||
|
@ -840,6 +838,8 @@ CL_ParseStatic (int version)
|
|||
}
|
||||
ent->colormod[3] = ENTALPHA_DECODE (state.baseline.alpha);
|
||||
ent->scale = state.baseline.scale / 16.0;
|
||||
VectorCopy (state.baseline.origin, ent->origin);
|
||||
CL_TransformEntity (ent, state.baseline.angles, true);
|
||||
|
||||
R_AddEfrags (ent);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ typedef struct {
|
|||
int seed;
|
||||
} beam_t;
|
||||
|
||||
#define BEAM_SEED_INTERVAL 72
|
||||
#define BEAM_SEED_PRIME 3191
|
||||
|
||||
typedef struct {
|
||||
float start;
|
||||
|
@ -238,12 +240,13 @@ beam_clear (beam_t *b)
|
|||
}
|
||||
|
||||
static inline void
|
||||
beam_setup (beam_t *b)
|
||||
beam_setup (beam_t *b, qboolean transform)
|
||||
{
|
||||
tent_t *tent;
|
||||
float forward, pitch, yaw, d;
|
||||
int ent_count;
|
||||
vec3_t dist, org;
|
||||
vec3_t dist, org, ang;
|
||||
unsigned seed;
|
||||
|
||||
// calculate pitch and yaw
|
||||
VectorSubtract (b->end, b->start, dist);
|
||||
|
@ -271,6 +274,10 @@ beam_setup (beam_t *b)
|
|||
VectorScale (dist, 30, dist);
|
||||
ent_count = ceil (d / 30);
|
||||
d = 0;
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
|
||||
while (ent_count--) {
|
||||
tent = new_temp_entity ();
|
||||
tent->next = b->tents;
|
||||
|
@ -279,8 +286,13 @@ beam_setup (beam_t *b)
|
|||
VectorMultAdd (org, d, dist, tent->ent.origin);
|
||||
d += 1.0;
|
||||
tent->ent.model = b->model;
|
||||
tent->ent.angles[0] = pitch;
|
||||
tent->ent.angles[1] = yaw;
|
||||
ang[PITCH] = pitch;
|
||||
ang[YAW] = yaw;
|
||||
if (transform) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
ang[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&tent->ent, ang, true);
|
||||
}
|
||||
R_AddEfrags (&tent->ent);
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +325,7 @@ CL_ParseBeam (model_t *m)
|
|||
if (b->entity != cl.viewentity) {
|
||||
// this will be done in CL_UpdateBeams
|
||||
VectorCopy (start, b->start);
|
||||
beam_setup (b);
|
||||
beam_setup (b, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,6 +420,7 @@ CL_ParseTEnt (void)
|
|||
if (!cl_spr_explod->cache.data)
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
ex->tent->ent.model = cl_spr_explod;
|
||||
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||
break;
|
||||
|
||||
case TE_TAREXPLOSION: // tarbaby explosion
|
||||
|
@ -493,9 +506,6 @@ CL_ParseTEnt (void)
|
|||
}
|
||||
}
|
||||
|
||||
#define BEAM_SEED_INTERVAL 72
|
||||
#define BEAM_SEED_PRIME 3191
|
||||
|
||||
static void
|
||||
CL_UpdateBeams (void)
|
||||
{
|
||||
|
@ -525,7 +535,7 @@ CL_UpdateBeams (void)
|
|||
if (b->entity == cl.viewentity) {
|
||||
beam_clear (b);
|
||||
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
|
||||
beam_setup (b);
|
||||
beam_setup (b, false);
|
||||
}
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
|
@ -534,7 +544,8 @@ CL_UpdateBeams (void)
|
|||
// add new entities for the lightning
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
t->ent.angles[2] = seed % 360;
|
||||
t->ent.angles[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&t->ent, t->ent.angles, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -691,6 +691,8 @@ V_CalcRefdef (void)
|
|||
|
||||
if (chase_active->int_val)
|
||||
Chase_Update ();
|
||||
|
||||
CL_TransformEntity (view, view->angles, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
void CL_SetSolidPlayers (int playernum);
|
||||
void CL_ClearPredict (void);
|
||||
void CL_SetUpPlayerPrediction(qboolean dopred);
|
||||
void CL_TransformEntity (struct entity_s * ent, const vec3_t angles,
|
||||
qboolean force);
|
||||
void CL_EmitEntities (void);
|
||||
void CL_ClearProjectiles (void);
|
||||
void CL_ParseProjectiles (qboolean nail2);
|
||||
|
|
|
@ -167,6 +167,38 @@ is_gib (entity_state_t *s1)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force)
|
||||
{
|
||||
vec3_t ang;
|
||||
vec_t *forward, *left, *up;
|
||||
|
||||
if (VectorIsZero (angles)) {
|
||||
VectorSet (1, 0, 0, ent->transform + 0);
|
||||
VectorSet (0, 1, 0, ent->transform + 4);
|
||||
VectorSet (0, 0, 1, ent->transform + 8);
|
||||
} else if (force || !VectorCompare (angles, ent->angles)) {
|
||||
forward = ent->transform + 0;
|
||||
left = ent->transform + 4;
|
||||
up = ent->transform + 8;
|
||||
VectorCopy (angles, ang);
|
||||
if (ent->model && ent->model->type == mod_alias) {
|
||||
// stupid quake bug
|
||||
// why, oh, why, do alias models pitch in the opposite direction
|
||||
// to everything else?
|
||||
ang[PITCH] = -ang[PITCH];
|
||||
}
|
||||
AngleVectors (ang, forward, left, up);
|
||||
VectorNegate (left, left); // AngleVectors is right-handed
|
||||
}
|
||||
VectorCopy (angles, ent->angles);
|
||||
ent->transform[3] = 0;
|
||||
ent->transform[7] = 0;
|
||||
ent->transform[11] = 0;
|
||||
VectorCopy (ent->origin, ent->transform + 12);
|
||||
ent->transform[15] = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
CL_LinkPacketEntities (void)
|
||||
{
|
||||
|
@ -272,11 +304,13 @@ CL_LinkPacketEntities (void)
|
|||
R_AddEfrags (ent);
|
||||
|
||||
if (model->flags & EF_ROTATE) { // rotate binary objects locally
|
||||
ent->angles[0] = 0;
|
||||
ent->angles[1] = anglemod (100 * cl.time);
|
||||
ent->angles[2] = 0;
|
||||
vec3_t ang;
|
||||
ang[PITCH] = 0;
|
||||
ang[YAW] = anglemod (100 * cl.time);
|
||||
ang[ROLL] = 0;
|
||||
CL_TransformEntity (ent, ang, false);
|
||||
} else {
|
||||
VectorCopy (s1->angles, ent->angles);
|
||||
CL_TransformEntity (ent, s1->angles, false);
|
||||
}
|
||||
|
||||
// add automatic particle trails
|
||||
|
@ -314,6 +348,9 @@ CL_LinkPacketEntities (void)
|
|||
CL_AddFlagModels
|
||||
|
||||
Called when the CTF flags are set. Flags are effectively temp entities.
|
||||
|
||||
NOTE: this must be called /after/ the entity has been transformed as it
|
||||
uses the entity's transform matrix to get the frame vectors
|
||||
*/
|
||||
static void
|
||||
CL_AddFlagModels (entity_t *ent, int team, int key)
|
||||
|
@ -322,9 +359,10 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
|
|||
16.0, 22.0, 26.0, 25.0, 24.0, 18.0, // 29-34 axpain
|
||||
16.0, 24.0, 24.0, 22.0, 18.0, 16.0, // 35-40 pain
|
||||
};
|
||||
float f;
|
||||
float f;
|
||||
entity_t *fent;
|
||||
vec3_t v_forward, v_right, v_up;
|
||||
vec_t *v_forward, *v_left;
|
||||
vec3_t ang;
|
||||
|
||||
if (cl_flagindex == -1)
|
||||
return;
|
||||
|
@ -343,15 +381,16 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
|
|||
fent->model = cl.model_precache[cl_flagindex];
|
||||
fent->skinnum = team;
|
||||
|
||||
AngleVectors (ent->angles, v_forward, v_right, v_up);
|
||||
v_forward[2] = -v_forward[2]; // reverse z component
|
||||
v_forward = ent->transform + 0;
|
||||
v_left = ent->transform + 4;
|
||||
|
||||
VectorMultAdd (ent->origin, -f, v_forward, fent->origin);
|
||||
VectorMultAdd (fent->origin, 22, v_right, fent->origin);
|
||||
VectorMultAdd (fent->origin, -22, v_left, fent->origin);
|
||||
fent->origin[2] -= 16.0;
|
||||
|
||||
VectorCopy (ent->angles, fent->angles);
|
||||
fent->angles[2] -= 45.0;
|
||||
VectorCopy (ent->angles, ang);
|
||||
ang[2] -= 45.0;
|
||||
CL_TransformEntity (fent, ang, false);
|
||||
|
||||
R_EnqueueEntity (fent); //FIXME should use efrag (needs smarter handling
|
||||
//in the player code)
|
||||
|
@ -374,7 +413,7 @@ CL_LinkPlayers (void)
|
|||
player_state_t exact;
|
||||
player_state_t *state;
|
||||
qboolean clientplayer;
|
||||
vec3_t org;
|
||||
vec3_t org, ang;
|
||||
|
||||
playertime = realtime - cls.latency + 0.02;
|
||||
if (playertime > realtime)
|
||||
|
@ -436,20 +475,21 @@ CL_LinkPlayers (void)
|
|||
// angles
|
||||
if (j == cl.playernum)
|
||||
{
|
||||
ent->angles[PITCH] = -cl.viewangles[PITCH] / 3.0;
|
||||
ent->angles[YAW] = cl.viewangles[YAW];
|
||||
ang[PITCH] = -cl.viewangles[PITCH] / 3.0;
|
||||
ang[YAW] = cl.viewangles[YAW];
|
||||
} else {
|
||||
ent->angles[PITCH] = -state->viewangles[PITCH] / 3.0;
|
||||
ent->angles[YAW] = state->viewangles[YAW];
|
||||
ang[PITCH] = -state->viewangles[PITCH] / 3.0;
|
||||
ang[YAW] = state->viewangles[YAW];
|
||||
}
|
||||
ent->angles[ROLL] = V_CalcRoll (ent->angles,
|
||||
state->pls.velocity) * 4.0;
|
||||
ang[ROLL] = V_CalcRoll (ang, state->pls.velocity) * 4.0;
|
||||
|
||||
ent->model = cl.model_precache[state->pls.modelindex];
|
||||
ent->frame = state->pls.frame;
|
||||
ent->colormap = info->translations;
|
||||
ent->skinnum = state->pls.skinnum;
|
||||
|
||||
CL_TransformEntity (ent, ang, false);
|
||||
|
||||
ent->min_light = 0;
|
||||
ent->fullbright = 0;
|
||||
|
||||
|
|
|
@ -981,7 +981,7 @@ CL_ParseStatic (void)
|
|||
ent->skinnum = es.skinnum;
|
||||
|
||||
VectorCopy (es.origin, ent->origin);
|
||||
VectorCopy (es.angles, ent->angles);
|
||||
CL_TransformEntity (ent, es.angles, true);
|
||||
|
||||
R_AddEfrags (ent);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,8 @@ typedef struct {
|
|||
int seed;
|
||||
} beam_t;
|
||||
|
||||
#define BEAM_SEED_INTERVAL 72
|
||||
#define BEAM_SEED_PRIME 3191
|
||||
|
||||
typedef struct {
|
||||
float start;
|
||||
|
@ -244,12 +246,13 @@ beam_clear (beam_t *b)
|
|||
}
|
||||
|
||||
static inline void
|
||||
beam_setup (beam_t *b)
|
||||
beam_setup (beam_t *b, qboolean transform)
|
||||
{
|
||||
tent_t *tent;
|
||||
float forward, pitch, yaw, d;
|
||||
int ent_count;
|
||||
vec3_t dist, org;
|
||||
vec3_t dist, org, ang;
|
||||
unsigned seed;
|
||||
|
||||
// calculate pitch and yaw
|
||||
VectorSubtract (b->end, b->start, dist);
|
||||
|
@ -277,6 +280,10 @@ beam_setup (beam_t *b)
|
|||
VectorScale (dist, 30, dist);
|
||||
ent_count = ceil (d / 30);
|
||||
d = 0;
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
|
||||
while (ent_count--) {
|
||||
tent = new_temp_entity ();
|
||||
tent->next = b->tents;
|
||||
|
@ -285,8 +292,13 @@ beam_setup (beam_t *b)
|
|||
VectorMultAdd (org, d, dist, tent->ent.origin);
|
||||
d += 1.0;
|
||||
tent->ent.model = b->model;
|
||||
tent->ent.angles[0] = pitch;
|
||||
tent->ent.angles[1] = yaw;
|
||||
ang[PITCH] = pitch;
|
||||
ang[YAW] = yaw;
|
||||
if (transform) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
ang[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&tent->ent, ang, true);
|
||||
}
|
||||
R_AddEfrags (&tent->ent);
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +331,7 @@ CL_ParseBeam (model_t *m)
|
|||
if (b->entity != cl.viewentity) {
|
||||
// this will be done in CL_UpdateBeams
|
||||
VectorCopy (start, b->start);
|
||||
beam_setup (b);
|
||||
beam_setup (b, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,6 +426,7 @@ CL_ParseTEnt (void)
|
|||
if (!cl_spr_explod->cache.data)
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
ex->tent->ent.model = cl_spr_explod;
|
||||
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||
break;
|
||||
|
||||
case TE_TAREXPLOSION: // tarbaby explosion
|
||||
|
@ -502,9 +515,6 @@ CL_ParseTEnt (void)
|
|||
}
|
||||
}
|
||||
|
||||
#define BEAM_SEED_INTERVAL 72
|
||||
#define BEAM_SEED_PRIME 3191
|
||||
|
||||
static void
|
||||
CL_UpdateBeams (void)
|
||||
{
|
||||
|
@ -534,7 +544,7 @@ CL_UpdateBeams (void)
|
|||
if (b->entity == cl.viewentity) {
|
||||
beam_clear (b);
|
||||
VectorCopy (cl.simorg, b->start);
|
||||
beam_setup (b);
|
||||
beam_setup (b, false);
|
||||
}
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
|
@ -543,7 +553,8 @@ CL_UpdateBeams (void)
|
|||
// add new entities for the lightning
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
t->ent.angles[2] = seed % 360;
|
||||
t->ent.angles[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&t->ent, t->ent.angles, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -636,6 +647,7 @@ CL_ParseProjectiles (qboolean nail2)
|
|||
pr->angles[0] = (bits[4] >> 4) * (360.0 / 16.0);
|
||||
pr->angles[1] = bits[5] * (360.0 / 256.0);
|
||||
pr->angles[2] = 0;
|
||||
CL_TransformEntity (&tent->ent, tent->ent.angles, true);
|
||||
|
||||
R_AddEfrags (&tent->ent);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
#include "qw/bothdefs.h"
|
||||
#include "cl_cam.h"
|
||||
#include "cl_ents.h"
|
||||
#include "cl_main.h"
|
||||
#include "client.h"
|
||||
#include "compat.h"
|
||||
|
@ -693,6 +694,7 @@ V_CalcRefdef (void)
|
|||
|
||||
if (cl.chase && chase_active->int_val)
|
||||
Chase_Update ();
|
||||
CL_TransformEntity (view, view->angles, true);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue