st/code/renderer/tr_x42-animverts.c

363 lines
10 KiB
C

/*
===========================================================================
Copyright (C) 2006 Hermitworks Entertainment Corp
This file is part of Space Trader source code.
Space Trader source code 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.
Space Trader source code 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 Space Trader source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "tr_local.h"
#include "tr_x42-local.h"
static void R_AnimateX42VertsTangentBasis( const affine_t *infs, uint numInfs, uint maxInfsPerVert,
const x42vertAnim_t * RESTRICT modVertPos, const x42vertTangent_t * RESTRICT modvertTan, uint numVerts,
vec4_t * RESTRICT oPos, size_t oPosStride, vec4_t * RESTRICT oNorm, size_t oNormStride,
vec4_t * RESTRICT oTan, size_t oTanStride, vec4_t * RESTRICT oBin, size_t oBinStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
uint j;
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
const x42vertTangent_t * RESTRICT vt = modvertTan + i;
affine_t m;
Affine_Scale( &m, infs + vp->idx[0], vp->wt[0] );
for( j = 1; j < maxInfsPerVert; j++ )
Affine_Mad( &m, infs + vp->idx[j], vp->wt[j], &m );
Affine_MulPos( *oPos, &m, vp->pos );
Affine_MulVec( *oTan, &m, vt->tan );
Affine_MulVec( *oBin, &m, vt->bit );
{
vec3_t n;
Vec3_Cross( n, *oTan, *oBin );
VectorScale( n, vt->nfac0 / VectorLength( n ), *oNorm );
}
oPos = (vec4_t*)((size_t)oPos + oPosStride);
oNorm = (vec4_t*)((size_t)oNorm + oNormStride);
oTan = (vec4_t*)((size_t)oTan + oTanStride);
oBin = (vec4_t*)((size_t)oBin + oBinStride);
}
}
static void R_AnimateX42VertsNormsOnly( const affine_t *infs, uint numInfs, uint maxInfsPerVert,
const x42vertAnim_t * RESTRICT modVertPos, const x42vertNormal_t * RESTRICT modVertNorm, uint numVerts,
vec4_t * RESTRICT oPos, size_t oPosStride, vec4_t * RESTRICT oNorm, size_t oNormStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
uint j;
vec3_t n;
float len;
#ifndef X42_SKIP_INVERSE_TRANSPOSE
float it[3][3], det;
#endif
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
const x42vertNormal_t * RESTRICT vn = modVertNorm + i;
affine_t m;
Affine_Scale( &m, infs + vp->idx[0], vp->wt[0] );
for( j = 1; j < maxInfsPerVert; j++ )
Affine_Mad( &m, infs + vp->idx[j], vp->wt[j], &m );
Affine_MulPos( *oPos, &m, vp->pos );
#ifdef X42_SKIP_INVERSE_TRANSPOSE
Affine_MulVec( n, &m, vn->norm );
#else
/*
Compute the cofactor matrix into it.
*/
it[0][0] = m.axis[1][1] * m.axis[2][2] - m.axis[1][2] * m.axis[2][1];
it[0][1] = m.axis[1][2] * m.axis[2][0] - m.axis[1][0] * m.axis[2][2];
it[0][2] = m.axis[1][0] * m.axis[2][1] - m.axis[1][1] * m.axis[2][0];
it[1][0] = m.axis[2][1] * m.axis[0][2] - m.axis[2][2] * m.axis[0][1];
it[1][1] = m.axis[2][2] * m.axis[0][0] - m.axis[2][0] * m.axis[0][2];
it[1][2] = m.axis[2][0] * m.axis[0][1] - m.axis[2][1] * m.axis[0][0];
it[2][0] = m.axis[0][1] * m.axis[1][2] - m.axis[0][2] * m.axis[1][1];
it[2][1] = m.axis[0][2] * m.axis[1][0] - m.axis[0][0] * m.axis[1][2];
it[2][2] = m.axis[0][0] * m.axis[1][1] - m.axis[0][1] * m.axis[1][0];
/*
Compute the determinant.
*/
det = m.axis[0][0] * it[0][0] + m.axis[0][1] * it[0][1] + m.axis[0][2] * it[0][2];
/*
Complete the inverse. Note that we're not taking the adjoint. This would be
redundant since we're computing an inverse-transpose:
adj( transpose( A ) ) = cof( transpose( transpose( A ) ) ) = cof( A )
*/
det = 1.0F / det;
it[0][0] *= det;
it[0][1] *= det;
it[0][2] *= det;
it[1][0] *= det;
it[1][1] *= det;
it[1][2] *= det;
it[2][0] *= det;
it[2][1] *= det;
it[2][2] *= det;
n[0] = it[0][0] * vn->norm[0] + it[1][0] * vn->norm[1] + it[2][0] * vn->norm[2];
n[1] = it[0][1] * vn->norm[0] + it[1][1] * vn->norm[1] + it[2][1] * vn->norm[2];
n[2] = it[0][2] * vn->norm[0] + it[1][2] * vn->norm[1] + it[2][2] * vn->norm[2];
#endif
//normalize and write the result
len = VectorLength( n );
VectorScale( n, 1.0F / len, *oNorm );
oPos = (vec4_t*)((size_t)oPos + oPosStride);
oNorm = (vec4_t*)((size_t)oNorm + oNormStride);
}
}
static void R_AnimateX42VertsNoNormals( const affine_t *infs, uint numInfs, uint maxInfsPerVert,
const x42vertAnim_t * RESTRICT modVertPos, uint numVerts,
vec4_t * RESTRICT oPos, size_t oPosStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
uint j;
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
affine_t m;
Affine_Scale( &m, infs + vp->idx[0], vp->wt[0] );
for( j = 1; j < maxInfsPerVert; j++ )
Affine_Mad( &m, infs + vp->idx[j], vp->wt[j], &m );
Affine_MulPos( *oPos, &m, vp->pos );
oPos = (vec4_t*)((size_t)oPos + oPosStride);
}
}
static void R_CopyX42VertsTangentBasis( const x42vertAnim_t * RESTRICT modVertPos,
const x42vertNormal_t * RESTRICT modVertNorm, const x42vertTangent_t * RESTRICT modvertTan,
uint numVerts, vec4_t * RESTRICT oPos, size_t oPosStride, vec4_t * RESTRICT oNorm, size_t oNormStride,
vec4_t * RESTRICT oTan, size_t oTanStride, vec4_t * RESTRICT oBin, size_t oBinStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
const x42vertNormal_t * RESTRICT vn = modVertNorm + i;
const x42vertTangent_t * RESTRICT vt = modvertTan + i;
VectorCopy( vp->pos, *oPos );
VectorCopy( vn->norm, *oNorm );
VectorCopy( vt->tan, *oTan );
VectorCopy( vt->bit, *oBin );
oPos = (vec4_t*)((size_t)oPos + oPosStride);
oNorm = (vec4_t*)((size_t)oNorm + oNormStride);
oTan = (vec4_t*)((size_t)oTan + oTanStride);
oBin = (vec4_t*)((size_t)oBin + oBinStride);
}
}
static void R_CopyX42VertsNormsOnly( const x42vertAnim_t * RESTRICT modVertPos,
const x42vertNormal_t * RESTRICT modVertNorm, uint numVerts, vec4_t * RESTRICT oPos,
size_t oPosStride, vec4_t * RESTRICT oNorm, size_t oNormStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
const x42vertNormal_t * RESTRICT vn = modVertNorm + i;
VectorCopy( vp->pos, *oPos );
VectorCopy( vn->norm, *oNorm );
oPos = (vec4_t*)((size_t)oPos + oPosStride);
oNorm = (vec4_t*)((size_t)oNorm + oNormStride);
}
}
static void R_CopyX42VertsNoNormals( const x42vertAnim_t * RESTRICT modVertPos, uint numVerts,
vec4_t * RESTRICT oPos, size_t oPosStride )
{
uint i;
for( i = 0; i < numVerts; i++ )
{
const x42vertAnim_t * RESTRICT vp = modVertPos + i;
VectorCopy( vp->pos, *oPos );
oPos = (vec4_t*)((size_t)oPos + oPosStride);
}
}
bool R_AnimateX42Group( const x42Model_t *mod, const x42group_t *g, const x42Pose_t *pose,
vec4_t * RESTRICT oPos, size_t oPosStride, vec4_t * RESTRICT oNorm, size_t oNormStride,
vec4_t * RESTRICT oTan, size_t oTanStride, vec4_t * RESTRICT oBin, size_t oBinStride )
{
uint i;
bool copyOnly = g->maxVertInfluences == 0;
affine_t infs[X42_MAX_INFLUENCES_PER_BATCH_V5];
if( !copyOnly )
{
for( i = 0; i < g->numInfluences; i++ )
{
const x42influence_t *inf = mod->influences + g->influences[i];
Affine_Mul( infs + i,
(inf->bone != X42_MODEL_BONE) ? pose->boneMats + inf->bone : &x42_m2q3,
&inf->meshToBone );
}
}
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
R_x42SSEBegin();
#endif
if( oTan && oBin && mod->vertTan )
{
if( copyOnly )
{
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
{
R_CopyX42VertsTangentBasis_SSE( mod->vertPos + g->firstVert, mod->vertNorm + g->firstVert,
mod->vertTan + g->firstVert, g->numVerts, oPos, oPosStride, oNorm, oNormStride,
oTan, oTanStride, oBin, oBinStride );
}
else
#endif
{
R_CopyX42VertsTangentBasis( mod->vertPos + g->firstVert, mod->vertNorm + g->firstVert,
mod->vertTan + g->firstVert, g->numVerts, oPos, oPosStride, oNorm, oNormStride,
oTan, oTanStride, oBin, oBinStride );
}
}
else
{
//not a simple copy
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
{
R_AnimateX42VertsTangentBasis_SSE( infs, g->numInfluences, g->maxVertInfluences, mod->vertPos + g->firstVert,
mod->vertTan + g->firstVert, g->numVerts,
oPos, oPosStride, oNorm, oNormStride, oTan, oTanStride, oBin, oBinStride );
}
else
#endif
{
R_AnimateX42VertsTangentBasis( infs, g->numInfluences, g->maxVertInfluences, mod->vertPos + g->firstVert,
mod->vertTan + g->firstVert, g->numVerts,
oPos, oPosStride, oNorm, oNormStride, oTan, oTanStride, oBin, oBinStride );
}
}
}
else if( oNorm && mod->vertNorm )
{
if( copyOnly )
{
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
{
R_CopyX42VertsNormsOnly_SSE( mod->vertPos + g->firstVert, mod->vertNorm + g->firstVert, g->numVerts,
oPos, oPosStride, oNorm, oNormStride );
}
else
#endif
{
R_CopyX42VertsNormsOnly( mod->vertPos + g->firstVert, mod->vertNorm + g->firstVert, g->numVerts,
oPos, oPosStride, oNorm, oNormStride );
}
}
else
{
//not copy only
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
{
R_AnimateX42VertsNormsOnly_SSE( infs, g->numInfluences, g->maxVertInfluences, mod->vertPos + g->firstVert,
mod->vertNorm + g->firstVert, g->numVerts, oPos, oPosStride, oNorm, oNormStride );
}
else
#endif
{
R_AnimateX42VertsNormsOnly( infs, g->numInfluences, g->maxVertInfluences, mod->vertPos + g->firstVert,
mod->vertNorm + g->firstVert, g->numVerts, oPos, oPosStride, oNorm, oNormStride );
}
}
}
else
{
if( copyOnly )
{
R_CopyX42VertsNoNormals( mod->vertPos + g->firstVert, g->numVerts, oPos, oPosStride );
}
else
{
R_AnimateX42VertsNoNormals( infs, g->numInfluences, g->maxVertInfluences, mod->vertPos + g->firstVert, g->numVerts,
oPos, oPosStride );
}
}
#ifndef TR_COMPILE_NO_SSE
if( R_AnimSupportsSSE() )
R_x42SSEEnd();
#endif
return true;
}