Add support with several separate meshes for body parts
FM models has several meshes for different body parts, where command lsit has section with different length sum of which equal to total command count.
This commit is contained in:
parent
f6319f8bc0
commit
6079adae75
|
@ -311,7 +311,7 @@ R_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
|
|||
dlight_t *dl;
|
||||
vec3_t dist;
|
||||
|
||||
if (!r_worldmodel->lightdata || !currententity)
|
||||
if (!r_worldmodel || !r_worldmodel->lightdata || !currententity)
|
||||
{
|
||||
color[0] = color[1] = color[2] = 1.0;
|
||||
return;
|
||||
|
|
|
@ -80,26 +80,154 @@ R_LerpVerts(entity_t *currententity, int nverts, dtrivertx_t *v, dtrivertx_t *ov
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
R_DrawAliasDrawCommands(entity_t *currententity, int *order, int *order_end,
|
||||
float alpha, dtrivertx_t *verts)
|
||||
{
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
int maxCount = 0;
|
||||
const int* tmpOrder = order;
|
||||
while (1)
|
||||
{
|
||||
int c = *tmpOrder++;
|
||||
if (!c)
|
||||
break;
|
||||
if ( c < 0 )
|
||||
c = -c;
|
||||
if ( c > maxCount )
|
||||
maxCount = c;
|
||||
|
||||
tmpOrder += 3 * c;
|
||||
}
|
||||
|
||||
YQ2_VLA( GLfloat, vtx, 3 * maxCount );
|
||||
YQ2_VLA( GLfloat, tex, 2 * maxCount );
|
||||
YQ2_VLA( GLfloat, clr, 4 * maxCount );
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned short total;
|
||||
GLenum type;
|
||||
int count;
|
||||
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count || order >= order_end)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
count = -count;
|
||||
|
||||
type = GL_TRIANGLE_FAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
}
|
||||
|
||||
total = count;
|
||||
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
YQ2_VLA(GLfloat, tex, 2*total);
|
||||
YQ2_VLA(GLfloat, clr, 4*total);
|
||||
#endif
|
||||
|
||||
unsigned int index_vtx = 0;
|
||||
unsigned int index_tex = 0;
|
||||
unsigned int index_clr = 0;
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
|
||||
{
|
||||
do
|
||||
{
|
||||
int index_xyz;
|
||||
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
clr[index_clr++] = shadelight[0];
|
||||
clr[index_clr++] = shadelight[1];
|
||||
clr[index_clr++] = shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
int index_xyz;
|
||||
float l;
|
||||
|
||||
/* texture coordinates come from the draw list */
|
||||
tex[index_tex++] = ((float *) order)[0];
|
||||
tex[index_tex++] = ((float *) order)[1];
|
||||
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
/* normals and vertexes come from the frame list */
|
||||
l = shadedots[verts[index_xyz].lightnormalindex];
|
||||
|
||||
clr[index_clr++] = l * shadelight[0];
|
||||
clr[index_clr++] = l * shadelight[1];
|
||||
clr[index_clr++] = l * shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, vtx);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tex);
|
||||
glColorPointer(4, GL_FLOAT, 0, clr);
|
||||
glDrawArrays(type, 0, total);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
YQ2_VLAFREE( vtx );
|
||||
YQ2_VLAFREE( tex );
|
||||
YQ2_VLAFREE( clr );
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpolates between two frames and origins
|
||||
*/
|
||||
static void
|
||||
R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
||||
{
|
||||
unsigned short total;
|
||||
GLenum type;
|
||||
float l;
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
int *order;
|
||||
int count;
|
||||
float frontlerp;
|
||||
float alpha;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
int index_xyz;
|
||||
float *lerp;
|
||||
int num_mesh_nodes;
|
||||
short *mesh_nodes;
|
||||
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ currententity->frame * paliashdr->framesize);
|
||||
|
@ -154,121 +282,26 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
|||
|
||||
R_LerpVerts(currententity, paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
|
||||
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
int maxCount = 0;
|
||||
const int* tmpOrder = order;
|
||||
while (1)
|
||||
num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2;
|
||||
mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t));
|
||||
|
||||
if (num_mesh_nodes > 0)
|
||||
{
|
||||
int c = *tmpOrder++;
|
||||
if (!c)
|
||||
break;
|
||||
if ( c < 0 )
|
||||
c = -c;
|
||||
if ( c > maxCount )
|
||||
maxCount = c;
|
||||
|
||||
tmpOrder += 3 * c;
|
||||
}
|
||||
|
||||
YQ2_VLA( GLfloat, vtx, 3 * maxCount );
|
||||
YQ2_VLA( GLfloat, tex, 2 * maxCount );
|
||||
YQ2_VLA( GLfloat, clr, 4 * maxCount );
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
int i;
|
||||
for (i = 0; i < num_mesh_nodes; i++)
|
||||
{
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
count = -count;
|
||||
|
||||
type = GL_TRIANGLE_FAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
}
|
||||
|
||||
total = count;
|
||||
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
YQ2_VLA(GLfloat, tex, 2*total);
|
||||
YQ2_VLA(GLfloat, clr, 4*total);
|
||||
#endif
|
||||
unsigned int index_vtx = 0;
|
||||
unsigned int index_tex = 0;
|
||||
unsigned int index_clr = 0;
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
|
||||
{
|
||||
do
|
||||
{
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
clr[index_clr++] = shadelight[0];
|
||||
clr[index_clr++] = shadelight[1];
|
||||
clr[index_clr++] = shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
/* texture coordinates come from the draw list */
|
||||
tex[index_tex++] = ((float *) order)[0];
|
||||
tex[index_tex++] = ((float *) order)[1];
|
||||
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
||||
/* normals and vertexes come from the frame list */
|
||||
l = shadedots[verts[index_xyz].lightnormalindex];
|
||||
|
||||
clr[index_clr++] = l * shadelight[0];
|
||||
clr[index_clr++] = l * shadelight[1];
|
||||
clr[index_clr++] = l * shadelight[2];
|
||||
clr[index_clr++] = alpha;
|
||||
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][0];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][1];
|
||||
vtx[index_vtx++] = s_lerped[index_xyz][2];
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, vtx);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, tex);
|
||||
glColorPointer(4, GL_FLOAT, 0, clr);
|
||||
glDrawArrays(type, 0, total);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
R_DrawAliasDrawCommands(currententity,
|
||||
order + mesh_nodes[i * 2],
|
||||
order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]),
|
||||
alpha, verts);
|
||||
}
|
||||
|
||||
YQ2_VLAFREE( vtx );
|
||||
YQ2_VLAFREE( tex );
|
||||
YQ2_VLAFREE( clr )
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawAliasDrawCommands(currententity,
|
||||
order, order + paliashdr->num_glcmds,
|
||||
alpha, verts);
|
||||
}
|
||||
|
||||
if (currententity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE |
|
||||
|
@ -279,28 +312,15 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdl_t *paliashdr, float backlerp)
|
|||
}
|
||||
|
||||
static void
|
||||
R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
||||
R_DrawAliasShadowCommand(entity_t *currententity, int *order, int *order_end,
|
||||
float height, float lheight)
|
||||
{
|
||||
unsigned short total;
|
||||
GLenum type;
|
||||
int *order;
|
||||
unsigned short total;
|
||||
vec3_t point;
|
||||
float height = 0, lheight;
|
||||
GLenum type;
|
||||
int count;
|
||||
|
||||
lheight = currententity->origin[2] - lightspot[2];
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
height = -lheight + 0.1f;
|
||||
|
||||
/* stencilbuffer shadows */
|
||||
if (gl_state.stencil && gl1_stencilshadow->value)
|
||||
{
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_EQUAL, 1, 2);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
#ifdef _MSC_VER // workaround for lack of VLAs (=> our workaround uses alloca() which is bad in loops)
|
||||
int maxCount = 0;
|
||||
const int* tmpOrder = order;
|
||||
while (1)
|
||||
|
@ -324,7 +344,7 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count)
|
||||
if (!count || order >= order_end)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
@ -333,19 +353,19 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
{
|
||||
count = -count;
|
||||
|
||||
type = GL_TRIANGLE_FAN;
|
||||
type = GL_TRIANGLE_FAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
type = GL_TRIANGLE_STRIP;
|
||||
}
|
||||
|
||||
total = count;
|
||||
total = count;
|
||||
|
||||
#ifndef _MSC_VER // we have real VLAs, so it's safe to use one in this loop
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
YQ2_VLA(GLfloat, vtx, 3*total);
|
||||
#endif
|
||||
unsigned int index_vtx = 0;
|
||||
unsigned int index_vtx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -356,22 +376,64 @@ R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
|||
point[1] -= shadevector[1] * (point[2] + lheight);
|
||||
point[2] = height;
|
||||
|
||||
vtx[index_vtx++] = point [ 0 ];
|
||||
vtx[index_vtx++] = point [ 1 ];
|
||||
vtx[index_vtx++] = point [ 2 ];
|
||||
vtx[index_vtx++] = point [ 0 ];
|
||||
vtx[index_vtx++] = point [ 1 ];
|
||||
vtx[index_vtx++] = point [ 2 ];
|
||||
|
||||
order += 3;
|
||||
}
|
||||
while (--count);
|
||||
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
glEnableClientState( GL_VERTEX_ARRAY );
|
||||
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vtx );
|
||||
glDrawArrays( type, 0, total );
|
||||
glVertexPointer( 3, GL_FLOAT, 0, vtx );
|
||||
glDrawArrays( type, 0, total );
|
||||
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
}
|
||||
YQ2_VLAFREE(vtx);
|
||||
}
|
||||
|
||||
static void
|
||||
R_DrawAliasShadow(entity_t *currententity, dmdl_t *paliashdr, int posenum)
|
||||
{
|
||||
int *order;
|
||||
float height = 0, lheight;
|
||||
int num_mesh_nodes;
|
||||
short *mesh_nodes;
|
||||
|
||||
lheight = currententity->origin[2] - lightspot[2];
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
height = -lheight + 0.1f;
|
||||
|
||||
/* stencilbuffer shadows */
|
||||
if (gl_state.stencil && gl1_stencilshadow->value)
|
||||
{
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_EQUAL, 1, 2);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
|
||||
}
|
||||
|
||||
num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2;
|
||||
mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t));
|
||||
|
||||
if (num_mesh_nodes > 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_mesh_nodes; i++)
|
||||
{
|
||||
R_DrawAliasShadowCommand(currententity,
|
||||
order + mesh_nodes[i * 2],
|
||||
order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]),
|
||||
height, lheight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawAliasShadowCommand(currententity,
|
||||
order, order + paliashdr->num_glcmds,
|
||||
height, lheight);
|
||||
}
|
||||
|
||||
/* stencilbuffer shadows */
|
||||
if (gl_state.stencil && gl1_stencilshadow->value)
|
||||
|
@ -392,18 +454,24 @@ R_CullAliasModel(const model_t *currentmodel, vec3_t bbox[8], entity_t *e)
|
|||
vec3_t angles;
|
||||
|
||||
paliashdr = (dmdl_t *)currentmodel->extradata;
|
||||
if (!paliashdr)
|
||||
{
|
||||
R_Printf(PRINT_ALL, "%s %s: Model is not fully loaded\n",
|
||||
__func__, currentmodel->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((e->frame >= paliashdr->num_frames) || (e->frame < 0))
|
||||
{
|
||||
R_Printf(PRINT_DEVELOPER, "R_CullAliasModel %s: no such frame %d\n",
|
||||
currentmodel->name, e->frame);
|
||||
R_Printf(PRINT_DEVELOPER, "%s %s: no such frame %d\n",
|
||||
__func__, currentmodel->name, e->frame);
|
||||
e->frame = 0;
|
||||
}
|
||||
|
||||
if ((e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
|
||||
{
|
||||
R_Printf(PRINT_DEVELOPER, "R_CullAliasModel %s: no such oldframe %d\n",
|
||||
currentmodel->name, e->oldframe);
|
||||
R_Printf(PRINT_DEVELOPER, "%s %s: no such oldframe %d\n",
|
||||
__func__, currentmodel->name, e->oldframe);
|
||||
e->oldframe = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,93 +104,11 @@ LerpVerts(qboolean powerUpEffect, int nverts, dtrivertx_t *v, dtrivertx_t *ov,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpolates between two frames and origins
|
||||
*/
|
||||
static void
|
||||
DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
||||
DrawAliasFrameLerpCommands(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight,
|
||||
int *order, int *order_end, float* shadedots, float alpha, qboolean colorOnly,
|
||||
dtrivertx_t *verts)
|
||||
{
|
||||
GLenum type;
|
||||
float l;
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
int *order;
|
||||
int count;
|
||||
float alpha;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
int index_xyz;
|
||||
float backlerp = entity->backlerp;
|
||||
float frontlerp = 1.0 - backlerp;
|
||||
float *lerp;
|
||||
// draw without texture? used for quad damage effect etc, I think
|
||||
qboolean colorOnly = 0 != (entity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
|
||||
RF_SHELL_HALF_DAM));
|
||||
|
||||
// TODO: maybe we could somehow store the non-rotated normal and do the dot in shader?
|
||||
float* shadedots = r_avertexnormal_dots[((int)(entity->angles[1] *
|
||||
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
|
||||
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->frame * paliashdr->framesize);
|
||||
verts = v = frame->verts;
|
||||
|
||||
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->oldframe * paliashdr->framesize);
|
||||
ov = oldframe->verts;
|
||||
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
|
||||
if (entity->flags & RF_TRANSLUCENT)
|
||||
{
|
||||
alpha = entity->alpha * 0.666f;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 1.0;
|
||||
}
|
||||
|
||||
if (colorOnly)
|
||||
{
|
||||
GL3_UseProgram(gl3state.si3DaliasColor.shaderProgram);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL3_UseProgram(gl3state.si3Dalias.shaderProgram);
|
||||
}
|
||||
|
||||
if(gl3_colorlight->value == 0.0f)
|
||||
{
|
||||
float avg = 0.333333f * (shadelight[0]+shadelight[1]+shadelight[2]);
|
||||
shadelight[0] = shadelight[1] = shadelight[2] = avg;
|
||||
}
|
||||
|
||||
/* move should be the delta back to the previous frame * backlerp */
|
||||
VectorSubtract(entity->oldorigin, entity->origin, delta);
|
||||
AngleVectors(entity->angles, vectors[0], vectors[1], vectors[2]);
|
||||
|
||||
move[0] = DotProduct(delta, vectors[0]); /* forward */
|
||||
move[1] = -DotProduct(delta, vectors[1]); /* left */
|
||||
move[2] = DotProduct(delta, vectors[2]); /* up */
|
||||
|
||||
VectorAdd(move, oldframe->translate, move);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
|
||||
|
||||
frontv[i] = frontlerp * frame->scale[i];
|
||||
backv[i] = backlerp * oldframe->scale[i];
|
||||
}
|
||||
|
||||
lerp = s_lerped[0];
|
||||
|
||||
LerpVerts(colorOnly, paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
|
||||
|
||||
YQ2_STATIC_ASSERT(sizeof(gl3_alias_vtx_t) == 9*sizeof(GLfloat), "invalid gl3_alias_vtx_t size");
|
||||
|
||||
// all the triangle fans and triangle strips of this model will be converted to
|
||||
// just triangles: the vertices stay the same and are batched in vtxBuf,
|
||||
// but idxBuf will contain indices to draw them all as GL_TRIANGLE
|
||||
|
@ -205,11 +123,13 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
|||
while (1)
|
||||
{
|
||||
GLushort nextVtxIdx = da_count(vtxBuf);
|
||||
GLenum type;
|
||||
int count;
|
||||
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count)
|
||||
if (!count || order >= order_end)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
@ -233,6 +153,7 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
|||
for(i=0; i<count; ++i)
|
||||
{
|
||||
int j=0;
|
||||
int index_xyz;
|
||||
gl3_alias_vtx_t* cur = &buf[i];
|
||||
index_xyz = order[2];
|
||||
order += 3;
|
||||
|
@ -250,8 +171,11 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
|||
int i;
|
||||
for(i=0; i<count; ++i)
|
||||
{
|
||||
int j=0;
|
||||
gl3_alias_vtx_t* cur = &buf[i];
|
||||
int index_xyz;
|
||||
int j = 0;
|
||||
float l;
|
||||
|
||||
/* texture coordinates come from the draw list */
|
||||
cur->texCoord[0] = ((float *) order)[0];
|
||||
cur->texCoord[1] = ((float *) order)[1];
|
||||
|
@ -325,66 +249,117 @@ DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
|||
glDrawElements(GL_TRIANGLES, da_count(idxBuf), GL_UNSIGNED_SHORT, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpolates between two frames and origins
|
||||
*/
|
||||
static void
|
||||
DrawAliasShadow(gl3_shadowinfo_t* shadowInfo)
|
||||
DrawAliasFrameLerp(dmdl_t *paliashdr, entity_t* entity, vec3_t shadelight)
|
||||
{
|
||||
GLenum type;
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
int *order;
|
||||
vec3_t point;
|
||||
float height = 0, lheight;
|
||||
int count;
|
||||
float alpha;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
float backlerp = entity->backlerp;
|
||||
float frontlerp = 1.0 - backlerp;
|
||||
float *lerp;
|
||||
int num_mesh_nodes;
|
||||
short *mesh_nodes;
|
||||
// draw without texture? used for quad damage effect etc, I think
|
||||
qboolean colorOnly = 0 != (entity->flags &
|
||||
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
|
||||
RF_SHELL_HALF_DAM));
|
||||
|
||||
dmdl_t* paliashdr = shadowInfo->paliashdr;
|
||||
entity_t* entity = shadowInfo->entity;
|
||||
// TODO: maybe we could somehow store the non-rotated normal and do the dot in shader?
|
||||
float* shadedots = r_avertexnormal_dots[((int)(entity->angles[1] *
|
||||
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
|
||||
|
||||
vec3_t shadevector;
|
||||
VectorCopy(shadowInfo->shadevector, shadevector);
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->frame * paliashdr->framesize);
|
||||
verts = v = frame->verts;
|
||||
|
||||
// all in this scope is to set s_lerped
|
||||
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->oldframe * paliashdr->framesize);
|
||||
ov = oldframe->verts;
|
||||
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
|
||||
if (entity->flags & RF_TRANSLUCENT)
|
||||
{
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
float backlerp = entity->backlerp;
|
||||
float frontlerp = 1.0f - backlerp;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->frame * paliashdr->framesize);
|
||||
verts = v = frame->verts;
|
||||
|
||||
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->oldframe * paliashdr->framesize);
|
||||
ov = oldframe->verts;
|
||||
|
||||
/* move should be the delta back to the previous frame * backlerp */
|
||||
VectorSubtract(entity->oldorigin, entity->origin, delta);
|
||||
AngleVectors(entity->angles, vectors[0], vectors[1], vectors[2]);
|
||||
|
||||
move[0] = DotProduct(delta, vectors[0]); /* forward */
|
||||
move[1] = -DotProduct(delta, vectors[1]); /* left */
|
||||
move[2] = DotProduct(delta, vectors[2]); /* up */
|
||||
|
||||
VectorAdd(move, oldframe->translate, move);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
|
||||
|
||||
frontv[i] = frontlerp * frame->scale[i];
|
||||
backv[i] = backlerp * oldframe->scale[i];
|
||||
}
|
||||
|
||||
// false: don't extrude vertices for powerup - this means the powerup shell
|
||||
// is not seen in the shadow, only the underlying model..
|
||||
LerpVerts(false, paliashdr->num_xyz, v, ov, verts, s_lerped[0], move, frontv, backv);
|
||||
alpha = entity->alpha * 0.666f;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 1.0;
|
||||
}
|
||||
|
||||
lheight = entity->origin[2] - shadowInfo->lightspot[2];
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
height = -lheight + 0.1f;
|
||||
if (colorOnly)
|
||||
{
|
||||
GL3_UseProgram(gl3state.si3DaliasColor.shaderProgram);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL3_UseProgram(gl3state.si3Dalias.shaderProgram);
|
||||
}
|
||||
|
||||
if(gl3_colorlight->value == 0.0f)
|
||||
{
|
||||
float avg = 0.333333f * (shadelight[0]+shadelight[1]+shadelight[2]);
|
||||
shadelight[0] = shadelight[1] = shadelight[2] = avg;
|
||||
}
|
||||
|
||||
/* move should be the delta back to the previous frame * backlerp */
|
||||
VectorSubtract(entity->oldorigin, entity->origin, delta);
|
||||
AngleVectors(entity->angles, vectors[0], vectors[1], vectors[2]);
|
||||
|
||||
move[0] = DotProduct(delta, vectors[0]); /* forward */
|
||||
move[1] = -DotProduct(delta, vectors[1]); /* left */
|
||||
move[2] = DotProduct(delta, vectors[2]); /* up */
|
||||
|
||||
VectorAdd(move, oldframe->translate, move);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
|
||||
|
||||
frontv[i] = frontlerp * frame->scale[i];
|
||||
backv[i] = backlerp * oldframe->scale[i];
|
||||
}
|
||||
|
||||
lerp = s_lerped[0];
|
||||
|
||||
LerpVerts(colorOnly, paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
|
||||
|
||||
YQ2_STATIC_ASSERT(sizeof(gl3_alias_vtx_t) == 9*sizeof(GLfloat), "invalid gl3_alias_vtx_t size");
|
||||
|
||||
num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2;
|
||||
mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t));
|
||||
|
||||
if (num_mesh_nodes > 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_mesh_nodes; i++)
|
||||
{
|
||||
DrawAliasFrameLerpCommands(paliashdr, entity, shadelight,
|
||||
order + mesh_nodes[i * 2],
|
||||
order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]),
|
||||
shadedots, alpha, colorOnly, verts);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawAliasFrameLerpCommands(paliashdr, entity, shadelight,
|
||||
order, order + paliashdr->num_glcmds,
|
||||
shadedots, alpha, colorOnly, verts);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DrawAliasShadowCommands(int *order, int *order_end, vec3_t shadevector,
|
||||
float height, float lheight)
|
||||
{
|
||||
// GL1 uses alpha 0.5, but in GL3 0.3 looks better
|
||||
GLfloat color[4] = {0, 0, 0, 0.3};
|
||||
|
||||
|
@ -395,13 +370,14 @@ DrawAliasShadow(gl3_shadowinfo_t* shadowInfo)
|
|||
|
||||
while (1)
|
||||
{
|
||||
int i, j;
|
||||
int i, j, count;
|
||||
GLenum type;
|
||||
GLushort nextVtxIdx = da_count(vtxBuf);
|
||||
|
||||
/* get the vertex count and primitive type */
|
||||
count = *order++;
|
||||
|
||||
if (!count)
|
||||
if (!count || order >= order_end)
|
||||
{
|
||||
break; /* done */
|
||||
}
|
||||
|
@ -421,6 +397,8 @@ DrawAliasShadow(gl3_shadowinfo_t* shadowInfo)
|
|||
|
||||
for(i=0; i<count; ++i)
|
||||
{
|
||||
vec3_t point;
|
||||
|
||||
/* normals and vertexes come from the frame list */
|
||||
VectorCopy(s_lerped[order[2]], point);
|
||||
|
||||
|
@ -486,6 +464,86 @@ DrawAliasShadow(gl3_shadowinfo_t* shadowInfo)
|
|||
glDrawElements(GL_TRIANGLES, da_count(idxBuf), GL_UNSIGNED_SHORT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
DrawAliasShadow(gl3_shadowinfo_t* shadowInfo)
|
||||
{
|
||||
int *order;
|
||||
float height = 0, lheight;
|
||||
int num_mesh_nodes;
|
||||
short *mesh_nodes;
|
||||
|
||||
dmdl_t* paliashdr = shadowInfo->paliashdr;
|
||||
entity_t* entity = shadowInfo->entity;
|
||||
|
||||
vec3_t shadevector;
|
||||
VectorCopy(shadowInfo->shadevector, shadevector);
|
||||
|
||||
// all in this scope is to set s_lerped
|
||||
{
|
||||
daliasframe_t *frame, *oldframe;
|
||||
dtrivertx_t *v, *ov, *verts;
|
||||
float backlerp = entity->backlerp;
|
||||
float frontlerp = 1.0f - backlerp;
|
||||
vec3_t move, delta, vectors[3];
|
||||
vec3_t frontv, backv;
|
||||
int i;
|
||||
|
||||
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->frame * paliashdr->framesize);
|
||||
verts = v = frame->verts;
|
||||
|
||||
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
|
||||
+ entity->oldframe * paliashdr->framesize);
|
||||
ov = oldframe->verts;
|
||||
|
||||
/* move should be the delta back to the previous frame * backlerp */
|
||||
VectorSubtract(entity->oldorigin, entity->origin, delta);
|
||||
AngleVectors(entity->angles, vectors[0], vectors[1], vectors[2]);
|
||||
|
||||
move[0] = DotProduct(delta, vectors[0]); /* forward */
|
||||
move[1] = -DotProduct(delta, vectors[1]); /* left */
|
||||
move[2] = DotProduct(delta, vectors[2]); /* up */
|
||||
|
||||
VectorAdd(move, oldframe->translate, move);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
|
||||
|
||||
frontv[i] = frontlerp * frame->scale[i];
|
||||
backv[i] = backlerp * oldframe->scale[i];
|
||||
}
|
||||
|
||||
// false: don't extrude vertices for powerup - this means the powerup shell
|
||||
// is not seen in the shadow, only the underlying model..
|
||||
LerpVerts(false, paliashdr->num_xyz, v, ov, verts, s_lerped[0], move, frontv, backv);
|
||||
}
|
||||
|
||||
lheight = entity->origin[2] - shadowInfo->lightspot[2];
|
||||
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
|
||||
height = -lheight + 0.1f;
|
||||
|
||||
num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2;
|
||||
mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t));
|
||||
|
||||
if (num_mesh_nodes > 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_mesh_nodes; i++)
|
||||
{
|
||||
DrawAliasShadowCommands(
|
||||
order + mesh_nodes[i * 2],
|
||||
order + min(paliashdr->num_glcmds, mesh_nodes[i * 2] + mesh_nodes[i * 2 + 1]),
|
||||
shadevector, height, lheight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawAliasShadowCommands(
|
||||
order, order + paliashdr->num_glcmds, shadevector, height, lheight);
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean
|
||||
CullAliasModel(vec3_t bbox[8], entity_t *e)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue