Update Renderer to latest ioq3 version.

This commit is contained in:
Richard Allen 2020-09-07 21:27:39 +00:00
parent 227ee5e84f
commit bdbae11650
5 changed files with 221 additions and 95 deletions

View file

@ -143,6 +143,35 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap)
return bestDepth; return bestDepth;
} }
float LightRay(vec2 dp, vec2 ds, sampler2D normalMap)
{
const int linearSearchSteps = 16;
// current size of search window
float size = 1.0 / float(linearSearchSteps);
// current height from initial texel depth
float height = 0.0;
float startDepth = SampleDepth(normalMap, dp);
// find a collision or escape
for(int i = 0; i < linearSearchSteps - 1; ++i)
{
height += size;
if (startDepth < height)
return 1.0;
float t = SampleDepth(normalMap, dp + ds * height);
if (startDepth > t + height)
return 0.0;
}
return 1.0;
}
#endif #endif
vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness) vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness)
@ -193,7 +222,7 @@ float CalcLightAttenuation(float point, float normDist)
return attenuation; return attenuation;
} }
#if defined(USE_BOX_CUBEMAP_PARALLAX)
vec4 hitCube(vec3 ray, vec3 pos, vec3 invSize, float lod, samplerCube tex) vec4 hitCube(vec3 ray, vec3 pos, vec3 invSize, float lod, samplerCube tex)
{ {
// find any hits on cubemap faces facing the camera // find any hits on cubemap faces facing the camera
@ -223,6 +252,7 @@ vec4 hitCube(vec3 ray, vec3 pos, vec3 invSize, float lod, samplerCube tex)
//return vec4(textureCubeLod(tex, tc, lod).rgb * fade, fade); //return vec4(textureCubeLod(tex, tc, lod).rgb * fade, fade);
return vec4(textureCubeLod(tex, tc, lod).rgb, 1.0); return vec4(textureCubeLod(tex, tc, lod).rgb, 1.0);
} }
#endif
void main() void main()
{ {
@ -252,7 +282,7 @@ void main()
vec2 texCoords = var_TexCoords.xy; vec2 texCoords = var_TexCoords.xy;
#if defined(USE_PARALLAXMAP) #if defined(USE_PARALLAXMAP)
vec3 offsetDir = viewDir * tangentToWorld; vec3 offsetDir = E * tangentToWorld;
offsetDir.xy *= -u_NormalScale.a / offsetDir.z; offsetDir.xy *= -u_NormalScale.a / offsetDir.z;
@ -319,6 +349,13 @@ void main()
#endif #endif
#endif #endif
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
offsetDir = L * tangentToWorld;
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
#endif
#if !defined(USE_LIGHT_VECTOR) #if !defined(USE_LIGHT_VECTOR)
ambientColor = lightColor; ambientColor = lightColor;
float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0); float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0);
@ -457,6 +494,12 @@ void main()
// enable when point lights are supported as primary lights // enable when point lights are supported as primary lights
//lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist); //lightColor *= CalcLightAttenuation(float(u_PrimaryLightDir.w > 0.0), u_PrimaryLightDir.w / sqrLightDist);
#if defined(USE_PARALLAXMAP) && defined(USE_PARALLAXMAP_SHADOWS)
offsetDir = L2 * tangentToWorld;
offsetDir.xy *= u_NormalScale.a / offsetDir.z;
lightColor *= LightRay(texCoords, offsetDir.xy, u_NormalMap);
#endif
gl_FragColor.rgb += lightColor * reflectance * NL2; gl_FragColor.rgb += lightColor * reflectance * NL2;
#endif #endif

View file

@ -1122,6 +1122,9 @@ void GLSL_InitGPUShaders(void)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n");
if (r_parallaxMapping->integer > 1) if (r_parallaxMapping->integer > 1)
Q_strcat(extradefines, 1024, "#define USE_RELIEFMAP\n"); Q_strcat(extradefines, 1024, "#define USE_RELIEFMAP\n");
if (r_parallaxMapShadows->integer)
Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP_SHADOWS\n");
} }
} }

