spingle/source/r_alias.c

997 lines
30 KiB
C
Raw Normal View History

2019-11-24 20:45:15 -08:00
/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2010-2014 QuakeSpasm developers
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 the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//r_alias.c -- alias model rendering
2019-12-02 07:07:37 -08:00
#include "q_defs.h"
2019-11-24 20:45:15 -08:00
extern cvar_t r_drawflat, gl_overbright_models, gl_fullbrights, r_lerpmodels, r_lerpmove; //johnfitz
//up to 16 color translated skins
gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz -- changed to an array of pointers
2019-11-25 17:40:18 -08:00
#define NUMVERTEXNORMALS 162
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
float r_avertexnormals[NUMVERTEXNORMALS][3] =
2019-11-24 20:45:15 -08:00
{
#include "anorms.h"
};
2019-11-25 17:40:18 -08:00
extern vec3_t lightcolor; //johnfitz -- replaces "float shadelight" for lit support
2019-11-24 20:45:15 -08:00
// precalculated dot products for quantized angles
#define SHADEDOT_QUANT 16
2019-11-25 17:40:18 -08:00
float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
2019-11-24 20:45:15 -08:00
{
#include "anorm_dots.h"
};
2019-11-25 17:40:18 -08:00
extern vec3_t lightspot;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
float *shadedots = r_avertexnormal_dots[0];
vec3_t shadevector;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
float entalpha; //johnfitz
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
bool overbright; //johnfitz
2019-11-24 20:45:15 -08:00
2019-11-25 15:28:38 -08:00
bool shading = true; //johnfitz -- if false, disable vertex shading for various reasons (fullbright, r_lightmap, showtris, etc)
2019-11-24 20:45:15 -08:00
//johnfitz -- struct for passing lerp information to drawing functions
2019-11-25 17:40:18 -08:00
typedef struct
{
2019-11-25 14:15:33 -08:00
int16_t pose1;
int16_t pose2;
2019-11-24 20:45:15 -08:00
float blend;
vec3_t origin;
vec3_t angles;
} lerpdata_t;
//johnfitz
static GLuint r_alias_program;
// uniforms used in vert shader
static GLuint blendLoc;
static GLuint shadevectorLoc;
static GLuint lightColorLoc;
// uniforms used in frag shader
static GLuint texLoc;
static GLuint fullbrightTexLoc;
static GLuint useFullbrightTexLoc;
static GLuint useOverbrightLoc;
static GLuint useAlphaTestLoc;
#define pose1VertexAttrIndex 0
#define pose1NormalAttrIndex 1
#define pose2VertexAttrIndex 2
#define pose2NormalAttrIndex 3
#define texCoordsAttrIndex 4
/*
=============
GLARB_GetXYZOffset
Returns the offset of the first vertex's meshxyz_t.xyz in the vbo for the given
model and pose.
=============
*/
2019-11-25 17:40:18 -08:00
static void *GLARB_GetXYZOffset(aliashdr_t *hdr, int32_t pose)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
const int32_t xyzoffs = offsetof(meshxyz_t, xyz);
return (void *)(currententity->model->vboxyzofs + (hdr->numverts_vbo * pose * sizeof(meshxyz_t)) + xyzoffs);
2019-11-24 20:45:15 -08:00
}
/*
=============
GLARB_GetNormalOffset
Returns the offset of the first vertex's meshxyz_t.normal in the vbo for the
given model and pose.
=============
*/
2019-11-25 17:40:18 -08:00
static void *GLARB_GetNormalOffset(aliashdr_t *hdr, int32_t pose)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
const int32_t normaloffs = offsetof(meshxyz_t, normal);
return (void *)(currententity->model->vboxyzofs + (hdr->numverts_vbo * pose * sizeof(meshxyz_t)) + normaloffs);
2019-11-24 20:45:15 -08:00
}
/*
=============
GLAlias_CreateShaders
=============
*/
2019-11-25 17:40:18 -08:00
void GLAlias_CreateShaders(void)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
const glsl_attrib_binding_t bindings[] =
{
2019-11-24 20:45:15 -08:00
{ "TexCoords", texCoordsAttrIndex },
{ "Pose1Vert", pose1VertexAttrIndex },
{ "Pose1Normal", pose1NormalAttrIndex },
{ "Pose2Vert", pose2VertexAttrIndex },
{ "Pose2Normal", pose2NormalAttrIndex }
};
const GLchar *vertSource = \
2019-11-25 17:40:18 -08:00
"#version 110\n"
"\n"
"uniform float Blend;\n"
"uniform vec3 ShadeVector;\n"
"uniform vec4 LightColor;\n"
"attribute vec4 TexCoords; // only xy are used \n"
"attribute vec4 Pose1Vert;\n"
"attribute vec3 Pose1Normal;\n"
"attribute vec4 Pose2Vert;\n"
"attribute vec3 Pose2Normal;\n"
"\n"
"varying float FogFragCoord;\n"
"\n"
"float r_avertexnormal_dot(vec3 vertexnormal) // from MH \n"
"{\n"
" float dot = dot(vertexnormal, ShadeVector);\n"
" // wtf - this reproduces anorm_dots within as reasonable a degree of tolerance as the >= 0 case\n"
" if (dot < 0.0)\n"
" return 1.0 + dot * (13.0 / 44.0);\n"
" else\n"
" return 1.0 + dot;\n"
"}\n"
"void main()\n"
"{\n"
" gl_TexCoord[0] = TexCoords;\n"
" vec4 lerpedVert = mix(vec4(Pose1Vert.xyz, 1.0), vec4(Pose2Vert.xyz, 1.0), Blend);\n"
" gl_Position = gl_ModelViewProjectionMatrix * lerpedVert;\n"
" FogFragCoord = gl_Position.w;\n"
" float dot1 = r_avertexnormal_dot(Pose1Normal);\n"
" float dot2 = r_avertexnormal_dot(Pose2Normal);\n"
" gl_FrontColor = LightColor * vec4(vec3(mix(dot1, dot2, Blend)), 1.0);\n"
"}\n";
2019-11-24 20:45:15 -08:00
const GLchar *fragSource = \
2019-11-25 17:40:18 -08:00
"#version 110\n"
"\n"
"uniform sampler2D Tex;\n"
"uniform sampler2D FullbrightTex;\n"
"uniform bool UseFullbrightTex;\n"
"uniform bool UseOverbright;\n"
"uniform bool UseAlphaTest;\n"
"\n"
"varying float FogFragCoord;\n"
"\n"
"void main()\n"
"{\n"
" vec4 result = texture2D(Tex, gl_TexCoord[0].xy);\n"
" if (UseAlphaTest && (result.a < 0.666))\n"
" discard;\n"
" result *= gl_Color;\n"
" if (UseOverbright)\n"
" result.rgb *= 2.0;\n"
" if (UseFullbrightTex)\n"
" result += texture2D(FullbrightTex, gl_TexCoord[0].xy);\n"
" result = clamp(result, 0.0, 1.0);\n"
" float fog = exp(-gl_Fog.density * gl_Fog.density * FogFragCoord * FogFragCoord);\n"
" fog = clamp(fog, 0.0, 1.0);\n"
" result = mix(gl_Fog.color, result, fog);\n"
" result.a = gl_Color.a;\n" // FIXME: This will make almost transparent things cut holes though heavy fog
" gl_FragColor = result;\n"
"}\n";
if(!gl_glsl_alias_able)
2019-11-24 20:45:15 -08:00
return;
r_alias_program = GL_CreateProgram(vertSource, fragSource, arraysizeof(bindings), bindings);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(r_alias_program != 0)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
// get uniform locations
blendLoc = GL_GetUniformLocation(&r_alias_program, "Blend");
shadevectorLoc = GL_GetUniformLocation(&r_alias_program, "ShadeVector");
lightColorLoc = GL_GetUniformLocation(&r_alias_program, "LightColor");
texLoc = GL_GetUniformLocation(&r_alias_program, "Tex");
fullbrightTexLoc = GL_GetUniformLocation(&r_alias_program, "FullbrightTex");
useFullbrightTexLoc = GL_GetUniformLocation(&r_alias_program, "UseFullbrightTex");
useOverbrightLoc = GL_GetUniformLocation(&r_alias_program, "UseOverbright");
useAlphaTestLoc = GL_GetUniformLocation(&r_alias_program, "UseAlphaTest");
2019-11-24 20:45:15 -08:00
}
}
/*
=============
GL_DrawAliasFrame_GLSL -- ericw
Optimized alias model drawing codepath.
Compared to the original GL_DrawAliasFrame, this makes 1 draw call,
no vertex data is uploaded (it's already in the r_meshvbo and r_meshindexesvbo
static VBOs), and lerping and lighting is done in the vertex shader.
Supports optional overbright, optional fullbright pixels.
Based on code by MH from RMQEngine
=============
*/
2019-11-25 17:40:18 -08:00
void GL_DrawAliasFrame_GLSL(aliashdr_t *paliashdr, lerpdata_t lerpdata, gltexture_t *tx, gltexture_t *fb)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float blend;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(lerpdata.pose1 != lerpdata.pose2)
2019-11-24 20:45:15 -08:00
{
blend = lerpdata.blend;
}
else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled
{
blend = 0;
}
2019-11-25 17:40:18 -08:00
GL_UseProgramFunc(r_alias_program);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
GL_BindBuffer(GL_ARRAY_BUFFER, currententity->model->meshvbo);
GL_BindBuffer(GL_ELEMENT_ARRAY_BUFFER, currententity->model->meshindexesvbo);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
GL_EnableVertexAttribArrayFunc(texCoordsAttrIndex);
GL_EnableVertexAttribArrayFunc(pose1VertexAttrIndex);
GL_EnableVertexAttribArrayFunc(pose2VertexAttrIndex);
GL_EnableVertexAttribArrayFunc(pose1NormalAttrIndex);
GL_EnableVertexAttribArrayFunc(pose2NormalAttrIndex);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
GL_VertexAttribPointerFunc(texCoordsAttrIndex, 2, GL_FLOAT, GL_FALSE, 0, (void *)(intptr_t)currententity->model->vbostofs);
GL_VertexAttribPointerFunc(pose1VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(meshxyz_t), GLARB_GetXYZOffset(paliashdr, lerpdata.pose1));
GL_VertexAttribPointerFunc(pose2VertexAttrIndex, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(meshxyz_t), GLARB_GetXYZOffset(paliashdr, lerpdata.pose2));
2019-11-24 20:45:15 -08:00
// GL_TRUE to normalize the signed bytes to [-1 .. 1]
2019-11-25 17:40:18 -08:00
GL_VertexAttribPointerFunc(pose1NormalAttrIndex, 4, GL_BYTE, GL_TRUE, sizeof(meshxyz_t), GLARB_GetNormalOffset(paliashdr, lerpdata.pose1));
GL_VertexAttribPointerFunc(pose2NormalAttrIndex, 4, GL_BYTE, GL_TRUE, sizeof(meshxyz_t), GLARB_GetNormalOffset(paliashdr, lerpdata.pose2));
2019-11-24 20:45:15 -08:00
// set uniforms
2019-11-25 17:40:18 -08:00
GL_Uniform1fFunc(blendLoc, blend);
GL_Uniform3fFunc(shadevectorLoc, shadevector[0], shadevector[1], shadevector[2]);
GL_Uniform4fFunc(lightColorLoc, lightcolor[0], lightcolor[1], lightcolor[2], entalpha);
GL_Uniform1iFunc(texLoc, 0);
GL_Uniform1iFunc(fullbrightTexLoc, 1);
GL_Uniform1iFunc(useFullbrightTexLoc, (fb != NULL) ? 1 : 0);
GL_Uniform1fFunc(useOverbrightLoc, overbright ? 1 : 0);
GL_Uniform1iFunc(useAlphaTestLoc, (currententity->model->flags & MF_HOLEY) ? 1 : 0);
2019-11-24 20:45:15 -08:00
// set textures
2019-11-25 17:40:18 -08:00
GL_SelectTexture(GL_TEXTURE0);
GL_Bind(tx);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(fb)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
GL_SelectTexture(GL_TEXTURE1);
GL_Bind(fb);
2019-11-24 20:45:15 -08:00
}
// draw
2019-11-25 17:40:18 -08:00
glDrawElements(GL_TRIANGLES, paliashdr->numindexes, GL_UNSIGNED_SHORT, (void *)(intptr_t)currententity->model->vboindexofs);
2019-11-24 20:45:15 -08:00
// clean up
2019-11-25 17:40:18 -08:00
GL_DisableVertexAttribArrayFunc(texCoordsAttrIndex);
GL_DisableVertexAttribArrayFunc(pose1VertexAttrIndex);
GL_DisableVertexAttribArrayFunc(pose2VertexAttrIndex);
GL_DisableVertexAttribArrayFunc(pose1NormalAttrIndex);
GL_DisableVertexAttribArrayFunc(pose2NormalAttrIndex);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
GL_UseProgramFunc(0);
GL_SelectTexture(GL_TEXTURE0);
2019-11-24 20:45:15 -08:00
rs_aliaspasses += paliashdr->numtris;
}
/*
=============
GL_DrawAliasFrame -- johnfitz -- rewritten to support colored light, lerping, entalpha, multitexture, and r_drawflat
=============
*/
2019-11-25 17:40:18 -08:00
void GL_DrawAliasFrame(aliashdr_t *paliashdr, lerpdata_t lerpdata)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float vertcolor[4];
2019-11-24 20:45:15 -08:00
trivertx_t *verts1, *verts2;
2019-11-25 17:40:18 -08:00
int32_t *commands;
int32_t count;
float u, v;
float blend, iblend;
2019-11-25 15:28:38 -08:00
bool lerping;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(lerpdata.pose1 != lerpdata.pose2)
2019-11-24 20:45:15 -08:00
{
lerping = true;
verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
verts2 = verts1;
verts1 += lerpdata.pose1 * paliashdr->poseverts;
verts2 += lerpdata.pose2 * paliashdr->poseverts;
blend = lerpdata.blend;
iblend = 1.0f - blend;
}
else // poses the same means either 1. the entity has paused its animation, or 2. r_lerpmodels is disabled
{
lerping = false;
verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
verts2 = verts1; // avoid bogus compiler warning
verts1 += lerpdata.pose1 * paliashdr->poseverts;
blend = iblend = 0; // avoid bogus compiler warning
}
2019-11-25 16:49:58 -08:00
commands = (int32_t *)((byte *)paliashdr + paliashdr->commands);
2019-11-24 20:45:15 -08:00
vertcolor[3] = entalpha; //never changes, so there's no need to put this inside the loop
2019-11-25 17:40:18 -08:00
while(1)
2019-11-24 20:45:15 -08:00
{
// get the vertex count and primitive type
count = *commands++;
2019-11-25 17:40:18 -08:00
if(!count)
break; // done
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(count < 0)
2019-11-24 20:45:15 -08:00
{
count = -count;
2019-11-25 17:40:18 -08:00
glBegin(GL_TRIANGLE_FAN);
2019-11-24 20:45:15 -08:00
}
else
2019-11-25 17:40:18 -08:00
glBegin(GL_TRIANGLE_STRIP);
2019-11-24 20:45:15 -08:00
do
{
u = ((float *)commands)[0];
v = ((float *)commands)[1];
2019-11-25 17:40:18 -08:00
if(mtexenabled)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
GL_MTexCoord2fFunc(GL_TEXTURE0_ARB, u, v);
GL_MTexCoord2fFunc(GL_TEXTURE1_ARB, u, v);
2019-11-24 20:45:15 -08:00
}
else
2019-11-25 17:40:18 -08:00
glTexCoord2f(u, v);
2019-11-24 20:45:15 -08:00
commands += 2;
2019-11-25 17:40:18 -08:00
if(shading)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(r_drawflat_cheatsafe)
2019-11-24 20:45:15 -08:00
{
2019-11-25 14:05:12 -08:00
srand(count * (uint32_t)(src_offset_t)commands);
2019-11-25 17:40:18 -08:00
glColor3f(rand() % 256 / 255.0, rand() % 256 / 255.0, rand() % 256 / 255.0);
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
else if(lerping)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
vertcolor[0] = (shadedots[verts1->lightnormalindex] * iblend + shadedots[verts2->lightnormalindex] * blend) * lightcolor[0];
vertcolor[1] = (shadedots[verts1->lightnormalindex] * iblend + shadedots[verts2->lightnormalindex] * blend) * lightcolor[1];
vertcolor[2] = (shadedots[verts1->lightnormalindex] * iblend + shadedots[verts2->lightnormalindex] * blend) * lightcolor[2];
glColor4fv(vertcolor);
2019-11-24 20:45:15 -08:00
}
else
{
vertcolor[0] = shadedots[verts1->lightnormalindex] * lightcolor[0];
vertcolor[1] = shadedots[verts1->lightnormalindex] * lightcolor[1];
vertcolor[2] = shadedots[verts1->lightnormalindex] * lightcolor[2];
2019-11-25 17:40:18 -08:00
glColor4fv(vertcolor);
2019-11-24 20:45:15 -08:00
}
}
2019-11-25 17:40:18 -08:00
if(lerping)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glVertex3f(verts1->v[0]*iblend + verts2->v[0]*blend,
verts1->v[1]*iblend + verts2->v[1]*blend,
verts1->v[2]*iblend + verts2->v[2]*blend);
2019-11-24 20:45:15 -08:00
verts1++;
verts2++;
}
else
{
2019-11-25 17:40:18 -08:00
glVertex3f(verts1->v[0], verts1->v[1], verts1->v[2]);
2019-11-24 20:45:15 -08:00
verts1++;
}
2019-11-25 17:40:18 -08:00
}
while(--count);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glEnd();
2019-11-24 20:45:15 -08:00
}
rs_aliaspasses += paliashdr->numtris;
}
/*
=================
R_SetupAliasFrame -- johnfitz -- rewritten to support lerping
=================
*/
2019-11-25 17:40:18 -08:00
void R_SetupAliasFrame(aliashdr_t *paliashdr, int32_t frame, lerpdata_t *lerpdata)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
entity_t *e = currententity;
int32_t posenum, numposes;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if((frame >= paliashdr->numframes) || (frame < 0))
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
Con_DPrintf("R_AliasSetupFrame: no such frame %" PRIi32 " for '%s'\n", frame, e->model->name);
2019-11-24 20:45:15 -08:00
frame = 0;
}
posenum = paliashdr->frames[frame].firstpose;
numposes = paliashdr->frames[frame].numposes;
2019-11-25 17:40:18 -08:00
if(numposes > 1)
2019-11-24 20:45:15 -08:00
{
e->lerptime = paliashdr->frames[frame].interval;
2019-11-25 16:49:58 -08:00
posenum += (int32_t)(cl.time / e->lerptime) % numposes;
2019-11-24 20:45:15 -08:00
}
else
e->lerptime = 0.1;
2019-11-25 17:40:18 -08:00
if(e->lerpflags & LERP_RESETANIM) //kill any lerp in progress
2019-11-24 20:45:15 -08:00
{
e->lerpstart = 0;
e->previouspose = posenum;
e->currentpose = posenum;
e->lerpflags -= LERP_RESETANIM;
}
2019-11-25 17:40:18 -08:00
else if(e->currentpose != posenum) // pose changed, start new lerp
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(e->lerpflags & LERP_RESETANIM2) //defer lerping one more time
2019-11-24 20:45:15 -08:00
{
e->lerpstart = 0;
e->previouspose = posenum;
e->currentpose = posenum;
e->lerpflags -= LERP_RESETANIM2;
}
else
{
e->lerpstart = cl.time;
e->previouspose = e->currentpose;
e->currentpose = posenum;
}
}
//set up values
2019-11-25 17:40:18 -08:00
if(r_lerpmodels.value && !(e->model->flags & MOD_NOLERP && r_lerpmodels.value != 2))
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(e->lerpflags & LERP_FINISH && numposes == 1)
lerpdata->blend = CLAMP(0, (cl.time - e->lerpstart) / (e->lerpfinish - e->lerpstart), 1);
2019-11-24 20:45:15 -08:00
else
2019-11-25 17:40:18 -08:00
lerpdata->blend = CLAMP(0, (cl.time - e->lerpstart) / e->lerptime, 1);
2019-11-24 20:45:15 -08:00
lerpdata->pose1 = e->previouspose;
lerpdata->pose2 = e->currentpose;
}
else //don't lerp
{
lerpdata->blend = 1;
lerpdata->pose1 = posenum;
lerpdata->pose2 = posenum;
}
}
/*
=================
R_SetupEntityTransform -- johnfitz -- set up transform part of lerpdata
=================
*/
2019-11-25 17:40:18 -08:00
void R_SetupEntityTransform(entity_t *e, lerpdata_t *lerpdata)
2019-11-24 20:45:15 -08:00
{
float blend;
vec3_t d;
2019-11-25 16:49:58 -08:00
int32_t i;
2019-11-24 20:45:15 -08:00
// if LERP_RESETMOVE, kill any lerps in progress
2019-11-25 17:40:18 -08:00
if(e->lerpflags & LERP_RESETMOVE)
2019-11-24 20:45:15 -08:00
{
e->movelerpstart = 0;
2019-11-25 17:40:18 -08:00
VectorCopy(e->origin, e->previousorigin);
VectorCopy(e->origin, e->currentorigin);
VectorCopy(e->angles, e->previousangles);
VectorCopy(e->angles, e->currentangles);
2019-11-24 20:45:15 -08:00
e->lerpflags -= LERP_RESETMOVE;
}
2019-11-25 17:40:18 -08:00
else if(!VectorCompare(e->origin, e->currentorigin) || !VectorCompare(e->angles, e->currentangles)) // origin/angles changed, start new lerp
2019-11-24 20:45:15 -08:00
{
e->movelerpstart = cl.time;
2019-11-25 17:40:18 -08:00
VectorCopy(e->currentorigin, e->previousorigin);
VectorCopy(e->origin, e->currentorigin);
VectorCopy(e->currentangles, e->previousangles);
VectorCopy(e->angles, e->currentangles);
2019-11-24 20:45:15 -08:00
}
//set up values
2019-11-25 17:40:18 -08:00
if(r_lerpmove.value && e != &cl.viewent && e->lerpflags & LERP_MOVESTEP)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(e->lerpflags & LERP_FINISH)
blend = CLAMP(0, (cl.time - e->movelerpstart) / (e->lerpfinish - e->movelerpstart), 1);
2019-11-24 20:45:15 -08:00
else
2019-11-25 17:40:18 -08:00
blend = CLAMP(0, (cl.time - e->movelerpstart) / 0.1, 1);
2019-11-24 20:45:15 -08:00
//translation
2019-11-25 17:40:18 -08:00
VectorSubtract(e->currentorigin, e->previousorigin, d);
2019-11-24 20:45:15 -08:00
lerpdata->origin[0] = e->previousorigin[0] + d[0] * blend;
lerpdata->origin[1] = e->previousorigin[1] + d[1] * blend;
lerpdata->origin[2] = e->previousorigin[2] + d[2] * blend;
//rotation
2019-11-25 17:40:18 -08:00
VectorSubtract(e->currentangles, e->previousangles, d);
for(i = 0; i < 3; i++)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(d[i] > 180) d[i] -= 360;
if(d[i] < -180) d[i] += 360;
2019-11-24 20:45:15 -08:00
}
lerpdata->angles[0] = e->previousangles[0] + d[0] * blend;
lerpdata->angles[1] = e->previousangles[1] + d[1] * blend;
lerpdata->angles[2] = e->previousangles[2] + d[2] * blend;
}
else //don't lerp
{
2019-11-25 17:40:18 -08:00
VectorCopy(e->origin, lerpdata->origin);
VectorCopy(e->angles, lerpdata->angles);
2019-11-24 20:45:15 -08:00
}
}
/*
=================
R_SetupAliasLighting -- johnfitz -- broken out from R_DrawAliasModel and rewritten
=================
*/
2019-11-25 17:40:18 -08:00
void R_SetupAliasLighting(entity_t *e)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
vec3_t dist;
float add;
int32_t i;
int32_t quantizedangle;
float radiansangle;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
R_LightPoint(e->origin);
2019-11-24 20:45:15 -08:00
//add dlights
2019-11-25 19:00:40 -08:00
for(i = 0 ; i < cl_max_dlights ; i++)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(cl_dlights[i].die >= cl.time)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
VectorSubtract(currententity->origin, cl_dlights[i].origin, dist);
2019-11-24 20:45:15 -08:00
add = cl_dlights[i].radius - VectorLength(dist);
2019-11-25 17:40:18 -08:00
if(add > 0)
VectorMA(lightcolor, add, cl_dlights[i].color, lightcolor);
2019-11-24 20:45:15 -08:00
}
}
// minimum light value on gun (24)
2019-11-25 17:40:18 -08:00
if(e == &cl.viewent)
2019-11-24 20:45:15 -08:00
{
add = 72.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]);
2019-11-25 17:40:18 -08:00
if(add > 0.0f)
2019-11-24 20:45:15 -08:00
{
lightcolor[0] += add / 3.0f;
lightcolor[1] += add / 3.0f;
lightcolor[2] += add / 3.0f;
}
}
// minimum light value on players (8)
2019-11-25 17:40:18 -08:00
if(currententity > cl_entities && currententity <= cl_entities + cl.maxclients)
2019-11-24 20:45:15 -08:00
{
add = 24.0f - (lightcolor[0] + lightcolor[1] + lightcolor[2]);
2019-11-25 17:40:18 -08:00
if(add > 0.0f)
2019-11-24 20:45:15 -08:00
{
lightcolor[0] += add / 3.0f;
lightcolor[1] += add / 3.0f;
lightcolor[2] += add / 3.0f;
}
}
// clamp lighting so it doesn't overbright as much (96)
2019-11-25 17:40:18 -08:00
if(overbright)
2019-11-24 20:45:15 -08:00
{
add = 288.0f / (lightcolor[0] + lightcolor[1] + lightcolor[2]);
2019-11-25 17:40:18 -08:00
if(add < 1.0f)
2019-11-24 20:45:15 -08:00
VectorScale(lightcolor, add, lightcolor);
}
//hack up the brightness when fullbrights but no overbrights (256)
2019-11-25 17:40:18 -08:00
if(gl_fullbrights.value && !gl_overbright_models.value)
if(e->model->flags & MOD_FBRIGHTHACK)
2019-11-24 20:45:15 -08:00
{
lightcolor[0] = 256.0f;
lightcolor[1] = 256.0f;
lightcolor[2] = 256.0f;
}
2019-11-25 16:49:58 -08:00
quantizedangle = ((int32_t)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1);
2019-11-24 20:45:15 -08:00
//ericw -- shadevector is passed to the shader to compute shadedots inside the
//shader, see GLAlias_CreateShaders()
radiansangle = (quantizedangle / 16.0) * 2.0 * 3.14159;
shadevector[0] = cos(-radiansangle);
shadevector[1] = sin(-radiansangle);
shadevector[2] = 1;
VectorNormalize(shadevector);
//ericw --
shadedots = r_avertexnormal_dots[quantizedangle];
2019-11-25 17:40:18 -08:00
VectorScale(lightcolor, 1.0f / 200.0f, lightcolor);
2019-11-24 20:45:15 -08:00
}
/*
=================
R_DrawAliasModel -- johnfitz -- almost completely rewritten
=================
*/
2019-11-25 17:40:18 -08:00
void R_DrawAliasModel(entity_t *e)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
aliashdr_t *paliashdr;
int32_t i, anim, skinnum;
gltexture_t *tx, *fb;
lerpdata_t lerpdata;
bool alphatest = !!(e->model->flags & MF_HOLEY);
2019-11-24 20:45:15 -08:00
//
// setup pose/lerp data -- do it first so we don't miss updates due to culling
//
2019-11-25 17:40:18 -08:00
paliashdr = (aliashdr_t *)Mod_Extradata(e->model);
R_SetupAliasFrame(paliashdr, e->frame, &lerpdata);
R_SetupEntityTransform(e, &lerpdata);
2019-11-24 20:45:15 -08:00
//
// cull it
//
2019-11-25 17:40:18 -08:00
if(R_CullModelForEntity(e))
2019-11-24 20:45:15 -08:00
return;
//
// transform it
//
2019-11-25 17:40:18 -08:00
glPushMatrix();
R_RotateForEntity(lerpdata.origin, lerpdata.angles);
glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
2019-11-24 20:45:15 -08:00
//
// random stuff
//
2019-11-25 17:40:18 -08:00
if(gl_smoothmodels.value && !r_drawflat_cheatsafe)
glShadeModel(GL_SMOOTH);
if(gl_affinemodels.value)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
2019-11-24 20:45:15 -08:00
overbright = gl_overbright_models.value;
shading = true;
//
// set up for alpha blending
//
2019-11-25 17:40:18 -08:00
if(r_drawflat_cheatsafe || r_lightmap_cheatsafe) //no alpha in drawflat or lightmap mode
2019-11-24 20:45:15 -08:00
entalpha = 1;
else
entalpha = ENTALPHA_DECODE(e->alpha);
2019-11-25 17:40:18 -08:00
if(entalpha == 0)
2019-11-24 20:45:15 -08:00
goto cleanup;
2019-11-25 17:40:18 -08:00
if(entalpha < 1)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(!gl_texture_env_combine) overbright = false; //overbright can't be done in a single pass without combiners
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
}
2019-11-25 17:40:18 -08:00
else if(alphatest)
glEnable(GL_ALPHA_TEST);
2019-11-24 20:45:15 -08:00
//
// set up lighting
//
rs_aliaspolys += paliashdr->numtris;
2019-11-25 17:40:18 -08:00
R_SetupAliasLighting(e);
2019-11-24 20:45:15 -08:00
//
// set up textures
//
GL_DisableMultitexture();
2019-11-25 17:40:18 -08:00
anim = (int32_t)(cl.time * 10) & 3;
2019-11-24 20:45:15 -08:00
skinnum = e->skinnum;
2019-11-25 17:40:18 -08:00
if((skinnum >= paliashdr->numskins) || (skinnum < 0))
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
Con_DPrintf("R_DrawAliasModel: no such skin # %" PRIi32 " for '%s'\n", skinnum, e->model->name);
2019-11-24 20:45:15 -08:00
// ericw -- display skin 0 for winquake compatibility
skinnum = 0;
}
tx = paliashdr->gltextures[skinnum][anim];
fb = paliashdr->fbtextures[skinnum][anim];
2019-11-25 17:40:18 -08:00
if(e->colormap != vid.colormap && !gl_nocolors.value)
2019-11-24 20:45:15 -08:00
{
i = e - cl_entities;
2019-11-25 17:40:18 -08:00
if(i >= 1 && i <= cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
tx = playertextures[i - 1];
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
if(!gl_fullbrights.value)
2019-11-24 20:45:15 -08:00
fb = NULL;
//
// draw it
//
2019-11-25 17:40:18 -08:00
if(r_drawflat_cheatsafe)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glDisable(GL_TEXTURE_2D);
GL_DrawAliasFrame(paliashdr, lerpdata);
glEnable(GL_TEXTURE_2D);
srand((int32_t)(cl.time * 1000)); //restore randomness
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
else if(r_fullbright_cheatsafe)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
GL_Bind(tx);
2019-11-24 20:45:15 -08:00
shading = false;
2019-11-25 17:40:18 -08:00
glColor4f(1, 1, 1, entalpha);
GL_DrawAliasFrame(paliashdr, lerpdata);
if(fb)
2019-11-24 20:45:15 -08:00
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_ONE, GL_ONE);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
2019-11-25 17:40:18 -08:00
glColor3f(entalpha, entalpha, entalpha);
Fog_StartAdditive();
GL_DrawAliasFrame(paliashdr, lerpdata);
Fog_StopAdditive();
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
}
}
2019-11-25 17:40:18 -08:00
else if(r_lightmap_cheatsafe)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
glDisable(GL_TEXTURE_2D);
2019-11-24 20:45:15 -08:00
shading = false;
2019-11-25 17:40:18 -08:00
glColor3f(1, 1, 1);
GL_DrawAliasFrame(paliashdr, lerpdata);
glEnable(GL_TEXTURE_2D);
2019-11-24 20:45:15 -08:00
}
// call fast path if possible. if the shader compliation failed for some reason,
// r_alias_program will be 0.
2019-11-25 17:40:18 -08:00
else if(r_alias_program != 0)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame_GLSL(paliashdr, lerpdata, tx, fb);
2019-11-24 20:45:15 -08:00
}
2019-11-25 17:40:18 -08:00
else if(overbright)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
if(gl_texture_env_combine && gl_mtexable && gl_texture_env_add && fb) //case 1: everything in one pass
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
GL_Bind(tx);
2019-11-24 20:45:15 -08:00
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
GL_EnableMultitexture(); // selects TEXTURE1
2019-11-25 17:40:18 -08:00
GL_Bind(fb);
2019-11-24 20:45:15 -08:00
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame(paliashdr, lerpdata);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
GL_DisableMultitexture();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
2019-11-25 17:40:18 -08:00
else if(gl_texture_env_combine) //case 2: overbright in one pass, then fullbright pass
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
// first pass
2019-11-24 20:45:15 -08:00
GL_Bind(tx);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f);
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame(paliashdr, lerpdata);
2019-11-24 20:45:15 -08:00
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2019-11-25 17:40:18 -08:00
// second pass
if(fb)
2019-11-24 20:45:15 -08:00
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_ONE, GL_ONE);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
shading = false;
2019-11-25 17:40:18 -08:00
glColor3f(entalpha, entalpha, entalpha);
Fog_StartAdditive();
GL_DrawAliasFrame(paliashdr, lerpdata);
Fog_StopAdditive();
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
}
else //case 3: overbright in two passes, then fullbright pass
{
2019-11-25 17:40:18 -08:00
// first pass
2019-11-24 20:45:15 -08:00
GL_Bind(tx);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame(paliashdr, lerpdata);
// second pass -- additive with black fog, to double the object colors but not the fog color
2019-11-24 20:45:15 -08:00
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_ONE, GL_ONE);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
2019-11-25 17:40:18 -08:00
Fog_StartAdditive();
GL_DrawAliasFrame(paliashdr, lerpdata);
Fog_StopAdditive();
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
2019-11-25 17:40:18 -08:00
// third pass
if(fb)
2019-11-24 20:45:15 -08:00
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind(fb);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_ONE, GL_ONE);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
shading = false;
2019-11-25 17:40:18 -08:00
glColor3f(entalpha, entalpha, entalpha);
Fog_StartAdditive();
GL_DrawAliasFrame(paliashdr, lerpdata);
Fog_StopAdditive();
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
}
}
else
{
2019-11-25 17:40:18 -08:00
if(gl_mtexable && gl_texture_env_add && fb) //case 4: fullbright mask using multitexture
2019-11-24 20:45:15 -08:00
{
GL_DisableMultitexture(); // selects TEXTURE0
2019-11-25 17:40:18 -08:00
GL_Bind(tx);
2019-11-24 20:45:15 -08:00
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_EnableMultitexture(); // selects TEXTURE1
2019-11-25 17:40:18 -08:00
GL_Bind(fb);
2019-11-24 20:45:15 -08:00
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame(paliashdr, lerpdata);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
GL_DisableMultitexture();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
else //case 5: fullbright mask without multitexture
{
2019-11-25 17:40:18 -08:00
// first pass
2019-11-24 20:45:15 -08:00
GL_Bind(tx);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2019-11-25 17:40:18 -08:00
GL_DrawAliasFrame(paliashdr, lerpdata);
// second pass
if(fb)
2019-11-24 20:45:15 -08:00
{
GL_Bind(fb);
glEnable(GL_BLEND);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_ONE, GL_ONE);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_FALSE);
shading = false;
2019-11-25 17:40:18 -08:00
glColor3f(entalpha, entalpha, entalpha);
Fog_StartAdditive();
GL_DrawAliasFrame(paliashdr, lerpdata);
Fog_StopAdditive();
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
2019-11-25 17:40:18 -08:00
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019-11-24 20:45:15 -08:00
glDisable(GL_BLEND);
}
}
}
cleanup:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2019-11-25 17:40:18 -08:00
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_FLAT);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
2019-11-25 17:40:18 -08:00
if(alphatest)
glDisable(GL_ALPHA_TEST);
glColor3f(1, 1, 1);
glPopMatrix();
2019-11-24 20:45:15 -08:00
}
//johnfitz -- values for shadow matrix
#define SHADOW_SKEW_X -0.7 //skew along x axis. -0.7 to mimic glquake shadows
#define SHADOW_SKEW_Y 0 //skew along y axis. 0 to mimic glquake shadows
#define SHADOW_VSCALE 0 //0=completely flat
#define SHADOW_HEIGHT 0.1 //how far above the floor to render the shadow
//johnfitz
/*
=============
GL_DrawAliasShadow -- johnfitz -- rewritten
TODO: orient shadow onto "lightplane" (a global mplane_t*)
=============
*/
2019-11-25 17:40:18 -08:00
void GL_DrawAliasShadow(entity_t *e)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
float shadowmatrix[16] = {1, 0, 0, 0,
0, 1, 0, 0,
SHADOW_SKEW_X, SHADOW_SKEW_Y, SHADOW_VSCALE, 0,
0, 0, SHADOW_HEIGHT, 1
};
float lheight;
aliashdr_t *paliashdr;
lerpdata_t lerpdata;
if(R_CullModelForEntity(e))
2019-11-24 20:45:15 -08:00
return;
2019-11-25 17:40:18 -08:00
if(e == &cl.viewent || e->model->flags & MOD_NOSHADOW)
2019-11-24 20:45:15 -08:00
return;
entalpha = ENTALPHA_DECODE(e->alpha);
2019-11-25 17:40:18 -08:00
if(entalpha == 0) return;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
paliashdr = (aliashdr_t *)Mod_Extradata(e->model);
R_SetupAliasFrame(paliashdr, e->frame, &lerpdata);
R_SetupEntityTransform(e, &lerpdata);
R_LightPoint(e->origin);
2019-11-24 20:45:15 -08:00
lheight = currententity->origin[2] - lightspot[2];
// set up matrix
2019-11-25 17:40:18 -08:00
glPushMatrix();
glTranslatef(lerpdata.origin[0], lerpdata.origin[1], lerpdata.origin[2]);
glTranslatef(0, 0, -lheight);
glMultMatrixf(shadowmatrix);
glTranslatef(0, 0, lheight);
glRotatef(lerpdata.angles[1], 0, 0, 1);
glRotatef(-lerpdata.angles[0], 0, 1, 0);
glRotatef(lerpdata.angles[2], 1, 0, 0);
glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
2019-11-24 20:45:15 -08:00
// draw it
glDepthMask(GL_FALSE);
2019-11-25 17:40:18 -08:00
glEnable(GL_BLEND);
GL_DisableMultitexture();
glDisable(GL_TEXTURE_2D);
2019-11-24 20:45:15 -08:00
shading = false;
2019-11-25 17:40:18 -08:00
glColor4f(0, 0, 0, entalpha * 0.5);
GL_DrawAliasFrame(paliashdr, lerpdata);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
2019-11-24 20:45:15 -08:00
glDepthMask(GL_TRUE);
//clean up
2019-11-25 17:40:18 -08:00
glPopMatrix();
2019-11-24 20:45:15 -08:00
}
/*
=================
R_DrawAliasModel_ShowTris -- johnfitz
=================
*/
2019-11-25 17:40:18 -08:00
void R_DrawAliasModel_ShowTris(entity_t *e)
2019-11-24 20:45:15 -08:00
{
2019-11-25 17:40:18 -08:00
aliashdr_t *paliashdr;
lerpdata_t lerpdata;
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
if(R_CullModelForEntity(e))
2019-11-24 20:45:15 -08:00
return;
2019-11-25 17:40:18 -08:00
paliashdr = (aliashdr_t *)Mod_Extradata(e->model);
R_SetupAliasFrame(paliashdr, e->frame, &lerpdata);
R_SetupEntityTransform(e, &lerpdata);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glPushMatrix();
R_RotateForEntity(lerpdata.origin, lerpdata.angles);
glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
2019-11-24 20:45:15 -08:00
shading = false;
2019-11-25 17:40:18 -08:00
glColor3f(1, 1, 1);
GL_DrawAliasFrame(paliashdr, lerpdata);
2019-11-24 20:45:15 -08:00
2019-11-25 17:40:18 -08:00
glPopMatrix();
2019-11-24 20:45:15 -08:00
}