2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA 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.
|
|
|
|
|
|
|
|
OpenMoHAA 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 OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
// skeletorbones.cpp : Skeletor bones
|
|
|
|
|
|
|
|
#include "q_shared.h"
|
|
|
|
#include "qcommon.h"
|
|
|
|
#include "skeletor.h"
|
|
|
|
|
|
|
|
char *skelBone_Names[ 8 ];
|
|
|
|
ChannelNameTable skeletor_c::m_channelNames;
|
|
|
|
ChannelNameTable skeletor_c::m_boneNames;
|
|
|
|
skelBone_World skeletor_c::m_worldBone;
|
|
|
|
|
|
|
|
skelBone_World::skelBone_World()
|
|
|
|
{
|
|
|
|
m_isDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SkeletorLoadBoneFromBuffer( skelChannelList_c *boneList, boneData_t *boneData, skelBone_Base **bone )
|
|
|
|
{
|
|
|
|
int newBoneIndex;
|
|
|
|
const char *boneName;
|
|
|
|
int newBoneParent;
|
|
|
|
skelBone_Base *parentBone;
|
|
|
|
|
|
|
|
newBoneIndex = boneList->GetLocalFromGlobal( boneData->channel );
|
|
|
|
|
|
|
|
if( !bone[ newBoneIndex ] )
|
|
|
|
{
|
|
|
|
boneName = skeletor_c::m_boneNames.FindName( boneData->channel );
|
|
|
|
|
|
|
|
if( boneData->parent < 0 )
|
|
|
|
{
|
|
|
|
newBoneParent = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newBoneParent = boneList->GetLocalFromGlobal( boneData->parent );
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( boneData->boneType )
|
|
|
|
{
|
|
|
|
case SKELBONE_ZERO:
|
|
|
|
{
|
|
|
|
skelBone_Zero *newBone = new skelBone_Zero;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_ROTATION:
|
|
|
|
{
|
|
|
|
skelBone_Rotation *newBone = new skelBone_Rotation;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
newBone->SetChannels( boneData->channelIndex[ 0 ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_POSROT:
|
|
|
|
{
|
|
|
|
skelBone_PosRot *newBone;
|
|
|
|
|
|
|
|
if( !strncmp( boneName, "Bip01", 5 ) )
|
|
|
|
{
|
|
|
|
newBone = new skelBone_Root;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newBone = new skelBone_PosRot;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
}
|
|
|
|
|
|
|
|
newBone->SetChannels( boneData->channelIndex[ 0 ], boneData->channelIndex[ 1 ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_IKSHOULDER:
|
|
|
|
{
|
|
|
|
skelBone_IKshoulder *newBone = new skelBone_IKshoulder;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_IKELBOW:
|
|
|
|
{
|
|
|
|
skelBone_IKelbow *newBone = new skelBone_IKelbow;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
newBone->SetBoneRefs( ( skelBone_IKshoulder * )bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_IKWRIST:
|
|
|
|
{
|
|
|
|
skelBone_IKwrist *newBone = new skelBone_IKwrist;
|
|
|
|
skelBone_IKshoulder *shoulder;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
shoulder = ( skelBone_IKshoulder * )bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ];
|
|
|
|
newBone->SetChannels( boneData->channelIndex[ 0 ], boneData->channelIndex[ 1 ] );
|
|
|
|
newBone->SetBoneRefs( shoulder );
|
|
|
|
shoulder->SetWristBone( newBone );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_AVROT:
|
|
|
|
{
|
|
|
|
skelBone_AvRot *newBone = new skelBone_AvRot;
|
|
|
|
skelBone_AvRot *ref1, *ref2;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
ref1 = ( skelBone_AvRot * )bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ];
|
|
|
|
ref2 = ( skelBone_AvRot * )bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 1 ] ) ];
|
|
|
|
newBone->SetBoneRefs( ref1, ref2 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_HOSEROT:
|
|
|
|
{
|
|
|
|
skelBone_HoseRot *newBone = new skelBone_HoseRot;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
newBone->SetBoneRefs( bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_HOSEROTBOTH:
|
|
|
|
{
|
|
|
|
skelBone_HoseRotBoth *newBone = new skelBone_HoseRotBoth;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
newBone->SetBoneRefs( bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SKELBONE_HOSEROTPARENT:
|
|
|
|
{
|
|
|
|
skelBone_HoseRotParent *newBone = new skelBone_HoseRotParent;
|
|
|
|
bone[ newBoneIndex ] = newBone;
|
|
|
|
newBone->SetBoneRefs( bone[ boneList->GetLocalFromGlobal( boneData->refIndex[ 0 ] ) ] );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
bone[ newBoneIndex ]->SetBaseValue( boneData );
|
|
|
|
|
|
|
|
if( newBoneParent < 0 )
|
|
|
|
{
|
|
|
|
parentBone = &skeletor_c::m_worldBone;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parentBone = bone[ newBoneParent ];
|
|
|
|
}
|
|
|
|
|
|
|
|
bone[ newBoneIndex ]->SetParent( parentBone );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SkeletorLoadBonesFromBuffer( skelChannelList_c *boneList, skelHeaderGame_t *buffer, skelBone_Base **bone )
|
|
|
|
{
|
|
|
|
int boneNum;
|
|
|
|
|
|
|
|
for( boneNum = 0; boneNum < buffer->numBones; boneNum++ )
|
|
|
|
{
|
|
|
|
SkeletorLoadBoneFromBuffer( boneList, &buffer->pBones[ boneNum ], bone );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float *DecodeRLEValue( skanChannelHdr *channelFrames, int desiredFrameNum )
|
|
|
|
{
|
|
|
|
skanGameFrame *foundFrame = channelFrames->ary_frames;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for( i = 0; i < channelFrames->nFramesInChannel; i++ )
|
|
|
|
{
|
|
|
|
if( foundFrame->nFrameNum >= desiredFrameNum )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
foundFrame++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( foundFrame->nFrameNum > desiredFrameNum )
|
|
|
|
{
|
|
|
|
foundFrame = &channelFrames->ary_frames[ foundFrame->nPrevFrameIndex ];
|
|
|
|
}
|
|
|
|
|
|
|
|
return foundFrame->pChannelData;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkelQuat skelAnimStoreFrameList_c::GetSlerpValue( int globalChannelNum ) const
|
|
|
|
{
|
|
|
|
SkelQuat actionQuat, movementQuat;
|
|
|
|
SkelQuat outQuat;
|
|
|
|
float totalWeight;
|
|
|
|
SkelQuat *pIncomingQuat;
|
|
|
|
float incomingWeight;
|
|
|
|
int localChannelNum;
|
|
|
|
float channelActionWeight;
|
|
|
|
//float movementWeight;
|
|
|
|
int nTotal;
|
|
|
|
int i;
|
|
|
|
const skanBlendInfo *pFrame;
|
|
|
|
float t;
|
|
|
|
|
|
|
|
actionQuat.Set( 0, 0, 0, 0 );
|
|
|
|
movementQuat.Set( 0, 0, 0, 0 );
|
|
|
|
|
|
|
|
nTotal = 0;
|
|
|
|
totalWeight = 0.0;
|
|
|
|
|
|
|
|
if( actionWeight > 0.001 )
|
|
|
|
{
|
|
|
|
for( i = 0; i < numActionFrames; i++ )
|
|
|
|
{
|
|
|
|
pFrame = &m_blendInfo[ i + 32 ];
|
|
|
|
|
|
|
|
localChannelNum = pFrame->pAnimationData->channelList.GetLocalFromGlobal( globalChannelNum );
|
|
|
|
if( localChannelNum >= 0 )
|
|
|
|
{
|
|
|
|
incomingWeight = pFrame->weight;
|
|
|
|
if( incomingWeight == 0.0 ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
pIncomingQuat = ( SkelQuat * )DecodeRLEValue( &pFrame->pAnimationData->ary_channels[ localChannelNum ], pFrame->frame );
|
|
|
|
totalWeight += incomingWeight;
|
|
|
|
nTotal++;
|
|
|
|
|
|
|
|
if( DotProduct4( *pIncomingQuat, actionQuat ) >= 0.0 )
|
|
|
|
{
|
|
|
|
actionQuat.x += pIncomingQuat->x * incomingWeight;
|
|
|
|
actionQuat.y += pIncomingQuat->y * incomingWeight;
|
|
|
|
actionQuat.z += pIncomingQuat->z * incomingWeight;
|
|
|
|
actionQuat.w += pIncomingQuat->w * incomingWeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actionQuat.x -= pIncomingQuat->x * incomingWeight;
|
|
|
|
actionQuat.y -= pIncomingQuat->y * incomingWeight;
|
|
|
|
actionQuat.z -= pIncomingQuat->z * incomingWeight;
|
|
|
|
actionQuat.w -= pIncomingQuat->w * incomingWeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( nTotal )
|
|
|
|
{
|
|
|
|
channelActionWeight = actionWeight;
|
|
|
|
if( nTotal > 1 ) {
|
|
|
|
t = 1.0 / actionQuat.Length();
|
|
|
|
} else {
|
|
|
|
t = 1.0 / totalWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
actionQuat.x = actionQuat.x * t;
|
|
|
|
actionQuat.y = actionQuat.y * t;
|
|
|
|
actionQuat.z = actionQuat.z * t;
|
|
|
|
actionQuat.w = actionQuat.w * t;
|
|
|
|
} else {
|
|
|
|
channelActionWeight = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
nTotal = 0;
|
|
|
|
totalWeight = 0.0;
|
|
|
|
|
|
|
|
if( channelActionWeight < 0.999 )
|
|
|
|
{
|
|
|
|
for( i = 0; i < numMovementFrames; i++ )
|
|
|
|
{
|
|
|
|
pFrame = &m_blendInfo[ i ];
|
|
|
|
|
|
|
|
localChannelNum = pFrame->pAnimationData->channelList.GetLocalFromGlobal( globalChannelNum );
|
|
|
|
if( localChannelNum >= 0 )
|
|
|
|
{
|
|
|
|
incomingWeight = pFrame->weight;
|
|
|
|
if( incomingWeight == 0.0 ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
pIncomingQuat = ( SkelQuat * )DecodeRLEValue( &pFrame->pAnimationData->ary_channels[ localChannelNum ], pFrame->frame );
|
|
|
|
totalWeight += incomingWeight;
|
|
|
|
nTotal++;
|
|
|
|
|
|
|
|
if( DotProduct4( *pIncomingQuat, movementQuat ) >= 0.0 )
|
|
|
|
{
|
|
|
|
movementQuat.x += pIncomingQuat->x * incomingWeight;
|
|
|
|
movementQuat.y += pIncomingQuat->y * incomingWeight;
|
|
|
|
movementQuat.z += pIncomingQuat->z * incomingWeight;
|
|
|
|
movementQuat.w += pIncomingQuat->w * incomingWeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
movementQuat.x -= pIncomingQuat->x * incomingWeight;
|
|
|
|
movementQuat.y -= pIncomingQuat->y * incomingWeight;
|
|
|
|
movementQuat.z -= pIncomingQuat->z * incomingWeight;
|
|
|
|
movementQuat.w -= pIncomingQuat->w * incomingWeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( nTotal )
|
|
|
|
{
|
|
|
|
if( nTotal > 1 ) {
|
|
|
|
t = 1.0 / movementQuat.Length();
|
|
|
|
} else {
|
|
|
|
t = 1.0 / totalWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
movementQuat.x = movementQuat.x * t;
|
|
|
|
movementQuat.y = movementQuat.y * t;
|
|
|
|
movementQuat.z = movementQuat.z * t;
|
|
|
|
movementQuat.w = movementQuat.w * t;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
movementQuat.w = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( channelActionWeight < 0.001 )
|
|
|
|
{
|
|
|
|
outQuat.x = movementQuat.x;
|
|
|
|
outQuat.y = movementQuat.y;
|
|
|
|
outQuat.z = movementQuat.z;
|
|
|
|
outQuat.w = movementQuat.w;
|
|
|
|
return outQuat;
|
|
|
|
}
|
|
|
|
else if( channelActionWeight >= 0.999 )
|
|
|
|
{
|
|
|
|
outQuat.x = actionQuat.x;
|
|
|
|
outQuat.y = actionQuat.y;
|
|
|
|
outQuat.z = actionQuat.z;
|
|
|
|
outQuat.w = actionQuat.w;
|
|
|
|
return outQuat;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = 1.0 - channelActionWeight;
|
|
|
|
|
|
|
|
if( DotProduct4( actionQuat, movementQuat ) >= 0.0 )
|
|
|
|
{
|
|
|
|
outQuat.x = movementQuat.x * t + actionQuat.x * channelActionWeight;
|
|
|
|
outQuat.y = movementQuat.y * t + actionQuat.y * channelActionWeight;
|
|
|
|
outQuat.z = movementQuat.z * t + actionQuat.z * channelActionWeight;
|
|
|
|
outQuat.w = movementQuat.w * t + actionQuat.w * channelActionWeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
outQuat.x = movementQuat.x * t - actionQuat.x * channelActionWeight;
|
|
|
|
outQuat.y = movementQuat.y * t - actionQuat.y * channelActionWeight;
|
|
|
|
outQuat.z = movementQuat.z * t - actionQuat.z * channelActionWeight;
|
|
|
|
outQuat.w = movementQuat.w * t - actionQuat.w * channelActionWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
t = 1.0 / outQuat.Length();
|
|
|
|
outQuat.x = outQuat.x * t;
|
|
|
|
outQuat.y = outQuat.y * t;
|
|
|
|
outQuat.z = outQuat.z * t;
|
|
|
|
outQuat.w = outQuat.w * t;
|
|
|
|
|
|
|
|
return outQuat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelAnimStoreFrameList_c::GetLerpValue3( int globalChannelNum, SkelVec3 *outVec ) const
|
|
|
|
{
|
|
|
|
float totalWeight;
|
|
|
|
SkelVec3 incomingVec;
|
|
|
|
float incomingWeight;
|
|
|
|
int localChannelNum;
|
|
|
|
vec3_t result;
|
|
|
|
float t;
|
|
|
|
float channelActionWeight;
|
|
|
|
int i;
|
|
|
|
const skanBlendInfo *pFrame;
|
|
|
|
|
|
|
|
totalWeight = 0.0;
|
|
|
|
|
|
|
|
if( actionWeight > 0.001 )
|
|
|
|
{
|
|
|
|
VectorClear( result );
|
|
|
|
|
|
|
|
for( i = 0; i < numActionFrames; i++ )
|
|
|
|
{
|
|
|
|
pFrame = &m_blendInfo[ i + 32 ];
|
|
|
|
|
|
|
|
localChannelNum = pFrame->pAnimationData->channelList.GetLocalFromGlobal( globalChannelNum );
|
|
|
|
if( localChannelNum >= 0 )
|
|
|
|
{
|
|
|
|
incomingWeight = pFrame->weight;
|
|
|
|
incomingVec = DecodeRLEValue( &pFrame->pAnimationData->ary_channels[ localChannelNum ], pFrame->frame );
|
|
|
|
totalWeight += incomingWeight;
|
|
|
|
result[ 0 ] += incomingVec[ 0 ] * incomingWeight;
|
|
|
|
result[ 1 ] += incomingVec[ 1 ] * incomingWeight;
|
|
|
|
result[ 2 ] += incomingVec[ 2 ] * incomingWeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( totalWeight != 0.0 )
|
|
|
|
{
|
|
|
|
t = 1.0 / totalWeight;
|
|
|
|
VectorScale( result, t, *outVec );
|
|
|
|
channelActionWeight = actionWeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VectorClear( *outVec );
|
|
|
|
channelActionWeight = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( channelActionWeight >= 0.999 || !numMovementFrames ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
totalWeight = 0.0;
|
|
|
|
VectorClear( result );
|
|
|
|
|
|
|
|
for( i = 0; i < numMovementFrames; i++ )
|
|
|
|
{
|
|
|
|
pFrame = &m_blendInfo[ i ];
|
|
|
|
|
|
|
|
localChannelNum = pFrame->pAnimationData->channelList.GetLocalFromGlobal( globalChannelNum );
|
|
|
|
if( localChannelNum >= 0 )
|
|
|
|
{
|
|
|
|
incomingWeight = pFrame->weight;
|
|
|
|
incomingVec = DecodeRLEValue( &pFrame->pAnimationData->ary_channels[ localChannelNum ], pFrame->frame );
|
|
|
|
totalWeight += incomingWeight;
|
|
|
|
result[ 0 ] += incomingVec[ 0 ] * incomingWeight;
|
|
|
|
result[ 1 ] += incomingVec[ 1 ] * incomingWeight;
|
|
|
|
result[ 2 ] += incomingVec[ 2 ] * incomingWeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( totalWeight != 0.0 )
|
|
|
|
{
|
|
|
|
t = 1.0 / totalWeight * ( 1.0 - channelActionWeight );
|
|
|
|
outVec->x = outVec->x * channelActionWeight + result[ 0 ] * t;
|
|
|
|
outVec->y = outVec->y * channelActionWeight + result[ 1 ] * t;
|
|
|
|
outVec->z = outVec->z * channelActionWeight + result[ 2 ] * t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base::skelBone_Base()
|
|
|
|
{
|
|
|
|
m_parent = NULL;
|
|
|
|
m_isDirty = true;
|
|
|
|
m_controller = NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
skelBone_Base::~skelBone_Base()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
int skelBone_Base::GetNumChannels( boneType_t boneType )
|
|
|
|
{
|
|
|
|
switch( boneType )
|
|
|
|
{
|
|
|
|
case SKELBONE_ROTATION:
|
|
|
|
return 1;
|
|
|
|
case SKELBONE_POSROT:
|
|
|
|
case SKELBONE_IKWRIST:
|
|
|
|
return 2;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_Base::GetNumBoneRefs( boneType_t boneType )
|
|
|
|
{
|
|
|
|
switch( boneType )
|
|
|
|
{
|
|
|
|
case SKELBONE_AVROT:
|
|
|
|
return 2;
|
|
|
|
case SKELBONE_IKELBOW:
|
|
|
|
case SKELBONE_IKWRIST:
|
|
|
|
case SKELBONE_HOSEROT:
|
|
|
|
case SKELBONE_HOSEROTBOTH:
|
|
|
|
case SKELBONE_HOSEROTPARENT:
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_Base::GetTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
if( m_isDirty )
|
|
|
|
{
|
|
|
|
return GetDirtyTransform( frames );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_Base::SetParent( skelBone_Base *parent )
|
|
|
|
{
|
|
|
|
m_parent = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_Base::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_Base::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_Base::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_Base::Parent() const
|
|
|
|
{
|
|
|
|
return m_parent;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_Zero::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
m_cachedValue = m_parent->GetTransform( frames );
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
m_isDirty = false;
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_Zero::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_Zero::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_Zero::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_Rotation::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelMat4 incomingValue;
|
|
|
|
SkelQuat incomingQuat;
|
|
|
|
|
|
|
|
incomingQuat = frames->GetSlerpValue( m_quatChannel );
|
|
|
|
incomingQuat.GetMat4( incomingValue );
|
|
|
|
VectorCopy( m_baseValue, incomingValue[ 3 ] );
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
m_cachedValue.Multiply( incomingValue, m_parent->GetTransform( frames ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_cachedValue = incomingValue;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
if( m_controller )
|
|
|
|
{
|
|
|
|
SkelMat3 m;
|
|
|
|
|
|
|
|
incomingQuat.Set( m_controller );
|
|
|
|
incomingQuat.GetMat3( m );
|
|
|
|
m_cachedValue.RotateBy( m );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void skelBone_Rotation::SetChannels( int num )
|
|
|
|
{
|
|
|
|
m_quatChannel = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_Rotation::SetBaseValue( boneData_t *data )
|
|
|
|
{
|
|
|
|
m_baseValue = data->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_Rotation::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return m_quatChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_Rotation::GetBoneRef( int bone )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_PosRot::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelVec3 incomingOffset;
|
|
|
|
SkelMat4 incomingValue;
|
|
|
|
SkelQuat incomingQuat;
|
|
|
|
|
|
|
|
incomingQuat = frames->GetSlerpValue( m_quatChannel );
|
|
|
|
frames->GetLerpValue3( m_offsetChannel, &incomingOffset );
|
|
|
|
incomingQuat.GetMat4( incomingValue );
|
|
|
|
VectorCopy( incomingOffset, incomingValue[ 3 ] );
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
m_cachedValue.Multiply( incomingValue, m_parent->GetTransform( frames ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_cachedValue = incomingValue;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
if( m_controller )
|
|
|
|
{
|
|
|
|
SkelMat3 m;
|
|
|
|
|
|
|
|
incomingQuat.Set( m_controller );
|
|
|
|
incomingQuat.GetMat3( m );
|
|
|
|
m_cachedValue.RotateBy( m );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_PosRot::SetChannels( int quatChannel, int offsetChannel )
|
|
|
|
{
|
|
|
|
m_quatChannel = quatChannel;
|
|
|
|
m_offsetChannel = offsetChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_PosRot::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_PosRot::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
if( num )
|
|
|
|
{
|
|
|
|
return m_quatChannel;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return m_offsetChannel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_PosRot::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_Root::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelVec3 incomingOffset;
|
|
|
|
SkelMat4 incomingValue;
|
|
|
|
SkelQuat incomingQuat;
|
|
|
|
|
|
|
|
incomingQuat = frames->GetSlerpValue( m_quatChannel );
|
|
|
|
frames->GetLerpValue3( m_offsetChannel, &incomingOffset );
|
|
|
|
incomingQuat.GetMat4( incomingValue );
|
|
|
|
VectorCopy( incomingOffset, incomingValue[ 3 ] );
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
m_cachedValue.Multiply( incomingValue, m_parent->GetTransform( frames ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_cachedValue = incomingValue;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
if( m_controller )
|
|
|
|
{
|
|
|
|
SkelMat3 m;
|
|
|
|
|
|
|
|
incomingQuat.Set( m_controller );
|
|
|
|
incomingQuat.GetMat3( m );
|
|
|
|
m_cachedValue.RotateBy( m );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_IKshoulder::skelBone_IKshoulder()
|
|
|
|
{
|
|
|
|
m_wrist = NULL;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_IKshoulder::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelMat4 baseMatrix, targetMatrix;
|
|
|
|
float desiredLength;
|
|
|
|
SkelVec3 newBaseY;
|
|
|
|
SkelVec3 newBaseZ;
|
|
|
|
SkelVec3 cross;
|
|
|
|
float cosUpperAngle;
|
|
|
|
float sinUpperAngle;
|
|
|
|
float maxLength;
|
|
|
|
float length;
|
|
|
|
float cosA;
|
|
|
|
float sinA;
|
|
|
|
|
|
|
|
if( !m_wrist )
|
|
|
|
{
|
|
|
|
m_cachedValue.MakeIdentity();
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
baseMatrix = m_parent->GetTransform( frames );
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
baseMatrix[ 3 ][ 0 ] += m_baseValue[ 0 ] * baseMatrix[ 0 ][ 0 ] + m_baseValue[ 1 ] * baseMatrix[ 1 ][ 0 ] + m_baseValue[ 2 ] * baseMatrix[ 2 ][ 0 ];
|
|
|
|
baseMatrix[ 3 ][ 1 ] += m_baseValue[ 0 ] * baseMatrix[ 0 ][ 1 ] + m_baseValue[ 1 ] * baseMatrix[ 1 ][ 1 ] + m_baseValue[ 2 ] * baseMatrix[ 2 ][ 1 ];
|
|
|
|
baseMatrix[ 3 ][ 2 ] += m_baseValue[ 0 ] * baseMatrix[ 0 ][ 2 ] + m_baseValue[ 1 ] * baseMatrix[ 1 ][ 2 ] + m_baseValue[ 2 ] * baseMatrix[ 2 ][ 2 ];
|
|
|
|
baseMatrix.InvertAxis( 0 );
|
|
|
|
baseMatrix.InvertAxis( 2 );
|
|
|
|
|
|
|
|
m_wristAngle = frames->GetSlerpValue( m_wrist->m_quatChannel );
|
|
|
|
m_wristAngle.GetMat4( targetMatrix );
|
|
|
|
|
|
|
|
frames->GetLerpValue3( m_wrist->m_offsetChannel, &m_wristPos );
|
|
|
|
m_cachedValue = baseMatrix;
|
|
|
|
VectorCopy( m_wristPos, targetMatrix[ 3 ] );
|
|
|
|
VectorSubtract( targetMatrix[ 3 ], baseMatrix[ 3 ], m_cachedValue[ 0 ] );
|
|
|
|
|
|
|
|
sinUpperAngle = VectorNormalize( m_cachedValue[ 0 ] );
|
|
|
|
|
|
|
|
newBaseY = baseMatrix[ 2 ];
|
|
|
|
newBaseZ = m_cachedValue[ 0 ];
|
|
|
|
|
|
|
|
CrossProduct( newBaseY, newBaseZ, cross );
|
|
|
|
VectorCopy( cross, m_cachedValue[ 1 ] );
|
|
|
|
|
|
|
|
newBaseY = targetMatrix[ 2 ];
|
|
|
|
newBaseZ = m_cachedValue[ 0 ];
|
|
|
|
|
|
|
|
CrossProduct( newBaseY, newBaseZ, cross );
|
|
|
|
VectorAdd( m_cachedValue[ 1 ], cross, m_cachedValue[ 1 ] );
|
|
|
|
|
|
|
|
desiredLength = VectorNormalize( m_cachedValue[ 1 ] );
|
|
|
|
|
|
|
|
if( !desiredLength ) {
|
|
|
|
m_cachedValue[ 1 ][ 1 ] = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
newBaseY = m_cachedValue[ 0 ];
|
|
|
|
newBaseZ = m_cachedValue[ 1 ];
|
|
|
|
|
|
|
|
CrossProduct( newBaseY, newBaseZ, cross );
|
|
|
|
VectorCopy( cross, m_cachedValue[ 2 ] );
|
|
|
|
|
|
|
|
cosUpperAngle = m_upperLength + m_lowerLength - 0.001;
|
|
|
|
|
|
|
|
if( sinUpperAngle > cosUpperAngle )
|
|
|
|
{
|
|
|
|
sinUpperAngle = cosUpperAngle;
|
|
|
|
|
|
|
|
m_wristPos = m_cachedValue[ 3 ];
|
|
|
|
|
|
|
|
m_wristPos[ 0 ] += m_cachedValue[ 0 ][ 0 ] * cosUpperAngle;
|
|
|
|
m_wristPos[ 1 ] += m_cachedValue[ 0 ][ 1 ] * cosUpperAngle;
|
|
|
|
m_wristPos[ 2 ] += m_cachedValue[ 0 ][ 2 ] * cosUpperAngle;
|
|
|
|
}
|
|
|
|
|
|
|
|
maxLength = ( sinUpperAngle * sinUpperAngle + m_upperLength * m_upperLength - m_lowerLength * m_lowerLength )
|
|
|
|
/ ( sinUpperAngle * m_upperLength + sinUpperAngle * m_upperLength );
|
|
|
|
|
|
|
|
if( maxLength > 1.0 ) {
|
|
|
|
maxLength = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_cosElbowAngle = -( ( m_lowerLength * m_lowerLength + m_upperLength * m_upperLength - sinUpperAngle * sinUpperAngle ) /
|
|
|
|
( m_upperLength * m_lowerLength + m_upperLength * m_lowerLength ) );
|
|
|
|
|
|
|
|
length = -sqrt( 1.0 - maxLength * maxLength );
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 0 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 0 ];
|
|
|
|
m_cachedValue[ 0 ][ 0 ] = cosA * maxLength - sinA * length;
|
|
|
|
m_cachedValue[ 1 ][ 0 ] = sinA * maxLength + cosA * length;
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 1 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 1 ];
|
|
|
|
m_cachedValue[ 0 ][ 1 ] = cosA * maxLength - sinA * length;
|
|
|
|
m_cachedValue[ 1 ][ 1 ] = sinA * maxLength + cosA * length;
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 2 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 2 ];
|
|
|
|
m_cachedValue[ 0 ][ 2 ] = cosA * maxLength - sinA * length;
|
|
|
|
m_cachedValue[ 1 ][ 2 ] = sinA * maxLength + cosA * length;
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKshoulder::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
m_baseValue = boneData->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_IKshoulder::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_IKshoulder::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return m_wrist;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKshoulder::SetElbowValue( float elbowOffset )
|
|
|
|
{
|
|
|
|
m_upperLength = elbowOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKshoulder::SetWristValue( float wristOffset )
|
|
|
|
{
|
|
|
|
m_lowerLength = wristOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKshoulder::SetWristBone( skelBone_IKwrist *wrist )
|
|
|
|
{
|
|
|
|
this->m_wrist = wrist;
|
|
|
|
}
|
|
|
|
|
|
|
|
float skelBone_IKshoulder::GetUpperLength()
|
|
|
|
{
|
|
|
|
return m_upperLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
float skelBone_IKshoulder::GetLowerLength()
|
|
|
|
{
|
|
|
|
return m_lowerLength;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_IKwrist::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
if( m_shoulder->m_isDirty ) {
|
|
|
|
m_shoulder->GetDirtyTransform( frames );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_shoulder->m_wristAngle.GetMat4( m_cachedValue );
|
|
|
|
VectorCopy( m_shoulder->m_wristPos, m_cachedValue[ 3 ] );
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKwrist::SetChannels( int quatChannel, int offsetChannel )
|
|
|
|
{
|
|
|
|
m_quatChannel = quatChannel;
|
|
|
|
m_offsetChannel = offsetChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKwrist::SetBoneRefs( skelBone_IKshoulder *shoulder )
|
|
|
|
{
|
|
|
|
m_shoulder = shoulder;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKwrist::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
m_shoulder->SetWristValue( boneData->length );
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_IKwrist::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_IKwrist::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return m_shoulder;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_IKelbow::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
float fLength;
|
|
|
|
float cosA, sinA;
|
|
|
|
|
|
|
|
m_cachedValue = m_shoulder->GetTransform( frames );
|
|
|
|
|
|
|
|
m_cachedValue[ 3 ][ 0 ] += m_cachedValue[ 0 ][ 0 ] * m_shoulder->m_upperLength;
|
|
|
|
m_cachedValue[ 3 ][ 1 ] += m_cachedValue[ 0 ][ 1 ] * m_shoulder->m_upperLength;
|
|
|
|
m_cachedValue[ 3 ][ 2 ] += m_cachedValue[ 0 ][ 2 ] * m_shoulder->m_upperLength;
|
|
|
|
|
|
|
|
fLength = sqrt( 1.0 - m_shoulder->m_cosElbowAngle * m_shoulder->m_cosElbowAngle );
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 0 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 0 ];
|
|
|
|
m_cachedValue[ 0 ][ 0 ] = cosA * m_shoulder->m_cosElbowAngle - sinA * fLength;
|
|
|
|
m_cachedValue[ 1 ][ 0 ] = sinA * m_shoulder->m_cosElbowAngle + cosA * fLength;
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 1 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 1 ];
|
|
|
|
m_cachedValue[ 0 ][ 1 ] = cosA * m_shoulder->m_cosElbowAngle - sinA * fLength;
|
|
|
|
m_cachedValue[ 1 ][ 1 ] = sinA * m_shoulder->m_cosElbowAngle + cosA * fLength;
|
|
|
|
|
|
|
|
cosA = m_cachedValue[ 0 ][ 2 ];
|
|
|
|
sinA = m_cachedValue[ 1 ][ 2 ];
|
|
|
|
m_cachedValue[ 0 ][ 2 ] = cosA * m_shoulder->m_cosElbowAngle - sinA * fLength;
|
|
|
|
m_cachedValue[ 1 ][ 2 ] = sinA * m_shoulder->m_cosElbowAngle + cosA * fLength;
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKelbow::SetBoneRefs( skelBone_IKshoulder *shoulder )
|
|
|
|
{
|
|
|
|
m_shoulder = shoulder;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_IKelbow::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
m_shoulder->SetElbowValue( boneData->length );
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_IKelbow::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_IKelbow::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return m_shoulder;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_AvRot::skelBone_AvRot()
|
|
|
|
{
|
|
|
|
m_reference1 = NULL;
|
|
|
|
m_reference2 = NULL;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_AvRot::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelQuat temp1, temp2;
|
|
|
|
SkelMat4 temp;
|
|
|
|
|
|
|
|
temp1 = m_reference1->GetTransform( frames );
|
|
|
|
temp2 = m_reference2->GetTransform( frames );
|
|
|
|
|
|
|
|
// lerp values
|
|
|
|
Slerp( temp1, temp2, m_bone2weight, &m_cachedQuat );
|
|
|
|
|
|
|
|
VectorCopy( m_basePos, m_cachedValue[ 3 ] );
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
temp.Multiply( m_cachedValue, m_parent->GetTransform( frames ) );
|
|
|
|
m_cachedValue = temp;
|
|
|
|
}
|
|
|
|
|
2016-03-27 11:49:47 +02:00
|
|
|
m_cachedQuat.GetMat4( m_cachedValue );
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_AvRot::SetBoneRefs( skelBone_Base *ref1, skelBone_Base *ref2 )
|
|
|
|
{
|
|
|
|
m_reference1 = ref1;
|
|
|
|
m_reference2 = ref2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_AvRot::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
m_basePos = boneData->offset;
|
|
|
|
m_bone2weight = boneData->weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_AvRot::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_AvRot::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
if( num )
|
|
|
|
{
|
|
|
|
return m_reference2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return m_reference1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_HoseRot::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2016-08-13 18:32:13 +02:00
|
|
|
SkelMat4 mat;
|
|
|
|
|
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
mat = m_parent->GetTransform( frames );
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetDirtyTransform( mat, m_target->GetTransform( frames ) );
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_HoseRot::GetDirtyTransform( SkelMat4& myParentTM, SkelMat4& targetTM )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelMat4 m;
|
|
|
|
SkelMat4 invParentTM;
|
|
|
|
SkelMat4 temp;
|
|
|
|
SkelVec3 rotaxis;
|
|
|
|
SkelVec3 targetup, targetaim;
|
|
|
|
SkelVec3 upaxis, aimaxis;
|
|
|
|
SkelVec3 tmp;
|
|
|
|
SkelQuat targetQuat;
|
|
|
|
float l, s, c;
|
|
|
|
float angle, vScale;
|
|
|
|
|
|
|
|
aimaxis = myParentTM[ 0 ];
|
|
|
|
targetaim = targetTM[ 0 ];
|
|
|
|
|
|
|
|
CrossProduct( targetaim, aimaxis, rotaxis );
|
|
|
|
|
|
|
|
s = VectorLengthSquared( rotaxis );
|
|
|
|
|
|
|
|
if( s == 0.0 ) {
|
|
|
|
rotaxis.x = 1.0;
|
|
|
|
} else if( s != 1.0 ) {
|
|
|
|
l = 1.0 / sqrt( s );
|
|
|
|
VectorScale( rotaxis, l, rotaxis );
|
|
|
|
}
|
|
|
|
|
|
|
|
s = DotProduct( aimaxis, targetaim );
|
|
|
|
if( s < 1.0 ) {
|
|
|
|
if( s > -0.999 ) {
|
|
|
|
angle = acos( s );
|
|
|
|
} else {
|
|
|
|
angle = 6.2831855f;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
angle = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vScale = angle * m_bendRatio;
|
|
|
|
if( vScale > m_bendMax ) {
|
|
|
|
vScale = m_bendMax;
|
|
|
|
}
|
|
|
|
|
|
|
|
temp[ 0 ][ 0 ] = myParentTM[ 0 ][ 0 ];
|
|
|
|
temp[ 0 ][ 1 ] = myParentTM[ 1 ][ 0 ];
|
|
|
|
temp[ 0 ][ 2 ] = myParentTM[ 2 ][ 0 ];
|
|
|
|
temp[ 1 ][ 0 ] = myParentTM[ 0 ][ 1 ];
|
|
|
|
temp[ 1 ][ 1 ] = myParentTM[ 1 ][ 1 ];
|
|
|
|
temp[ 1 ][ 2 ] = myParentTM[ 2 ][ 1 ];
|
|
|
|
temp[ 2 ][ 0 ] = myParentTM[ 0 ][ 2 ];
|
|
|
|
temp[ 2 ][ 1 ] = myParentTM[ 1 ][ 2 ];
|
|
|
|
temp[ 2 ][ 2 ] = myParentTM[ 2 ][ 2 ];
|
|
|
|
temp[ 3 ][ 0 ] = -( myParentTM[ 0 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 0 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 0 ][ 2 ] * myParentTM[ 3 ][ 2 ] );
|
|
|
|
temp[ 3 ][ 1 ] = -( myParentTM[ 1 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 1 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 1 ][ 2 ] * myParentTM[ 3 ][ 2 ] );
|
|
|
|
temp[ 3 ][ 2 ] = -( myParentTM[ 2 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 2 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 2 ][ 2 ] * myParentTM[ 3 ][ 2 ] );
|
|
|
|
|
|
|
|
m.Multiply( temp, myParentTM );
|
|
|
|
|
|
|
|
VectorCopy( rotaxis, tmp );
|
|
|
|
rotaxis[ 0 ] = tmp[ 0 ] * temp[ 0 ][ 0 ] + tmp[ 1 ] * temp[ 1 ][ 0 ] + tmp[ 2 ] * temp[ 2 ][ 0 ];
|
|
|
|
rotaxis[ 1 ] = tmp[ 0 ] * temp[ 0 ][ 1 ] + tmp[ 1 ] * temp[ 1 ][ 1 ] + tmp[ 2 ] * temp[ 2 ][ 1 ];
|
|
|
|
rotaxis[ 2 ] = tmp[ 0 ] * temp[ 0 ][ 2 ] + tmp[ 1 ] * temp[ 1 ][ 2 ] + tmp[ 2 ] * temp[ 2 ][ 2 ];
|
|
|
|
|
|
|
|
targetaim.y = cos( vScale * 0.5 );
|
|
|
|
targetup.y = rotaxis.x * targetaim.y;
|
|
|
|
targetup.z = rotaxis.y * targetaim.y;
|
|
|
|
targetaim.x = rotaxis.z * targetaim.y;
|
|
|
|
|
|
|
|
c = cos( vScale * 0.5 );
|
|
|
|
l = sqrt( 1.0 - c * c );
|
|
|
|
|
|
|
|
m_cachedQuat[ 0 ] = rotaxis[ 0 ] * l;
|
|
|
|
m_cachedQuat[ 1 ] = rotaxis[ 1 ] * l;
|
|
|
|
m_cachedQuat[ 2 ] = rotaxis[ 2 ] * l;
|
|
|
|
m_cachedQuat[ 3 ] = c;
|
|
|
|
|
|
|
|
if( m_spinRatio < 1.0 )
|
|
|
|
{
|
|
|
|
m.Multiply( targetTM, temp );
|
|
|
|
MatToQuat( m.val, targetQuat.val );
|
|
|
|
Slerp( targetQuat, m_cachedQuat, m_spinRatio, &m_cachedQuat );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_cachedQuat.GetMat4( m_cachedValue );
|
|
|
|
VectorCopy( m_basePos, m_cachedValue[ 3 ] );
|
|
|
|
|
|
|
|
m.Multiply( m_cachedValue, myParentTM );
|
|
|
|
m_cachedValue = m;
|
|
|
|
|
|
|
|
m_isDirty = false;
|
|
|
|
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_HoseRot::SetBoneRefs( skelBone_Base *ref )
|
|
|
|
{
|
|
|
|
m_target = ref;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_HoseRot::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
m_bendRatio = boneData->bendRatio;
|
|
|
|
m_bendMax = boneData->bendMax;
|
|
|
|
m_spinRatio = boneData->spinRatio;
|
|
|
|
m_basePos = boneData->offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_HoseRot::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_HoseRot::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return m_target;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_HoseRotBoth::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelMat4 myParentTM;
|
|
|
|
SkelMat4 targetTM;
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
myParentTM = m_parent->GetTransform( frames );
|
|
|
|
targetTM = m_target->GetTransform( frames );
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
VectorInverse( targetTM[ 0 ] );
|
|
|
|
VectorInverse( targetTM[ 2 ] );
|
|
|
|
VectorInverse( myParentTM[ 0 ] );
|
|
|
|
VectorInverse( myParentTM[ 2 ] );
|
|
|
|
|
|
|
|
return skelBone_HoseRot::GetDirtyTransform( myParentTM, targetTM );
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_HoseRotBoth::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
skelBone_HoseRot::SetBaseValue( boneData );
|
|
|
|
m_basePos.x = -m_basePos.x;
|
|
|
|
m_basePos.z = -m_basePos.z;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_HoseRotParent::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
SkelMat4 myParentTM;
|
|
|
|
SkelMat4 targetTM;
|
|
|
|
|
2016-08-13 18:32:13 +02:00
|
|
|
if( m_parent )
|
|
|
|
{
|
|
|
|
myParentTM = m_parent->GetTransform( frames );
|
|
|
|
targetTM = m_target->GetTransform( frames );
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
VectorInverse( myParentTM[ 0 ] );
|
|
|
|
VectorInverse( myParentTM[ 2 ] );
|
|
|
|
|
|
|
|
return skelBone_HoseRot::GetDirtyTransform( myParentTM, targetTM );
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_HoseRotParent::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
skelBone_HoseRot::SetBaseValue( boneData );
|
|
|
|
m_basePos.x = -m_basePos.x;
|
|
|
|
m_basePos.z = -m_basePos.z;
|
|
|
|
}
|
|
|
|
|
2023-01-30 00:23:47 +01:00
|
|
|
SkelMat4 &skelBone_World::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
m_cachedValue.MakeIdentity();
|
|
|
|
m_isDirty = false;
|
|
|
|
return m_cachedValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void skelBone_World::SetBaseValue( boneData_t *boneData )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int skelBone_World::GetChannelIndex( int num )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
skelBone_Base *skelBone_World::GetBoneRef( int num )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|