View file

@ -30,6 +30,7 @@ glRefConfig_t glRefConfig;
qboolean textureFilterAnisotropic = qfalse; qboolean textureFilterAnisotropic = qfalse;
int maxAnisotropy = 0; int maxAnisotropy = 0;
float displayAspect = 0.0f; float displayAspect = 0.0f;
qboolean haveClampToEdge = qfalse;
glstate_t glState; glstate_t glState;
@ -131,6 +132,7 @@ cvar_t *r_normalMapping;
cvar_t *r_specularMapping; cvar_t *r_specularMapping;
cvar_t *r_deluxeMapping; cvar_t *r_deluxeMapping;
cvar_t *r_parallaxMapping; cvar_t *r_parallaxMapping;
cvar_t *r_parallaxMapShadows;
cvar_t *r_cubeMapping; cvar_t *r_cubeMapping;
cvar_t *r_cubemapSize; cvar_t *r_cubemapSize;
cvar_t *r_deluxeSpecular; cvar_t *r_deluxeSpecular;
@ -284,6 +286,12 @@ static void InitOpenGL( void )
} }
} }
// check for GLSL function textureCubeLod()
if ( r_cubeMapping->integer && !QGL_VERSION_ATLEAST( 3, 0 ) ) {
ri.Printf( PRINT_WARNING, "WARNING: Disabled r_cubeMapping because it requires OpenGL 3.0\n" );
ri.Cvar_Set( "r_cubeMapping", "0" );
}
// set default state // set default state
GL_SetDefaultState(); GL_SetDefaultState();
} }
@ -1235,6 +1243,7 @@ void R_Register( void )
r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_specularMapping = ri.Cvar_Get( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_parallaxMapShadows = ri.Cvar_Get( "r_parallaxMapShadows", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH ); r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
r_deluxeSpecular = ri.Cvar_Get("r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH); r_deluxeSpecular = ri.Cvar_Get("r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH);
@ -1544,6 +1553,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
textureFilterAnisotropic = qfalse; textureFilterAnisotropic = qfalse;
maxAnisotropy = 0; maxAnisotropy = 0;
displayAspect = 0.0f; displayAspect = 0.0f;
haveClampToEdge = qfalse;
Com_Memset( &glState, 0, sizeof( glState ) ); Com_Memset( &glState, 0, sizeof( glState ) );
} }

View file

