mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +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_NEED (void, glMatrixMode, (GLenum mode))
|
||||||
QFGL_DONT_NEED (void, glMinmax, (GLenum target, GLenum internalformat, GLboolean sink))
|
QFGL_DONT_NEED (void, glMinmax, (GLenum target, GLenum internalformat, GLboolean sink))
|
||||||
QFGL_DONT_NEED (void, glMultMatrixd, (const GLdouble * m))
|
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_NEED (void, glNewList, (GLuint list, GLenum mode))
|
||||||
QFGL_DONT_NEED (void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz))
|
QFGL_DONT_NEED (void, glNormal3b, (GLbyte nx, GLbyte ny, GLbyte nz))
|
||||||
QFGL_NEED (void, glNormal3bv, (const GLbyte * v))
|
QFGL_NEED (void, glNormal3bv, (const GLbyte * v))
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef struct entity_s {
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
vec3_t old_origin;
|
vec3_t old_origin;
|
||||||
vec3_t angles;
|
vec3_t angles;
|
||||||
|
vec_t transform[4 * 4];
|
||||||
struct model_s *model; // NULL = no model
|
struct model_s *model; // NULL = no model
|
||||||
int frame;
|
int frame;
|
||||||
byte *colormap;
|
byte *colormap;
|
||||||
|
|
|
@ -110,16 +110,15 @@ R_DrawSpriteModel_f (entity_t *e)
|
||||||
float *up, *right;
|
float *up, *right;
|
||||||
msprite_t *psprite;
|
msprite_t *psprite;
|
||||||
mspriteframe_t *frame;
|
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
|
// don't bother culling, it's just a single polygon without a surface cache
|
||||||
frame = R_GetSpriteFrame (e);
|
frame = R_GetSpriteFrame (e);
|
||||||
psprite = e->model->cache.data;
|
psprite = e->model->cache.data;
|
||||||
|
|
||||||
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
||||||
AngleVectors (e->angles, v_forward, v_right, v_up);
|
up = e->transform + 2 * 4;
|
||||||
up = v_up;
|
right = e->transform + 1 * 4;
|
||||||
right = v_right;
|
|
||||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||||
v_up[0] = 0;
|
v_up[0] = 0;
|
||||||
v_up[1] = 0;
|
v_up[1] = 0;
|
||||||
|
@ -179,7 +178,7 @@ R_DrawSpriteModel_VA_f (entity_t *e)
|
||||||
// unsigned int vacount;
|
// unsigned int vacount;
|
||||||
msprite_t *psprite;
|
msprite_t *psprite;
|
||||||
mspriteframe_t *frame;
|
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;
|
varray_t2f_c4ub_v3f_t *VA;
|
||||||
|
|
||||||
VA = spriteVertexArray; // FIXME: Despair
|
VA = spriteVertexArray; // FIXME: Despair
|
||||||
|
@ -191,9 +190,8 @@ R_DrawSpriteModel_VA_f (entity_t *e)
|
||||||
qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR
|
qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR
|
||||||
|
|
||||||
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
||||||
AngleVectors (e->angles, v_forward, v_right, v_up);
|
up = e->transform + 2 * 4;
|
||||||
up = v_up;
|
right = e->transform + 1 * 4;
|
||||||
right = v_right;
|
|
||||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||||
v_up[0] = 0;
|
v_up[0] = 0;
|
||||||
v_up[1] = 0;
|
v_up[1] = 0;
|
||||||
|
|
|
@ -203,11 +203,7 @@ glrmain_init (void)
|
||||||
void
|
void
|
||||||
R_RotateForEntity (entity_t *e)
|
R_RotateForEntity (entity_t *e)
|
||||||
{
|
{
|
||||||
qfglTranslatef (e->origin[0], e->origin[1], e->origin[2]);
|
qfglMultMatrixf (e->transform);
|
||||||
|
|
||||||
qfglRotatef ( e->angles[YAW], 0, 0, 1);
|
|
||||||
qfglRotatef (-e->angles[PITCH], 0, 1, 0);
|
|
||||||
qfglRotatef ( e->angles[ROLL], 1, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -388,7 +388,7 @@ R_DrawBrushModel (entity_t *e)
|
||||||
|
|
||||||
model = e->model;
|
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;
|
rotated = true;
|
||||||
radius = model->radius;
|
radius = model->radius;
|
||||||
#if 0 //QSG FIXME
|
#if 0 //QSG FIXME
|
||||||
|
@ -423,13 +423,12 @@ R_DrawBrushModel (entity_t *e)
|
||||||
|
|
||||||
VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
|
VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
|
||||||
if (rotated) {
|
if (rotated) {
|
||||||
vec3_t temp, forward, right, up;
|
vec3_t temp;
|
||||||
|
|
||||||
VectorCopy (modelorg, temp);
|
VectorCopy (modelorg, temp);
|
||||||
AngleVectors (e->angles, forward, right, up);
|
modelorg[0] = DotProduct (temp, e->transform + 0);
|
||||||
modelorg[0] = DotProduct (temp, forward);
|
modelorg[1] = DotProduct (temp, e->transform + 4);
|
||||||
modelorg[1] = -DotProduct (temp, right);
|
modelorg[2] = DotProduct (temp, e->transform + 8);
|
||||||
modelorg[2] = DotProduct (temp, up);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
psurf = &model->surfaces[model->firstmodelsurface];
|
psurf = &model->surfaces[model->firstmodelsurface];
|
||||||
|
@ -449,9 +448,7 @@ R_DrawBrushModel (entity_t *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
qfglPushMatrix ();
|
qfglPushMatrix ();
|
||||||
e->angles[0] = -e->angles[0]; // stupid quake bug
|
|
||||||
R_RotateForEntity (e);
|
R_RotateForEntity (e);
|
||||||
e->angles[0] = -e->angles[0]; // stupid quake bug
|
|
||||||
|
|
||||||
// Build lightmap chains
|
// Build lightmap chains
|
||||||
for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
|
for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
|
||||||
|
|
|
@ -360,16 +360,10 @@ R_AliasSetUpTransform (int trivial_accept)
|
||||||
float rotationmatrix[3][4], t2matrix[3][4];
|
float rotationmatrix[3][4], t2matrix[3][4];
|
||||||
static float tmatrix[3][4];
|
static float tmatrix[3][4];
|
||||||
static float viewmatrix[3][4];
|
static float viewmatrix[3][4];
|
||||||
vec3_t angles;
|
|
||||||
|
|
||||||
// TODO: should really be stored with the entity instead of being reconstructed
|
VectorCopy (currententity->transform + 0, alias_forward);
|
||||||
// TODO: should use a look-up table
|
VectorNegate (currententity->transform + 4, alias_right);
|
||||||
// TODO: could cache lazily, stored in the entity
|
VectorCopy (currententity->transform + 8, alias_up);
|
||||||
|
|
||||||
angles[ROLL] = currententity->angles[ROLL];
|
|
||||||
angles[PITCH] = -currententity->angles[PITCH];
|
|
||||||
angles[YAW] = currententity->angles[YAW];
|
|
||||||
AngleVectors (angles, alias_forward, alias_right, alias_up);
|
|
||||||
|
|
||||||
tmatrix[0][0] = pmdl->scale[0];
|
tmatrix[0][0] = pmdl->scale[0];
|
||||||
tmatrix[1][1] = pmdl->scale[1];
|
tmatrix[1][1] = pmdl->scale[1];
|
||||||
|
|
|
@ -80,64 +80,9 @@ R_EntityRotate (vec3_t vec)
|
||||||
void
|
void
|
||||||
R_RotateBmodel (void)
|
R_RotateBmodel (void)
|
||||||
{
|
{
|
||||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
VectorCopy (currententity->transform + 0, entity_rotation[0]);
|
||||||
|
VectorCopy (currententity->transform + 4, entity_rotation[1]);
|
||||||
// TODO: should use a look-up table
|
VectorCopy (currententity->transform + 8, entity_rotation[2]);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// rotate modelorg and the transformation matrix
|
// rotate modelorg and the transformation matrix
|
||||||
R_EntityRotate (modelorg);
|
R_EntityRotate (modelorg);
|
||||||
|
|
|
@ -550,8 +550,8 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
|
||||||
|
|
||||||
clipflags = 0;
|
clipflags = 0;
|
||||||
|
|
||||||
if (currententity->angles[0] || currententity->angles[1]
|
if (currententity->transform[0] != 1 || currententity->transform[5] != 1
|
||||||
|| currententity->angles[2]) {
|
|| currententity->transform[10] != 1) {
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
||||||
d -= view_clipplanes[i].dist;
|
d -= view_clipplanes[i].dist;
|
||||||
|
|
|
@ -364,8 +364,9 @@ R_DrawSprite (void)
|
||||||
} else if (psprite->type == SPR_ORIENTED) {
|
} else if (psprite->type == SPR_ORIENTED) {
|
||||||
// generate the sprite's axes, according to the sprite's world
|
// generate the sprite's axes, according to the sprite's world
|
||||||
// orientation
|
// orientation
|
||||||
AngleVectors (currententity->angles, r_spritedesc.vpn,
|
VectorCopy (currententity->transform + 0, r_spritedesc.vpn);
|
||||||
r_spritedesc.vright, r_spritedesc.vup);
|
VectorNegate (currententity->transform + 4, r_spritedesc.vright);
|
||||||
|
VectorCopy (currententity->transform + 8, r_spritedesc.vup);
|
||||||
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
||||||
// generate the sprite's axes, parallel to the viewplane, but rotated
|
// generate the sprite's axes, parallel to the viewplane, but rotated
|
||||||
// in that plane around the center according to the sprite entity's
|
// 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];
|
float rotationmatrix[3][4], t2matrix[3][4];
|
||||||
static float tmatrix[3][4];
|
static float tmatrix[3][4];
|
||||||
static float viewmatrix[3][4];
|
static float viewmatrix[3][4];
|
||||||
vec3_t angles;
|
|
||||||
|
|
||||||
// TODO: should really be stored with the entity instead of being reconstructed
|
VectorCopy (currententity->transform + 0, alias_forward);
|
||||||
// TODO: should use a look-up table
|
VectorNegate (currententity->transform + 4, alias_right);
|
||||||
// TODO: could cache lazily, stored in the entity
|
VectorCopy (currententity->transform + 8, alias_up);
|
||||||
|
|
||||||
angles[ROLL] = currententity->angles[ROLL];
|
|
||||||
angles[PITCH] = -currententity->angles[PITCH];
|
|
||||||
angles[YAW] = currententity->angles[YAW];
|
|
||||||
AngleVectors (angles, alias_forward, alias_right, alias_up);
|
|
||||||
|
|
||||||
tmatrix[0][0] = pmdl->scale[0];
|
tmatrix[0][0] = pmdl->scale[0];
|
||||||
tmatrix[1][1] = pmdl->scale[1];
|
tmatrix[1][1] = pmdl->scale[1];
|
||||||
|
|
|
@ -80,64 +80,9 @@ R_EntityRotate (vec3_t vec)
|
||||||
void
|
void
|
||||||
R_RotateBmodel (void)
|
R_RotateBmodel (void)
|
||||||
{
|
{
|
||||||
float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3];
|
VectorCopy (currententity->transform + 0, entity_rotation[0]);
|
||||||
|
VectorCopy (currententity->transform + 4, entity_rotation[1]);
|
||||||
// TODO: should use a look-up table
|
VectorCopy (currententity->transform + 8, entity_rotation[2]);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// rotate modelorg and the transformation matrix
|
// rotate modelorg and the transformation matrix
|
||||||
R_EntityRotate (modelorg);
|
R_EntityRotate (modelorg);
|
||||||
|
|
|
@ -569,8 +569,8 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
|
||||||
|
|
||||||
clipflags = 0;
|
clipflags = 0;
|
||||||
|
|
||||||
if (currententity->angles[0] || currententity->angles[1]
|
if (currententity->transform[0] != 1 || currententity->transform[5] != 1
|
||||||
|| currententity->angles[2]) {
|
|| currententity->transform[10] != 1) {
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
d = DotProduct (currententity->origin, view_clipplanes[i].normal);
|
||||||
d -= view_clipplanes[i].dist;
|
d -= view_clipplanes[i].dist;
|
||||||
|
|
|
@ -357,8 +357,9 @@ R_DrawSprite (void)
|
||||||
} else if (psprite->type == SPR_ORIENTED) {
|
} else if (psprite->type == SPR_ORIENTED) {
|
||||||
// generate the sprite's axes, according to the sprite's world
|
// generate the sprite's axes, according to the sprite's world
|
||||||
// orientation
|
// orientation
|
||||||
AngleVectors (currententity->angles, r_spritedesc.vpn,
|
VectorCopy (currententity->transform + 0, r_spritedesc.vpn);
|
||||||
r_spritedesc.vright, r_spritedesc.vup);
|
VectorNegate (currententity->transform + 4, r_spritedesc.vright);
|
||||||
|
VectorCopy (currententity->transform + 8, r_spritedesc.vup);
|
||||||
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
} else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) {
|
||||||
// generate the sprite's axes, parallel to the viewplane, but rotated
|
// generate the sprite's axes, parallel to the viewplane, but rotated
|
||||||
// in that plane around the center according to the sprite entity's
|
// 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_Init_Entity (struct entity_s *ent);
|
||||||
void CL_ParseTEnt (void);
|
void CL_ParseTEnt (void);
|
||||||
void CL_SignonReply (void);
|
void CL_SignonReply (void);
|
||||||
|
void CL_TransformEntity (struct entity_s *ent, const vec3_t
|
||||||
|
angles, qboolean force);
|
||||||
void CL_RelinkEntities (void);
|
void CL_RelinkEntities (void);
|
||||||
void CL_ClearEnts (void);
|
void CL_ClearEnts (void);
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,38 @@ CL_LerpPoint (void)
|
||||||
return frac;
|
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
|
void
|
||||||
CL_RelinkEntities (void)
|
CL_RelinkEntities (void)
|
||||||
{
|
{
|
||||||
|
@ -251,18 +283,24 @@ CL_RelinkEntities (void)
|
||||||
|| fabs (delta[2]) > 100) {
|
|| fabs (delta[2]) > 100) {
|
||||||
// assume a teleportation, not a motion
|
// assume a teleportation, not a motion
|
||||||
VectorCopy (state->msg_origins[0], ent->origin);
|
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;
|
ent->pose1 = ent->pose2 = -1;
|
||||||
} else {
|
} else {
|
||||||
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
|
vec3_t angles, d;
|
||||||
// interpolate the origin and angles
|
// interpolate the origin and angles
|
||||||
for (j = 0; j < 3; j++) {
|
VectorMultAdd (state->msg_origins[1], f, delta, ent->origin);
|
||||||
d = state->msg_angles[0][j] - state->msg_angles[1][j];
|
if (!(ent->model->flags & EF_ROTATE)) {
|
||||||
if (d > 180)
|
VectorSubtract (state->msg_angles[0],
|
||||||
d -= 360;
|
state->msg_angles[1], d);
|
||||||
else if (d < -180)
|
for (j = 0; j < 3; j++) {
|
||||||
d += 360;
|
if (d[j] > 180)
|
||||||
ent->angles[j] = state->msg_angles[1][j] + f * d;
|
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) {
|
if (i != cl.viewentity || chase_active->int_val) {
|
||||||
|
@ -278,18 +316,20 @@ CL_RelinkEntities (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotate binary objects locally
|
// rotate binary objects locally
|
||||||
if (ent->model->flags & EF_ROTATE)
|
if (ent->model->flags & EF_ROTATE) {
|
||||||
ent->angles[1] = bobjrotate;
|
vec3_t angles;
|
||||||
|
VectorCopy (state->msg_angles[0], angles);
|
||||||
|
angles[YAW] = bobjrotate;
|
||||||
|
CL_TransformEntity (ent, angles, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (state->effects & EF_BRIGHTFIELD)
|
if (state->effects & EF_BRIGHTFIELD)
|
||||||
R_EntityParticles (ent);
|
R_EntityParticles (ent);
|
||||||
if (state->effects & EF_MUZZLEFLASH) {
|
if (state->effects & EF_MUZZLEFLASH) {
|
||||||
vec3_t fv, rv, uv;
|
vec_t *fv = ent->transform;
|
||||||
|
|
||||||
dl = R_AllocDlight (i);
|
dl = R_AllocDlight (i);
|
||||||
if (dl) {
|
if (dl) {
|
||||||
AngleVectors (ent->angles, fv, rv, uv);
|
|
||||||
|
|
||||||
VectorMultAdd (ent->origin, 18, fv, dl->origin);
|
VectorMultAdd (ent->origin, 18, fv, dl->origin);
|
||||||
dl->origin[2] += 16;
|
dl->origin[2] += 16;
|
||||||
dl->radius = 200 + (rand () & 31);
|
dl->radius = 200 + (rand () & 31);
|
||||||
|
|
|
@ -344,9 +344,8 @@ CL_PrintEntities_f (void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Sys_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n",
|
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->model->name, ent->frame, VectorExpand (ent->origin),
|
||||||
ent->origin[1], ent->origin[2], ent->angles[0],
|
VectorExpand (ent->angles));
|
||||||
ent->angles[1], ent->angles[2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -628,7 +628,7 @@ CL_ParseUpdate (int bits)
|
||||||
VectorCopy (state->msg_origins[0], state->msg_origins[1]);
|
VectorCopy (state->msg_origins[0], state->msg_origins[1]);
|
||||||
VectorCopy (state->msg_origins[0], ent->origin);
|
VectorCopy (state->msg_origins[0], ent->origin);
|
||||||
VectorCopy (state->msg_angles[0], state->msg_angles[1]);
|
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;
|
state->forcelink = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,8 +821,6 @@ CL_ParseStatic (int version)
|
||||||
CL_ParseBaseline (&state, version);
|
CL_ParseBaseline (&state, version);
|
||||||
|
|
||||||
// copy it to the current state
|
// copy it to the current state
|
||||||
VectorCopy (state.baseline.origin, ent->origin);
|
|
||||||
VectorCopy (state.baseline.angles, ent->angles);
|
|
||||||
//FIXME alpha & lerp
|
//FIXME alpha & lerp
|
||||||
ent->model = cl.model_precache[state.baseline.modelindex];
|
ent->model = cl.model_precache[state.baseline.modelindex];
|
||||||
ent->frame = state.baseline.frame;
|
ent->frame = state.baseline.frame;
|
||||||
|
@ -840,6 +838,8 @@ CL_ParseStatic (int version)
|
||||||
}
|
}
|
||||||
ent->colormod[3] = ENTALPHA_DECODE (state.baseline.alpha);
|
ent->colormod[3] = ENTALPHA_DECODE (state.baseline.alpha);
|
||||||
ent->scale = state.baseline.scale / 16.0;
|
ent->scale = state.baseline.scale / 16.0;
|
||||||
|
VectorCopy (state.baseline.origin, ent->origin);
|
||||||
|
CL_TransformEntity (ent, state.baseline.angles, true);
|
||||||
|
|
||||||
R_AddEfrags (ent);
|
R_AddEfrags (ent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,8 @@ typedef struct {
|
||||||
int seed;
|
int seed;
|
||||||
} beam_t;
|
} beam_t;
|
||||||
|
|
||||||
|
#define BEAM_SEED_INTERVAL 72
|
||||||
|
#define BEAM_SEED_PRIME 3191
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float start;
|
float start;
|
||||||
|
@ -238,12 +240,13 @@ beam_clear (beam_t *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
beam_setup (beam_t *b)
|
beam_setup (beam_t *b, qboolean transform)
|
||||||
{
|
{
|
||||||
tent_t *tent;
|
tent_t *tent;
|
||||||
float forward, pitch, yaw, d;
|
float forward, pitch, yaw, d;
|
||||||
int ent_count;
|
int ent_count;
|
||||||
vec3_t dist, org;
|
vec3_t dist, org, ang;
|
||||||
|
unsigned seed;
|
||||||
|
|
||||||
// calculate pitch and yaw
|
// calculate pitch and yaw
|
||||||
VectorSubtract (b->end, b->start, dist);
|
VectorSubtract (b->end, b->start, dist);
|
||||||
|
@ -271,6 +274,10 @@ beam_setup (beam_t *b)
|
||||||
VectorScale (dist, 30, dist);
|
VectorScale (dist, 30, dist);
|
||||||
ent_count = ceil (d / 30);
|
ent_count = ceil (d / 30);
|
||||||
d = 0;
|
d = 0;
|
||||||
|
|
||||||
|
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||||
|
BEAM_SEED_INTERVAL);
|
||||||
|
|
||||||
while (ent_count--) {
|
while (ent_count--) {
|
||||||
tent = new_temp_entity ();
|
tent = new_temp_entity ();
|
||||||
tent->next = b->tents;
|
tent->next = b->tents;
|
||||||
|
@ -279,8 +286,13 @@ beam_setup (beam_t *b)
|
||||||
VectorMultAdd (org, d, dist, tent->ent.origin);
|
VectorMultAdd (org, d, dist, tent->ent.origin);
|
||||||
d += 1.0;
|
d += 1.0;
|
||||||
tent->ent.model = b->model;
|
tent->ent.model = b->model;
|
||||||
tent->ent.angles[0] = pitch;
|
ang[PITCH] = pitch;
|
||||||
tent->ent.angles[1] = yaw;
|
ang[YAW] = yaw;
|
||||||
|
if (transform) {
|
||||||
|
seed = seed * BEAM_SEED_PRIME;
|
||||||
|
ang[ROLL] = seed % 360;
|
||||||
|
CL_TransformEntity (&tent->ent, ang, true);
|
||||||
|
}
|
||||||
R_AddEfrags (&tent->ent);
|
R_AddEfrags (&tent->ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +325,7 @@ CL_ParseBeam (model_t *m)
|
||||||
if (b->entity != cl.viewentity) {
|
if (b->entity != cl.viewentity) {
|
||||||
// this will be done in CL_UpdateBeams
|
// this will be done in CL_UpdateBeams
|
||||||
VectorCopy (start, b->start);
|
VectorCopy (start, b->start);
|
||||||
beam_setup (b);
|
beam_setup (b, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +420,7 @@ CL_ParseTEnt (void)
|
||||||
if (!cl_spr_explod->cache.data)
|
if (!cl_spr_explod->cache.data)
|
||||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||||
ex->tent->ent.model = cl_spr_explod;
|
ex->tent->ent.model = cl_spr_explod;
|
||||||
|
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TE_TAREXPLOSION: // tarbaby explosion
|
case TE_TAREXPLOSION: // tarbaby explosion
|
||||||
|
@ -493,9 +506,6 @@ CL_ParseTEnt (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BEAM_SEED_INTERVAL 72
|
|
||||||
#define BEAM_SEED_PRIME 3191
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CL_UpdateBeams (void)
|
CL_UpdateBeams (void)
|
||||||
{
|
{
|
||||||
|
@ -525,7 +535,7 @@ CL_UpdateBeams (void)
|
||||||
if (b->entity == cl.viewentity) {
|
if (b->entity == cl.viewentity) {
|
||||||
beam_clear (b);
|
beam_clear (b);
|
||||||
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
|
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
|
||||||
beam_setup (b);
|
beam_setup (b, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||||
|
@ -534,7 +544,8 @@ CL_UpdateBeams (void)
|
||||||
// add new entities for the lightning
|
// add new entities for the lightning
|
||||||
for (t = b->tents; t; t = t->next) {
|
for (t = b->tents; t; t = t->next) {
|
||||||
seed = seed * BEAM_SEED_PRIME;
|
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)
|
if (chase_active->int_val)
|
||||||
Chase_Update ();
|
Chase_Update ();
|
||||||
|
|
||||||
|
CL_TransformEntity (view, view->angles, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
void CL_SetSolidPlayers (int playernum);
|
void CL_SetSolidPlayers (int playernum);
|
||||||
void CL_ClearPredict (void);
|
void CL_ClearPredict (void);
|
||||||
void CL_SetUpPlayerPrediction(qboolean dopred);
|
void CL_SetUpPlayerPrediction(qboolean dopred);
|
||||||
|
void CL_TransformEntity (struct entity_s * ent, const vec3_t angles,
|
||||||
|
qboolean force);
|
||||||
void CL_EmitEntities (void);
|
void CL_EmitEntities (void);
|
||||||
void CL_ClearProjectiles (void);
|
void CL_ClearProjectiles (void);
|
||||||
void CL_ParseProjectiles (qboolean nail2);
|
void CL_ParseProjectiles (qboolean nail2);
|
||||||
|
|
|
@ -167,6 +167,38 @@ is_gib (entity_state_t *s1)
|
||||||
return 0;
|
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
|
static void
|
||||||
CL_LinkPacketEntities (void)
|
CL_LinkPacketEntities (void)
|
||||||
{
|
{
|
||||||
|
@ -272,11 +304,13 @@ CL_LinkPacketEntities (void)
|
||||||
R_AddEfrags (ent);
|
R_AddEfrags (ent);
|
||||||
|
|
||||||
if (model->flags & EF_ROTATE) { // rotate binary objects locally
|
if (model->flags & EF_ROTATE) { // rotate binary objects locally
|
||||||
ent->angles[0] = 0;
|
vec3_t ang;
|
||||||
ent->angles[1] = anglemod (100 * cl.time);
|
ang[PITCH] = 0;
|
||||||
ent->angles[2] = 0;
|
ang[YAW] = anglemod (100 * cl.time);
|
||||||
|
ang[ROLL] = 0;
|
||||||
|
CL_TransformEntity (ent, ang, false);
|
||||||
} else {
|
} else {
|
||||||
VectorCopy (s1->angles, ent->angles);
|
CL_TransformEntity (ent, s1->angles, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add automatic particle trails
|
// add automatic particle trails
|
||||||
|
@ -314,6 +348,9 @@ CL_LinkPacketEntities (void)
|
||||||
CL_AddFlagModels
|
CL_AddFlagModels
|
||||||
|
|
||||||
Called when the CTF flags are set. Flags are effectively temp entities.
|
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
|
static void
|
||||||
CL_AddFlagModels (entity_t *ent, int team, int key)
|
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, 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
|
16.0, 24.0, 24.0, 22.0, 18.0, 16.0, // 35-40 pain
|
||||||
};
|
};
|
||||||
float f;
|
float f;
|
||||||
entity_t *fent;
|
entity_t *fent;
|
||||||
vec3_t v_forward, v_right, v_up;
|
vec_t *v_forward, *v_left;
|
||||||
|
vec3_t ang;
|
||||||
|
|
||||||
if (cl_flagindex == -1)
|
if (cl_flagindex == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -343,15 +381,16 @@ CL_AddFlagModels (entity_t *ent, int team, int key)
|
||||||
fent->model = cl.model_precache[cl_flagindex];
|
fent->model = cl.model_precache[cl_flagindex];
|
||||||
fent->skinnum = team;
|
fent->skinnum = team;
|
||||||
|
|
||||||
AngleVectors (ent->angles, v_forward, v_right, v_up);
|
v_forward = ent->transform + 0;
|
||||||
v_forward[2] = -v_forward[2]; // reverse z component
|
v_left = ent->transform + 4;
|
||||||
|
|
||||||
VectorMultAdd (ent->origin, -f, v_forward, fent->origin);
|
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;
|
fent->origin[2] -= 16.0;
|
||||||
|
|
||||||
VectorCopy (ent->angles, fent->angles);
|
VectorCopy (ent->angles, ang);
|
||||||
fent->angles[2] -= 45.0;
|
ang[2] -= 45.0;
|
||||||
|
CL_TransformEntity (fent, ang, false);
|
||||||
|
|
||||||
R_EnqueueEntity (fent); //FIXME should use efrag (needs smarter handling
|
R_EnqueueEntity (fent); //FIXME should use efrag (needs smarter handling
|
||||||
//in the player code)
|
//in the player code)
|
||||||
|
@ -374,7 +413,7 @@ CL_LinkPlayers (void)
|
||||||
player_state_t exact;
|
player_state_t exact;
|
||||||
player_state_t *state;
|
player_state_t *state;
|
||||||
qboolean clientplayer;
|
qboolean clientplayer;
|
||||||
vec3_t org;
|
vec3_t org, ang;
|
||||||
|
|
||||||
playertime = realtime - cls.latency + 0.02;
|
playertime = realtime - cls.latency + 0.02;
|
||||||
if (playertime > realtime)
|
if (playertime > realtime)
|
||||||
|
@ -436,20 +475,21 @@ CL_LinkPlayers (void)
|
||||||
// angles
|
// angles
|
||||||
if (j == cl.playernum)
|
if (j == cl.playernum)
|
||||||
{
|
{
|
||||||
ent->angles[PITCH] = -cl.viewangles[PITCH] / 3.0;
|
ang[PITCH] = -cl.viewangles[PITCH] / 3.0;
|
||||||
ent->angles[YAW] = cl.viewangles[YAW];
|
ang[YAW] = cl.viewangles[YAW];
|
||||||
} else {
|
} else {
|
||||||
ent->angles[PITCH] = -state->viewangles[PITCH] / 3.0;
|
ang[PITCH] = -state->viewangles[PITCH] / 3.0;
|
||||||
ent->angles[YAW] = state->viewangles[YAW];
|
ang[YAW] = state->viewangles[YAW];
|
||||||
}
|
}
|
||||||
ent->angles[ROLL] = V_CalcRoll (ent->angles,
|
ang[ROLL] = V_CalcRoll (ang, state->pls.velocity) * 4.0;
|
||||||
state->pls.velocity) * 4.0;
|
|
||||||
|
|
||||||
ent->model = cl.model_precache[state->pls.modelindex];
|
ent->model = cl.model_precache[state->pls.modelindex];
|
||||||
ent->frame = state->pls.frame;
|
ent->frame = state->pls.frame;
|
||||||
ent->colormap = info->translations;
|
ent->colormap = info->translations;
|
||||||
ent->skinnum = state->pls.skinnum;
|
ent->skinnum = state->pls.skinnum;
|
||||||
|
|
||||||
|
CL_TransformEntity (ent, ang, false);
|
||||||
|
|
||||||
ent->min_light = 0;
|
ent->min_light = 0;
|
||||||
ent->fullbright = 0;
|
ent->fullbright = 0;
|
||||||
|
|
||||||
|
|
|
@ -981,7 +981,7 @@ CL_ParseStatic (void)
|
||||||
ent->skinnum = es.skinnum;
|
ent->skinnum = es.skinnum;
|
||||||
|
|
||||||
VectorCopy (es.origin, ent->origin);
|
VectorCopy (es.origin, ent->origin);
|
||||||
VectorCopy (es.angles, ent->angles);
|
CL_TransformEntity (ent, es.angles, true);
|
||||||
|
|
||||||
R_AddEfrags (ent);
|
R_AddEfrags (ent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,8 @@ typedef struct {
|
||||||
int seed;
|
int seed;
|
||||||
} beam_t;
|
} beam_t;
|
||||||
|
|
||||||
|
#define BEAM_SEED_INTERVAL 72
|
||||||
|
#define BEAM_SEED_PRIME 3191
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float start;
|
float start;
|
||||||
|
@ -244,12 +246,13 @@ beam_clear (beam_t *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
beam_setup (beam_t *b)
|
beam_setup (beam_t *b, qboolean transform)
|
||||||
{
|
{
|
||||||
tent_t *tent;
|
tent_t *tent;
|
||||||
float forward, pitch, yaw, d;
|
float forward, pitch, yaw, d;
|
||||||
int ent_count;
|
int ent_count;
|
||||||
vec3_t dist, org;
|
vec3_t dist, org, ang;
|
||||||
|
unsigned seed;
|
||||||
|
|
||||||
// calculate pitch and yaw
|
// calculate pitch and yaw
|
||||||
VectorSubtract (b->end, b->start, dist);
|
VectorSubtract (b->end, b->start, dist);
|
||||||
|
@ -277,6 +280,10 @@ beam_setup (beam_t *b)
|
||||||
VectorScale (dist, 30, dist);
|
VectorScale (dist, 30, dist);
|
||||||
ent_count = ceil (d / 30);
|
ent_count = ceil (d / 30);
|
||||||
d = 0;
|
d = 0;
|
||||||
|
|
||||||
|
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||||
|
BEAM_SEED_INTERVAL);
|
||||||
|
|
||||||
while (ent_count--) {
|
while (ent_count--) {
|
||||||
tent = new_temp_entity ();
|
tent = new_temp_entity ();
|
||||||
tent->next = b->tents;
|
tent->next = b->tents;
|
||||||
|
@ -285,8 +292,13 @@ beam_setup (beam_t *b)
|
||||||
VectorMultAdd (org, d, dist, tent->ent.origin);
|
VectorMultAdd (org, d, dist, tent->ent.origin);
|
||||||
d += 1.0;
|
d += 1.0;
|
||||||
tent->ent.model = b->model;
|
tent->ent.model = b->model;
|
||||||
tent->ent.angles[0] = pitch;
|
ang[PITCH] = pitch;
|
||||||
tent->ent.angles[1] = yaw;
|
ang[YAW] = yaw;
|
||||||
|
if (transform) {
|
||||||
|
seed = seed * BEAM_SEED_PRIME;
|
||||||
|
ang[ROLL] = seed % 360;
|
||||||
|
CL_TransformEntity (&tent->ent, ang, true);
|
||||||
|
}
|
||||||
R_AddEfrags (&tent->ent);
|
R_AddEfrags (&tent->ent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,7 +331,7 @@ CL_ParseBeam (model_t *m)
|
||||||
if (b->entity != cl.viewentity) {
|
if (b->entity != cl.viewentity) {
|
||||||
// this will be done in CL_UpdateBeams
|
// this will be done in CL_UpdateBeams
|
||||||
VectorCopy (start, b->start);
|
VectorCopy (start, b->start);
|
||||||
beam_setup (b);
|
beam_setup (b, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +426,7 @@ CL_ParseTEnt (void)
|
||||||
if (!cl_spr_explod->cache.data)
|
if (!cl_spr_explod->cache.data)
|
||||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||||
ex->tent->ent.model = cl_spr_explod;
|
ex->tent->ent.model = cl_spr_explod;
|
||||||
|
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TE_TAREXPLOSION: // tarbaby explosion
|
case TE_TAREXPLOSION: // tarbaby explosion
|
||||||
|
@ -502,9 +515,6 @@ CL_ParseTEnt (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BEAM_SEED_INTERVAL 72
|
|
||||||
#define BEAM_SEED_PRIME 3191
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CL_UpdateBeams (void)
|
CL_UpdateBeams (void)
|
||||||
{
|
{
|
||||||
|
@ -534,7 +544,7 @@ CL_UpdateBeams (void)
|
||||||
if (b->entity == cl.viewentity) {
|
if (b->entity == cl.viewentity) {
|
||||||
beam_clear (b);
|
beam_clear (b);
|
||||||
VectorCopy (cl.simorg, b->start);
|
VectorCopy (cl.simorg, b->start);
|
||||||
beam_setup (b);
|
beam_setup (b, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||||
|
@ -543,7 +553,8 @@ CL_UpdateBeams (void)
|
||||||
// add new entities for the lightning
|
// add new entities for the lightning
|
||||||
for (t = b->tents; t; t = t->next) {
|
for (t = b->tents; t; t = t->next) {
|
||||||
seed = seed * BEAM_SEED_PRIME;
|
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[0] = (bits[4] >> 4) * (360.0 / 16.0);
|
||||||
pr->angles[1] = bits[5] * (360.0 / 256.0);
|
pr->angles[1] = bits[5] * (360.0 / 256.0);
|
||||||
pr->angles[2] = 0;
|
pr->angles[2] = 0;
|
||||||
|
CL_TransformEntity (&tent->ent, tent->ent.angles, true);
|
||||||
|
|
||||||
R_AddEfrags (&tent->ent);
|
R_AddEfrags (&tent->ent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
||||||
|
|
||||||
#include "qw/bothdefs.h"
|
#include "qw/bothdefs.h"
|
||||||
#include "cl_cam.h"
|
#include "cl_cam.h"
|
||||||
|
#include "cl_ents.h"
|
||||||
#include "cl_main.h"
|
#include "cl_main.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
@ -693,6 +694,7 @@ V_CalcRefdef (void)
|
||||||
|
|
||||||
if (cl.chase && chase_active->int_val)
|
if (cl.chase && chase_active->int_val)
|
||||||
Chase_Update ();
|
Chase_Update ();
|
||||||
|
CL_TransformEntity (view, view->angles, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue