diff --git a/src/client/refresh/gl1/gl1_light.c b/src/client/refresh/gl1/gl1_light.c index 2a02bc06..9b310caa 100644 --- a/src/client/refresh/gl1/gl1_light.c +++ b/src/client/refresh/gl1/gl1_light.c @@ -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; diff --git a/src/client/refresh/gl1/gl1_mesh.c b/src/client/refresh/gl1/gl1_mesh.c index e7b257b1..a4cc4034 100644 --- a/src/client/refresh/gl1/gl1_mesh.c +++ b/src/client/refresh/gl1/gl1_mesh.c @@ -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; } diff --git a/src/client/refresh/gl3/gl3_mesh.c b/src/client/refresh/gl3/gl3_mesh.c index e9e73f85..dbadda8a 100644 --- a/src/client/refresh/gl3/gl3_mesh.c +++ b/src/client/refresh/gl3/gl3_mesh.c @@ -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; itexCoord[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; ipaliashdr; + 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) {