mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 10:21:21 +00:00
[renderer] Merge sprite billboarding code
As the sw renderer's implementation was the closest to id's, it was used as the model (thus a fair bit of cleanup is still needed). This fixes some incorrect implementations in glsl and gl.
This commit is contained in:
parent
8c5c39cbe4
commit
3a17e062da
7 changed files with 178 additions and 279 deletions
|
@ -93,4 +93,7 @@ void R_MarkLeaves (void);
|
|||
void GL_SetPalette (void *data, const byte *palette);
|
||||
void GLSL_SetPalette (void *data, const byte *palette);
|
||||
|
||||
int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec,
|
||||
vec3_t bbup, vec3_t bbright, vec3_t bbpn);
|
||||
|
||||
#endif//__r_internal_h
|
||||
|
|
|
@ -29,6 +29,7 @@ video_renderer_common_sources = \
|
|||
libs/video/renderer/font8x8.c \
|
||||
libs/video/renderer/noisetextures.c \
|
||||
libs/video/renderer/r_alias.c \
|
||||
libs/video/renderer/r_billboard.c \
|
||||
libs/video/renderer/r_bsp.c \
|
||||
libs/video/renderer/r_dyn_textures.c \
|
||||
libs/video/renderer/r_efrag.c \
|
||||
|
|
|
@ -105,24 +105,23 @@ static void
|
|||
R_DrawSpriteModel_f (entity_t *e)
|
||||
{
|
||||
float modelalpha, color[4];
|
||||
vec4f_t up = {}, right = {};
|
||||
vec4f_t cameravec = {};
|
||||
vec4f_t up = {}, right = {}, pn = {};
|
||||
vec4f_t origin, point;
|
||||
msprite_t *psprite;
|
||||
msprite_t *sprite = e->renderer.model->cache.data;
|
||||
mspriteframe_t *frame;
|
||||
|
||||
origin = Transform_GetWorldPosition (e->transform);
|
||||
VectorCopy (r_origin, cameravec);
|
||||
cameravec -= origin;
|
||||
|
||||
// don't bother culling, it's just a single polygon without a surface cache
|
||||
frame = R_GetSpriteFrame (e);
|
||||
psprite = e->renderer.model->cache.data;
|
||||
|
||||
if (psprite->type == SPR_ORIENTED) { // bullet marks on walls
|
||||
up = Transform_Up (e->transform);
|
||||
right = Transform_Right (e->transform);
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||
up = (vec4f_t) { 0, 0, 1, 0 };
|
||||
VectorCopy (vright, right);
|
||||
} else { // normal sprite
|
||||
VectorCopy (vup, up);
|
||||
VectorCopy (vright, right);
|
||||
if (!R_BillboardFrame (e, sprite->type, &cameravec[0],
|
||||
&up[0], &right[0], &pn[0])) {
|
||||
// the orientation is undefined so can't draw the sprite
|
||||
return;
|
||||
}
|
||||
|
||||
VectorCopy (e->renderer.colormod, color);
|
||||
|
@ -136,7 +135,6 @@ R_DrawSpriteModel_f (entity_t *e)
|
|||
|
||||
qfglColor4fv (color);
|
||||
|
||||
origin = Transform_GetWorldPosition (e->transform);
|
||||
point = origin + frame->down * up + frame->left * right;
|
||||
|
||||
qfglTexCoord2f (0, 1);
|
||||
|
|
|
@ -214,9 +214,9 @@ glsl_R_DrawSprite (entity_t *ent)
|
|||
{
|
||||
msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data;
|
||||
mspriteframe_t *frame1, *frame2;
|
||||
float blend, sr, cr, dot;
|
||||
vec3_t tvec;
|
||||
vec4f_t svpn = {}, svright = {}, svup = {}, rot;
|
||||
float blend;
|
||||
vec4f_t cameravec = {};
|
||||
vec4f_t svpn = {}, svright = {}, svup = {};
|
||||
static quat_t color = { 1, 1, 1, 1};
|
||||
float vertsa[6][3], vertsb[6][3];
|
||||
static float uvab[6][4] = {
|
||||
|
@ -228,76 +228,14 @@ glsl_R_DrawSprite (entity_t *ent)
|
|||
{ 0, 1, 0, 1 },
|
||||
};
|
||||
|
||||
switch (sprite->type) {
|
||||
case SPR_FACING_UPRIGHT:
|
||||
// generate the sprite's exes with svup straight up in worldspace
|
||||
// and svright perpendicular to r_origin. This will not work if the
|
||||
// view direction is very close to straight up or down because the
|
||||
// cross product will be between two nearly parallel vectors and
|
||||
// starts to approach an undefined staate, so we don't draw if the
|
||||
// two vectors are less than 1 degree apart
|
||||
VectorNegate (r_origin, tvec);
|
||||
VectorNormalize (tvec);
|
||||
dot = tvec[2]; // same as DotProcut (tvec, svup) because
|
||||
// svup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.99848)) // cos (1 degree)
|
||||
return;
|
||||
VectorSet (0, 0, 1, svup);
|
||||
// CrossProduct (svup, -r_origin, svright)
|
||||
VectorSet (tvec[1], -tvec[0], 0, svright);
|
||||
svright = normalf (svright);
|
||||
// CrossProduct (svright, svup, svpn);
|
||||
VectorSet (-svright[1], svright[0], 0, svpn);
|
||||
break;
|
||||
case SPR_VP_PARALLEL:
|
||||
// generate the prite's axes completely parallel to the viewplane.
|
||||
// There are no problem situations, because the prite is always in
|
||||
// the same position relative to the viewer.
|
||||
VectorCopy (vup, svup);
|
||||
VectorCopy (vright, svright);
|
||||
VectorCopy (vpn, svpn);
|
||||
break;
|
||||
case SPR_VP_PARALLEL_UPRIGHT:
|
||||
// generate the sprite's axes with svup straight up in worldspace,
|
||||
// and svright parallel to the viewplane. This will not work if the
|
||||
// view diretion iss very close to straight up or down because the
|
||||
// cross prodcut will be between two nearly parallel vectors and
|
||||
// starts to approach an undefined state, so we don't draw if the
|
||||
// two vectros are less that 1 degree apart
|
||||
dot = vpn[2];
|
||||
if ((dot > 0.999848) || (dot < -0.99848)) // cos (1 degree)
|
||||
return;
|
||||
VectorSet (0, 0, 1, svup);
|
||||
// CrossProduct (svup, -r_origin, svright)
|
||||
VectorSet (vpn[1], -vpn[0], 0, svright);
|
||||
svright = normalf (svright);
|
||||
// CrossProduct (svright, svup, svpn);
|
||||
VectorSet (-svright[1], svright[0], 0, svpn);
|
||||
break;
|
||||
case SPR_ORIENTED:
|
||||
// generate the prite's axes according to the sprite's world
|
||||
// orientation
|
||||
svup = Transform_Up (ent->transform);
|
||||
svright = Transform_Right (ent->transform);
|
||||
svpn = Transform_Forward (ent->transform);
|
||||
break;
|
||||
case SPR_VP_PARALLEL_ORIENTED:
|
||||
// generate the sprite's axes parallel to the viewplane, but
|
||||
// rotated in that plane round the center according to the sprite
|
||||
// entity's roll angle. Thus svpn stays the same, but svright and
|
||||
// svup rotate
|
||||
rot = Transform_GetLocalRotation (ent->transform);
|
||||
//FIXME assumes the entity is only rolled
|
||||
sr = 2 * rot[0] * rot[3];
|
||||
cr = rot[3] * rot[3] - rot[0] * rot[0];
|
||||
VectorCopy (vpn, svpn);
|
||||
VectorScale (vright, cr, svright);
|
||||
VectorMultAdd (svright, sr, vup, svright);
|
||||
VectorScale (vup, cr, svup);
|
||||
VectorMultAdd (svup, -sr, vright, svup);
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("R_DrawSprite: Bad sprite type %d", sprite->type);
|
||||
vec4f_t origin = Transform_GetWorldPosition (ent->transform);
|
||||
VectorCopy (r_origin, cameravec);
|
||||
cameravec -= origin;
|
||||
|
||||
if (!R_BillboardFrame (ent, sprite->type, &cameravec[0],
|
||||
&svup[0], &svright[0], &svpn[0])) {
|
||||
// the orientation is undefined so can't draw the sprite
|
||||
return;
|
||||
}
|
||||
|
||||
R_GetSpriteFrames (ent, sprite, &frame1, &frame2, &blend);
|
||||
|
@ -312,7 +250,6 @@ glsl_R_DrawSprite (entity_t *ent)
|
|||
qfeglVertexAttrib4fv (quake_sprite.colorb.location, color);
|
||||
qfeglVertexAttrib1f (quake_sprite.blend.location, blend);
|
||||
|
||||
vec4f_t origin = Transform_GetWorldPosition (ent->transform);
|
||||
make_quad (frame1, origin, svpn, svright, svup, vertsa);
|
||||
make_quad (frame2, origin, svpn, svright, svup, vertsb);
|
||||
|
||||
|
|
134
libs/video/renderer/r_billboard.c
Normal file
134
libs/video/renderer/r_billboard.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
r_billboard.c
|
||||
|
||||
Billboard frame setup
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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 <string.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "QF/render.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
|
||||
|
||||
int
|
||||
R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec,
|
||||
vec3_t bbup, vec3_t bbright, vec3_t bbpn)
|
||||
{
|
||||
vec3_t tvec;
|
||||
float dot;
|
||||
|
||||
switch (orientation) {
|
||||
case SPR_FACING_UPRIGHT:
|
||||
// generate the sprite's axes, with vup straight up in worldspace,
|
||||
// and bbright perpendicular to cameravec. This will not work if
|
||||
// the camera origin is directly above the entity origin
|
||||
// (cameravec is straight up or down), because the cross product
|
||||
// will be between two nearly parallel vectors and starts to
|
||||
// approach an undefined state, so we don't draw if the two
|
||||
// vectors are less than 1 degree apart
|
||||
VectorNegate (cameravec, tvec);
|
||||
VectorNormalize (tvec);
|
||||
dot = tvec[2]; // same as DotProduct (tvec, bbup) because
|
||||
// bbup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree)
|
||||
return 0;
|
||||
VectorSet (0, 0, 1, bbup);
|
||||
//CrossProduct(bbup, -cameravec, bbright)
|
||||
VectorSet (tvec[1], -tvec[0], 0, bbright);
|
||||
VectorNormalize (bbright);
|
||||
//CrossProduct (bbright, bbup, bbpn)
|
||||
VectorSet (-bbright[1], bbright[0], 0, bbpn);
|
||||
break;
|
||||
case SPR_VP_PARALLEL:
|
||||
// generate the sprite's axes, completely parallel to the
|
||||
// viewplane. There are no problem situations, because the
|
||||
// sprite is always in the same orientation relative to the viewer
|
||||
VectorCopy (vup, bbup);
|
||||
VectorCopy (vright, bbright);
|
||||
VectorCopy (vpn, bbpn);
|
||||
break;
|
||||
case SPR_VP_PARALLEL_UPRIGHT:
|
||||
// generate the sprite's axes, with vup straight up in worldspace,
|
||||
// and bbright parallel to the viewplane.
|
||||
// This will not work if the view direction is very close to
|
||||
// straight up or down, because the cross product will be between
|
||||
// two nearly parallel vectors and starts to approach an undefined
|
||||
// state, so we don't draw if the two vectors are less than 1
|
||||
// degree apart
|
||||
dot = vpn[2]; // same as DotProduct (vpn, bbup) because
|
||||
// bbup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) =
|
||||
return 0;
|
||||
VectorSet (0, 0, 1, bbup);
|
||||
//CrossProduct(bbup, vpn, bbright)
|
||||
VectorSet (vpn[1], -vpn[0], 0, bbright);
|
||||
VectorNormalize (bbright);
|
||||
//CrossProduct (bbright, bbup, bbpn)
|
||||
VectorSet (-bbright[1], bbright[0], 0, bbpn);
|
||||
break;
|
||||
case SPR_ORIENTED:
|
||||
{
|
||||
// generate the sprite's axes, according to the sprite's world
|
||||
// orientation
|
||||
mat4f_t mat;
|
||||
Transform_GetWorldMatrix (ent->transform, mat);
|
||||
VectorCopy (mat[0], bbpn);
|
||||
VectorNegate (mat[1], bbright);
|
||||
VectorCopy (mat[2], bbup);
|
||||
}
|
||||
break;
|
||||
case 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 roll angle. So vpn stays the same, but
|
||||
// vright and vup rotate
|
||||
vec4f_t rot = Transform_GetLocalRotation (ent->transform);
|
||||
// FIXME needs proper testing (need to find, make, or fake a
|
||||
// parallel oriented sprite)
|
||||
rot = qmulf (r_refdef.viewrotation, rot);
|
||||
QuatMultVec (&rot[0], vpn, bbpn);
|
||||
QuatMultVec (&rot[0], vright, bbright);
|
||||
QuatMultVec (&rot[0], vup, bbup);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("R_BillboardFrame: Bad orientation %d", orientation);
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -284,109 +284,22 @@ R_GetSpriteframe (msprite_t *psprite)
|
|||
void
|
||||
R_DrawSprite (void)
|
||||
{
|
||||
int i;
|
||||
msprite_t *psprite;
|
||||
vec3_t tvec;
|
||||
float dot, sr, cr;
|
||||
msprite_t *sprite = currententity->renderer.model->cache.data;
|
||||
|
||||
psprite = currententity->renderer.model->cache.data;
|
||||
|
||||
r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);
|
||||
r_spritedesc.pspriteframe = R_GetSpriteframe (sprite);
|
||||
|
||||
sprite_width = r_spritedesc.pspriteframe->width;
|
||||
sprite_height = r_spritedesc.pspriteframe->height;
|
||||
|
||||
// TODO: make this caller-selectable
|
||||
if (psprite->type == SPR_FACING_UPRIGHT) {
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// r_spritedesc.vright perpendicular to modelorg.
|
||||
// This will not work if the view direction is very close to straight
|
||||
// up or down, because the cross product will be between two nearly
|
||||
// parallel vectors and starts to approach an undefined state, so we
|
||||
// don't draw if the two vectors are less than 1 degree apart
|
||||
tvec[0] = -modelorg[0];
|
||||
tvec[1] = -modelorg[1];
|
||||
tvec[2] = -modelorg[2];
|
||||
VectorNormalize (tvec);
|
||||
dot = tvec[2]; // same as DotProduct (tvec,
|
||||
// r_spritedesc.vup) because
|
||||
// r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) =
|
||||
// 0.999848
|
||||
return;
|
||||
r_spritedesc.vup[0] = 0;
|
||||
r_spritedesc.vup[1] = 0;
|
||||
r_spritedesc.vup[2] = 1;
|
||||
r_spritedesc.vright[0] = tvec[1];
|
||||
//CrossProduct(r_spritedesc.vup, -modelorg, r_spritedesc.vright)
|
||||
r_spritedesc.vright[1] = -tvec[0];
|
||||
r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (r_spritedesc.vright);
|
||||
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
|
||||
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
|
||||
r_spritedesc.vpn[2] = 0;
|
||||
//CrossProduct (r_spritedesc.vright, r_spritedesc.vup, r_spritedesc.vpn)
|
||||
} else if (psprite->type == SPR_VP_PARALLEL) {
|
||||
// generate the sprite's axes, completely parallel to the viewplane.
|
||||
// There are no problem situations, because the sprite is always in the
|
||||
// same position relative to the viewer
|
||||
for (i = 0; i < 3; i++) {
|
||||
r_spritedesc.vup[i] = vup[i];
|
||||
r_spritedesc.vright[i] = vright[i];
|
||||
r_spritedesc.vpn[i] = vpn[i];
|
||||
}
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// r_spritedesc.vright parallel to the viewplane.
|
||||
// This will not work if the view direction is very close to straight
|
||||
// up or down, because the cross product will be between two nearly
|
||||
// parallel vectors and starts to approach an undefined state, so we
|
||||
// don't draw if the two vectors are less than 1 degree apart
|
||||
dot = vpn[2]; // same as DotProduct (vpn,
|
||||
// r_spritedesc.vup) because
|
||||
// r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) =
|
||||
// 0.999848
|
||||
return;
|
||||
r_spritedesc.vup[0] = 0;
|
||||
r_spritedesc.vup[1] = 0;
|
||||
r_spritedesc.vup[2] = 1;
|
||||
r_spritedesc.vright[0] = vpn[1];
|
||||
//CrossProduct (r_spritedesc.vup, vpn,
|
||||
r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright)
|
||||
r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (r_spritedesc.vright);
|
||||
r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
|
||||
r_spritedesc.vpn[1] = r_spritedesc.vright[0];
|
||||
r_spritedesc.vpn[2] = 0;
|
||||
//CrossProduct (r_spritedesc.vright, r_spritedesc.vup, r_spritedesc.vpn)
|
||||
} else if (psprite->type == SPR_ORIENTED) {
|
||||
// generate the sprite's axes, according to the sprite's world
|
||||
// orientation
|
||||
mat4f_t mat;
|
||||
Transform_GetWorldMatrix (currententity->transform, mat);
|
||||
VectorCopy (mat[0], r_spritedesc.vpn);
|
||||
VectorNegate (mat[1], r_spritedesc.vright);
|
||||
VectorCopy (mat[2], 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
|
||||
// roll angle. So vpn stays the same, but vright and vup rotate
|
||||
vec4f_t rot = Transform_GetLocalRotation (currententity->transform);
|
||||
//FIXME assumes the entity is only rolled
|
||||
sr = 2 * rot[0] * rot[3];
|
||||
cr = rot[3] * rot[3] - rot[0] * rot[0];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
r_spritedesc.vpn[i] = vpn[i];
|
||||
r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
|
||||
r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
|
||||
}
|
||||
} else {
|
||||
Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
|
||||
if (!R_BillboardFrame (currententity, sprite->type, modelorg,
|
||||
r_spritedesc.vup,
|
||||
r_spritedesc.vright,
|
||||
r_spritedesc.vpn)) {
|
||||
// the orientation is undefined so can't draw the sprite
|
||||
return;
|
||||
}
|
||||
|
||||
R_RotateSprite (psprite->beamlength);
|
||||
R_RotateSprite (sprite->beamlength);
|
||||
|
||||
R_SetupAndDrawSprite ();
|
||||
}
|
||||
|
|
|
@ -280,109 +280,22 @@ R_GetSpriteframe (msprite_t *psprite)
|
|||
void
|
||||
sw32_R_DrawSprite (void)
|
||||
{
|
||||
int i;
|
||||
msprite_t *psprite;
|
||||
vec3_t tvec;
|
||||
float dot, sr, cr;
|
||||
msprite_t *sprite = currententity->renderer.model->cache.data;
|
||||
|
||||
psprite = currententity->renderer.model->cache.data;
|
||||
|
||||
sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);
|
||||
sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (sprite);
|
||||
|
||||
sprite_width = sw32_r_spritedesc.pspriteframe->width;
|
||||
sprite_height = sw32_r_spritedesc.pspriteframe->height;
|
||||
|
||||
// TODO: make this caller-selectable
|
||||
if (psprite->type == SPR_FACING_UPRIGHT) {
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// sw32_r_spritedesc.vright perpendicular to modelorg.
|
||||
// This will not work if the view direction is very close to straight
|
||||
// up or down, because the cross product will be between two nearly
|
||||
// parallel vectors and starts to approach an undefined state, so we
|
||||
// don't draw if the two vectors are less than 1 degree apart
|
||||
tvec[0] = -modelorg[0];
|
||||
tvec[1] = -modelorg[1];
|
||||
tvec[2] = -modelorg[2];
|
||||
VectorNormalize (tvec);
|
||||
dot = tvec[2]; // same as DotProduct (tvec,
|
||||
// sw32_r_spritedesc.vup) because
|
||||
// sw32_r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) =
|
||||
// 0.999848
|
||||
return;
|
||||
sw32_r_spritedesc.vup[0] = 0;
|
||||
sw32_r_spritedesc.vup[1] = 0;
|
||||
sw32_r_spritedesc.vup[2] = 1;
|
||||
sw32_r_spritedesc.vright[0] = tvec[1];
|
||||
//CrossProduct(sw32_r_spritedesc.vup, -modelorg, sw32_r_spritedesc.vright)
|
||||
sw32_r_spritedesc.vright[1] = -tvec[0];
|
||||
sw32_r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (sw32_r_spritedesc.vright);
|
||||
sw32_r_spritedesc.vpn[0] = -sw32_r_spritedesc.vright[1];
|
||||
sw32_r_spritedesc.vpn[1] = sw32_r_spritedesc.vright[0];
|
||||
sw32_r_spritedesc.vpn[2] = 0;
|
||||
//CrossProduct (sw32_r_spritedesc.vright, sw32_r_spritedesc.vup, sw32_r_spritedesc.vpn)
|
||||
} else if (psprite->type == SPR_VP_PARALLEL) {
|
||||
// generate the sprite's axes, completely parallel to the viewplane.
|
||||
// There are no problem situations, because the sprite is always in the
|
||||
// same position relative to the viewer
|
||||
for (i = 0; i < 3; i++) {
|
||||
sw32_r_spritedesc.vup[i] = vup[i];
|
||||
sw32_r_spritedesc.vright[i] = vright[i];
|
||||
sw32_r_spritedesc.vpn[i] = vpn[i];
|
||||
}
|
||||
} else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) {
|
||||
// generate the sprite's axes, with vup straight up in worldspace, and
|
||||
// sw32_r_spritedesc.vright parallel to the viewplane.
|
||||
// This will not work if the view direction is very close to straight
|
||||
// up or down, because the cross product will be between two nearly
|
||||
// parallel vectors and starts to approach an undefined state, so we
|
||||
// don't draw if the two vectors are less than 1 degree apart
|
||||
dot = vpn[2]; // same as DotProduct (vpn,
|
||||
// sw32_r_spritedesc.vup) because
|
||||
// sw32_r_spritedesc.vup is 0, 0, 1
|
||||
if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) =
|
||||
// 0.999848
|
||||
return;
|
||||
sw32_r_spritedesc.vup[0] = 0;
|
||||
sw32_r_spritedesc.vup[1] = 0;
|
||||
sw32_r_spritedesc.vup[2] = 1;
|
||||
sw32_r_spritedesc.vright[0] = vpn[1];
|
||||
//CrossProduct (sw32_r_spritedesc.vup, vpn,
|
||||
sw32_r_spritedesc.vright[1] = -vpn[0]; // sw32_r_spritedesc.vright)
|
||||
sw32_r_spritedesc.vright[2] = 0;
|
||||
VectorNormalize (sw32_r_spritedesc.vright);
|
||||
sw32_r_spritedesc.vpn[0] = -sw32_r_spritedesc.vright[1];
|
||||
sw32_r_spritedesc.vpn[1] = sw32_r_spritedesc.vright[0];
|
||||
sw32_r_spritedesc.vpn[2] = 0;
|
||||
//CrossProduct (sw32_r_spritedesc.vright, sw32_r_spritedesc.vup, sw32_r_spritedesc.vpn)
|
||||
} else if (psprite->type == SPR_ORIENTED) {
|
||||
// generate the sprite's axes, according to the sprite's world
|
||||
// orientation
|
||||
mat4f_t mat;
|
||||
Transform_GetWorldMatrix (currententity->transform, mat);
|
||||
VectorCopy (mat[0], r_spritedesc.vpn);
|
||||
VectorNegate (mat[1], r_spritedesc.vright);
|
||||
VectorCopy (mat[2], 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
|
||||
// roll angle. So vpn stays the same, but vright and vup rotate
|
||||
vec4f_t rot = Transform_GetLocalRotation (currententity->transform);
|
||||
//FIXME assumes the entity is only rolled
|
||||
sr = 2 * rot[0] * rot[3];
|
||||
cr = rot[3] * rot[3] - rot[0] * rot[0];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
sw32_r_spritedesc.vpn[i] = vpn[i];
|
||||
sw32_r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
|
||||
sw32_r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
|
||||
}
|
||||
} else {
|
||||
Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
|
||||
if (!R_BillboardFrame (currententity, sprite->type, modelorg,
|
||||
r_spritedesc.vup,
|
||||
r_spritedesc.vright,
|
||||
r_spritedesc.vpn)) {
|
||||
// the orientation is undefined so can't draw the sprite
|
||||
return;
|
||||
}
|
||||
|
||||
R_RotateSprite (psprite->beamlength);
|
||||
R_RotateSprite (sprite->beamlength);
|
||||
|
||||
R_SetupAndDrawSprite ();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue