You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

900 lines
26 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plController.h"
#include "hsInterp.h"
#include "hsResMgr.h"
#include "../plTransform/hsEuler.h"
#include "plAnimTimeConvert.h"
/////////////////////////////////////////////
// Controller interp caching
/////////////////////////////////////////////
static const char *kInvalidInterpString = "Invalid call to plController::Interp()";
plControllerCacheInfo::plControllerCacheInfo() : fNumSubControllers(0), fSubControllers(nil), fKeyIndex(0), fAtc(nil) {}
plControllerCacheInfo::~plControllerCacheInfo()
{
int i;
for (i = 0; i < fNumSubControllers; i++)
delete fSubControllers[i];
delete [] fSubControllers;
}
void plControllerCacheInfo::SetATC(plAnimTimeConvert *atc)
{
fAtc = atc;
int i;
for (i = 0; i < fNumSubControllers; i++)
if (fSubControllers[i])
fSubControllers[i]->SetATC(atc);
}
//////////////////////////////////////////////////////////////////////////////////////////
plLeafController::~plLeafController()
{
delete [] fKeys;
}
void plLeafController::Interp(hsScalar time, hsScalar* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kScalarKeyFrame || fType == hsKeyFrame::kBezScalarKeyFrame, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
if (fType == hsKeyFrame::kScalarKeyFrame)
{
hsScalarKey *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsScalarKey), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(k1->fValue, k2->fValue, t, result);
}
else
{
hsBezScalarKey *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsBezScalarKey), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::BezInterp(k1, k2, t, result);
}
}
void plLeafController::Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kPoint3KeyFrame || fType == hsKeyFrame::kBezPoint3KeyFrame, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
if (fType == hsKeyFrame::kPoint3KeyFrame)
{
hsPoint3Key *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsPoint3Key), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(&k1->fValue, &k2->fValue, t, result);
}
else
{
hsBezPoint3Key *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsBezPoint3Key), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::BezInterp(k1, k2, t, result);
}
}
void plLeafController::Interp(hsScalar time, hsScaleValue* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kScaleKeyFrame || fType == hsKeyFrame::kBezScaleKeyFrame, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
if (fType == hsKeyFrame::kScaleKeyFrame)
{
hsScaleKey *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsScaleKey), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(&k1->fValue, &k2->fValue, t, result);
}
else
{
hsBezScaleKey *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsBezScaleKey), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::BezInterp(k1, k2, t, result);
}
}
void plLeafController::Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kQuatKeyFrame ||
fType == hsKeyFrame::kCompressedQuatKeyFrame32 ||
fType == hsKeyFrame::kCompressedQuatKeyFrame64, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
if (fType == hsKeyFrame::kQuatKeyFrame)
{
hsQuatKey *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsQuatKey), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(&k1->fValue, &k2->fValue, t, result);
}
else if (fType == hsKeyFrame::kCompressedQuatKeyFrame32)
{
hsCompressedQuatKey32 *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsCompressedQuatKey32), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsQuat q1, q2;
k1->GetQuat(q1);
k2->GetQuat(q2);
hsInterp::LinInterp(&q1, &q2, t, result);
}
else // (fType == hsKeyFrame::kCompressedQuatKeyFrame64)
{
hsCompressedQuatKey64 *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsCompressedQuatKey64), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsQuat q1, q2;
k1->GetQuat(q1);
k2->GetQuat(q2);
hsInterp::LinInterp(&q1, &q2, t, result);
}
}
void plLeafController::Interp(hsScalar time, hsMatrix33* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kMatrix33KeyFrame, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
hsMatrix33Key *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsMatrix33Key), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(&k1->fValue, &k2->fValue, t, result);
}
void plLeafController::Interp(hsScalar time, hsMatrix44* result, plControllerCacheInfo *cache) const
{
hsAssert(fType == hsKeyFrame::kMatrix44KeyFrame, kInvalidInterpString);
hsBool tryForward = (cache? cache->fAtc->IsForewards() : true);
hsMatrix44Key *k1, *k2;
hsScalar t;
UInt32 *idxStore = (cache ? &cache->fKeyIndex : &fLastKeyIdx);
hsInterp::GetBoundaryKeyFrames(time, fNumKeys, fKeys, sizeof(hsMatrix44Key), (hsKeyFrame**)&k1, (hsKeyFrame**)&k2, idxStore, &t, tryForward);
hsInterp::LinInterp(&k1->fValue, &k2->fValue, t, result);
}
void plLeafController::Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache) const
{
hsPoint3 value;
Interp(time, &value, cache);
result->r = value.fX;
result->g = value.fY;
result->b = value.fZ;
}
plControllerCacheInfo *plLeafController::CreateCache() const
{
plControllerCacheInfo *cache = TRACKED_NEW plControllerCacheInfo;
cache->fNumSubControllers = 0;
return cache;
}
hsScalar plLeafController::GetLength() const
{
UInt32 stride = GetStride();
if (stride == 0 || fNumKeys == 0)
return 0;
UInt8 *ptr = (UInt8 *)fKeys;
return ((hsKeyFrame *)(ptr + (fNumKeys - 1) * stride))->fFrame / MAX_FRAMES_PER_SEC;
}
UInt32 plLeafController::GetStride() const
{
switch (fType)
{
case hsKeyFrame::kPoint3KeyFrame:
return sizeof(hsPoint3Key);
case hsKeyFrame::kBezPoint3KeyFrame:
return sizeof(hsBezPoint3Key);
case hsKeyFrame::kScalarKeyFrame:
return sizeof(hsScalarKey);
case hsKeyFrame::kBezScalarKeyFrame:
return sizeof(hsBezScalarKey);
case hsKeyFrame::kScaleKeyFrame:
return sizeof(hsScaleKey);
case hsKeyFrame::kBezScaleKeyFrame:
return sizeof(hsBezScaleKey);
case hsKeyFrame::kQuatKeyFrame:
return sizeof(hsQuatKey);
case hsKeyFrame::kCompressedQuatKeyFrame32:
return sizeof(hsCompressedQuatKey32);
case hsKeyFrame::kCompressedQuatKeyFrame64:
return sizeof(hsCompressedQuatKey64);
case hsKeyFrame::k3dsMaxKeyFrame:
return sizeof(hsG3DSMaxKeyFrame);
case hsKeyFrame::kMatrix33KeyFrame:
return sizeof(hsMatrix33Key);
case hsKeyFrame::kMatrix44KeyFrame:
return sizeof(hsMatrix44Key);
case hsKeyFrame::kUnknownKeyFrame:
default:
return 0;
}
}
hsPoint3Key *plLeafController::GetPoint3Key(UInt32 i) const
{
if (fType != hsKeyFrame::kPoint3KeyFrame)
return nil;
return (hsPoint3Key *)((UInt8 *)fKeys + i * sizeof(hsPoint3Key));
}
hsBezPoint3Key *plLeafController::GetBezPoint3Key(UInt32 i) const
{
if (fType != hsKeyFrame::kBezPoint3KeyFrame)
return nil;
return (hsBezPoint3Key *)((UInt8 *)fKeys + i * sizeof(hsBezPoint3Key));
}
hsScalarKey *plLeafController::GetScalarKey(UInt32 i) const
{
if (fType != hsKeyFrame::kScalarKeyFrame)
return nil;
return (hsScalarKey *)((UInt8 *)fKeys + i * sizeof(hsScalarKey));
}
hsBezScalarKey *plLeafController::GetBezScalarKey(UInt32 i) const
{
if (fType != hsKeyFrame::kBezScalarKeyFrame)
return nil;
return (hsBezScalarKey *)((UInt8 *)fKeys + i * sizeof(hsBezScalarKey));
}
hsScaleKey *plLeafController::GetScaleKey(UInt32 i) const
{
if (fType != hsKeyFrame::kScaleKeyFrame)
return nil;
return (hsScaleKey *)((UInt8 *)fKeys + i * sizeof(hsScaleKey));
}
hsBezScaleKey *plLeafController::GetBezScaleKey(UInt32 i) const
{
if (fType != hsKeyFrame::kBezScaleKeyFrame)
return nil;
return (hsBezScaleKey *)((UInt8 *)fKeys + i * sizeof(hsBezScaleKey));
}
hsQuatKey *plLeafController::GetQuatKey(UInt32 i) const
{
if (fType != hsKeyFrame::kQuatKeyFrame)
return nil;
return (hsQuatKey *)((UInt8 *)fKeys + i * sizeof(hsQuatKey));
}
hsCompressedQuatKey32 *plLeafController::GetCompressedQuatKey32(UInt32 i) const
{
if (fType != hsKeyFrame::kCompressedQuatKeyFrame32)
return nil;
return (hsCompressedQuatKey32 *)((UInt8 *)fKeys + i * sizeof(hsCompressedQuatKey32));
}
hsCompressedQuatKey64 *plLeafController::GetCompressedQuatKey64(UInt32 i) const
{
if (fType != hsKeyFrame::kCompressedQuatKeyFrame64)
return nil;
return (hsCompressedQuatKey64 *)((UInt8 *)fKeys + i * sizeof(hsCompressedQuatKey64));
}
hsG3DSMaxKeyFrame *plLeafController::Get3DSMaxKey(UInt32 i) const
{
if (fType != hsKeyFrame::k3dsMaxKeyFrame)
return nil;
return (hsG3DSMaxKeyFrame *)((UInt8 *)fKeys + i * sizeof(hsG3DSMaxKeyFrame));
}
hsMatrix33Key *plLeafController::GetMatrix33Key(UInt32 i) const
{
if (fType != hsKeyFrame::kMatrix33KeyFrame)
return nil;
return (hsMatrix33Key *)((UInt8 *)fKeys + i * sizeof(hsMatrix33Key));
}
hsMatrix44Key *plLeafController::GetMatrix44Key(UInt32 i) const
{
if (fType != hsKeyFrame::kMatrix44KeyFrame)
return nil;
return (hsMatrix44Key *)((UInt8 *)fKeys + i * sizeof(hsMatrix44Key));
}
void plLeafController::GetKeyTimes(hsTArray<hsScalar> &keyTimes) const
{
int cIdx;
int kIdx;
UInt32 stride = GetStride();
UInt8 *keyPtr = (UInt8 *)fKeys;
for (cIdx = 0, kIdx = 0; cIdx < fNumKeys, kIdx < keyTimes.GetCount();)
{
hsScalar kTime = keyTimes[kIdx];
hsScalar cTime = ((hsKeyFrame*)(keyPtr + cIdx * stride))->fFrame / MAX_FRAMES_PER_SEC;
if (cTime < kTime)
{
keyTimes.InsertAtIndex(kIdx, cTime);
cIdx++;
kIdx++;
}
else if (cTime > kTime)
{
kIdx++;
}
else
{
kIdx++;
cIdx++;
}
}
// All remaining times in the controller are later than the original keyTimes set
for (; cIdx < fNumKeys; cIdx++)
{
hsScalar cTime = ((hsKeyFrame*)(keyPtr + cIdx * stride))->fFrame / MAX_FRAMES_PER_SEC;
keyTimes.Append(cTime);
}
}
void plLeafController::AllocKeys(UInt32 numKeys, UInt8 type)
{
delete fKeys;
fNumKeys = numKeys;
fType = type;
switch (fType)
{
case hsKeyFrame::kPoint3KeyFrame:
fKeys = TRACKED_NEW hsPoint3Key[fNumKeys];
break;
case hsKeyFrame::kBezPoint3KeyFrame:
fKeys = TRACKED_NEW hsBezPoint3Key[fNumKeys];
break;
case hsKeyFrame::kScalarKeyFrame:
fKeys = TRACKED_NEW hsScalarKey[fNumKeys];
break;
case hsKeyFrame::kBezScalarKeyFrame:
fKeys = TRACKED_NEW hsBezScalarKey[fNumKeys];
break;
case hsKeyFrame::kScaleKeyFrame:
fKeys = TRACKED_NEW hsScaleKey[fNumKeys];
break;
case hsKeyFrame::kBezScaleKeyFrame:
fKeys = TRACKED_NEW hsBezScaleKey[fNumKeys];
break;
case hsKeyFrame::kQuatKeyFrame:
fKeys = TRACKED_NEW hsQuatKey[fNumKeys];
break;
case hsKeyFrame::kCompressedQuatKeyFrame32:
fKeys = TRACKED_NEW hsCompressedQuatKey32[fNumKeys];
break;
case hsKeyFrame::kCompressedQuatKeyFrame64:
fKeys = TRACKED_NEW hsCompressedQuatKey64[fNumKeys];
break;
case hsKeyFrame::k3dsMaxKeyFrame:
fKeys = TRACKED_NEW hsG3DSMaxKeyFrame[fNumKeys];
break;
case hsKeyFrame::kMatrix33KeyFrame:
fKeys = TRACKED_NEW hsMatrix33Key[fNumKeys];
break;
case hsKeyFrame::kMatrix44KeyFrame:
fKeys = TRACKED_NEW hsMatrix44Key[fNumKeys];
break;
case hsKeyFrame::kUnknownKeyFrame:
default:
hsAssert(false, "Trying to allocate unknown keyframe type");
break;
}
}
void plLeafController::QuickScalarController(int numKeys, hsScalar* times, hsScalar* values, UInt32 valueStrides)
{
AllocKeys(numKeys, hsKeyFrame::kScalarKeyFrame);
int i;
for( i = 0; i < numKeys; i++ )
{
((hsScalarKey*)fKeys)[i].fFrame = (UInt16)(*times++ * MAX_FRAMES_PER_SEC);
((hsScalarKey*)fKeys)[i].fValue = *values;
values = (hsScalar *)((UInt8 *)values + valueStrides);
}
}
// If all the keys are the same, this controller is pretty useless.
// This situation actually comes up a lot because of the biped killer
// trying to convert character studio animations.
hsBool plLeafController::AllKeysMatch() const
{
if (fNumKeys <= 1)
return true;
int idx;
for (idx = 1; idx < fNumKeys; idx++)
{
switch (fType)
{
case hsKeyFrame::kPoint3KeyFrame:
{
hsPoint3Key *k1 = GetPoint3Key(idx - 1);
hsPoint3Key *k2 = GetPoint3Key(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kBezPoint3KeyFrame:
{
hsBezPoint3Key *k1 = GetBezPoint3Key(idx - 1);
hsBezPoint3Key *k2 = GetBezPoint3Key(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kScalarKeyFrame:
{
hsScalarKey *k1 = GetScalarKey(idx - 1);
hsScalarKey *k2 = GetScalarKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kBezScalarKeyFrame:
{
hsBezScalarKey *k1 = GetBezScalarKey(idx - 1);
hsBezScalarKey *k2 = GetBezScalarKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kScaleKeyFrame:
{
hsScaleKey *k1 = GetScaleKey(idx - 1);
hsScaleKey *k2 = GetScaleKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kBezScaleKeyFrame:
{
hsBezScaleKey *k1 = GetBezScaleKey(idx - 1);
hsBezScaleKey *k2 = GetBezScaleKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kQuatKeyFrame:
{
hsQuatKey *k1 = GetQuatKey(idx - 1);
hsQuatKey *k2 = GetQuatKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kCompressedQuatKeyFrame32:
{
hsCompressedQuatKey32 *k1 = GetCompressedQuatKey32(idx - 1);
hsCompressedQuatKey32 *k2 = GetCompressedQuatKey32(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kCompressedQuatKeyFrame64:
{
hsCompressedQuatKey64 *k1 = GetCompressedQuatKey64(idx - 1);
hsCompressedQuatKey64 *k2 = GetCompressedQuatKey64(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::k3dsMaxKeyFrame:
{
hsG3DSMaxKeyFrame *k1 = Get3DSMaxKey(idx - 1);
hsG3DSMaxKeyFrame *k2 = Get3DSMaxKey(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kMatrix33KeyFrame:
{
hsMatrix33Key *k1 = GetMatrix33Key(idx - 1);
hsMatrix33Key *k2 = GetMatrix33Key(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kMatrix44KeyFrame:
{
hsMatrix44Key *k1 = GetMatrix44Key(idx - 1);
hsMatrix44Key *k2 = GetMatrix44Key(idx);
if (!k1->CompareValue(k2))
return false;
break;
}
case hsKeyFrame::kUnknownKeyFrame:
default:
hsAssert(false, "Trying to compare unknown keyframe type");
return false;
}
}
return true;
}
hsBool plLeafController::PurgeRedundantSubcontrollers()
{
return AllKeysMatch();
}
void plLeafController::Read(hsStream* s, hsResMgr *mgr)
{
UInt8 type = s->ReadByte();
UInt32 numKeys = s->ReadSwap32();
AllocKeys(numKeys, type);
int i;
switch (fType)
{
case hsKeyFrame::kPoint3KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsPoint3Key *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kBezPoint3KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezPoint3Key *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kScalarKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsScalarKey *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kBezScalarKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezScalarKey *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kScaleKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsScaleKey *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kBezScaleKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezScaleKey *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kQuatKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsQuatKey *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kCompressedQuatKeyFrame32:
for (i = 0; i < fNumKeys; i++)
((hsCompressedQuatKey32 *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kCompressedQuatKeyFrame64:
for (i = 0; i < fNumKeys; i++)
((hsCompressedQuatKey64 *)fKeys)[i].Read(s);
break;
case hsKeyFrame::k3dsMaxKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsG3DSMaxKeyFrame *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kMatrix33KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsMatrix33Key *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kMatrix44KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsMatrix44Key *)fKeys)[i].Read(s);
break;
case hsKeyFrame::kUnknownKeyFrame:
default:
hsAssert(false, "Reading in controller with unknown key data");
break;
}
}
void plLeafController::Write(hsStream* s, hsResMgr *mgr)
{
s->WriteByte(fType);
s->WriteSwap32(fNumKeys);
int i;
switch (fType)
{
case hsKeyFrame::kPoint3KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsPoint3Key *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kBezPoint3KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezPoint3Key *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kScalarKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsScalarKey *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kBezScalarKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezScalarKey *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kScaleKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsScaleKey *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kBezScaleKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsBezScaleKey *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kQuatKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsQuatKey *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kCompressedQuatKeyFrame32:
for (i = 0; i < fNumKeys; i++)
((hsCompressedQuatKey32 *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kCompressedQuatKeyFrame64:
for (i = 0; i < fNumKeys; i++)
((hsCompressedQuatKey64 *)fKeys)[i].Write(s);
break;
case hsKeyFrame::k3dsMaxKeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsG3DSMaxKeyFrame *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kMatrix33KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsMatrix33Key *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kMatrix44KeyFrame:
for (i = 0; i < fNumKeys; i++)
((hsMatrix44Key *)fKeys)[i].Write(s);
break;
case hsKeyFrame::kUnknownKeyFrame:
default:
hsAssert(false, "Writing controller with unknown key data");
break;
}
}
/////////////////////////////////////////////////////////////////////////////////
plCompoundController::plCompoundController() : fXController(nil), fYController(nil), fZController(nil) {}
plCompoundController::~plCompoundController()
{
delete fXController;
delete fYController;
delete fZController;
}
void plCompoundController::Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache) const
{
if (fXController)
fXController->Interp(time, &result->fX, (cache ? cache->fSubControllers[0] : nil));
if (fYController)
fYController->Interp(time, &result->fY, (cache ? cache->fSubControllers[1] : nil));
if (fZController)
fZController->Interp(time, &result->fZ, (cache ? cache->fSubControllers[2] : nil));
}
void plCompoundController::Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache) const
{
hsEuler eul(0,0,0,EulOrdXYZs);
fXController->Interp(time, &eul.fX, (cache ? cache->fSubControllers[0] : nil));
fYController->Interp(time, &eul.fY, (cache ? cache->fSubControllers[1] : nil));
fZController->Interp(time, &eul.fZ, (cache ? cache->fSubControllers[2] : nil));
eul.GetQuat(result);
}
void plCompoundController::Interp(hsScalar time, hsAffineParts* parts, plControllerCacheInfo *cache) const
{
if (fXController)
fXController->Interp(time, &parts->fT, (cache ? cache->fSubControllers[0] : nil));
if (fYController)
fYController->Interp(time, &parts->fQ, (cache ? cache->fSubControllers[1] : nil));
hsScaleValue sv;
if (fZController)
{
fZController->Interp(time, &sv, (cache ? cache->fSubControllers[2] : nil));
parts->fU = sv.fQ;
parts->fK = sv.fS;
}
}
void plCompoundController::Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache) const
{
fXController->Interp(time, &result->r, (cache ? cache->fSubControllers[0] : nil));
fYController->Interp(time, &result->g, (cache ? cache->fSubControllers[1] : nil));
fZController->Interp(time, &result->b, (cache ? cache->fSubControllers[2] : nil));
}
hsScalar plCompoundController::GetLength() const
{
hsScalar len=0;
int i;
for(i=0; i<3; i++)
{
if (GetController(i))
len = hsMaximum(len, GetController(i)->GetLength());
}
return len;
}
void plCompoundController::GetKeyTimes(hsTArray<hsScalar> &keyTimes) const
{
if (fXController)
fXController->GetKeyTimes(keyTimes);
if (fYController)
fYController->GetKeyTimes(keyTimes);
if (fZController)
fZController->GetKeyTimes(keyTimes);
}
hsBool plCompoundController::AllKeysMatch() const
{
return (!fXController || fXController->AllKeysMatch()) &&
(!fYController || fYController->AllKeysMatch()) &&
(!fZController || fZController->AllKeysMatch());
}
// Careful here... We might detect that one of our subcontrollers
// has animation keys that all have the same value. That doesn't
// mean they're all zero though. An avatar animation might have
// elbow bend a constant 90 degrees through the entire anim, but
// if we delete the controller and assume zero, we'll have problems.
// Transform controller channels get around this by sampling the source
// first and using that to fill in the missing subcontrollers.
//
// Note: that one of our subcontrollers could itself be a compound
// controller. An example would be a controller for XYZ Euler angles
// that's a sub of the pos/rot/scale transform controller.
// It's possible that some of these sub-sub controllers could be
// removed, but then we'd have to store the default values somewhere.
// At the moment, this doesn't seem likely to save us enough space
// to be worth the effort. (This is why this function doesn't
// recursively call purge on its subcontrollers.)
hsBool plCompoundController::PurgeRedundantSubcontrollers()
{
if (fXController && fXController->AllKeysMatch())
{
delete fXController;
fXController = nil;
}
if (fYController && fYController->AllKeysMatch())
{
delete fYController;
fYController = nil;
}
if (fZController && fZController->AllKeysMatch())
{
delete fZController;
fZController = nil;
}
return (!fXController && !fYController && !fZController);
}
plControllerCacheInfo* plCompoundController::CreateCache() const
{
plControllerCacheInfo* cache = TRACKED_NEW plControllerCacheInfo;
cache->fNumSubControllers = 3;
cache->fSubControllers = TRACKED_NEW plControllerCacheInfo*[cache->fNumSubControllers];
int i;
for (i = 0; i < cache->fNumSubControllers; i++)
cache->fSubControllers[i] = (GetController(i) ? GetController(i)->CreateCache() : nil);
return cache;
}
plController* plCompoundController::GetController(Int32 i) const
{
return (i==0 ? fXController : (i==1 ? fYController : fZController));
}
void plCompoundController::SetController(Int32 i, plController* c)
{
delete GetController(i);
(i==0 ? fXController : (i==1 ? fYController : fZController)) = c;
}
void plCompoundController::Read(hsStream* stream, hsResMgr *mgr)
{
fXController = plController::ConvertNoRef(mgr->ReadCreatable(stream));
fYController = plController::ConvertNoRef(mgr->ReadCreatable(stream));
fZController = plController::ConvertNoRef(mgr->ReadCreatable(stream));
}
void plCompoundController::Write(hsStream* stream, hsResMgr *mgr)
{
mgr->WriteCreatable(stream, fXController);
mgr->WriteCreatable(stream, fYController);
mgr->WriteCreatable(stream, fZController);
}