@ -954,6 +954,12 @@ typedef struct srfBspSurface_s
float *heightLodError; float *heightLodError;
} srfBspSurface_t; } srfBspSurface_t;
typedef struct {
vec3_t translate;
quat_t rotate;
vec3_t scale;
} iqmTransform_t;
// inter-quake-model // inter-quake-model
typedef struct { typedef struct {
int num_vertexes; int num_vertexes;
@ -988,8 +994,9 @@ typedef struct {
char *jointNames; char *jointNames;
int *jointParents; int *jointParents;
float *jointMats; float *bindJoints; // [num_joints * 12]
float *poseMats; float *invBindJoints; // [num_joints * 12]
iqmTransform_t *poses; // [num_frames * num_poses]
float *bounds; float *bounds;
int numVaoSurfaces; int numVaoSurfaces;
@ -1771,6 +1778,7 @@ extern cvar_t *r_normalMapping;
extern cvar_t *r_specularMapping; extern cvar_t *r_specularMapping;
extern cvar_t *r_deluxeMapping; extern cvar_t *r_deluxeMapping;
extern cvar_t *r_parallaxMapping; extern cvar_t *r_parallaxMapping;
extern cvar_t *r_parallaxMapShadows;
extern cvar_t *r_cubeMapping; extern cvar_t *r_cubeMapping;
extern cvar_t *r_cubemapSize; extern cvar_t *r_cubemapSize;
extern cvar_t *r_deluxeSpecular; extern cvar_t *r_deluxeSpecular;

View file

@ -2,6 +2,7 @@
=========================================================================== ===========================================================================
Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu> Copyright (C) 2011 Thilo Schulz <thilo@tjps.eu>
Copyright (C) 2011 Matthias Bentrup <matthias.bentrup@googlemail.com> Copyright (C) 2011 Matthias Bentrup <matthias.bentrup@googlemail.com>
Copyright (C) 2011-2019 Zack Middleton <zturtleman@gmail.com>
This file is part of Quake III Arena source code. This file is part of Quake III Arena source code.
@ -44,7 +45,7 @@ static qboolean IQM_CheckRange( iqmHeader_t *header, int offset,
} }
// "multiply" 3x4 matrices, these are assumed to be the top 3 rows // "multiply" 3x4 matrices, these are assumed to be the top 3 rows
// of a 4x4 matrix with the last row = (0 0 0 1) // of a 4x4 matrix with the last row = (0 0 0 1)
static void Matrix34Multiply( float *a, float *b, float *out ) { static void Matrix34Multiply( const float *a, const float *b, float *out ) {
out[ 0] = a[0] * b[0] + a[1] * b[4] + a[ 2] * b[ 8]; out[ 0] = a[0] * b[0] + a[1] * b[4] + a[ 2] * b[ 8];
out[ 1] = a[0] * b[1] + a[1] * b[5] + a[ 2] * b[ 9]; out[ 1] = a[0] * b[1] + a[1] * b[5] + a[ 2] * b[ 9];
out[ 2] = a[0] * b[2] + a[1] * b[6] + a[ 2] * b[10]; out[ 2] = a[0] * b[2] + a[1] * b[6] + a[ 2] * b[10];
@ -58,23 +59,7 @@ static void Matrix34Multiply( float *a, float *b, float *out ) {
out[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10]; out[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10];
out[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11]; out[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11];
} }
static void InterpolateMatrix( float *a, float *b, float lerp, float *mat ) { static void JointToMatrix( const quat_t rot, const vec3_t scale, const vec3_t trans,
float unLerp = 1.0f - lerp;
mat[ 0] = a[ 0] * unLerp + b[ 0] * lerp;
mat[ 1] = a[ 1] * unLerp + b[ 1] * lerp;
mat[ 2] = a[ 2] * unLerp + b[ 2] * lerp;
mat[ 3] = a[ 3] * unLerp + b[ 3] * lerp;
mat[ 4] = a[ 4] * unLerp + b[ 4] * lerp;
mat[ 5] = a[ 5] * unLerp + b[ 5] * lerp;
mat[ 6] = a[ 6] * unLerp + b[ 6] * lerp;
mat[ 7] = a[ 7] * unLerp + b[ 7] * lerp;
mat[ 8] = a[ 8] * unLerp + b[ 8] * lerp;
mat[ 9] = a[ 9] * unLerp + b[ 9] * lerp;
mat[10] = a[10] * unLerp + b[10] * lerp;
mat[11] = a[11] * unLerp + b[11] * lerp;
}
static void JointToMatrix( vec4_t rot, vec3_t scale, vec3_t trans,
float *mat ) { float *mat ) {
float xx = 2.0f * rot[0] * rot[0]; float xx = 2.0f * rot[0] * rot[0];
float yy = 2.0f * rot[1] * rot[1]; float yy = 2.0f * rot[1] * rot[1];
@ -99,8 +84,7 @@ static void JointToMatrix( vec4_t rot, vec3_t scale, vec3_t trans,
mat[10] = scale[2] * (1.0f - (xx + yy)); mat[10] = scale[2] * (1.0f - (xx + yy));
mat[11] = trans[2]; mat[11] = trans[2];
} }
static void Matrix34Invert( float *inMat, float *outMat ) static void Matrix34Invert( const float *inMat, float *outMat ) {
{
vec3_t trans; vec3_t trans;
float invSqrLen, *v; float invSqrLen, *v;
@ -120,6 +104,62 @@ static void Matrix34Invert( float *inMat, float *outMat )
outMat[ 7] = -DotProduct(outMat + 4, trans); outMat[ 7] = -DotProduct(outMat + 4, trans);
outMat[11] = -DotProduct(outMat + 8, trans); outMat[11] = -DotProduct(outMat + 8, trans);
} }
static void QuatSlerp(const quat_t from, const quat_t _to, float fraction, quat_t out) {
float angle, cosAngle, sinAngle, backlerp, lerp;
quat_t to;
// cos() of angle
cosAngle = from[0] * _to[0] + from[1] * _to[1] + from[2] * _to[2] + from[3] * _to[3];
// negative handling is needed for taking shortest path (required for model joints)
if ( cosAngle < 0.0f ) {
cosAngle = -cosAngle;
to[0] = - _to[0];
to[1] = - _to[1];
to[2] = - _to[2];
to[3] = - _to[3];
} else {
QuatCopy( _to, to );
}
if ( cosAngle < 0.999999f ) {
// spherical lerp (slerp)
angle = acosf( cosAngle );
sinAngle = sinf( angle );
backlerp = sinf( ( 1.0f - fraction ) * angle ) / sinAngle;
lerp = sinf( fraction * angle ) / sinAngle;
} else {
// linear lerp
backlerp = 1.0f - fraction;
lerp = fraction;
}
out[0] = from[0] * backlerp + to[0] * lerp;
out[1] = from[1] * backlerp + to[1] * lerp;
out[2] = from[2] * backlerp + to[2] * lerp;
out[3] = from[3] * backlerp + to[3] * lerp;
}
static vec_t QuatNormalize2( const quat_t v, quat_t out) {
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
if (length) {
/* writing it this way allows gcc to recognize that rsqrt can be used */
ilength = 1/(float)sqrt (length);
/* sqrt(length) = length * (1 / sqrt(length)) */
length *= ilength;
out[0] = v[0]*ilength;
out[1] = v[1]*ilength;
out[2] = v[2]*ilength;
out[3] = v[3]*ilength;
} else {
out[0] = out[1] = out[2] = 0;
out[3] = -1;
}
return length;
}
/* /*
================= =================
@ -139,7 +179,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
unsigned short *framedata; unsigned short *framedata;
char *str; char *str;
int i, j, k; int i, j, k;
float jointInvMats[IQM_MAX_JOINTS * 12] = {0.0f}; iqmTransform_t *transform;
float *mat, *matInv; float *mat, *matInv;
size_t size, joint_names; size_t size, joint_names;
byte *dataPtr; byte *dataPtr;
@ -562,10 +602,11 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
if( header->num_joints ) { if( header->num_joints ) {
size += joint_names; // joint names size += joint_names; // joint names
size += header->num_joints * sizeof(int); // joint parents size += header->num_joints * sizeof(int); // joint parents
size += header->num_joints * 12 * sizeof( float ); // joint mats size += header->num_joints * 12 * sizeof(float); // bind joint matricies
size += header->num_joints * 12 * sizeof(float); // inverse bind joint matricies
} }
if( header->num_poses ) { if( header->num_poses ) {
size += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats size += header->num_poses * header->num_frames * sizeof(iqmTransform_t); // pose transforms
} }
if( header->ofs_bounds ) { if( header->ofs_bounds ) {
size += header->num_frames * 6 * sizeof(float); // model bounds size += header->num_frames * 6 * sizeof(float); // model bounds
@ -636,12 +677,15 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->jointParents = (int*)dataPtr; iqmData->jointParents = (int*)dataPtr;
dataPtr += header->num_joints * sizeof(int); // joint parents dataPtr += header->num_joints * sizeof(int); // joint parents
iqmData->jointMats = (float*)dataPtr; iqmData->bindJoints = (float*)dataPtr;
dataPtr += header->num_joints * 12 * sizeof( float ); // joint mats dataPtr += header->num_joints * 12 * sizeof(float); // bind joint matricies
iqmData->invBindJoints = (float*)dataPtr;
dataPtr += header->num_joints * 12 * sizeof(float); // inverse bind joint matricies
} }
if( header->num_poses ) { if( header->num_poses ) {
iqmData->poseMats = (float*)dataPtr; iqmData->poses = (iqmTransform_t*)dataPtr;
dataPtr += header->num_poses * header->num_frames * 12 * sizeof( float ); // pose mats dataPtr += header->num_poses * header->num_frames * sizeof(iqmTransform_t); // pose transforms
} }
if( header->ofs_bounds ) { if( header->ofs_bounds ) {
iqmData->bounds = (float*)dataPtr; iqmData->bounds = (float*)dataPtr;
@ -807,22 +851,23 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
iqmData->jointParents[i] = joint->parent; iqmData->jointParents[i] = joint->parent;
} }
// calculate joint matrices and their inverses // calculate bind joint matrices and their inverses
// joint inverses are needed only until the pose matrices are calculated mat = iqmData->bindJoints;
mat = iqmData->jointMats; matInv = iqmData->invBindJoints;
matInv = jointInvMats;
joint = (iqmJoint_t *)((byte *)header + header->ofs_joints); joint = (iqmJoint_t *)((byte *)header + header->ofs_joints);
for( i = 0; i < header->num_joints; i++, joint++ ) { for( i = 0; i < header->num_joints; i++, joint++ ) {
float baseFrame[12], invBaseFrame[12]; float baseFrame[12], invBaseFrame[12];
QuatNormalize2( joint->rotate, joint->rotate );
JointToMatrix( joint->rotate, joint->scale, joint->translate, baseFrame ); JointToMatrix( joint->rotate, joint->scale, joint->translate, baseFrame );
Matrix34Invert( baseFrame, invBaseFrame ); Matrix34Invert( baseFrame, invBaseFrame );
if ( joint->parent >= 0 ) if ( joint->parent >= 0 )
{ {
Matrix34Multiply( iqmData->jointMats + 12 * joint->parent, baseFrame, mat ); Matrix34Multiply( iqmData->bindJoints + 12 * joint->parent, baseFrame, mat );
mat += 12; mat += 12;
Matrix34Multiply( invBaseFrame, jointInvMats + 12 * joint->parent, matInv ); Matrix34Multiply( invBaseFrame, iqmData->invBindJoints + 12 * joint->parent, matInv );
matInv += 12; matInv += 12;
} }
else else
@ -837,16 +882,15 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
if( header->num_poses ) if( header->num_poses )
{ {
// calculate pose matrices // calculate pose transforms
transform = iqmData->poses;
framedata = (unsigned short *)((byte *)header + header->ofs_frames); framedata = (unsigned short *)((byte *)header + header->ofs_frames);
mat = iqmData->poseMats;
for( i = 0; i < header->num_frames; i++ ) { for( i = 0; i < header->num_frames; i++ ) {
pose = (iqmPose_t *)((byte *)header + header->ofs_poses); pose = (iqmPose_t *)((byte *)header + header->ofs_poses);
for( j = 0; j < header->num_poses; j++, pose++ ) { for( j = 0; j < header->num_poses; j++, pose++, transform++ ) {
vec3_t translate; vec3_t translate;
vec4_t rotate; quat_t rotate;
vec3_t scale; vec3_t scale;
float mat1[12], mat2[12];
translate[0] = pose->channeloffset[0]; translate[0] = pose->channeloffset[0];
if( pose->mask & 0x001) if( pose->mask & 0x001)
@ -881,18 +925,9 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na
if( pose->mask & 0x200) if( pose->mask & 0x200)
scale[2] += *framedata++ * pose->channelscale[9]; scale[2] += *framedata++ * pose->channelscale[9];
// construct transformation matrix VectorCopy( translate, transform->translate );
JointToMatrix( rotate, scale, translate, mat1 ); QuatNormalize2( rotate, transform->rotate );
VectorCopy( scale, transform->scale );
if( pose->parent >= 0 ) {
Matrix34Multiply( iqmData->jointMats + 12 * pose->parent,
mat1, mat2 );
} else {
Com_Memcpy( mat2, mat1, sizeof(mat1) );
}
Matrix34Multiply( mat2, jointInvMats + 12 * j, mat );
mat += 12;
} }
} }
} }
@ -1306,37 +1341,59 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
static void ComputePoseMats( iqmData_t *data, int frame, int oldframe, static void ComputePoseMats( iqmData_t *data, int frame, int oldframe,
float backlerp, float *mat ) { float backlerp, float *poseMats ) {
float *mat1, *mat2; iqmTransform_t relativeJoints[IQM_MAX_JOINTS];
int *joint = data->jointParents; iqmTransform_t *relativeJoint;
int i; const iqmTransform_t *pose;
const iqmTransform_t *oldpose;
const int *jointParent;
const float *invBindMat;
float *poseMat, lerp;
int i;
relativeJoint = relativeJoints;
// copy or lerp animation frame pose
if ( oldframe == frame ) { if ( oldframe == frame ) {
mat1 = data->poseMats + 12 * data->num_poses * frame; pose = &data->poses[frame * data->num_poses];
for( i = 0; i < data->num_poses; i++, joint++ ) { for ( i = 0; i < data->num_poses; i++, pose++, relativeJoint++ ) {
if( *joint >= 0 ) { VectorCopy( pose->translate, relativeJoint->translate );
Matrix34Multiply( mat + 12 * *joint, QuatCopy( pose->rotate, relativeJoint->rotate );
mat1 + 12*i, mat + 12*i ); VectorCopy( pose->scale, relativeJoint->scale );
} else {
Com_Memcpy( mat + 12*i, mat1 + 12*i, 12 * sizeof(float) );
}
} }
} else { } else {
mat1 = data->poseMats + 12 * data->num_poses * frame; lerp = 1.0f - backlerp;
mat2 = data->poseMats + 12 * data->num_poses * oldframe; pose = &data->poses[frame * data->num_poses];
oldpose = &data->poses[oldframe * data->num_poses];
for( i = 0; i < data->num_poses; i++, joint++ ) { for ( i = 0; i < data->num_poses; i++, oldpose++, pose++, relativeJoint++ ) {
if( *joint >= 0 ) { relativeJoint->translate[0] = oldpose->translate[0] * backlerp + pose->translate[0] * lerp;
float tmpMat[12]; relativeJoint->translate[1] = oldpose->translate[1] * backlerp + pose->translate[1] * lerp;
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, relativeJoint->translate[2] = oldpose->translate[2] * backlerp + pose->translate[2] * lerp;
backlerp, tmpMat );
Matrix34Multiply( mat + 12 * *joint, relativeJoint->scale[0] = oldpose->scale[0] * backlerp + pose->scale[0] * lerp;
tmpMat, mat + 12*i ); relativeJoint->scale[1] = oldpose->scale[1] * backlerp + pose->scale[1] * lerp;
relativeJoint->scale[2] = oldpose->scale[2] * backlerp + pose->scale[2] * lerp;
} else {
InterpolateMatrix( mat1 + 12*i, mat2 + 12*i, QuatSlerp( oldpose->rotate, pose->rotate, lerp, relativeJoint->rotate );
backlerp, mat + 12*i ); }
} }
// multiply by inverse of bind pose and parent 'pose mat' (bind pose transform matrix)
relativeJoint = relativeJoints;
jointParent = data->jointParents;
invBindMat = data->invBindJoints;
poseMat = poseMats;
for ( i = 0; i < data->num_poses; i++, relativeJoint++, jointParent++, invBindMat += 12, poseMat += 12 ) {
float mat1[12], mat2[12];
JointToMatrix( relativeJoint->rotate, relativeJoint->scale, relativeJoint->translate, mat1 );
if ( *jointParent >= 0 ) {
Matrix34Multiply( &data->bindJoints[(*jointParent)*12], mat1, mat2 );
Matrix34Multiply( mat2, invBindMat, mat1 );
Matrix34Multiply( &poseMats[(*jointParent)*12], mat1, poseMat );
} else {
Matrix34Multiply( mat1, invBindMat, poseMat );
} }
} }
} }
@ -1347,7 +1404,7 @@ static void ComputeJointMats( iqmData_t *data, int frame, int oldframe,
int i; int i;
if ( data->num_poses == 0 ) { if ( data->num_poses == 0 ) {
Com_Memcpy( mat, data->jointMats, data->num_joints * 12 * sizeof(float) ); Com_Memcpy( mat, data->bindJoints, data->num_joints * 12 * sizeof(float) );
return; return;
} }
@ -1359,7 +1416,7 @@ static void ComputeJointMats( iqmData_t *data, int frame, int oldframe,
Com_Memcpy(outmat, mat1, sizeof(outmat)); Com_Memcpy(outmat, mat1, sizeof(outmat));
Matrix34Multiply( outmat, data->jointMats + 12*i, mat1 ); Matrix34Multiply( outmat, data->bindJoints + 12*i, mat1 );
} }
} }
@ -1428,19 +1485,20 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
float *nrmMat = &influenceNrmMat[9*i]; float *nrmMat = &influenceNrmMat[9*i];
int j; int j;
float blendWeights[4]; float blendWeights[4];
int numWeights;
for ( numWeights = 0; numWeights < 4; numWeights++ ) { if ( data->blendWeightsType == IQM_FLOAT ) {
if ( data->blendWeightsType == IQM_FLOAT ) blendWeights[0] = data->influenceBlendWeights.f[4*influence + 0];
blendWeights[numWeights] = data->influenceBlendWeights.f[4*influence + numWeights]; blendWeights[1] = data->influenceBlendWeights.f[4*influence + 1];
else blendWeights[2] = data->influenceBlendWeights.f[4*influence + 2];
blendWeights[numWeights] = (float)data->influenceBlendWeights.b[4*influence + numWeights] / 255.0f; blendWeights[3] = data->influenceBlendWeights.f[4*influence + 3];
} else {
if ( blendWeights[numWeights] <= 0.0f ) blendWeights[0] = (float)data->influenceBlendWeights.b[4*influence + 0] / 255.0f;
break; blendWeights[1] = (float)data->influenceBlendWeights.b[4*influence + 1] / 255.0f;
blendWeights[2] = (float)data->influenceBlendWeights.b[4*influence + 2] / 255.0f;
blendWeights[3] = (float)data->influenceBlendWeights.b[4*influence + 3] / 255.0f;
} }
if ( numWeights == 0 ) { if ( blendWeights[0] <= 0.0f ) {
// no blend joint, use identity matrix. // no blend joint, use identity matrix.
vtxMat[0] = identityMatrix[0]; vtxMat[0] = identityMatrix[0];
vtxMat[1] = identityMatrix[1]; vtxMat[1] = identityMatrix[1];
@ -1470,7 +1528,11 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) {
vtxMat[10] = blendWeights[0] * poseMats[12 * data->influenceBlendIndexes[4*influence + 0] + 10]; vtxMat[10] = blendWeights[0] * poseMats[12 * data->influenceBlendIndexes[4*influence + 0] + 10];
vtxMat[11] = blendWeights[0] * poseMats[12 * data->influenceBlendIndexes[4*influence + 0] + 11]; vtxMat[11] = blendWeights[0] * poseMats[12 * data->influenceBlendIndexes[4*influence + 0] + 11];
for( j = 1; j < numWeights; j++ ) { for( j = 1; j < 3; j++ ) {
if ( blendWeights[j] <= 0.0f ) {
break;
}
vtxMat[0] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 0]; vtxMat[0] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 0];
vtxMat[1] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 1]; vtxMat[1] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 1];
vtxMat[2] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 2]; vtxMat[2] += blendWeights[j] * poseMats[12 * data->influenceBlendIndexes[4*influence + j] + 2];