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:
Denis Pauk 2023-09-18 23:51:42 +03:00
parent f6319f8bc0
commit 6079adae75
3 changed files with 418 additions and 292 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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)
{