mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Fix line endings and tabs
This commit is contained in:
@ -1,31 +1,31 @@
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib/inc")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plInterp_SOURCES
|
||||
hsInterp.cpp
|
||||
hsKeys.cpp
|
||||
plAnimPath.cpp
|
||||
plAnimTimeConvert.cpp
|
||||
plATCEaseCurves.cpp
|
||||
plController.cpp
|
||||
plModulator.cpp
|
||||
)
|
||||
|
||||
set(plInterp_HEADERS
|
||||
hsInterp.h
|
||||
hsKeys.h
|
||||
hsTimedValue.h
|
||||
plAnimEaseTypes.h
|
||||
plAnimPath.h
|
||||
plAnimTimeConvert.h
|
||||
plController.h
|
||||
plInterpCreatable.h
|
||||
plModulator.h
|
||||
)
|
||||
|
||||
add_library(plInterp STATIC ${plInterp_SOURCES} ${plInterp_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plInterp_SOURCES})
|
||||
source_group("Header Files" FILES ${plInterp_HEADERS})
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib/inc")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plInterp_SOURCES
|
||||
hsInterp.cpp
|
||||
hsKeys.cpp
|
||||
plAnimPath.cpp
|
||||
plAnimTimeConvert.cpp
|
||||
plATCEaseCurves.cpp
|
||||
plController.cpp
|
||||
plModulator.cpp
|
||||
)
|
||||
|
||||
set(plInterp_HEADERS
|
||||
hsInterp.h
|
||||
hsKeys.h
|
||||
hsTimedValue.h
|
||||
plAnimEaseTypes.h
|
||||
plAnimPath.h
|
||||
plAnimTimeConvert.h
|
||||
plController.h
|
||||
plInterpCreatable.h
|
||||
plModulator.h
|
||||
)
|
||||
|
||||
add_library(plInterp STATIC ${plInterp_SOURCES} ${plInterp_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plInterp_SOURCES})
|
||||
source_group("Header Files" FILES ${plInterp_HEADERS})
|
||||
|
@ -1,494 +1,494 @@
|
||||
/*==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 "hsTypes.h"
|
||||
#include "hsInterp.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "hsColorRGBA.h"
|
||||
#include "hsPoint2.h"
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// linear interpolation
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void hsInterp::LinInterp(hsScalar k1, hsScalar k2, hsScalar t, hsScalar* result)
|
||||
{
|
||||
*result = k1 + t * (k2 - k1);
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsScalarTriple* k1, const hsScalarTriple* k2, hsScalar t,
|
||||
hsScalarTriple* result)
|
||||
{
|
||||
if (t==0.0)
|
||||
*result = *k1;
|
||||
else
|
||||
if (t==1.0)
|
||||
*result = *k2;
|
||||
else
|
||||
{
|
||||
LinInterp(k1->fX, k2->fX, t, &result->fX);
|
||||
LinInterp(k1->fY, k2->fY, t, &result->fY);
|
||||
LinInterp(k1->fZ, k2->fZ, t, &result->fZ);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsColorRGBA* k1, const hsColorRGBA* k2, hsScalar t,
|
||||
hsColorRGBA* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
result->r = k1->r;
|
||||
result->g = k1->g;
|
||||
result->b = k1->b;
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
result->a = k1->a;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t==1.0)
|
||||
{
|
||||
result->r = k2->r;
|
||||
result->g = k2->g;
|
||||
result->b = k2->b;
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
result->a = k2->a;
|
||||
return;
|
||||
}
|
||||
|
||||
LinInterp(k1->r, k2->r, t, &result->r);
|
||||
LinInterp(k1->g, k2->g, t, &result->g);
|
||||
LinInterp(k1->b, k2->b, t, &result->b);
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
LinInterp(k1->a, k2->a, t, &result->a);
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsMatrix33* k1, const hsMatrix33* k2, hsScalar t,
|
||||
hsMatrix33* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
result->fMap[0][0] = k1->fMap[0][0];
|
||||
result->fMap[0][1] = k1->fMap[0][1];
|
||||
result->fMap[0][2] = k1->fMap[0][2];
|
||||
|
||||
result->fMap[1][0] = k1->fMap[1][0];
|
||||
result->fMap[1][1] = k1->fMap[1][1];
|
||||
result->fMap[1][2] = k1->fMap[1][2];
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
result->fMap[2][0] = k1->fMap[2][0];
|
||||
result->fMap[2][1] = k1->fMap[2][1];
|
||||
result->fMap[2][2] = k1->fMap[2][2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t==1.0)
|
||||
{
|
||||
// copy
|
||||
result->fMap[0][0] = k2->fMap[0][0];
|
||||
result->fMap[0][1] = k2->fMap[0][1];
|
||||
result->fMap[0][2] = k2->fMap[0][2];
|
||||
|
||||
result->fMap[1][0] = k2->fMap[1][0];
|
||||
result->fMap[1][1] = k2->fMap[1][1];
|
||||
result->fMap[1][2] = k2->fMap[1][2];
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
result->fMap[2][0] = k2->fMap[2][0];
|
||||
result->fMap[2][1] = k2->fMap[2][1];
|
||||
result->fMap[2][2] = k2->fMap[2][2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LinInterp(k1->fMap[0][0], k2->fMap[0][0], t, &result->fMap[0][0]);
|
||||
LinInterp(k1->fMap[0][1], k2->fMap[0][1], t, &result->fMap[0][1]);
|
||||
LinInterp(k1->fMap[0][2], k2->fMap[0][2], t, &result->fMap[0][2]);
|
||||
|
||||
LinInterp(k1->fMap[1][0], k2->fMap[1][0], t, &result->fMap[1][0]);
|
||||
LinInterp(k1->fMap[1][1], k2->fMap[1][1], t, &result->fMap[1][1]);
|
||||
LinInterp(k1->fMap[1][2], k2->fMap[1][2], t, &result->fMap[1][2]);
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
LinInterp(k1->fMap[2][0], k2->fMap[2][0], t, &result->fMap[2][0]);
|
||||
LinInterp(k1->fMap[2][1], k2->fMap[2][1], t, &result->fMap[2][1]);
|
||||
LinInterp(k1->fMap[2][2], k2->fMap[2][2], t, &result->fMap[2][2]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
void hsInterp::LinInterp(const hsMatrix44* mat1, const hsMatrix44* mat2, hsScalar t,
|
||||
hsMatrix44* out, UInt32 flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
{
|
||||
if( 0 == t )
|
||||
{
|
||||
*out = *mat1;
|
||||
return;
|
||||
}
|
||||
|
||||
if( hsScalar1 == t )
|
||||
{
|
||||
*out = *mat2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( flags & kIgnorePartsScale )
|
||||
{
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
{
|
||||
// interp rotation with quats
|
||||
hsQuat q1, q2, qOut;
|
||||
q1.SetFromMatrix(mat1);
|
||||
q2.SetFromMatrix(mat2);
|
||||
LinInterp(&q1, &q2, t, &qOut);
|
||||
|
||||
qOut.Normalize();
|
||||
qOut.MakeMatrix(out);
|
||||
}
|
||||
else
|
||||
out->Reset();
|
||||
#if 1
|
||||
hsAssert(mat2->fMap[3][0]==0 && mat2->fMap[3][1]==0 && mat2->fMap[3][2]==0 && mat2->fMap[3][3]==1,
|
||||
"matrix prob?");
|
||||
#else
|
||||
// copy
|
||||
for(int i=0; i<3; i++)
|
||||
out->fMap[3][i] = mat2->fMap[3][i];
|
||||
#endif
|
||||
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
{
|
||||
// interp translation
|
||||
hsPoint3 p1,p2,pOut;
|
||||
mat1->GetTranslate(&p1);
|
||||
mat2->GetTranslate(&p2);
|
||||
LinInterp(&p1, &p2, t, &pOut);
|
||||
out->SetTranslate(&pOut);
|
||||
out->NotIdentity(); // in case no rot
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Complete decomp and parts interp
|
||||
|
||||
gemAffineParts gemParts1, gemParts2;
|
||||
hsAffineParts parts1, parts2, partsOut;
|
||||
|
||||
decomp_affine(mat1->fMap, &gemParts1);
|
||||
AP_SET(parts1, gemParts1);
|
||||
|
||||
decomp_affine(mat2->fMap, &gemParts2);
|
||||
AP_SET(parts2, gemParts2);
|
||||
|
||||
LinInterp(&parts1, &parts2, t, &partsOut, flags); // flags will be parsed here
|
||||
|
||||
partsOut.ComposeMatrix(out);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsQuat* k1, const hsQuat* k2, hsScalar t, hsQuat* result)
|
||||
{
|
||||
if (t==0.0)
|
||||
*result = *k1;
|
||||
else
|
||||
if (t==1.0)
|
||||
*result = *k2;
|
||||
else
|
||||
{
|
||||
result->SetFromSlerp(*k1, *k2, t);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsScaleValue* k1, const hsScaleValue* k2, hsScalar t,
|
||||
hsScaleValue* result)
|
||||
{
|
||||
LinInterp(&k1->fS, &k2->fS, t, &result->fS); // Stretch rotation
|
||||
LinInterp(&k1->fQ, &k2->fQ, t, &result->fQ); // Stretch factor
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsAffineParts* k1, const hsAffineParts* k2, hsScalar t,
|
||||
hsAffineParts* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
result->fT = k1->fT;
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
result->fQ = k1->fQ;
|
||||
if (!(flags & kIgnorePartsScale))
|
||||
{
|
||||
// same as preserveScale
|
||||
result->fU = k1->fU;
|
||||
result->fK = k1->fK;
|
||||
}
|
||||
result->fF = k1->fF;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & kPreservePartsScale)
|
||||
{
|
||||
result->fU = k1->fU; // just copy scale from 1st key
|
||||
result->fK = k1->fK;
|
||||
}
|
||||
|
||||
if (t==1.0)
|
||||
{
|
||||
// copy
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
result->fT = k2->fT;
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
result->fQ = k2->fQ;
|
||||
if (!(flags & (kIgnorePartsScale | kPreservePartsScale)))
|
||||
{
|
||||
result->fU = k2->fU;
|
||||
result->fK = k2->fK;
|
||||
}
|
||||
result->fF = k2->fF;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(k1->fF!=k2->fF)
|
||||
hsStatusMessageF("WARNING: Inequality in affine parts flip value.");
|
||||
|
||||
// hsAssert(k1->fF==k2->fF, "inequality in affine parts flip value");
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
LinInterp(&k1->fT, &k2->fT, t, &result->fT); // Translation
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
{
|
||||
LinInterp(&k1->fQ, &k2->fQ, t, &result->fQ); // Essential rotation
|
||||
}
|
||||
|
||||
if (!(flags & (kIgnorePartsScale | kPreservePartsScale)))
|
||||
{
|
||||
LinInterp(&k1->fU, &k2->fU, t, &result->fU); // Stretch rotation
|
||||
LinInterp(&k1->fK, &k2->fK, t, &result->fK); // Stretch factor
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!(flags & kIgnorePartsDet))
|
||||
LinInterp(k1->fF, k2->fF, t, &result->fF); // Flip rot var
|
||||
#else
|
||||
result->fF = k1->fF;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// Key interpolation
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void hsInterp::BezScalarEval(const hsScalar value1, const hsScalar outTan,
|
||||
const hsScalar value2, const hsScalar inTan,
|
||||
const hsScalar t, const hsScalar tanScale, hsScalar *result)
|
||||
{
|
||||
#if 0
|
||||
// If the tangents were what you'd expect them to be... Hermite splines, than this code
|
||||
// would make sense. But no, Max likes to store them in a scaled form based on the
|
||||
// time of each frame. If we ever optimize this further, we could do the scaling on export,
|
||||
// but I need this to work right now before all the artists hate me too much.
|
||||
const hsScalar t2 = t * t;
|
||||
const hsScalar t3 = t2 * t;
|
||||
|
||||
const hsScalar term1 = 2 * t3 - 3 * t2;
|
||||
|
||||
*result = ((term1 + 1) * value1) +
|
||||
(-term1 * value2) +
|
||||
((t3 - 2 * t2 + 1) * outTan) +
|
||||
((t3 - t2) * inTan);
|
||||
#else
|
||||
const hsScalar oneMinusT = (1.0f - t);
|
||||
const hsScalar tSq = t * t;
|
||||
const hsScalar oneMinusTSq = oneMinusT * oneMinusT;
|
||||
|
||||
*result = (oneMinusT * oneMinusTSq * value1) +
|
||||
(3.f * t * oneMinusTSq * (value1 + outTan * tanScale)) +
|
||||
(3.f * tSq * oneMinusT * (value2 + inTan * tanScale)) +
|
||||
(tSq * t * value2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezPoint3Key* k1, const hsBezPoint3Key* k2, const hsScalar t, hsScalarTriple* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue.fX, k1->fOutTan.fX, k2->fValue.fX, k2->fInTan.fX, t, scale, &result->fX);
|
||||
BezScalarEval(k1->fValue.fY, k1->fOutTan.fY, k2->fValue.fY, k2->fInTan.fY, t, scale, &result->fY);
|
||||
BezScalarEval(k1->fValue.fZ, k1->fOutTan.fZ, k2->fValue.fZ, k2->fInTan.fZ, t, scale, &result->fZ);
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezScalarKey* k1, const hsBezScalarKey* k2, const hsScalar t, hsScalar* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue, k1->fOutTan, k2->fValue, k2->fInTan, t, scale, result);
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezScaleKey* k1, const hsBezScaleKey* k2, const hsScalar t, hsScaleValue* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue.fS.fX, k1->fOutTan.fX, k2->fValue.fS.fX, k2->fInTan.fX, t, scale, &result->fS.fX);
|
||||
BezScalarEval(k1->fValue.fS.fY, k1->fOutTan.fY, k2->fValue.fS.fY, k2->fInTan.fY, t, scale, &result->fS.fY);
|
||||
BezScalarEval(k1->fValue.fS.fZ, k1->fOutTan.fZ, k2->fValue.fS.fZ, k2->fInTan.fZ, t, scale, &result->fS.fZ);
|
||||
|
||||
// Slerp scale axis
|
||||
LinInterp(&k1->fValue.fQ, &k2->fValue.fQ, t, &result->fQ);
|
||||
}
|
||||
|
||||
//
|
||||
// Get an element from an array of unknown type
|
||||
//
|
||||
static inline hsKeyFrame* GetKey(Int32 i, void *keys, Int32 size)
|
||||
{
|
||||
return (hsKeyFrame*) ((char*)keys + size * i);
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
// Given a list of keys, and a time, fills in the 2 boundary keys and
|
||||
// a fraction (p=0-1) indicating where the time falls between them.
|
||||
// Returns the index of the first key which can be passed in as a hint (lastKeyIdx)
|
||||
// for the next search.
|
||||
//
|
||||
void hsInterp::GetBoundaryKeyFrames(hsScalar time, UInt32 numKeys, void *keys, UInt32 size,
|
||||
hsKeyFrame **kF1, hsKeyFrame **kF2, UInt32 *lastKeyIdx, hsScalar *p, hsBool forwards)
|
||||
{
|
||||
hsAssert(numKeys>1, "Must have more than 1 keyframe");
|
||||
int k1, k2;
|
||||
UInt16 frame = (UInt16)(time * MAX_FRAMES_PER_SEC);
|
||||
|
||||
// boundary case, past end
|
||||
if (frame > GetKey(numKeys-1, keys, size)->fFrame)
|
||||
{
|
||||
k1=k2=numKeys-1;
|
||||
(*kF2) = GetKey(k1, keys, size);
|
||||
(*kF1) = (*kF2);
|
||||
*p = 0.0;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
hsKeyFrame *key1, *key2;
|
||||
// boundary case, before start
|
||||
if (frame < (key1=GetKey(0, keys, size))->fFrame)
|
||||
{
|
||||
k1=k2=0;
|
||||
(*kF1) = GetKey(k1, keys, size);
|
||||
(*kF2) = (*kF1);
|
||||
*p = 0.0;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// prime loop
|
||||
int i;
|
||||
i = 1;
|
||||
if (*lastKeyIdx > 0 && *lastKeyIdx < numKeys - 1)
|
||||
{
|
||||
// new starting point for search
|
||||
if (forwards)
|
||||
key1 = GetKey(*lastKeyIdx, keys, size);
|
||||
else
|
||||
key2 = GetKey(*lastKeyIdx + 1, keys, size);
|
||||
|
||||
i = *lastKeyIdx + 1;
|
||||
}
|
||||
else if (!forwards)
|
||||
{
|
||||
key2 = GetKey(1, keys, size);
|
||||
}
|
||||
|
||||
// search pairs of keys
|
||||
int count;
|
||||
if (forwards)
|
||||
{
|
||||
for (count = 1; count <= numKeys; count++, i++)
|
||||
{
|
||||
if (i >= numKeys)
|
||||
{
|
||||
key1 = GetKey(0, keys, size);
|
||||
i = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
key2 = GetKey(i, keys, size);
|
||||
if (frame <= key2->fFrame && frame >= key1->fFrame)
|
||||
{
|
||||
k2=i;
|
||||
k1=i-1;
|
||||
(*kF2) = key2;
|
||||
(*kF1) = key1;
|
||||
*p = (time - (*kF1)->fFrame / MAX_FRAMES_PER_SEC) / (((*kF2)->fFrame - (*kF1)->fFrame) / MAX_FRAMES_PER_SEC);
|
||||
goto ret;
|
||||
}
|
||||
key1=key2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (count = 1; count <= numKeys; count++, i--)
|
||||
{
|
||||
if (i < 1)
|
||||
{
|
||||
i = numKeys - 1;
|
||||
key2 = GetKey(i, keys, size);
|
||||
count++;
|
||||
}
|
||||
|
||||
key1 = GetKey(i - 1, keys, size);
|
||||
if (frame <= key2->fFrame && frame >= key1->fFrame)
|
||||
{
|
||||
k2 = i;
|
||||
k1 = i - 1;
|
||||
(*kF2) = key2;
|
||||
(*kF1) = key1;
|
||||
*p = (time - (*kF1)->fFrame / MAX_FRAMES_PER_SEC) / (((*kF2)->fFrame - (*kF1)->fFrame) / MAX_FRAMES_PER_SEC);
|
||||
goto ret;
|
||||
}
|
||||
key2=key1;
|
||||
}
|
||||
}
|
||||
|
||||
ret:
|
||||
;
|
||||
|
||||
#if 0
|
||||
char str[128];
|
||||
sprintf(str, "k1=%d, k2=%d, p=%f\n", k1, k2, *p);
|
||||
OutputDebugString(str);
|
||||
#endif
|
||||
*lastKeyIdx = k1;
|
||||
}
|
||||
|
||||
|
||||
/*==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 "hsTypes.h"
|
||||
#include "hsInterp.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "hsColorRGBA.h"
|
||||
#include "hsPoint2.h"
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// linear interpolation
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
void hsInterp::LinInterp(hsScalar k1, hsScalar k2, hsScalar t, hsScalar* result)
|
||||
{
|
||||
*result = k1 + t * (k2 - k1);
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsScalarTriple* k1, const hsScalarTriple* k2, hsScalar t,
|
||||
hsScalarTriple* result)
|
||||
{
|
||||
if (t==0.0)
|
||||
*result = *k1;
|
||||
else
|
||||
if (t==1.0)
|
||||
*result = *k2;
|
||||
else
|
||||
{
|
||||
LinInterp(k1->fX, k2->fX, t, &result->fX);
|
||||
LinInterp(k1->fY, k2->fY, t, &result->fY);
|
||||
LinInterp(k1->fZ, k2->fZ, t, &result->fZ);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsColorRGBA* k1, const hsColorRGBA* k2, hsScalar t,
|
||||
hsColorRGBA* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
result->r = k1->r;
|
||||
result->g = k1->g;
|
||||
result->b = k1->b;
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
result->a = k1->a;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t==1.0)
|
||||
{
|
||||
result->r = k2->r;
|
||||
result->g = k2->g;
|
||||
result->b = k2->b;
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
result->a = k2->a;
|
||||
return;
|
||||
}
|
||||
|
||||
LinInterp(k1->r, k2->r, t, &result->r);
|
||||
LinInterp(k1->g, k2->g, t, &result->g);
|
||||
LinInterp(k1->b, k2->b, t, &result->b);
|
||||
if (!(flags & kIgnoreAlpha))
|
||||
LinInterp(k1->a, k2->a, t, &result->a);
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsMatrix33* k1, const hsMatrix33* k2, hsScalar t,
|
||||
hsMatrix33* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
result->fMap[0][0] = k1->fMap[0][0];
|
||||
result->fMap[0][1] = k1->fMap[0][1];
|
||||
result->fMap[0][2] = k1->fMap[0][2];
|
||||
|
||||
result->fMap[1][0] = k1->fMap[1][0];
|
||||
result->fMap[1][1] = k1->fMap[1][1];
|
||||
result->fMap[1][2] = k1->fMap[1][2];
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
result->fMap[2][0] = k1->fMap[2][0];
|
||||
result->fMap[2][1] = k1->fMap[2][1];
|
||||
result->fMap[2][2] = k1->fMap[2][2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (t==1.0)
|
||||
{
|
||||
// copy
|
||||
result->fMap[0][0] = k2->fMap[0][0];
|
||||
result->fMap[0][1] = k2->fMap[0][1];
|
||||
result->fMap[0][2] = k2->fMap[0][2];
|
||||
|
||||
result->fMap[1][0] = k2->fMap[1][0];
|
||||
result->fMap[1][1] = k2->fMap[1][1];
|
||||
result->fMap[1][2] = k2->fMap[1][2];
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
result->fMap[2][0] = k2->fMap[2][0];
|
||||
result->fMap[2][1] = k2->fMap[2][1];
|
||||
result->fMap[2][2] = k2->fMap[2][2];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LinInterp(k1->fMap[0][0], k2->fMap[0][0], t, &result->fMap[0][0]);
|
||||
LinInterp(k1->fMap[0][1], k2->fMap[0][1], t, &result->fMap[0][1]);
|
||||
LinInterp(k1->fMap[0][2], k2->fMap[0][2], t, &result->fMap[0][2]);
|
||||
|
||||
LinInterp(k1->fMap[1][0], k2->fMap[1][0], t, &result->fMap[1][0]);
|
||||
LinInterp(k1->fMap[1][1], k2->fMap[1][1], t, &result->fMap[1][1]);
|
||||
LinInterp(k1->fMap[1][2], k2->fMap[1][2], t, &result->fMap[1][2]);
|
||||
|
||||
if (!(flags & kIgnoreLastMatRow))
|
||||
{
|
||||
LinInterp(k1->fMap[2][0], k2->fMap[2][0], t, &result->fMap[2][0]);
|
||||
LinInterp(k1->fMap[2][1], k2->fMap[2][1], t, &result->fMap[2][1]);
|
||||
LinInterp(k1->fMap[2][2], k2->fMap[2][2], t, &result->fMap[2][2]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
void hsInterp::LinInterp(const hsMatrix44* mat1, const hsMatrix44* mat2, hsScalar t,
|
||||
hsMatrix44* out, UInt32 flags)
|
||||
{
|
||||
if (flags == 0)
|
||||
{
|
||||
if( 0 == t )
|
||||
{
|
||||
*out = *mat1;
|
||||
return;
|
||||
}
|
||||
|
||||
if( hsScalar1 == t )
|
||||
{
|
||||
*out = *mat2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( flags & kIgnorePartsScale )
|
||||
{
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
{
|
||||
// interp rotation with quats
|
||||
hsQuat q1, q2, qOut;
|
||||
q1.SetFromMatrix(mat1);
|
||||
q2.SetFromMatrix(mat2);
|
||||
LinInterp(&q1, &q2, t, &qOut);
|
||||
|
||||
qOut.Normalize();
|
||||
qOut.MakeMatrix(out);
|
||||
}
|
||||
else
|
||||
out->Reset();
|
||||
#if 1
|
||||
hsAssert(mat2->fMap[3][0]==0 && mat2->fMap[3][1]==0 && mat2->fMap[3][2]==0 && mat2->fMap[3][3]==1,
|
||||
"matrix prob?");
|
||||
#else
|
||||
// copy
|
||||
for(int i=0; i<3; i++)
|
||||
out->fMap[3][i] = mat2->fMap[3][i];
|
||||
#endif
|
||||
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
{
|
||||
// interp translation
|
||||
hsPoint3 p1,p2,pOut;
|
||||
mat1->GetTranslate(&p1);
|
||||
mat2->GetTranslate(&p2);
|
||||
LinInterp(&p1, &p2, t, &pOut);
|
||||
out->SetTranslate(&pOut);
|
||||
out->NotIdentity(); // in case no rot
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Complete decomp and parts interp
|
||||
|
||||
gemAffineParts gemParts1, gemParts2;
|
||||
hsAffineParts parts1, parts2, partsOut;
|
||||
|
||||
decomp_affine(mat1->fMap, &gemParts1);
|
||||
AP_SET(parts1, gemParts1);
|
||||
|
||||
decomp_affine(mat2->fMap, &gemParts2);
|
||||
AP_SET(parts2, gemParts2);
|
||||
|
||||
LinInterp(&parts1, &parts2, t, &partsOut, flags); // flags will be parsed here
|
||||
|
||||
partsOut.ComposeMatrix(out);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsQuat* k1, const hsQuat* k2, hsScalar t, hsQuat* result)
|
||||
{
|
||||
if (t==0.0)
|
||||
*result = *k1;
|
||||
else
|
||||
if (t==1.0)
|
||||
*result = *k2;
|
||||
else
|
||||
{
|
||||
result->SetFromSlerp(*k1, *k2, t);
|
||||
}
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsScaleValue* k1, const hsScaleValue* k2, hsScalar t,
|
||||
hsScaleValue* result)
|
||||
{
|
||||
LinInterp(&k1->fS, &k2->fS, t, &result->fS); // Stretch rotation
|
||||
LinInterp(&k1->fQ, &k2->fQ, t, &result->fQ); // Stretch factor
|
||||
}
|
||||
|
||||
void hsInterp::LinInterp(const hsAffineParts* k1, const hsAffineParts* k2, hsScalar t,
|
||||
hsAffineParts* result, UInt32 flags)
|
||||
{
|
||||
if (t==0.0)
|
||||
{
|
||||
// copy
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
result->fT = k1->fT;
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
result->fQ = k1->fQ;
|
||||
if (!(flags & kIgnorePartsScale))
|
||||
{
|
||||
// same as preserveScale
|
||||
result->fU = k1->fU;
|
||||
result->fK = k1->fK;
|
||||
}
|
||||
result->fF = k1->fF;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & kPreservePartsScale)
|
||||
{
|
||||
result->fU = k1->fU; // just copy scale from 1st key
|
||||
result->fK = k1->fK;
|
||||
}
|
||||
|
||||
if (t==1.0)
|
||||
{
|
||||
// copy
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
result->fT = k2->fT;
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
result->fQ = k2->fQ;
|
||||
if (!(flags & (kIgnorePartsScale | kPreservePartsScale)))
|
||||
{
|
||||
result->fU = k2->fU;
|
||||
result->fK = k2->fK;
|
||||
}
|
||||
result->fF = k2->fF;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(k1->fF!=k2->fF)
|
||||
hsStatusMessageF("WARNING: Inequality in affine parts flip value.");
|
||||
|
||||
// hsAssert(k1->fF==k2->fF, "inequality in affine parts flip value");
|
||||
if (!(flags & kIgnorePartsPos))
|
||||
LinInterp(&k1->fT, &k2->fT, t, &result->fT); // Translation
|
||||
if (!(flags & kIgnorePartsRot))
|
||||
{
|
||||
LinInterp(&k1->fQ, &k2->fQ, t, &result->fQ); // Essential rotation
|
||||
}
|
||||
|
||||
if (!(flags & (kIgnorePartsScale | kPreservePartsScale)))
|
||||
{
|
||||
LinInterp(&k1->fU, &k2->fU, t, &result->fU); // Stretch rotation
|
||||
LinInterp(&k1->fK, &k2->fK, t, &result->fK); // Stretch factor
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!(flags & kIgnorePartsDet))
|
||||
LinInterp(k1->fF, k2->fF, t, &result->fF); // Flip rot var
|
||||
#else
|
||||
result->fF = k1->fF;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
// Key interpolation
|
||||
///////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void hsInterp::BezScalarEval(const hsScalar value1, const hsScalar outTan,
|
||||
const hsScalar value2, const hsScalar inTan,
|
||||
const hsScalar t, const hsScalar tanScale, hsScalar *result)
|
||||
{
|
||||
#if 0
|
||||
// If the tangents were what you'd expect them to be... Hermite splines, than this code
|
||||
// would make sense. But no, Max likes to store them in a scaled form based on the
|
||||
// time of each frame. If we ever optimize this further, we could do the scaling on export,
|
||||
// but I need this to work right now before all the artists hate me too much.
|
||||
const hsScalar t2 = t * t;
|
||||
const hsScalar t3 = t2 * t;
|
||||
|
||||
const hsScalar term1 = 2 * t3 - 3 * t2;
|
||||
|
||||
*result = ((term1 + 1) * value1) +
|
||||
(-term1 * value2) +
|
||||
((t3 - 2 * t2 + 1) * outTan) +
|
||||
((t3 - t2) * inTan);
|
||||
#else
|
||||
const hsScalar oneMinusT = (1.0f - t);
|
||||
const hsScalar tSq = t * t;
|
||||
const hsScalar oneMinusTSq = oneMinusT * oneMinusT;
|
||||
|
||||
*result = (oneMinusT * oneMinusTSq * value1) +
|
||||
(3.f * t * oneMinusTSq * (value1 + outTan * tanScale)) +
|
||||
(3.f * tSq * oneMinusT * (value2 + inTan * tanScale)) +
|
||||
(tSq * t * value2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezPoint3Key* k1, const hsBezPoint3Key* k2, const hsScalar t, hsScalarTriple* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue.fX, k1->fOutTan.fX, k2->fValue.fX, k2->fInTan.fX, t, scale, &result->fX);
|
||||
BezScalarEval(k1->fValue.fY, k1->fOutTan.fY, k2->fValue.fY, k2->fInTan.fY, t, scale, &result->fY);
|
||||
BezScalarEval(k1->fValue.fZ, k1->fOutTan.fZ, k2->fValue.fZ, k2->fInTan.fZ, t, scale, &result->fZ);
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezScalarKey* k1, const hsBezScalarKey* k2, const hsScalar t, hsScalar* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue, k1->fOutTan, k2->fValue, k2->fInTan, t, scale, result);
|
||||
}
|
||||
|
||||
void hsInterp::BezInterp(const hsBezScaleKey* k1, const hsBezScaleKey* k2, const hsScalar t, hsScaleValue* result)
|
||||
{
|
||||
hsScalar scale = (k2->fFrame - k1->fFrame) * MAX_TICKS_PER_FRAME / 3.f;
|
||||
BezScalarEval(k1->fValue.fS.fX, k1->fOutTan.fX, k2->fValue.fS.fX, k2->fInTan.fX, t, scale, &result->fS.fX);
|
||||
BezScalarEval(k1->fValue.fS.fY, k1->fOutTan.fY, k2->fValue.fS.fY, k2->fInTan.fY, t, scale, &result->fS.fY);
|
||||
BezScalarEval(k1->fValue.fS.fZ, k1->fOutTan.fZ, k2->fValue.fS.fZ, k2->fInTan.fZ, t, scale, &result->fS.fZ);
|
||||
|
||||
// Slerp scale axis
|
||||
LinInterp(&k1->fValue.fQ, &k2->fValue.fQ, t, &result->fQ);
|
||||
}
|
||||
|
||||
//
|
||||
// Get an element from an array of unknown type
|
||||
//
|
||||
static inline hsKeyFrame* GetKey(Int32 i, void *keys, Int32 size)
|
||||
{
|
||||
return (hsKeyFrame*) ((char*)keys + size * i);
|
||||
}
|
||||
|
||||
//
|
||||
// STATIC
|
||||
// Given a list of keys, and a time, fills in the 2 boundary keys and
|
||||
// a fraction (p=0-1) indicating where the time falls between them.
|
||||
// Returns the index of the first key which can be passed in as a hint (lastKeyIdx)
|
||||
// for the next search.
|
||||
//
|
||||
void hsInterp::GetBoundaryKeyFrames(hsScalar time, UInt32 numKeys, void *keys, UInt32 size,
|
||||
hsKeyFrame **kF1, hsKeyFrame **kF2, UInt32 *lastKeyIdx, hsScalar *p, hsBool forwards)
|
||||
{
|
||||
hsAssert(numKeys>1, "Must have more than 1 keyframe");
|
||||
int k1, k2;
|
||||
UInt16 frame = (UInt16)(time * MAX_FRAMES_PER_SEC);
|
||||
|
||||
// boundary case, past end
|
||||
if (frame > GetKey(numKeys-1, keys, size)->fFrame)
|
||||
{
|
||||
k1=k2=numKeys-1;
|
||||
(*kF2) = GetKey(k1, keys, size);
|
||||
(*kF1) = (*kF2);
|
||||
*p = 0.0;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
hsKeyFrame *key1, *key2;
|
||||
// boundary case, before start
|
||||
if (frame < (key1=GetKey(0, keys, size))->fFrame)
|
||||
{
|
||||
k1=k2=0;
|
||||
(*kF1) = GetKey(k1, keys, size);
|
||||
(*kF2) = (*kF1);
|
||||
*p = 0.0;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// prime loop
|
||||
int i;
|
||||
i = 1;
|
||||
if (*lastKeyIdx > 0 && *lastKeyIdx < numKeys - 1)
|
||||
{
|
||||
// new starting point for search
|
||||
if (forwards)
|
||||
key1 = GetKey(*lastKeyIdx, keys, size);
|
||||
else
|
||||
key2 = GetKey(*lastKeyIdx + 1, keys, size);
|
||||
|
||||
i = *lastKeyIdx + 1;
|
||||
}
|
||||
else if (!forwards)
|
||||
{
|
||||
key2 = GetKey(1, keys, size);
|
||||
}
|
||||
|
||||
// search pairs of keys
|
||||
int count;
|
||||
if (forwards)
|
||||
{
|
||||
for (count = 1; count <= numKeys; count++, i++)
|
||||
{
|
||||
if (i >= numKeys)
|
||||
{
|
||||
key1 = GetKey(0, keys, size);
|
||||
i = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
key2 = GetKey(i, keys, size);
|
||||
if (frame <= key2->fFrame && frame >= key1->fFrame)
|
||||
{
|
||||
k2=i;
|
||||
k1=i-1;
|
||||
(*kF2) = key2;
|
||||
(*kF1) = key1;
|
||||
*p = (time - (*kF1)->fFrame / MAX_FRAMES_PER_SEC) / (((*kF2)->fFrame - (*kF1)->fFrame) / MAX_FRAMES_PER_SEC);
|
||||
goto ret;
|
||||
}
|
||||
key1=key2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (count = 1; count <= numKeys; count++, i--)
|
||||
{
|
||||
if (i < 1)
|
||||
{
|
||||
i = numKeys - 1;
|
||||
key2 = GetKey(i, keys, size);
|
||||
count++;
|
||||
}
|
||||
|
||||
key1 = GetKey(i - 1, keys, size);
|
||||
if (frame <= key2->fFrame && frame >= key1->fFrame)
|
||||
{
|
||||
k2 = i;
|
||||
k1 = i - 1;
|
||||
(*kF2) = key2;
|
||||
(*kF1) = key1;
|
||||
*p = (time - (*kF1)->fFrame / MAX_FRAMES_PER_SEC) / (((*kF2)->fFrame - (*kF1)->fFrame) / MAX_FRAMES_PER_SEC);
|
||||
goto ret;
|
||||
}
|
||||
key2=key1;
|
||||
}
|
||||
}
|
||||
|
||||
ret:
|
||||
;
|
||||
|
||||
#if 0
|
||||
char str[128];
|
||||
sprintf(str, "k1=%d, k2=%d, p=%f\n", k1, k2, *p);
|
||||
OutputDebugString(str);
|
||||
#endif
|
||||
*lastKeyIdx = k1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,82 +1,82 @@
|
||||
/*==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==*/
|
||||
#ifndef HSINTERP_inc
|
||||
#define HSINTERP_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsKeys.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Performs interpolation of keyframes & values.
|
||||
// t param should be 0-1
|
||||
//
|
||||
struct hsColorRGBA;
|
||||
class hsAffineParts;
|
||||
class hsInterp
|
||||
{
|
||||
public:
|
||||
enum IgnoreFlags
|
||||
{
|
||||
kIgnoreAlpha = 0x1,
|
||||
kIgnoreLastMatRow = 0x2,
|
||||
kIgnorePartsPos = 0x4,
|
||||
kIgnorePartsRot = 0x8,
|
||||
kIgnorePartsScale = 0x10, // result gets no scale
|
||||
kIgnorePartsDet = 0x20,
|
||||
kPreservePartsScale = 0x40 // result gets the scale of key1
|
||||
};
|
||||
|
||||
static void BezScalarEval(const hsScalar value1, const hsScalar outTan,
|
||||
const hsScalar value2, const hsScalar inTan,
|
||||
const hsScalar t, const hsScalar scale, hsScalar *result);
|
||||
static void BezInterp(const hsBezPoint3Key *k1, const hsBezPoint3Key *k2, const hsScalar t, hsScalarTriple *result);
|
||||
static void BezInterp(const hsBezScalarKey *k1, const hsBezScalarKey *k2, const hsScalar t, hsScalar *result);
|
||||
static void BezInterp(const hsBezScaleKey *k1, const hsBezScaleKey *k2, const hsScalar t, hsScaleValue *result);
|
||||
|
||||
// simple linear interpolation
|
||||
static void LinInterp(const hsScalar k1, const hsScalar k2, const hsScalar t, hsScalar *result);
|
||||
static void LinInterp(const hsScalarTriple *k1, const hsScalarTriple *k2, const hsScalar t, hsScalarTriple *result);
|
||||
static void LinInterp(const hsColorRGBA *k1, const hsColorRGBA *k2, const hsScalar t, hsColorRGBA *result, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsMatrix33 *k1, const hsMatrix33 *k2, const hsScalar t, hsMatrix33 *result, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsMatrix44 *mat1, const hsMatrix44 *mat2, const hsScalar t, hsMatrix44 *out, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsQuat *k1, const hsQuat *k2, const hsScalar t, hsQuat *result);
|
||||
static void LinInterp(const hsScaleValue *k1, const hsScaleValue *k2, const hsScalar t, hsScaleValue *result);
|
||||
static void LinInterp(const hsAffineParts *k1, const hsAffineParts *k2, const hsScalar t, hsAffineParts *result, UInt32 ignoreFlags=0);
|
||||
|
||||
// Given a time value, find the enclosing keyframes and normalize time (0-1)
|
||||
static void GetBoundaryKeyFrames(hsScalar time, UInt32 numKeys, void *keys,
|
||||
UInt32 keySize, hsKeyFrame **kF1, hsKeyFrame **kF2, UInt32 *lastKeyIdx, hsScalar *p, hsBool forwards);
|
||||
|
||||
};
|
||||
|
||||
#define MAX_FRAMES_PER_SEC 30.0f
|
||||
#define MAX_TICKS_PER_FRAME 160.0f
|
||||
#define MAX_TICKS_PER_SEC (MAX_TICKS_PER_FRAME*MAX_FRAMES_PER_SEC)
|
||||
|
||||
#endif // #ifndef HSINTERP_inc
|
||||
/*==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==*/
|
||||
#ifndef HSINTERP_inc
|
||||
#define HSINTERP_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsKeys.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Performs interpolation of keyframes & values.
|
||||
// t param should be 0-1
|
||||
//
|
||||
struct hsColorRGBA;
|
||||
class hsAffineParts;
|
||||
class hsInterp
|
||||
{
|
||||
public:
|
||||
enum IgnoreFlags
|
||||
{
|
||||
kIgnoreAlpha = 0x1,
|
||||
kIgnoreLastMatRow = 0x2,
|
||||
kIgnorePartsPos = 0x4,
|
||||
kIgnorePartsRot = 0x8,
|
||||
kIgnorePartsScale = 0x10, // result gets no scale
|
||||
kIgnorePartsDet = 0x20,
|
||||
kPreservePartsScale = 0x40 // result gets the scale of key1
|
||||
};
|
||||
|
||||
static void BezScalarEval(const hsScalar value1, const hsScalar outTan,
|
||||
const hsScalar value2, const hsScalar inTan,
|
||||
const hsScalar t, const hsScalar scale, hsScalar *result);
|
||||
static void BezInterp(const hsBezPoint3Key *k1, const hsBezPoint3Key *k2, const hsScalar t, hsScalarTriple *result);
|
||||
static void BezInterp(const hsBezScalarKey *k1, const hsBezScalarKey *k2, const hsScalar t, hsScalar *result);
|
||||
static void BezInterp(const hsBezScaleKey *k1, const hsBezScaleKey *k2, const hsScalar t, hsScaleValue *result);
|
||||
|
||||
// simple linear interpolation
|
||||
static void LinInterp(const hsScalar k1, const hsScalar k2, const hsScalar t, hsScalar *result);
|
||||
static void LinInterp(const hsScalarTriple *k1, const hsScalarTriple *k2, const hsScalar t, hsScalarTriple *result);
|
||||
static void LinInterp(const hsColorRGBA *k1, const hsColorRGBA *k2, const hsScalar t, hsColorRGBA *result, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsMatrix33 *k1, const hsMatrix33 *k2, const hsScalar t, hsMatrix33 *result, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsMatrix44 *mat1, const hsMatrix44 *mat2, const hsScalar t, hsMatrix44 *out, UInt32 ignoreFlags=0);
|
||||
static void LinInterp(const hsQuat *k1, const hsQuat *k2, const hsScalar t, hsQuat *result);
|
||||
static void LinInterp(const hsScaleValue *k1, const hsScaleValue *k2, const hsScalar t, hsScaleValue *result);
|
||||
static void LinInterp(const hsAffineParts *k1, const hsAffineParts *k2, const hsScalar t, hsAffineParts *result, UInt32 ignoreFlags=0);
|
||||
|
||||
// Given a time value, find the enclosing keyframes and normalize time (0-1)
|
||||
static void GetBoundaryKeyFrames(hsScalar time, UInt32 numKeys, void *keys,
|
||||
UInt32 keySize, hsKeyFrame **kF1, hsKeyFrame **kF2, UInt32 *lastKeyIdx, hsScalar *p, hsBool forwards);
|
||||
|
||||
};
|
||||
|
||||
#define MAX_FRAMES_PER_SEC 30.0f
|
||||
#define MAX_TICKS_PER_FRAME 160.0f
|
||||
#define MAX_TICKS_PER_SEC (MAX_TICKS_PER_FRAME*MAX_FRAMES_PER_SEC)
|
||||
|
||||
#endif // #ifndef HSINTERP_inc
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,239 +1,239 @@
|
||||
/*==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==*/
|
||||
#ifndef HSKEYS_inc
|
||||
#define HSKEYS_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsQuat.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "hsMatrix33.h"
|
||||
#include "hsMatrix44.h"
|
||||
|
||||
// No virtuals. Keep these nice and lean.
|
||||
struct hsKeyFrame
|
||||
{
|
||||
// Used by plController to specify which keys it has.
|
||||
enum
|
||||
{
|
||||
kUnknownKeyFrame,
|
||||
kPoint3KeyFrame,
|
||||
kBezPoint3KeyFrame,
|
||||
kScalarKeyFrame,
|
||||
kBezScalarKeyFrame,
|
||||
kScaleKeyFrame,
|
||||
kBezScaleKeyFrame,
|
||||
kQuatKeyFrame,
|
||||
kCompressedQuatKeyFrame32,
|
||||
kCompressedQuatKeyFrame64,
|
||||
k3dsMaxKeyFrame,
|
||||
kMatrix33KeyFrame,
|
||||
kMatrix44KeyFrame,
|
||||
};
|
||||
|
||||
UInt16 fFrame;
|
||||
static const int kMaxFrameNumber;
|
||||
};
|
||||
|
||||
struct hsPoint3Key : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsPoint3Key *key);
|
||||
};
|
||||
|
||||
struct hsBezPoint3Key : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fInTan;
|
||||
hsPoint3 fOutTan;
|
||||
hsPoint3 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezPoint3Key *key);
|
||||
};
|
||||
|
||||
struct hsScalarKey : public hsKeyFrame
|
||||
{
|
||||
hsScalar fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsScalarKey *key);
|
||||
};
|
||||
|
||||
struct hsBezScalarKey : public hsKeyFrame
|
||||
{
|
||||
hsScalar fInTan;
|
||||
hsScalar fOutTan;
|
||||
hsScalar fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezScalarKey *key);
|
||||
};
|
||||
|
||||
struct hsQuatKey : public hsKeyFrame
|
||||
{
|
||||
hsQuat fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsQuatKey *key);
|
||||
};
|
||||
|
||||
struct hsCompressedQuatKey32 : public hsKeyFrame
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCompQuatNukeX,
|
||||
kCompQuatNukeY,
|
||||
kCompQuatNukeZ,
|
||||
kCompQuatNukeW,
|
||||
};
|
||||
|
||||
static const hsScalar kOneOverRootTwo;
|
||||
static const hsScalar k10BitScaleRange;
|
||||
|
||||
void SetQuat(hsQuat &q);
|
||||
void GetQuat(hsQuat &q);
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsCompressedQuatKey32 *key);
|
||||
|
||||
protected:
|
||||
UInt32 fData;
|
||||
};
|
||||
|
||||
struct hsCompressedQuatKey64 : public hsKeyFrame
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCompQuatNukeX,
|
||||
kCompQuatNukeY,
|
||||
kCompQuatNukeZ,
|
||||
kCompQuatNukeW,
|
||||
};
|
||||
|
||||
static const hsScalar kOneOverRootTwo;
|
||||
static const hsScalar k20BitScaleRange;
|
||||
static const hsScalar k21BitScaleRange;
|
||||
|
||||
void SetQuat(hsQuat &q);
|
||||
void GetQuat(hsQuat &q);
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsCompressedQuatKey64 *key);
|
||||
|
||||
protected:
|
||||
UInt32 fData[2];
|
||||
};
|
||||
|
||||
struct hsScaleValue : public hsKeyFrame
|
||||
{
|
||||
hsVector3 fS; /* Scale components for x,y,z */
|
||||
hsQuat fQ; /* The axis along which the scale is applied */
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
int operator==(const hsScaleValue& a) const { return (fS == a.fS && fQ == a.fQ); }
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
struct hsScaleKey : public hsKeyFrame
|
||||
{
|
||||
hsScaleValue fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsScaleKey *key);
|
||||
};
|
||||
|
||||
struct hsBezScaleKey : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fInTan;
|
||||
hsPoint3 fOutTan;
|
||||
hsScaleValue fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezScaleKey *key);
|
||||
};
|
||||
|
||||
struct hsG3DSMaxKeyFrame : public hsKeyFrame
|
||||
{
|
||||
hsAffineParts fParts;
|
||||
|
||||
void Reset() { fParts.Reset(); } // Make parts identity
|
||||
|
||||
void Set(hsMatrix44 *mat, UInt16 frame);
|
||||
void Set(const hsAffineParts &parts, UInt16 frame);
|
||||
|
||||
hsMatrix44* GetMatrix44(hsMatrix44 *mat) { fParts.ComposeMatrix(mat); return mat; }
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsG3DSMaxKeyFrame *key);
|
||||
};
|
||||
|
||||
struct hsMatrix33Key : public hsKeyFrame
|
||||
{
|
||||
hsMatrix33 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsMatrix33Key *key);
|
||||
};
|
||||
|
||||
struct hsMatrix44Key : public hsKeyFrame
|
||||
{
|
||||
hsMatrix44 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsMatrix44Key *key);
|
||||
};
|
||||
|
||||
#endif
|
||||
/*==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==*/
|
||||
#ifndef HSKEYS_inc
|
||||
#define HSKEYS_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsQuat.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "hsMatrix33.h"
|
||||
#include "hsMatrix44.h"
|
||||
|
||||
// No virtuals. Keep these nice and lean.
|
||||
struct hsKeyFrame
|
||||
{
|
||||
// Used by plController to specify which keys it has.
|
||||
enum
|
||||
{
|
||||
kUnknownKeyFrame,
|
||||
kPoint3KeyFrame,
|
||||
kBezPoint3KeyFrame,
|
||||
kScalarKeyFrame,
|
||||
kBezScalarKeyFrame,
|
||||
kScaleKeyFrame,
|
||||
kBezScaleKeyFrame,
|
||||
kQuatKeyFrame,
|
||||
kCompressedQuatKeyFrame32,
|
||||
kCompressedQuatKeyFrame64,
|
||||
k3dsMaxKeyFrame,
|
||||
kMatrix33KeyFrame,
|
||||
kMatrix44KeyFrame,
|
||||
};
|
||||
|
||||
UInt16 fFrame;
|
||||
static const int kMaxFrameNumber;
|
||||
};
|
||||
|
||||
struct hsPoint3Key : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsPoint3Key *key);
|
||||
};
|
||||
|
||||
struct hsBezPoint3Key : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fInTan;
|
||||
hsPoint3 fOutTan;
|
||||
hsPoint3 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezPoint3Key *key);
|
||||
};
|
||||
|
||||
struct hsScalarKey : public hsKeyFrame
|
||||
{
|
||||
hsScalar fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsScalarKey *key);
|
||||
};
|
||||
|
||||
struct hsBezScalarKey : public hsKeyFrame
|
||||
{
|
||||
hsScalar fInTan;
|
||||
hsScalar fOutTan;
|
||||
hsScalar fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezScalarKey *key);
|
||||
};
|
||||
|
||||
struct hsQuatKey : public hsKeyFrame
|
||||
{
|
||||
hsQuat fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsQuatKey *key);
|
||||
};
|
||||
|
||||
struct hsCompressedQuatKey32 : public hsKeyFrame
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCompQuatNukeX,
|
||||
kCompQuatNukeY,
|
||||
kCompQuatNukeZ,
|
||||
kCompQuatNukeW,
|
||||
};
|
||||
|
||||
static const hsScalar kOneOverRootTwo;
|
||||
static const hsScalar k10BitScaleRange;
|
||||
|
||||
void SetQuat(hsQuat &q);
|
||||
void GetQuat(hsQuat &q);
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsCompressedQuatKey32 *key);
|
||||
|
||||
protected:
|
||||
UInt32 fData;
|
||||
};
|
||||
|
||||
struct hsCompressedQuatKey64 : public hsKeyFrame
|
||||
{
|
||||
enum
|
||||
{
|
||||
kCompQuatNukeX,
|
||||
kCompQuatNukeY,
|
||||
kCompQuatNukeZ,
|
||||
kCompQuatNukeW,
|
||||
};
|
||||
|
||||
static const hsScalar kOneOverRootTwo;
|
||||
static const hsScalar k20BitScaleRange;
|
||||
static const hsScalar k21BitScaleRange;
|
||||
|
||||
void SetQuat(hsQuat &q);
|
||||
void GetQuat(hsQuat &q);
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsCompressedQuatKey64 *key);
|
||||
|
||||
protected:
|
||||
UInt32 fData[2];
|
||||
};
|
||||
|
||||
struct hsScaleValue : public hsKeyFrame
|
||||
{
|
||||
hsVector3 fS; /* Scale components for x,y,z */
|
||||
hsQuat fQ; /* The axis along which the scale is applied */
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
int operator==(const hsScaleValue& a) const { return (fS == a.fS && fQ == a.fQ); }
|
||||
};
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
struct hsScaleKey : public hsKeyFrame
|
||||
{
|
||||
hsScaleValue fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsScaleKey *key);
|
||||
};
|
||||
|
||||
struct hsBezScaleKey : public hsKeyFrame
|
||||
{
|
||||
hsPoint3 fInTan;
|
||||
hsPoint3 fOutTan;
|
||||
hsScaleValue fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsBezScaleKey *key);
|
||||
};
|
||||
|
||||
struct hsG3DSMaxKeyFrame : public hsKeyFrame
|
||||
{
|
||||
hsAffineParts fParts;
|
||||
|
||||
void Reset() { fParts.Reset(); } // Make parts identity
|
||||
|
||||
void Set(hsMatrix44 *mat, UInt16 frame);
|
||||
void Set(const hsAffineParts &parts, UInt16 frame);
|
||||
|
||||
hsMatrix44* GetMatrix44(hsMatrix44 *mat) { fParts.ComposeMatrix(mat); return mat; }
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsG3DSMaxKeyFrame *key);
|
||||
};
|
||||
|
||||
struct hsMatrix33Key : public hsKeyFrame
|
||||
{
|
||||
hsMatrix33 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsMatrix33Key *key);
|
||||
};
|
||||
|
||||
struct hsMatrix44Key : public hsKeyFrame
|
||||
{
|
||||
hsMatrix44 fValue;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream);
|
||||
|
||||
hsBool CompareValue(hsMatrix44Key *key);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,220 +1,220 @@
|
||||
/*==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==*/
|
||||
|
||||
#ifndef hsTimedValue_inc
|
||||
#define hsTimedValue_inc
|
||||
|
||||
#include "hsStream.h"
|
||||
|
||||
template <class T>
|
||||
class hsTimedValue {
|
||||
public:
|
||||
enum {
|
||||
kIdle = 0x1,
|
||||
kInstant = 0x2
|
||||
};
|
||||
protected:
|
||||
UInt32 fFlags;
|
||||
hsScalar fDuration;
|
||||
hsScalar fStartTime;
|
||||
|
||||
T fValue;
|
||||
T fGoal;
|
||||
T fFrom;
|
||||
|
||||
public:
|
||||
hsTimedValue() : fFlags(kIdle|kInstant), fDuration(0) {}
|
||||
hsTimedValue(const T& v) : fFlags(kIdle|kInstant), fDuration(0) { SetValue(v); }
|
||||
|
||||
UInt32 GetFlags() { return fFlags; }
|
||||
|
||||
void SetDuration(hsScalar duration);
|
||||
hsScalar GetDuration() const { return fDuration; }
|
||||
|
||||
hsBool32 operator==(const hsTimedValue<T>& v);
|
||||
hsTimedValue<T>& operator=(const T& v) { SetValue(v); return *this; }
|
||||
hsTimedValue<T>& operator+=(const T& v) { SetValue(v + fValue); return *this; }
|
||||
|
||||
void SetTempValue(const T& v) { fValue = v; }
|
||||
void SetValue(const T& v) { fFrom = fGoal = fValue = v; fFlags |= kIdle; }
|
||||
const T& GetValue() const { return fValue; }
|
||||
|
||||
void SetGoal(const T& g) { fGoal = g; }
|
||||
const T& GetGoal() const { return fGoal; }
|
||||
|
||||
void Reset() { fFlags |= (kIdle | kInstant); }
|
||||
|
||||
void StartClock(hsScalar s);
|
||||
hsScalar GetStartTime() const { return fStartTime; }
|
||||
|
||||
const T& GetFrom() const { return fFrom; }
|
||||
|
||||
void Update(hsScalar s);
|
||||
|
||||
void WriteScalar(hsStream* s, hsScalar currSecs);
|
||||
void Write(hsStream* s, hsScalar currSecs);
|
||||
|
||||
void ReadScalar(hsStream* s, hsScalar currSecs);
|
||||
void Read(hsStream* s, hsScalar currSecs);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::WriteScalar(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
s->WriteSwap32(fFlags);
|
||||
|
||||
s->WriteSwapScalar(fValue);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
s->WriteSwapScalar(fDuration);
|
||||
s->WriteSwapScalar(currSecs - fStartTime);
|
||||
|
||||
s->WriteSwapScalar(fGoal);
|
||||
s->WriteSwapScalar(fFrom);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Write(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
s->WriteSwap32(fFlags);
|
||||
|
||||
fValue.Write(s);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
s->WriteSwapScalar(fDuration);
|
||||
s->WriteSwapScalar(currSecs - fStartTime);
|
||||
|
||||
fGoal.Write(s);
|
||||
fFrom.Write(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::ReadScalar(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
fFlags = s->ReadSwap32();
|
||||
|
||||
fValue = s->ReadSwapScalar();
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
fDuration = s->ReadSwapScalar();
|
||||
fStartTime = currSecs - s->ReadSwapScalar();
|
||||
|
||||
fGoal = s->ReadSwapScalar();
|
||||
fFrom = s->ReadSwapScalar();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Read(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
fFlags = s->ReadSwap32();
|
||||
|
||||
fValue.Read(s);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
fDuration = s->ReadSwapScalar();
|
||||
fStartTime = currSecs - s->ReadSwapScalar();
|
||||
|
||||
fGoal.Read(s);
|
||||
fFrom.Read(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::SetDuration(hsScalar duration)
|
||||
{
|
||||
fDuration = duration;
|
||||
if( fDuration > 0 )
|
||||
fFlags &= ~kInstant;
|
||||
else
|
||||
fFlags |= kInstant;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
hsBool32 hsTimedValue<T>::operator==(const hsTimedValue<T>& v)
|
||||
{
|
||||
if ((fFlags == v.fFlags) &&
|
||||
(fDuration == v.fDuration) &&
|
||||
(fStartTime == v.fStartTime) &&
|
||||
(fValue == v.fValue) &&
|
||||
(fGoal == v.fGoal) &&
|
||||
(fFrom == v.fFrom))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::StartClock(hsScalar s)
|
||||
{
|
||||
fStartTime = s;
|
||||
|
||||
if( fFlags & kInstant )
|
||||
{
|
||||
fFlags |= kIdle;
|
||||
fValue = fGoal;
|
||||
return;
|
||||
}
|
||||
|
||||
fFlags &= ~kIdle;
|
||||
|
||||
if( fValue == fGoal )
|
||||
fFlags |= kIdle;
|
||||
|
||||
fFrom = fValue;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Update(hsScalar s)
|
||||
{
|
||||
if( fFlags & kIdle )
|
||||
return;
|
||||
|
||||
hsAssert(fDuration > 0, "Instant should always be idle");
|
||||
|
||||
hsScalar interp = (s - fStartTime) / fDuration;
|
||||
|
||||
if( interp >= hsScalar1 )
|
||||
{
|
||||
fValue = fGoal;
|
||||
interp = hsScalar1;
|
||||
fFlags |= kIdle;
|
||||
}
|
||||
else
|
||||
fValue = fFrom + (fGoal - fFrom) * interp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // hsTimedValue_inc
|
||||
/*==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==*/
|
||||
|
||||
#ifndef hsTimedValue_inc
|
||||
#define hsTimedValue_inc
|
||||
|
||||
#include "hsStream.h"
|
||||
|
||||
template <class T>
|
||||
class hsTimedValue {
|
||||
public:
|
||||
enum {
|
||||
kIdle = 0x1,
|
||||
kInstant = 0x2
|
||||
};
|
||||
protected:
|
||||
UInt32 fFlags;
|
||||
hsScalar fDuration;
|
||||
hsScalar fStartTime;
|
||||
|
||||
T fValue;
|
||||
T fGoal;
|
||||
T fFrom;
|
||||
|
||||
public:
|
||||
hsTimedValue() : fFlags(kIdle|kInstant), fDuration(0) {}
|
||||
hsTimedValue(const T& v) : fFlags(kIdle|kInstant), fDuration(0) { SetValue(v); }
|
||||
|
||||
UInt32 GetFlags() { return fFlags; }
|
||||
|
||||
void SetDuration(hsScalar duration);
|
||||
hsScalar GetDuration() const { return fDuration; }
|
||||
|
||||
hsBool32 operator==(const hsTimedValue<T>& v);
|
||||
hsTimedValue<T>& operator=(const T& v) { SetValue(v); return *this; }
|
||||
hsTimedValue<T>& operator+=(const T& v) { SetValue(v + fValue); return *this; }
|
||||
|
||||
void SetTempValue(const T& v) { fValue = v; }
|
||||
void SetValue(const T& v) { fFrom = fGoal = fValue = v; fFlags |= kIdle; }
|
||||
const T& GetValue() const { return fValue; }
|
||||
|
||||
void SetGoal(const T& g) { fGoal = g; }
|
||||
const T& GetGoal() const { return fGoal; }
|
||||
|
||||
void Reset() { fFlags |= (kIdle | kInstant); }
|
||||
|
||||
void StartClock(hsScalar s);
|
||||
hsScalar GetStartTime() const { return fStartTime; }
|
||||
|
||||
const T& GetFrom() const { return fFrom; }
|
||||
|
||||
void Update(hsScalar s);
|
||||
|
||||
void WriteScalar(hsStream* s, hsScalar currSecs);
|
||||
void Write(hsStream* s, hsScalar currSecs);
|
||||
|
||||
void ReadScalar(hsStream* s, hsScalar currSecs);
|
||||
void Read(hsStream* s, hsScalar currSecs);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::WriteScalar(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
s->WriteSwap32(fFlags);
|
||||
|
||||
s->WriteSwapScalar(fValue);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
s->WriteSwapScalar(fDuration);
|
||||
s->WriteSwapScalar(currSecs - fStartTime);
|
||||
|
||||
s->WriteSwapScalar(fGoal);
|
||||
s->WriteSwapScalar(fFrom);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Write(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
s->WriteSwap32(fFlags);
|
||||
|
||||
fValue.Write(s);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
s->WriteSwapScalar(fDuration);
|
||||
s->WriteSwapScalar(currSecs - fStartTime);
|
||||
|
||||
fGoal.Write(s);
|
||||
fFrom.Write(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::ReadScalar(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
fFlags = s->ReadSwap32();
|
||||
|
||||
fValue = s->ReadSwapScalar();
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
fDuration = s->ReadSwapScalar();
|
||||
fStartTime = currSecs - s->ReadSwapScalar();
|
||||
|
||||
fGoal = s->ReadSwapScalar();
|
||||
fFrom = s->ReadSwapScalar();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Read(hsStream* s, hsScalar currSecs)
|
||||
{
|
||||
fFlags = s->ReadSwap32();
|
||||
|
||||
fValue.Read(s);
|
||||
|
||||
if( !(fFlags & kIdle) )
|
||||
{
|
||||
fDuration = s->ReadSwapScalar();
|
||||
fStartTime = currSecs - s->ReadSwapScalar();
|
||||
|
||||
fGoal.Read(s);
|
||||
fFrom.Read(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::SetDuration(hsScalar duration)
|
||||
{
|
||||
fDuration = duration;
|
||||
if( fDuration > 0 )
|
||||
fFlags &= ~kInstant;
|
||||
else
|
||||
fFlags |= kInstant;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
hsBool32 hsTimedValue<T>::operator==(const hsTimedValue<T>& v)
|
||||
{
|
||||
if ((fFlags == v.fFlags) &&
|
||||
(fDuration == v.fDuration) &&
|
||||
(fStartTime == v.fStartTime) &&
|
||||
(fValue == v.fValue) &&
|
||||
(fGoal == v.fGoal) &&
|
||||
(fFrom == v.fFrom))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::StartClock(hsScalar s)
|
||||
{
|
||||
fStartTime = s;
|
||||
|
||||
if( fFlags & kInstant )
|
||||
{
|
||||
fFlags |= kIdle;
|
||||
fValue = fGoal;
|
||||
return;
|
||||
}
|
||||
|
||||
fFlags &= ~kIdle;
|
||||
|
||||
if( fValue == fGoal )
|
||||
fFlags |= kIdle;
|
||||
|
||||
fFrom = fValue;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void hsTimedValue<T>::Update(hsScalar s)
|
||||
{
|
||||
if( fFlags & kIdle )
|
||||
return;
|
||||
|
||||
hsAssert(fDuration > 0, "Instant should always be idle");
|
||||
|
||||
hsScalar interp = (s - fStartTime) / fDuration;
|
||||
|
||||
if( interp >= hsScalar1 )
|
||||
{
|
||||
fValue = fGoal;
|
||||
interp = hsScalar1;
|
||||
fFlags |= kIdle;
|
||||
}
|
||||
else
|
||||
fValue = fFrom + (fGoal - fFrom) * interp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // hsTimedValue_inc
|
||||
|
@ -1,347 +1,347 @@
|
||||
/*==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 "plAnimEaseTypes.h"
|
||||
#include "plAnimTimeConvert.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plATCEaseCurve *plATCEaseCurve::CreateEaseCurve(UInt8 type, hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
if (type == plAnimEaseTypes::kConstAccel)
|
||||
return TRACKED_NEW plConstAccelEaseCurve(minLength, maxLength, length, startSpeed, goalSpeed);
|
||||
if (type == plAnimEaseTypes::kSpline)
|
||||
return TRACKED_NEW plSplineEaseCurve(minLength, maxLength, length, startSpeed, goalSpeed);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plATCEaseCurve::RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate /* = false */)
|
||||
{
|
||||
hsScalar rate = 1;
|
||||
|
||||
if (fSpeed == goalSpeed && fStartSpeed == startSpeed) // already there, no need to do anything
|
||||
return;
|
||||
|
||||
if (preserveRate)
|
||||
rate = (fSpeed - fStartSpeed) / fLength;
|
||||
|
||||
fStartSpeed = startSpeed;
|
||||
fSpeed = goalSpeed;
|
||||
|
||||
if (preserveRate)
|
||||
SetLengthOnRate(rate);
|
||||
}
|
||||
|
||||
void plATCEaseCurve::SetLengthOnRate(hsScalar rate)
|
||||
{
|
||||
fLength = (fSpeed - fStartSpeed) / rate;
|
||||
if (fLength < 0)
|
||||
fLength = -fLength;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetMinDistance()
|
||||
{
|
||||
if (fMinLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fMinLength;
|
||||
hsScalar result = PositionGivenTime(fMinLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetMaxDistance()
|
||||
{
|
||||
if (fMaxLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fMaxLength;
|
||||
hsScalar result = PositionGivenTime(fMaxLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetNormDistance()
|
||||
{
|
||||
if (fNormLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fNormLength;
|
||||
hsScalar result = PositionGivenTime(fNormLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
void plATCEaseCurve::Read(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Read(s, mgr);
|
||||
|
||||
fMinLength = s->ReadSwapScalar();
|
||||
fMaxLength = s->ReadSwapScalar();
|
||||
fNormLength = fLength = s->ReadSwapScalar();
|
||||
fStartSpeed = s->ReadSwapScalar();
|
||||
fSpeed = s->ReadSwapScalar();
|
||||
fBeginWorldTime = s->ReadSwapDouble();
|
||||
}
|
||||
|
||||
void plATCEaseCurve::Write(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Write(s, mgr);
|
||||
|
||||
s->WriteSwapScalar(fMinLength);
|
||||
s->WriteSwapScalar(fMaxLength);
|
||||
s->WriteSwapScalar(fNormLength);
|
||||
s->WriteSwapScalar(fStartSpeed);
|
||||
s->WriteSwapScalar(fSpeed);
|
||||
s->WriteSwapDouble(fBeginWorldTime);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plConstAccelEaseCurve::plConstAccelEaseCurve()
|
||||
{
|
||||
fMinLength = fMaxLength = fNormLength = fLength = 1;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(0, 1);
|
||||
}
|
||||
|
||||
plConstAccelEaseCurve::plConstAccelEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
fMinLength = minLength;
|
||||
fMaxLength = maxLength;
|
||||
fNormLength = fLength = length;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(startSpeed, goalSpeed);
|
||||
}
|
||||
|
||||
plATCEaseCurve *plConstAccelEaseCurve::Clone() const
|
||||
{
|
||||
plConstAccelEaseCurve *curve = TRACKED_NEW plConstAccelEaseCurve;
|
||||
curve->fStartSpeed = fStartSpeed;
|
||||
curve->fMinLength = fMinLength;
|
||||
curve->fMaxLength = fMaxLength;
|
||||
curve->fNormLength = fNormLength;
|
||||
curve->fBeginWorldTime = fBeginWorldTime;
|
||||
curve->fLength = fLength;
|
||||
curve->fSpeed = fSpeed;
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void plConstAccelEaseCurve::SetLengthOnDistance(hsScalar dist)
|
||||
{
|
||||
fLength = 2 * dist / (fSpeed + fStartSpeed);
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::PositionGivenTime(hsScalar time) const
|
||||
{
|
||||
return (hsScalar)(fStartSpeed * time + (0.5 * (fSpeed - fStartSpeed) / fLength) * time * time);
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::VelocityGivenTime(hsScalar time) const
|
||||
{
|
||||
return fStartSpeed + ((fSpeed - fStartSpeed) / fLength) * time;
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::TimeGivenVelocity(hsScalar velocity) const
|
||||
{
|
||||
return (velocity - fStartSpeed) / ((fSpeed - fStartSpeed) / fLength);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plSplineEaseCurve::plSplineEaseCurve()
|
||||
{
|
||||
fMinLength = fMaxLength = fNormLength = fLength = 1;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(0, 1);
|
||||
}
|
||||
|
||||
plSplineEaseCurve::plSplineEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
fMinLength = minLength;
|
||||
fMaxLength = maxLength;
|
||||
fNormLength = fLength = length;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(startSpeed, goalSpeed);
|
||||
}
|
||||
|
||||
plATCEaseCurve *plSplineEaseCurve::Clone() const
|
||||
{
|
||||
plSplineEaseCurve *curve = TRACKED_NEW plSplineEaseCurve;
|
||||
curve->fStartSpeed = fStartSpeed;
|
||||
curve->fMinLength = fMinLength;
|
||||
curve->fMaxLength = fMaxLength;
|
||||
curve->fNormLength = fNormLength;
|
||||
curve->fBeginWorldTime = fBeginWorldTime;
|
||||
curve->fLength = fLength;
|
||||
curve->fSpeed = fSpeed;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
curve->fCoef[i] = fCoef[i];
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate /* = false */)
|
||||
{
|
||||
plATCEaseCurve::RecalcToSpeed(startSpeed, goalSpeed, preserveRate);
|
||||
|
||||
// These are greatly simplified because the in/out tangents are always zero
|
||||
// Note: "b" is always zero for the ease splines we're currently doing (and will remain that way
|
||||
// so long as the initial acceleration is zero. Can optimize a bit of the eval math to take
|
||||
// advantage of this.
|
||||
hsScalar a, b, c, d;
|
||||
|
||||
a = fStartSpeed;
|
||||
b = 0;
|
||||
c = -3 * fStartSpeed + 3 * fSpeed;
|
||||
d = 2 * fStartSpeed - 2 * fSpeed;
|
||||
|
||||
fCoef[0] = a;
|
||||
fCoef[1] = b;
|
||||
fCoef[2] = c;
|
||||
fCoef[3] = d;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::SetLengthOnDistance(hsScalar dist)
|
||||
{
|
||||
hsScalar curDist = PositionGivenTime(fLength);
|
||||
|
||||
fLength = fLength * dist / curDist;
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::PositionGivenTime(hsScalar time) const
|
||||
{
|
||||
hsScalar t1, t2, t3, t4;
|
||||
t1 = time / fLength;
|
||||
t2 = t1 * t1;
|
||||
t3 = t2 * t1;
|
||||
t4 = t3 * t1;
|
||||
|
||||
return fLength * (fCoef[0] * t1 + fCoef[1] * t2 / 2 + fCoef[2] * t3 / 3 + fCoef[3] * t4 / 4);
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::VelocityGivenTime(hsScalar time) const
|
||||
{
|
||||
hsScalar t1, t2, t3;
|
||||
t1 = time / fLength;
|
||||
t2 = t1 * t1;
|
||||
t3 = t2 * t1;
|
||||
return fCoef[0] + fCoef[1] * t1 + fCoef[2] * t2 + fCoef[3] * t3;
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::TimeGivenVelocity(hsScalar velocity) const
|
||||
{
|
||||
// Code based off of Graphics Gems V, pp 11-12 and
|
||||
// http://www.worldserver.com/turk/opensource/FindCubicRoots.c.txt
|
||||
|
||||
// Solving the equation: fCoef[0] + fCoef[1] * t + fCoef[2] * t^2 + fCoef[3] * t^3 - velocity = 0
|
||||
|
||||
hsScalar root;
|
||||
hsScalar a = (fCoef[0] - velocity) / fCoef[3];
|
||||
hsScalar b = fCoef[1] / fCoef[3];
|
||||
hsScalar c = fCoef[2] / fCoef[3];
|
||||
|
||||
hsScalar Q = (c * c - 3 * b) / 9;
|
||||
hsScalar R = (2 * c * c * c - 9 * c * b + 27 * a) / 54;
|
||||
hsScalar Q3 = Q * Q * Q;
|
||||
hsScalar D = Q3 - R * R;
|
||||
|
||||
if (D >= 0)
|
||||
{
|
||||
// 3 roots, find the one in the range [0, 1]
|
||||
const hsScalar pi = 3.14159;
|
||||
double theta = acos(R / sqrt(Q3));
|
||||
double sqrtQ = sqrt(Q);
|
||||
|
||||
root = (hsScalar)(-2 * sqrtQ * cos((theta + 4 * pi) / 3) - c / 3); // Middle root, most likely to match
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
root = (hsScalar)(-2 * sqrtQ * cos((theta + 2 * pi) / 3) - c / 3); // Lower root
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
root = (hsScalar)(-2 * sqrtQ * cos(theta / 3) - c / 3); // Upper root
|
||||
}
|
||||
}
|
||||
}
|
||||
else // One root to the equation (I don't expect this to happen for ease splines, but JIC)
|
||||
{
|
||||
double E = sqrt(-D) + pow(fabs(R), 1.f / 3.f);
|
||||
root = (hsScalar)((E + Q / E) - c / 3);
|
||||
if (R > 0)
|
||||
root = -root;
|
||||
}
|
||||
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
hsAssert(false, "No valid root found while solving animation spline");
|
||||
// Either a bug, or a rare case of floating-point inaccuracy. Either way, guess
|
||||
// the proper root as either the start or end of the curve based on the velocity.
|
||||
hsScalar dStart = velocity - fStartSpeed;
|
||||
if (dStart < 0)
|
||||
dStart = -dStart;
|
||||
hsScalar dEnd = velocity - fSpeed;
|
||||
if (dEnd < 0)
|
||||
dEnd = -dEnd;
|
||||
|
||||
root = (dStart < dEnd ? 0.f : 1.f);
|
||||
}
|
||||
|
||||
return root * fLength;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::Read(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plATCEaseCurve::Read(s, mgr);
|
||||
|
||||
fCoef[0] = s->ReadSwapScalar();
|
||||
fCoef[1] = s->ReadSwapScalar();
|
||||
fCoef[2] = s->ReadSwapScalar();
|
||||
fCoef[3] = s->ReadSwapScalar();
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::Write(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plATCEaseCurve::Write(s, mgr);
|
||||
|
||||
s->WriteSwapScalar(fCoef[0]);
|
||||
s->WriteSwapScalar(fCoef[1]);
|
||||
s->WriteSwapScalar(fCoef[2]);
|
||||
s->WriteSwapScalar(fCoef[3]);
|
||||
}
|
||||
|
||||
/*==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 "plAnimEaseTypes.h"
|
||||
#include "plAnimTimeConvert.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plATCEaseCurve *plATCEaseCurve::CreateEaseCurve(UInt8 type, hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
if (type == plAnimEaseTypes::kConstAccel)
|
||||
return TRACKED_NEW plConstAccelEaseCurve(minLength, maxLength, length, startSpeed, goalSpeed);
|
||||
if (type == plAnimEaseTypes::kSpline)
|
||||
return TRACKED_NEW plSplineEaseCurve(minLength, maxLength, length, startSpeed, goalSpeed);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plATCEaseCurve::RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate /* = false */)
|
||||
{
|
||||
hsScalar rate = 1;
|
||||
|
||||
if (fSpeed == goalSpeed && fStartSpeed == startSpeed) // already there, no need to do anything
|
||||
return;
|
||||
|
||||
if (preserveRate)
|
||||
rate = (fSpeed - fStartSpeed) / fLength;
|
||||
|
||||
fStartSpeed = startSpeed;
|
||||
fSpeed = goalSpeed;
|
||||
|
||||
if (preserveRate)
|
||||
SetLengthOnRate(rate);
|
||||
}
|
||||
|
||||
void plATCEaseCurve::SetLengthOnRate(hsScalar rate)
|
||||
{
|
||||
fLength = (fSpeed - fStartSpeed) / rate;
|
||||
if (fLength < 0)
|
||||
fLength = -fLength;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetMinDistance()
|
||||
{
|
||||
if (fMinLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fMinLength;
|
||||
hsScalar result = PositionGivenTime(fMinLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetMaxDistance()
|
||||
{
|
||||
if (fMaxLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fMaxLength;
|
||||
hsScalar result = PositionGivenTime(fMaxLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
hsScalar plATCEaseCurve::GetNormDistance()
|
||||
{
|
||||
if (fNormLength == 0)
|
||||
return 0;
|
||||
|
||||
hsScalar oldLength = fLength;
|
||||
fLength = fNormLength;
|
||||
hsScalar result = PositionGivenTime(fNormLength);
|
||||
fLength = oldLength;
|
||||
return result;
|
||||
}
|
||||
|
||||
void plATCEaseCurve::Read(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Read(s, mgr);
|
||||
|
||||
fMinLength = s->ReadSwapScalar();
|
||||
fMaxLength = s->ReadSwapScalar();
|
||||
fNormLength = fLength = s->ReadSwapScalar();
|
||||
fStartSpeed = s->ReadSwapScalar();
|
||||
fSpeed = s->ReadSwapScalar();
|
||||
fBeginWorldTime = s->ReadSwapDouble();
|
||||
}
|
||||
|
||||
void plATCEaseCurve::Write(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Write(s, mgr);
|
||||
|
||||
s->WriteSwapScalar(fMinLength);
|
||||
s->WriteSwapScalar(fMaxLength);
|
||||
s->WriteSwapScalar(fNormLength);
|
||||
s->WriteSwapScalar(fStartSpeed);
|
||||
s->WriteSwapScalar(fSpeed);
|
||||
s->WriteSwapDouble(fBeginWorldTime);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plConstAccelEaseCurve::plConstAccelEaseCurve()
|
||||
{
|
||||
fMinLength = fMaxLength = fNormLength = fLength = 1;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(0, 1);
|
||||
}
|
||||
|
||||
plConstAccelEaseCurve::plConstAccelEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
fMinLength = minLength;
|
||||
fMaxLength = maxLength;
|
||||
fNormLength = fLength = length;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(startSpeed, goalSpeed);
|
||||
}
|
||||
|
||||
plATCEaseCurve *plConstAccelEaseCurve::Clone() const
|
||||
{
|
||||
plConstAccelEaseCurve *curve = TRACKED_NEW plConstAccelEaseCurve;
|
||||
curve->fStartSpeed = fStartSpeed;
|
||||
curve->fMinLength = fMinLength;
|
||||
curve->fMaxLength = fMaxLength;
|
||||
curve->fNormLength = fNormLength;
|
||||
curve->fBeginWorldTime = fBeginWorldTime;
|
||||
curve->fLength = fLength;
|
||||
curve->fSpeed = fSpeed;
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void plConstAccelEaseCurve::SetLengthOnDistance(hsScalar dist)
|
||||
{
|
||||
fLength = 2 * dist / (fSpeed + fStartSpeed);
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::PositionGivenTime(hsScalar time) const
|
||||
{
|
||||
return (hsScalar)(fStartSpeed * time + (0.5 * (fSpeed - fStartSpeed) / fLength) * time * time);
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::VelocityGivenTime(hsScalar time) const
|
||||
{
|
||||
return fStartSpeed + ((fSpeed - fStartSpeed) / fLength) * time;
|
||||
}
|
||||
|
||||
hsScalar plConstAccelEaseCurve::TimeGivenVelocity(hsScalar velocity) const
|
||||
{
|
||||
return (velocity - fStartSpeed) / ((fSpeed - fStartSpeed) / fLength);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
plSplineEaseCurve::plSplineEaseCurve()
|
||||
{
|
||||
fMinLength = fMaxLength = fNormLength = fLength = 1;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(0, 1);
|
||||
}
|
||||
|
||||
plSplineEaseCurve::plSplineEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed)
|
||||
{
|
||||
fMinLength = minLength;
|
||||
fMaxLength = maxLength;
|
||||
fNormLength = fLength = length;
|
||||
fBeginWorldTime = 0;
|
||||
|
||||
RecalcToSpeed(startSpeed, goalSpeed);
|
||||
}
|
||||
|
||||
plATCEaseCurve *plSplineEaseCurve::Clone() const
|
||||
{
|
||||
plSplineEaseCurve *curve = TRACKED_NEW plSplineEaseCurve;
|
||||
curve->fStartSpeed = fStartSpeed;
|
||||
curve->fMinLength = fMinLength;
|
||||
curve->fMaxLength = fMaxLength;
|
||||
curve->fNormLength = fNormLength;
|
||||
curve->fBeginWorldTime = fBeginWorldTime;
|
||||
curve->fLength = fLength;
|
||||
curve->fSpeed = fSpeed;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
curve->fCoef[i] = fCoef[i];
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate /* = false */)
|
||||
{
|
||||
plATCEaseCurve::RecalcToSpeed(startSpeed, goalSpeed, preserveRate);
|
||||
|
||||
// These are greatly simplified because the in/out tangents are always zero
|
||||
// Note: "b" is always zero for the ease splines we're currently doing (and will remain that way
|
||||
// so long as the initial acceleration is zero. Can optimize a bit of the eval math to take
|
||||
// advantage of this.
|
||||
hsScalar a, b, c, d;
|
||||
|
||||
a = fStartSpeed;
|
||||
b = 0;
|
||||
c = -3 * fStartSpeed + 3 * fSpeed;
|
||||
d = 2 * fStartSpeed - 2 * fSpeed;
|
||||
|
||||
fCoef[0] = a;
|
||||
fCoef[1] = b;
|
||||
fCoef[2] = c;
|
||||
fCoef[3] = d;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::SetLengthOnDistance(hsScalar dist)
|
||||
{
|
||||
hsScalar curDist = PositionGivenTime(fLength);
|
||||
|
||||
fLength = fLength * dist / curDist;
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::PositionGivenTime(hsScalar time) const
|
||||
{
|
||||
hsScalar t1, t2, t3, t4;
|
||||
t1 = time / fLength;
|
||||
t2 = t1 * t1;
|
||||
t3 = t2 * t1;
|
||||
t4 = t3 * t1;
|
||||
|
||||
return fLength * (fCoef[0] * t1 + fCoef[1] * t2 / 2 + fCoef[2] * t3 / 3 + fCoef[3] * t4 / 4);
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::VelocityGivenTime(hsScalar time) const
|
||||
{
|
||||
hsScalar t1, t2, t3;
|
||||
t1 = time / fLength;
|
||||
t2 = t1 * t1;
|
||||
t3 = t2 * t1;
|
||||
return fCoef[0] + fCoef[1] * t1 + fCoef[2] * t2 + fCoef[3] * t3;
|
||||
}
|
||||
|
||||
hsScalar plSplineEaseCurve::TimeGivenVelocity(hsScalar velocity) const
|
||||
{
|
||||
// Code based off of Graphics Gems V, pp 11-12 and
|
||||
// http://www.worldserver.com/turk/opensource/FindCubicRoots.c.txt
|
||||
|
||||
// Solving the equation: fCoef[0] + fCoef[1] * t + fCoef[2] * t^2 + fCoef[3] * t^3 - velocity = 0
|
||||
|
||||
hsScalar root;
|
||||
hsScalar a = (fCoef[0] - velocity) / fCoef[3];
|
||||
hsScalar b = fCoef[1] / fCoef[3];
|
||||
hsScalar c = fCoef[2] / fCoef[3];
|
||||
|
||||
hsScalar Q = (c * c - 3 * b) / 9;
|
||||
hsScalar R = (2 * c * c * c - 9 * c * b + 27 * a) / 54;
|
||||
hsScalar Q3 = Q * Q * Q;
|
||||
hsScalar D = Q3 - R * R;
|
||||
|
||||
if (D >= 0)
|
||||
{
|
||||
// 3 roots, find the one in the range [0, 1]
|
||||
const hsScalar pi = 3.14159;
|
||||
double theta = acos(R / sqrt(Q3));
|
||||
double sqrtQ = sqrt(Q);
|
||||
|
||||
root = (hsScalar)(-2 * sqrtQ * cos((theta + 4 * pi) / 3) - c / 3); // Middle root, most likely to match
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
root = (hsScalar)(-2 * sqrtQ * cos((theta + 2 * pi) / 3) - c / 3); // Lower root
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
root = (hsScalar)(-2 * sqrtQ * cos(theta / 3) - c / 3); // Upper root
|
||||
}
|
||||
}
|
||||
}
|
||||
else // One root to the equation (I don't expect this to happen for ease splines, but JIC)
|
||||
{
|
||||
double E = sqrt(-D) + pow(fabs(R), 1.f / 3.f);
|
||||
root = (hsScalar)((E + Q / E) - c / 3);
|
||||
if (R > 0)
|
||||
root = -root;
|
||||
}
|
||||
|
||||
if (root < 0.f || root > 1.f)
|
||||
{
|
||||
hsAssert(false, "No valid root found while solving animation spline");
|
||||
// Either a bug, or a rare case of floating-point inaccuracy. Either way, guess
|
||||
// the proper root as either the start or end of the curve based on the velocity.
|
||||
hsScalar dStart = velocity - fStartSpeed;
|
||||
if (dStart < 0)
|
||||
dStart = -dStart;
|
||||
hsScalar dEnd = velocity - fSpeed;
|
||||
if (dEnd < 0)
|
||||
dEnd = -dEnd;
|
||||
|
||||
root = (dStart < dEnd ? 0.f : 1.f);
|
||||
}
|
||||
|
||||
return root * fLength;
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::Read(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plATCEaseCurve::Read(s, mgr);
|
||||
|
||||
fCoef[0] = s->ReadSwapScalar();
|
||||
fCoef[1] = s->ReadSwapScalar();
|
||||
fCoef[2] = s->ReadSwapScalar();
|
||||
fCoef[3] = s->ReadSwapScalar();
|
||||
}
|
||||
|
||||
void plSplineEaseCurve::Write(hsStream *s, hsResMgr *mgr)
|
||||
{
|
||||
plATCEaseCurve::Write(s, mgr);
|
||||
|
||||
s->WriteSwapScalar(fCoef[0]);
|
||||
s->WriteSwapScalar(fCoef[1]);
|
||||
s->WriteSwapScalar(fCoef[2]);
|
||||
s->WriteSwapScalar(fCoef[3]);
|
||||
}
|
||||
|
||||
|
@ -1,43 +1,43 @@
|
||||
/*==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==*/
|
||||
#ifndef PL_ANIM_EASE_TYPES
|
||||
#define PL_ANIM_EASE_TYPES
|
||||
|
||||
// Silly little header so that both export and runtime code can use these
|
||||
// constants without including tons of unneccessary stuff
|
||||
|
||||
namespace plAnimEaseTypes
|
||||
{
|
||||
enum {
|
||||
kNoEase,
|
||||
kConstAccel,
|
||||
kSpline,
|
||||
};
|
||||
};
|
||||
|
||||
#define ENTIRE_ANIMATION_NAME "(Entire Animation)"
|
||||
|
||||
/*==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==*/
|
||||
#ifndef PL_ANIM_EASE_TYPES
|
||||
#define PL_ANIM_EASE_TYPES
|
||||
|
||||
// Silly little header so that both export and runtime code can use these
|
||||
// constants without including tons of unneccessary stuff
|
||||
|
||||
namespace plAnimEaseTypes
|
||||
{
|
||||
enum {
|
||||
kNoEase,
|
||||
kConstAccel,
|
||||
kSpline,
|
||||
};
|
||||
};
|
||||
|
||||
#define ENTIRE_ANIMATION_NAME "(Entire Animation)"
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,172 +1,172 @@
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plAnimPath_inc
|
||||
#define plAnimPath_inc
|
||||
|
||||
#include "hsTemplates.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsMatrix44.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "pnFactory/plCreatable.h"
|
||||
|
||||
class plCompoundController;
|
||||
|
||||
class plAnimPath : public plCreatable
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
kNone = 0x0,
|
||||
kFavorFwdSearch = 0x1, // only move fwd on the curve when searching
|
||||
kFavorBwdSearch = 0x2, // only move bwd on the curve when searching
|
||||
kCalcPosOnly = 0x4, // only compute pos when calling SetCurTime()
|
||||
kFarthest = 0x8,
|
||||
kWrap = 0x10,
|
||||
kIncrement = 0x20, // find the nearest / farthest point, but increment toward it
|
||||
};
|
||||
protected:
|
||||
// The final product info
|
||||
hsMatrix44 fXform;
|
||||
hsPoint3 fPos;
|
||||
hsVector3 fVel;
|
||||
hsVector3 fAccel;
|
||||
hsScalar fTime; // presumably seconds
|
||||
|
||||
// The paramters (and options) for this curve.
|
||||
UInt32 fAnimPathFlags; // currently set at runtime only
|
||||
hsScalar fMinDistSq;
|
||||
hsScalar fLength; // presumably seconds
|
||||
|
||||
// Controller stuff only works in local space.
|
||||
hsMatrix44 fLocalToWorld;
|
||||
hsMatrix44 fWorldToLocal;
|
||||
|
||||
// Bounding sphere available for ignoring out of range
|
||||
hsPoint3 fCenter;
|
||||
hsScalar fRadius;
|
||||
|
||||
plCompoundController* fController;
|
||||
|
||||
hsAffineParts fParts;
|
||||
|
||||
// These are temps during a search. They're here to avoid recalc.
|
||||
mutable hsScalar fLastTime;
|
||||
mutable hsScalar fLastDistSq;
|
||||
mutable hsScalar fThisTime;
|
||||
mutable hsScalar fThisDistSq;
|
||||
mutable hsScalar fNextTime;
|
||||
mutable hsScalar fNextDistSq;
|
||||
mutable hsScalar fDelTime;
|
||||
mutable hsPoint3 fPrevPos, fCurPos;
|
||||
|
||||
void ICalcBounds();
|
||||
hsScalar ICalcTotalLength();
|
||||
hsScalar IShiftFore(hsPoint3 &pt) const;
|
||||
hsScalar IShiftBack(hsPoint3 &pt) const;
|
||||
hsScalar ISubDivFore(hsPoint3 &pt) const;
|
||||
hsScalar ISubDivBack(hsPoint3 &pt) const;
|
||||
void IInitInterval(hsScalar time, hsScalar delTime, hsPoint3 &pt) const;
|
||||
hsScalar ICheckInterval(hsPoint3 &pt) const;
|
||||
hsScalar IBestTime() const { return fLastDistSq < fThisDistSq
|
||||
? (fLastDistSq < fNextDistSq
|
||||
? fLastTime
|
||||
: fNextTime)
|
||||
: (fThisDistSq < fNextDistSq
|
||||
? fThisTime
|
||||
: fNextTime); }
|
||||
|
||||
// Visualization helper
|
||||
void IMakeSegment(hsTArray<UInt16>& idx, hsTArray<hsPoint3>& pos,
|
||||
hsPoint3& p1, hsPoint3& p2);
|
||||
|
||||
// For computing arclen
|
||||
struct ArcLenDeltaInfo
|
||||
{
|
||||
hsScalar fT;
|
||||
hsScalar fArcLenDelta; // arc len distance from prev sample point (array entry)
|
||||
ArcLenDeltaInfo(hsScalar t, hsScalar del) : fT(t),fArcLenDelta(del) {}
|
||||
ArcLenDeltaInfo() : fT(0),fArcLenDelta(0) {}
|
||||
};
|
||||
hsTArray<ArcLenDeltaInfo> fArcLenDeltas;
|
||||
public:
|
||||
plAnimPath();
|
||||
virtual ~plAnimPath();
|
||||
|
||||
CLASSNAME_REGISTER( plAnimPath );
|
||||
GETINTERFACE_ANY( plAnimPath, plCreatable );
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
|
||||
const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
|
||||
|
||||
// Visualization helper
|
||||
void MakeDrawList(hsTArray<UInt16>& idx, hsTArray<hsPoint3>& pos);
|
||||
|
||||
void SetAnimPathFlags(UInt32 f) { fAnimPathFlags=f; }
|
||||
UInt32 GetAnimPathFlags() const { return fAnimPathFlags; }
|
||||
|
||||
void SetWrap(hsBool on) { if(on)fAnimPathFlags |= kWrap; else fAnimPathFlags &= ~kWrap; }
|
||||
hsBool GetWrap() const { return 0 != (fAnimPathFlags & kWrap); }
|
||||
|
||||
void SetFarthest(hsBool on) { if(on)fAnimPathFlags |= kFarthest; else fAnimPathFlags &= ~kFarthest; }
|
||||
hsBool GetFarthest() const { return 0 != (fAnimPathFlags & kFarthest); }
|
||||
|
||||
void SetCurTime(hsScalar t, UInt32 calcFlags=0);
|
||||
hsScalar GetCurTime() const { return fTime; }
|
||||
|
||||
void SetController(plCompoundController* tmc);
|
||||
plCompoundController* GetController() const { return fController; }
|
||||
hsScalar GetLength() const { return fLength; } // seconds
|
||||
|
||||
void SetMinDistance(hsScalar d) { fMinDistSq = d*d; }
|
||||
hsScalar GetMinDistance() const { return hsSquareRoot(fMinDistSq); }
|
||||
|
||||
hsMatrix44* GetMatrix44(hsMatrix44* xOut) const { *xOut = fXform; return xOut; }
|
||||
hsPoint3* GetPosition(hsPoint3* pOut) const { *pOut = fPos; return pOut; }
|
||||
hsVector3* GetVelocity(hsVector3* vOut) const { *vOut = fVel; return vOut; }
|
||||
hsVector3* GetDirection(hsVector3* dOut) const { dOut->Set(fXform.fMap[0][2], fXform.fMap[1][2], fXform.fMap[2][2]); return dOut; }
|
||||
hsVector3* GetUp(hsVector3* uOut) const { uOut->Set(fXform.fMap[0][1], fXform.fMap[1][1], fXform.fMap[2][1]); return uOut; }
|
||||
hsVector3* GetAcceleration(hsVector3* aOut) const { *aOut = fAccel; return aOut; }
|
||||
|
||||
hsBool OutOfRange(hsPoint3 &pt, hsScalar range) const;
|
||||
const hsAffineParts* Parts() const { return &fParts; }
|
||||
void InitParts(const hsAffineParts& p) { fParts = p; }
|
||||
|
||||
hsScalar GetExtremePoint(hsPoint3 &worldPt) const; // Exhaustive search
|
||||
hsScalar GetExtremePoint(hsScalar lastTime, hsScalar delTime, hsPoint3 &worldPt) const; // Incremental search
|
||||
|
||||
// for arclen usage
|
||||
void ComputeArcLenDeltas(Int32 numSamples=256);
|
||||
hsScalar GetLookAheadTime(hsScalar startTime, hsScalar arcLength, hsBool bwd, Int32* startSrchIdx);
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif plAnimPath_inc
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plAnimPath_inc
|
||||
#define plAnimPath_inc
|
||||
|
||||
#include "hsTemplates.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsMatrix44.h"
|
||||
#include "plTransform/hsAffineParts.h"
|
||||
#include "pnFactory/plCreatable.h"
|
||||
|
||||
class plCompoundController;
|
||||
|
||||
class plAnimPath : public plCreatable
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
kNone = 0x0,
|
||||
kFavorFwdSearch = 0x1, // only move fwd on the curve when searching
|
||||
kFavorBwdSearch = 0x2, // only move bwd on the curve when searching
|
||||
kCalcPosOnly = 0x4, // only compute pos when calling SetCurTime()
|
||||
kFarthest = 0x8,
|
||||
kWrap = 0x10,
|
||||
kIncrement = 0x20, // find the nearest / farthest point, but increment toward it
|
||||
};
|
||||
protected:
|
||||
// The final product info
|
||||
hsMatrix44 fXform;
|
||||
hsPoint3 fPos;
|
||||
hsVector3 fVel;
|
||||
hsVector3 fAccel;
|
||||
hsScalar fTime; // presumably seconds
|
||||
|
||||
// The paramters (and options) for this curve.
|
||||
UInt32 fAnimPathFlags; // currently set at runtime only
|
||||
hsScalar fMinDistSq;
|
||||
hsScalar fLength; // presumably seconds
|
||||
|
||||
// Controller stuff only works in local space.
|
||||
hsMatrix44 fLocalToWorld;
|
||||
hsMatrix44 fWorldToLocal;
|
||||
|
||||
// Bounding sphere available for ignoring out of range
|
||||
hsPoint3 fCenter;
|
||||
hsScalar fRadius;
|
||||
|
||||
plCompoundController* fController;
|
||||
|
||||
hsAffineParts fParts;
|
||||
|
||||
// These are temps during a search. They're here to avoid recalc.
|
||||
mutable hsScalar fLastTime;
|
||||
mutable hsScalar fLastDistSq;
|
||||
mutable hsScalar fThisTime;
|
||||
mutable hsScalar fThisDistSq;
|
||||
mutable hsScalar fNextTime;
|
||||
mutable hsScalar fNextDistSq;
|
||||
mutable hsScalar fDelTime;
|
||||
mutable hsPoint3 fPrevPos, fCurPos;
|
||||
|
||||
void ICalcBounds();
|
||||
hsScalar ICalcTotalLength();
|
||||
hsScalar IShiftFore(hsPoint3 &pt) const;
|
||||
hsScalar IShiftBack(hsPoint3 &pt) const;
|
||||
hsScalar ISubDivFore(hsPoint3 &pt) const;
|
||||
hsScalar ISubDivBack(hsPoint3 &pt) const;
|
||||
void IInitInterval(hsScalar time, hsScalar delTime, hsPoint3 &pt) const;
|
||||
hsScalar ICheckInterval(hsPoint3 &pt) const;
|
||||
hsScalar IBestTime() const { return fLastDistSq < fThisDistSq
|
||||
? (fLastDistSq < fNextDistSq
|
||||
? fLastTime
|
||||
: fNextTime)
|
||||
: (fThisDistSq < fNextDistSq
|
||||
? fThisTime
|
||||
: fNextTime); }
|
||||
|
||||
// Visualization helper
|
||||
void IMakeSegment(hsTArray<UInt16>& idx, hsTArray<hsPoint3>& pos,
|
||||
hsPoint3& p1, hsPoint3& p2);
|
||||
|
||||
// For computing arclen
|
||||
struct ArcLenDeltaInfo
|
||||
{
|
||||
hsScalar fT;
|
||||
hsScalar fArcLenDelta; // arc len distance from prev sample point (array entry)
|
||||
ArcLenDeltaInfo(hsScalar t, hsScalar del) : fT(t),fArcLenDelta(del) {}
|
||||
ArcLenDeltaInfo() : fT(0),fArcLenDelta(0) {}
|
||||
};
|
||||
hsTArray<ArcLenDeltaInfo> fArcLenDeltas;
|
||||
public:
|
||||
plAnimPath();
|
||||
virtual ~plAnimPath();
|
||||
|
||||
CLASSNAME_REGISTER( plAnimPath );
|
||||
GETINTERFACE_ANY( plAnimPath, plCreatable );
|
||||
|
||||
void Reset();
|
||||
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
|
||||
const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
|
||||
|
||||
// Visualization helper
|
||||
void MakeDrawList(hsTArray<UInt16>& idx, hsTArray<hsPoint3>& pos);
|
||||
|
||||
void SetAnimPathFlags(UInt32 f) { fAnimPathFlags=f; }
|
||||
UInt32 GetAnimPathFlags() const { return fAnimPathFlags; }
|
||||
|
||||
void SetWrap(hsBool on) { if(on)fAnimPathFlags |= kWrap; else fAnimPathFlags &= ~kWrap; }
|
||||
hsBool GetWrap() const { return 0 != (fAnimPathFlags & kWrap); }
|
||||
|
||||
void SetFarthest(hsBool on) { if(on)fAnimPathFlags |= kFarthest; else fAnimPathFlags &= ~kFarthest; }
|
||||
hsBool GetFarthest() const { return 0 != (fAnimPathFlags & kFarthest); }
|
||||
|
||||
void SetCurTime(hsScalar t, UInt32 calcFlags=0);
|
||||
hsScalar GetCurTime() const { return fTime; }
|
||||
|
||||
void SetController(plCompoundController* tmc);
|
||||
plCompoundController* GetController() const { return fController; }
|
||||
hsScalar GetLength() const { return fLength; } // seconds
|
||||
|
||||
void SetMinDistance(hsScalar d) { fMinDistSq = d*d; }
|
||||
hsScalar GetMinDistance() const { return hsSquareRoot(fMinDistSq); }
|
||||
|
||||
hsMatrix44* GetMatrix44(hsMatrix44* xOut) const { *xOut = fXform; return xOut; }
|
||||
hsPoint3* GetPosition(hsPoint3* pOut) const { *pOut = fPos; return pOut; }
|
||||
hsVector3* GetVelocity(hsVector3* vOut) const { *vOut = fVel; return vOut; }
|
||||
hsVector3* GetDirection(hsVector3* dOut) const { dOut->Set(fXform.fMap[0][2], fXform.fMap[1][2], fXform.fMap[2][2]); return dOut; }
|
||||
hsVector3* GetUp(hsVector3* uOut) const { uOut->Set(fXform.fMap[0][1], fXform.fMap[1][1], fXform.fMap[2][1]); return uOut; }
|
||||
hsVector3* GetAcceleration(hsVector3* aOut) const { *aOut = fAccel; return aOut; }
|
||||
|
||||
hsBool OutOfRange(hsPoint3 &pt, hsScalar range) const;
|
||||
const hsAffineParts* Parts() const { return &fParts; }
|
||||
void InitParts(const hsAffineParts& p) { fParts = p; }
|
||||
|
||||
hsScalar GetExtremePoint(hsPoint3 &worldPt) const; // Exhaustive search
|
||||
hsScalar GetExtremePoint(hsScalar lastTime, hsScalar delTime, hsPoint3 &worldPt) const; // Incremental search
|
||||
|
||||
// for arclen usage
|
||||
void ComputeArcLenDeltas(Int32 numSamples=256);
|
||||
hsScalar GetLookAheadTime(hsScalar startTime, hsScalar arcLength, hsBool bwd, Int32* startSrchIdx);
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif plAnimPath_inc
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,306 +1,306 @@
|
||||
/*==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==*/
|
||||
#ifndef plAnimTimeConvert_inc
|
||||
#define plAnimTimeConvert_inc
|
||||
|
||||
#include "pnFactory/plCreatable.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "pnNetCommon/plSynchedValue.h"
|
||||
|
||||
#pragma warning (disable: 4284)
|
||||
|
||||
class plSynchedObject;
|
||||
class plAnimCmdMsg;
|
||||
class plEventCallbackMsg;
|
||||
class plATCEaseCurve;
|
||||
class plATCState;
|
||||
class plATCAnim;
|
||||
class plAGMasterMod;
|
||||
|
||||
class plAnimTimeConvert : public plCreatable
|
||||
{
|
||||
friend class plAnimTimeConvertSDLModifier;
|
||||
friend class plAGAnimInstance;
|
||||
|
||||
protected:
|
||||
UInt16 fFlags;
|
||||
hsScalar fBegin;
|
||||
hsScalar fEnd;
|
||||
hsScalar fLoopEnd;
|
||||
hsScalar fLoopBegin;
|
||||
hsScalar fSpeed;
|
||||
hsScalar fCurrentAnimTime;
|
||||
hsScalar fWrapTime;
|
||||
double fLastEvalWorldTime;
|
||||
// Do not change fLastEvalWorldTime anywhere except WorldToAnimTime()
|
||||
|
||||
plSynchedObject* fOwner;
|
||||
double fLastStateChange;
|
||||
|
||||
typedef std::list<plATCState *> plATCStateList;
|
||||
plATCStateList fStates;
|
||||
|
||||
hsTArray<hsScalar> fStopPoints;
|
||||
hsTArray<plEventCallbackMsg*> fCallbackMsgs;
|
||||
|
||||
/////////////////////////
|
||||
// Ease In/Out stuff
|
||||
|
||||
plATCEaseCurve *fEaseInCurve;
|
||||
plATCEaseCurve *fEaseOutCurve;
|
||||
plATCEaseCurve *fSpeedEaseCurve;
|
||||
plATCEaseCurve *fCurrentEaseCurve; // One of the above, or nil
|
||||
|
||||
//
|
||||
/////////////////////////
|
||||
|
||||
hsScalar fInitialBegin;
|
||||
hsScalar fInitialEnd;
|
||||
|
||||
static hsScalar ICalcEaseTime(const plATCEaseCurve *curve, double start, double end);
|
||||
void IClearSpeedEase();
|
||||
|
||||
void ICheckTimeCallbacks(hsScalar frameStart, hsScalar frameStop);
|
||||
hsBool ITimeInFrame(hsScalar secs, hsScalar start, hsScalar stop);
|
||||
void ISendCallback(int i);
|
||||
|
||||
plAnimTimeConvert& IStop(double time, hsScalar animTime);
|
||||
hsBool IIsStoppedAt(const double &wSecs, const UInt32 &flags, const plATCEaseCurve *curve) const;
|
||||
plAnimTimeConvert& IProcessStateChange(double worldTime, hsScalar animTime = -1);
|
||||
void IFlushOldStates();
|
||||
void IClearAllStates();
|
||||
plATCState *IGetState(double wSecs) const;
|
||||
plATCState *IGetLatestState() const;
|
||||
|
||||
plAnimTimeConvert& SetFlag(UInt8 f, hsBool on) { if(on)fFlags |= f; else fFlags &= ~f; return *this; }
|
||||
|
||||
public:
|
||||
plAnimTimeConvert();
|
||||
virtual ~plAnimTimeConvert();
|
||||
|
||||
void Init(plATCAnim *anim, plAGAnimInstance *instance, plAGMasterMod *master);
|
||||
|
||||
CLASSNAME_REGISTER( plAnimTimeConvert );
|
||||
GETINTERFACE_ANY( plAnimTimeConvert, plCreatable );
|
||||
|
||||
void SetOwner(plSynchedObject* o);
|
||||
const plSynchedObject* GetOwner() const { return fOwner; }
|
||||
|
||||
// ALL WorldToAnimTime functions are only valid if called with a time >= fLastEvalWorldTime.
|
||||
hsBool IsStoppedAt(double wSecs) const;
|
||||
hsScalar WorldToAnimTime(double wSecs);
|
||||
hsScalar WorldToAnimTimeNoUpdate(double wSecs) const; // convert time but don't fire triggers or set state
|
||||
|
||||
protected:
|
||||
static hsScalar IWorldToAnimTimeNoUpdate(double wSecs, plATCState *state);
|
||||
hsScalar IWorldToAnimTimeBeforeState(double wSecs) const;
|
||||
|
||||
public:
|
||||
void SetBegin(hsScalar s) { fBegin = s; }
|
||||
void SetEnd(hsScalar s) { fEnd = s; }
|
||||
void SetSpeed(hsScalar goal, hsScalar rate = 0);
|
||||
void SetLoopPoints(hsScalar begin, hsScalar end) { SetLoopBegin(begin); SetLoopEnd(end); }
|
||||
void SetLoopBegin(hsScalar s) { fLoopBegin = s; }
|
||||
void SetLoopEnd(hsScalar s) { fLoopEnd = s; }
|
||||
void SetEase(hsBool easeIn, UInt8 inType, hsScalar minLength, hsScalar maxLength, hsScalar inLength);
|
||||
void SetCurrentEaseCurve(int x); // 0=nil, 1=easeIn, 2=easeOut, 3=speed
|
||||
|
||||
hsScalar GetBegin() const { return fBegin; }
|
||||
hsScalar GetEnd() const { return fEnd; }
|
||||
hsScalar GetLoopBegin() const { return fLoopBegin; }
|
||||
hsScalar GetLoopEnd() const { return fLoopEnd; }
|
||||
hsScalar GetSpeed() const { return fSpeed; }
|
||||
hsTArray<hsScalar> &GetStopPoints() { return fStopPoints; }
|
||||
hsScalar GetBestStopDist(hsScalar min, hsScalar max, hsScalar norm, hsScalar time) const;
|
||||
int GetCurrentEaseCurve() const; // returns 0=nil, 1=easeIn, 2=easeOut, 3=speed
|
||||
|
||||
void ResizeStates(int cnt);
|
||||
void ResetWrap();
|
||||
|
||||
plAnimTimeConvert& ClearFlags() { fFlags = kNone; return *this; }
|
||||
hsBool GetFlag(UInt8 f) const { return (fFlags & f) ? true : false; }
|
||||
|
||||
plAnimTimeConvert& InitStop(); // Called when initializing an anim that doesn't autostart
|
||||
plAnimTimeConvert& Stop(hsBool on);
|
||||
plAnimTimeConvert& Stop(double s = -1.0);
|
||||
plAnimTimeConvert& Start(double s = -1.0);
|
||||
plAnimTimeConvert& PlayToTime(hsScalar time);
|
||||
plAnimTimeConvert& PlayToPercentage(hsScalar percent); // zero to one.
|
||||
|
||||
plAnimTimeConvert& Loop(hsBool on);
|
||||
plAnimTimeConvert& Loop() { return Loop(true); }
|
||||
plAnimTimeConvert& NoLoop() { return Loop(false); }
|
||||
|
||||
plAnimTimeConvert& Backwards(hsBool on);
|
||||
plAnimTimeConvert& Backwards();
|
||||
plAnimTimeConvert& Forewards();
|
||||
|
||||
hsBool IsStopped() const { return 0 != (fFlags & kStopped); }
|
||||
hsBool IsLooped() const { return 0 != (fFlags & kLoop); }
|
||||
hsBool IsBackwards() const { return 0 != (fFlags & kBackwards); }
|
||||
hsBool IsForewards() const { return !(fFlags & kBackwards); }
|
||||
|
||||
double LastEvalWorldTime() const { return fLastEvalWorldTime; }
|
||||
hsScalar CurrentAnimTime() const { return fCurrentAnimTime; }
|
||||
void SetCurrentAnimTime(hsScalar s, hsBool jump = false);
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
|
||||
hsBool HandleCmd(plAnimCmdMsg* msg);
|
||||
void AddCallback(plEventCallbackMsg* pMsg);
|
||||
void RemoveCallback(plEventCallbackMsg* pMsg);
|
||||
void ClearCallbacks();
|
||||
void EnableCallbacks(hsBool val);
|
||||
|
||||
enum plAnimTimeFlags {
|
||||
kNone = 0x0,
|
||||
kStopped = 0x1,
|
||||
kLoop = 0x2,
|
||||
kBackwards = 0x4,
|
||||
kWrap = 0x8,
|
||||
kNeedsReset = 0x10,
|
||||
kEasingIn = 0x20,
|
||||
kForcedMove = 0x40,
|
||||
kNoCallbacks = 0x80,
|
||||
|
||||
kFlagsMask = 0xff
|
||||
};
|
||||
|
||||
enum plEaseCurveType {
|
||||
kEaseNone,
|
||||
kEaseIn,
|
||||
kEaseOut,
|
||||
kEaseSpeed,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Rules for happy ease curves:
|
||||
// 1. Any time value between 0 and fLength is kosher.
|
||||
// 2. Velocity values accepted/returned are in the range [fStartSpeed, fSpeed]
|
||||
// (some tolerance for values REALLY close to the limit, to account for floating-point inaccuracy)
|
||||
|
||||
class plATCEaseCurve : public plCreatable
|
||||
{
|
||||
protected:
|
||||
hsScalar fStartSpeed;
|
||||
hsScalar fMinLength;
|
||||
hsScalar fMaxLength;
|
||||
hsScalar fNormLength;
|
||||
|
||||
public:
|
||||
CLASSNAME_REGISTER( plATCEaseCurve );
|
||||
GETINTERFACE_ANY( plATCEaseCurve, plCreatable );
|
||||
|
||||
double fBeginWorldTime;
|
||||
hsScalar fLength;
|
||||
hsScalar fSpeed; // The anim's target ("full") speed.
|
||||
|
||||
static plATCEaseCurve *CreateEaseCurve(UInt8 type, hsScalar minLength, hsScalar maxLength, hsScalar normLength,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
double GetEndWorldTime() const { return fBeginWorldTime + fLength; }
|
||||
|
||||
virtual plATCEaseCurve *Clone() const = 0;
|
||||
virtual void Read(hsStream *s, hsResMgr *mgr);
|
||||
virtual void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
virtual void RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate = false);
|
||||
virtual void SetLengthOnRate(hsScalar rate);
|
||||
virtual void SetLengthOnDistance(hsScalar dist) = 0;
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const = 0;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const = 0;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const = 0;
|
||||
virtual hsScalar GetMinDistance();
|
||||
virtual hsScalar GetMaxDistance();
|
||||
virtual hsScalar GetNormDistance();
|
||||
};
|
||||
|
||||
class plConstAccelEaseCurve : public plATCEaseCurve
|
||||
{
|
||||
public:
|
||||
plConstAccelEaseCurve();
|
||||
plConstAccelEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
CLASSNAME_REGISTER( plConstAccelEaseCurve );
|
||||
GETINTERFACE_ANY( plConstAccelEaseCurve, plATCEaseCurve );
|
||||
|
||||
virtual plATCEaseCurve *Clone() const;
|
||||
virtual void SetLengthOnDistance(hsScalar dist);
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const;
|
||||
};
|
||||
|
||||
class plSplineEaseCurve : public plATCEaseCurve
|
||||
{
|
||||
public:
|
||||
plSplineEaseCurve();
|
||||
plSplineEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
CLASSNAME_REGISTER( plSplineEaseCurve );
|
||||
GETINTERFACE_ANY( plSplineEaseCurve, plATCEaseCurve );
|
||||
|
||||
virtual void Read(hsStream *s, hsResMgr *mgr);
|
||||
virtual void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
virtual plATCEaseCurve *Clone() const;
|
||||
virtual void RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate = false);
|
||||
virtual void SetLengthOnDistance(hsScalar dist);
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const;
|
||||
|
||||
hsScalar fCoef[4];
|
||||
};
|
||||
|
||||
class plATCState
|
||||
{
|
||||
public:
|
||||
plATCState() : fEaseCurve(nil) {}
|
||||
~plATCState() { delete fEaseCurve; }
|
||||
|
||||
void Read(hsStream *s, hsResMgr *mgr);
|
||||
void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
double fStartWorldTime;
|
||||
hsScalar fStartAnimTime;
|
||||
|
||||
UInt8 fFlags;
|
||||
hsScalar fBegin;
|
||||
hsScalar fEnd;
|
||||
hsScalar fLoopBegin;
|
||||
hsScalar fLoopEnd;
|
||||
hsScalar fSpeed;
|
||||
hsScalar fWrapTime;
|
||||
plATCEaseCurve *fEaseCurve;
|
||||
};
|
||||
|
||||
|
||||
#endif // plAnimTimeConvert_inc
|
||||
/*==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==*/
|
||||
#ifndef plAnimTimeConvert_inc
|
||||
#define plAnimTimeConvert_inc
|
||||
|
||||
#include "pnFactory/plCreatable.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "pnNetCommon/plSynchedValue.h"
|
||||
|
||||
#pragma warning (disable: 4284)
|
||||
|
||||
class plSynchedObject;
|
||||
class plAnimCmdMsg;
|
||||
class plEventCallbackMsg;
|
||||
class plATCEaseCurve;
|
||||
class plATCState;
|
||||
class plATCAnim;
|
||||
class plAGMasterMod;
|
||||
|
||||
class plAnimTimeConvert : public plCreatable
|
||||
{
|
||||
friend class plAnimTimeConvertSDLModifier;
|
||||
friend class plAGAnimInstance;
|
||||
|
||||
protected:
|
||||
UInt16 fFlags;
|
||||
hsScalar fBegin;
|
||||
hsScalar fEnd;
|
||||
hsScalar fLoopEnd;
|
||||
hsScalar fLoopBegin;
|
||||
hsScalar fSpeed;
|
||||
hsScalar fCurrentAnimTime;
|
||||
hsScalar fWrapTime;
|
||||
double fLastEvalWorldTime;
|
||||
// Do not change fLastEvalWorldTime anywhere except WorldToAnimTime()
|
||||
|
||||
plSynchedObject* fOwner;
|
||||
double fLastStateChange;
|
||||
|
||||
typedef std::list<plATCState *> plATCStateList;
|
||||
plATCStateList fStates;
|
||||
|
||||
hsTArray<hsScalar> fStopPoints;
|
||||
hsTArray<plEventCallbackMsg*> fCallbackMsgs;
|
||||
|
||||
/////////////////////////
|
||||
// Ease In/Out stuff
|
||||
|
||||
plATCEaseCurve *fEaseInCurve;
|
||||
plATCEaseCurve *fEaseOutCurve;
|
||||
plATCEaseCurve *fSpeedEaseCurve;
|
||||
plATCEaseCurve *fCurrentEaseCurve; // One of the above, or nil
|
||||
|
||||
//
|
||||
/////////////////////////
|
||||
|
||||
hsScalar fInitialBegin;
|
||||
hsScalar fInitialEnd;
|
||||
|
||||
static hsScalar ICalcEaseTime(const plATCEaseCurve *curve, double start, double end);
|
||||
void IClearSpeedEase();
|
||||
|
||||
void ICheckTimeCallbacks(hsScalar frameStart, hsScalar frameStop);
|
||||
hsBool ITimeInFrame(hsScalar secs, hsScalar start, hsScalar stop);
|
||||
void ISendCallback(int i);
|
||||
|
||||
plAnimTimeConvert& IStop(double time, hsScalar animTime);
|
||||
hsBool IIsStoppedAt(const double &wSecs, const UInt32 &flags, const plATCEaseCurve *curve) const;
|
||||
plAnimTimeConvert& IProcessStateChange(double worldTime, hsScalar animTime = -1);
|
||||
void IFlushOldStates();
|
||||
void IClearAllStates();
|
||||
plATCState *IGetState(double wSecs) const;
|
||||
plATCState *IGetLatestState() const;
|
||||
|
||||
plAnimTimeConvert& SetFlag(UInt8 f, hsBool on) { if(on)fFlags |= f; else fFlags &= ~f; return *this; }
|
||||
|
||||
public:
|
||||
plAnimTimeConvert();
|
||||
virtual ~plAnimTimeConvert();
|
||||
|
||||
void Init(plATCAnim *anim, plAGAnimInstance *instance, plAGMasterMod *master);
|
||||
|
||||
CLASSNAME_REGISTER( plAnimTimeConvert );
|
||||
GETINTERFACE_ANY( plAnimTimeConvert, plCreatable );
|
||||
|
||||
void SetOwner(plSynchedObject* o);
|
||||
const plSynchedObject* GetOwner() const { return fOwner; }
|
||||
|
||||
// ALL WorldToAnimTime functions are only valid if called with a time >= fLastEvalWorldTime.
|
||||
hsBool IsStoppedAt(double wSecs) const;
|
||||
hsScalar WorldToAnimTime(double wSecs);
|
||||
hsScalar WorldToAnimTimeNoUpdate(double wSecs) const; // convert time but don't fire triggers or set state
|
||||
|
||||
protected:
|
||||
static hsScalar IWorldToAnimTimeNoUpdate(double wSecs, plATCState *state);
|
||||
hsScalar IWorldToAnimTimeBeforeState(double wSecs) const;
|
||||
|
||||
public:
|
||||
void SetBegin(hsScalar s) { fBegin = s; }
|
||||
void SetEnd(hsScalar s) { fEnd = s; }
|
||||
void SetSpeed(hsScalar goal, hsScalar rate = 0);
|
||||
void SetLoopPoints(hsScalar begin, hsScalar end) { SetLoopBegin(begin); SetLoopEnd(end); }
|
||||
void SetLoopBegin(hsScalar s) { fLoopBegin = s; }
|
||||
void SetLoopEnd(hsScalar s) { fLoopEnd = s; }
|
||||
void SetEase(hsBool easeIn, UInt8 inType, hsScalar minLength, hsScalar maxLength, hsScalar inLength);
|
||||
void SetCurrentEaseCurve(int x); // 0=nil, 1=easeIn, 2=easeOut, 3=speed
|
||||
|
||||
hsScalar GetBegin() const { return fBegin; }
|
||||
hsScalar GetEnd() const { return fEnd; }
|
||||
hsScalar GetLoopBegin() const { return fLoopBegin; }
|
||||
hsScalar GetLoopEnd() const { return fLoopEnd; }
|
||||
hsScalar GetSpeed() const { return fSpeed; }
|
||||
hsTArray<hsScalar> &GetStopPoints() { return fStopPoints; }
|
||||
hsScalar GetBestStopDist(hsScalar min, hsScalar max, hsScalar norm, hsScalar time) const;
|
||||
int GetCurrentEaseCurve() const; // returns 0=nil, 1=easeIn, 2=easeOut, 3=speed
|
||||
|
||||
void ResizeStates(int cnt);
|
||||
void ResetWrap();
|
||||
|
||||
plAnimTimeConvert& ClearFlags() { fFlags = kNone; return *this; }
|
||||
hsBool GetFlag(UInt8 f) const { return (fFlags & f) ? true : false; }
|
||||
|
||||
plAnimTimeConvert& InitStop(); // Called when initializing an anim that doesn't autostart
|
||||
plAnimTimeConvert& Stop(hsBool on);
|
||||
plAnimTimeConvert& Stop(double s = -1.0);
|
||||
plAnimTimeConvert& Start(double s = -1.0);
|
||||
plAnimTimeConvert& PlayToTime(hsScalar time);
|
||||
plAnimTimeConvert& PlayToPercentage(hsScalar percent); // zero to one.
|
||||
|
||||
plAnimTimeConvert& Loop(hsBool on);
|
||||
plAnimTimeConvert& Loop() { return Loop(true); }
|
||||
plAnimTimeConvert& NoLoop() { return Loop(false); }
|
||||
|
||||
plAnimTimeConvert& Backwards(hsBool on);
|
||||
plAnimTimeConvert& Backwards();
|
||||
plAnimTimeConvert& Forewards();
|
||||
|
||||
hsBool IsStopped() const { return 0 != (fFlags & kStopped); }
|
||||
hsBool IsLooped() const { return 0 != (fFlags & kLoop); }
|
||||
hsBool IsBackwards() const { return 0 != (fFlags & kBackwards); }
|
||||
hsBool IsForewards() const { return !(fFlags & kBackwards); }
|
||||
|
||||
double LastEvalWorldTime() const { return fLastEvalWorldTime; }
|
||||
hsScalar CurrentAnimTime() const { return fCurrentAnimTime; }
|
||||
void SetCurrentAnimTime(hsScalar s, hsBool jump = false);
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
|
||||
hsBool HandleCmd(plAnimCmdMsg* msg);
|
||||
void AddCallback(plEventCallbackMsg* pMsg);
|
||||
void RemoveCallback(plEventCallbackMsg* pMsg);
|
||||
void ClearCallbacks();
|
||||
void EnableCallbacks(hsBool val);
|
||||
|
||||
enum plAnimTimeFlags {
|
||||
kNone = 0x0,
|
||||
kStopped = 0x1,
|
||||
kLoop = 0x2,
|
||||
kBackwards = 0x4,
|
||||
kWrap = 0x8,
|
||||
kNeedsReset = 0x10,
|
||||
kEasingIn = 0x20,
|
||||
kForcedMove = 0x40,
|
||||
kNoCallbacks = 0x80,
|
||||
|
||||
kFlagsMask = 0xff
|
||||
};
|
||||
|
||||
enum plEaseCurveType {
|
||||
kEaseNone,
|
||||
kEaseIn,
|
||||
kEaseOut,
|
||||
kEaseSpeed,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Rules for happy ease curves:
|
||||
// 1. Any time value between 0 and fLength is kosher.
|
||||
// 2. Velocity values accepted/returned are in the range [fStartSpeed, fSpeed]
|
||||
// (some tolerance for values REALLY close to the limit, to account for floating-point inaccuracy)
|
||||
|
||||
class plATCEaseCurve : public plCreatable
|
||||
{
|
||||
protected:
|
||||
hsScalar fStartSpeed;
|
||||
hsScalar fMinLength;
|
||||
hsScalar fMaxLength;
|
||||
hsScalar fNormLength;
|
||||
|
||||
public:
|
||||
CLASSNAME_REGISTER( plATCEaseCurve );
|
||||
GETINTERFACE_ANY( plATCEaseCurve, plCreatable );
|
||||
|
||||
double fBeginWorldTime;
|
||||
hsScalar fLength;
|
||||
hsScalar fSpeed; // The anim's target ("full") speed.
|
||||
|
||||
static plATCEaseCurve *CreateEaseCurve(UInt8 type, hsScalar minLength, hsScalar maxLength, hsScalar normLength,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
double GetEndWorldTime() const { return fBeginWorldTime + fLength; }
|
||||
|
||||
virtual plATCEaseCurve *Clone() const = 0;
|
||||
virtual void Read(hsStream *s, hsResMgr *mgr);
|
||||
virtual void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
virtual void RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate = false);
|
||||
virtual void SetLengthOnRate(hsScalar rate);
|
||||
virtual void SetLengthOnDistance(hsScalar dist) = 0;
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const = 0;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const = 0;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const = 0;
|
||||
virtual hsScalar GetMinDistance();
|
||||
virtual hsScalar GetMaxDistance();
|
||||
virtual hsScalar GetNormDistance();
|
||||
};
|
||||
|
||||
class plConstAccelEaseCurve : public plATCEaseCurve
|
||||
{
|
||||
public:
|
||||
plConstAccelEaseCurve();
|
||||
plConstAccelEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
CLASSNAME_REGISTER( plConstAccelEaseCurve );
|
||||
GETINTERFACE_ANY( plConstAccelEaseCurve, plATCEaseCurve );
|
||||
|
||||
virtual plATCEaseCurve *Clone() const;
|
||||
virtual void SetLengthOnDistance(hsScalar dist);
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const;
|
||||
};
|
||||
|
||||
class plSplineEaseCurve : public plATCEaseCurve
|
||||
{
|
||||
public:
|
||||
plSplineEaseCurve();
|
||||
plSplineEaseCurve(hsScalar minLength, hsScalar maxLength, hsScalar length,
|
||||
hsScalar startSpeed, hsScalar goalSpeed);
|
||||
|
||||
CLASSNAME_REGISTER( plSplineEaseCurve );
|
||||
GETINTERFACE_ANY( plSplineEaseCurve, plATCEaseCurve );
|
||||
|
||||
virtual void Read(hsStream *s, hsResMgr *mgr);
|
||||
virtual void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
virtual plATCEaseCurve *Clone() const;
|
||||
virtual void RecalcToSpeed(hsScalar startSpeed, hsScalar goalSpeed, hsBool preserveRate = false);
|
||||
virtual void SetLengthOnDistance(hsScalar dist);
|
||||
virtual hsScalar PositionGivenTime(hsScalar time) const;
|
||||
virtual hsScalar VelocityGivenTime(hsScalar time) const;
|
||||
virtual hsScalar TimeGivenVelocity(hsScalar velocity) const;
|
||||
|
||||
hsScalar fCoef[4];
|
||||
};
|
||||
|
||||
class plATCState
|
||||
{
|
||||
public:
|
||||
plATCState() : fEaseCurve(nil) {}
|
||||
~plATCState() { delete fEaseCurve; }
|
||||
|
||||
void Read(hsStream *s, hsResMgr *mgr);
|
||||
void Write(hsStream *s, hsResMgr *mgr);
|
||||
|
||||
double fStartWorldTime;
|
||||
hsScalar fStartAnimTime;
|
||||
|
||||
UInt8 fFlags;
|
||||
hsScalar fBegin;
|
||||
hsScalar fEnd;
|
||||
hsScalar fLoopBegin;
|
||||
hsScalar fLoopEnd;
|
||||
hsScalar fSpeed;
|
||||
hsScalar fWrapTime;
|
||||
plATCEaseCurve *fEaseCurve;
|
||||
};
|
||||
|
||||
|
||||
#endif // plAnimTimeConvert_inc
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,214 +1,214 @@
|
||||
/*==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==*/
|
||||
#ifndef HSCONTROLLER_inc
|
||||
#define HSCONTROLLER_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "pnFactory/plCreatable.h"
|
||||
#include "hsColorRGBA.h"
|
||||
#include "hsKeys.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
class hsResMgr;
|
||||
|
||||
struct hsScaleValue;
|
||||
struct hsScalarKey;
|
||||
struct hsPoint3Key;
|
||||
struct hsScalarTriple;
|
||||
struct hsMatrix33;
|
||||
struct hsMatrix44;
|
||||
class hsQuat;
|
||||
class hsAffineParts;
|
||||
class plScalarCurve;
|
||||
class plAnimTimeConvert;
|
||||
class plCompoundController;
|
||||
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
// base controller class.
|
||||
// Controllers correspond to Max controllers.
|
||||
// Some are leaf controllers which actually have keys, these can also have
|
||||
// multiple ease and multiplier controllers.
|
||||
// Some are compound controllers, which just contain other (leaf) controllers.
|
||||
// Leaf controllers have lists of keys (or plCurves which are just wrappers for
|
||||
// the lists of keys).
|
||||
//
|
||||
|
||||
class plControllerCacheInfo
|
||||
{
|
||||
public:
|
||||
UInt8 fNumSubControllers;
|
||||
plControllerCacheInfo **fSubControllers;
|
||||
|
||||
UInt32 fKeyIndex;
|
||||
plAnimTimeConvert *fAtc;
|
||||
|
||||
plControllerCacheInfo();
|
||||
~plControllerCacheInfo();
|
||||
|
||||
void SetATC(plAnimTimeConvert *atc);
|
||||
};
|
||||
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
// defines base methods
|
||||
//
|
||||
class plController : public plCreatable
|
||||
{
|
||||
public:
|
||||
CLASSNAME_REGISTER( plController );
|
||||
GETINTERFACE_ANY( plController, plCreatable );
|
||||
|
||||
virtual void Interp(hsScalar time, hsScalar* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsScaleValue* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsMatrix33* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsMatrix44* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsAffineParts* parts, plControllerCacheInfo *cache = nil) const {}
|
||||
|
||||
virtual plControllerCacheInfo* CreateCache() const { return nil; } // Caller must handle deleting the pointer.
|
||||
virtual hsScalar GetLength() const = 0;
|
||||
virtual void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const = 0;
|
||||
virtual hsBool AllKeysMatch() const = 0;
|
||||
|
||||
// Checks each of our subcontrollers (if we have any) and deletes any that
|
||||
// are nothing but matching keys. Returns true if this controller itself
|
||||
// is redundant.
|
||||
virtual hsBool PurgeRedundantSubcontrollers() = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
class plLeafController : public plController
|
||||
{
|
||||
friend class plCompoundController;
|
||||
|
||||
protected:
|
||||
UInt8 fType;
|
||||
void *fKeys; // Need to pay attend to fType to determine what these actually are
|
||||
UInt32 fNumKeys;
|
||||
mutable UInt32 fLastKeyIdx;
|
||||
|
||||
public:
|
||||
plLeafController() : fType(hsKeyFrame::kUnknownKeyFrame), fKeys(nil), fNumKeys(0), fLastKeyIdx(0) {}
|
||||
virtual ~plLeafController();
|
||||
|
||||
CLASSNAME_REGISTER( plLeafController );
|
||||
GETINTERFACE_ANY( plLeafController, plController );
|
||||
|
||||
void Interp(hsScalar time, hsScalar* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScaleValue* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsMatrix33* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsMatrix44* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const;
|
||||
|
||||
virtual plControllerCacheInfo* CreateCache() const;
|
||||
hsScalar GetLength() const;
|
||||
UInt32 GetStride() const;
|
||||
|
||||
hsPoint3Key *GetPoint3Key(UInt32 i) const;
|
||||
hsBezPoint3Key *GetBezPoint3Key(UInt32 i) const;
|
||||
hsScalarKey *GetScalarKey(UInt32 i) const;
|
||||
hsBezScalarKey *GetBezScalarKey(UInt32 i) const;
|
||||
hsScaleKey *GetScaleKey(UInt32 i) const;
|
||||
hsBezScaleKey *GetBezScaleKey(UInt32 i) const;
|
||||
hsQuatKey *GetQuatKey(UInt32 i) const;
|
||||
hsCompressedQuatKey32 *GetCompressedQuatKey32(UInt32 i) const;
|
||||
hsCompressedQuatKey64 *GetCompressedQuatKey64(UInt32 i) const;
|
||||
hsG3DSMaxKeyFrame *Get3DSMaxKey(UInt32 i) const;
|
||||
hsMatrix33Key *GetMatrix33Key(UInt32 i) const;
|
||||
hsMatrix44Key *GetMatrix44Key(UInt32 i) const;
|
||||
|
||||
UInt8 GetType() const { return fType; }
|
||||
UInt32 GetNumKeys() const { return fNumKeys; }
|
||||
void *GetKeyBuffer() const { return fKeys; }
|
||||
void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const;
|
||||
void AllocKeys(UInt32 n, UInt8 type);
|
||||
void QuickScalarController(int numKeys, hsScalar* times, hsScalar* values, UInt32 valueStrides);
|
||||
hsBool AllKeysMatch() const;
|
||||
hsBool PurgeRedundantSubcontrollers();
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr);
|
||||
void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NON-LEAF (container) CONTROLLERS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
class plCompoundController : public plController
|
||||
{
|
||||
private:
|
||||
plController* fXController;
|
||||
plController* fYController;
|
||||
plController* fZController;
|
||||
|
||||
public:
|
||||
plCompoundController(); // allocs leaf controllers
|
||||
~plCompoundController();
|
||||
|
||||
CLASSNAME_REGISTER( plCompoundController );
|
||||
GETINTERFACE_ANY( plCompoundController, plController );
|
||||
|
||||
void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsAffineParts* parts, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const;
|
||||
|
||||
plControllerCacheInfo* CreateCache() const;
|
||||
plController *GetXController() const { return fXController; }
|
||||
plController *GetYController() const { return fYController; }
|
||||
plController *GetZController() const { return fZController; }
|
||||
plController *GetPosController() const { return fXController; }
|
||||
plController *GetRotController() const { return fYController; }
|
||||
plController *GetScaleController() const { return fZController; }
|
||||
plController *GetController(Int32 i) const;
|
||||
hsScalar GetLength() const;
|
||||
void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const;
|
||||
hsBool AllKeysMatch() const;
|
||||
hsBool PurgeRedundantSubcontrollers();
|
||||
|
||||
void SetXController(plController *c) { delete fXController; fXController = c; }
|
||||
void SetYController(plController *c) { delete fYController; fYController = c; }
|
||||
void SetZController(plController *c) { delete fZController; fZController = c; }
|
||||
void SetPosController(plController *c) { delete fXController; fXController = c; }
|
||||
void SetRotController(plController *c) { delete fYController; fYController = c; }
|
||||
void SetScaleController(plController *c) { delete fZController; fZController = c; }
|
||||
void SetController(Int32 i, plController* c);
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr);
|
||||
void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*==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==*/
|
||||
#ifndef HSCONTROLLER_inc
|
||||
#define HSCONTROLLER_inc
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "pnFactory/plCreatable.h"
|
||||
#include "hsColorRGBA.h"
|
||||
#include "hsKeys.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
class hsResMgr;
|
||||
|
||||
struct hsScaleValue;
|
||||
struct hsScalarKey;
|
||||
struct hsPoint3Key;
|
||||
struct hsScalarTriple;
|
||||
struct hsMatrix33;
|
||||
struct hsMatrix44;
|
||||
class hsQuat;
|
||||
class hsAffineParts;
|
||||
class plScalarCurve;
|
||||
class plAnimTimeConvert;
|
||||
class plCompoundController;
|
||||
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
// base controller class.
|
||||
// Controllers correspond to Max controllers.
|
||||
// Some are leaf controllers which actually have keys, these can also have
|
||||
// multiple ease and multiplier controllers.
|
||||
// Some are compound controllers, which just contain other (leaf) controllers.
|
||||
// Leaf controllers have lists of keys (or plCurves which are just wrappers for
|
||||
// the lists of keys).
|
||||
//
|
||||
|
||||
class plControllerCacheInfo
|
||||
{
|
||||
public:
|
||||
UInt8 fNumSubControllers;
|
||||
plControllerCacheInfo **fSubControllers;
|
||||
|
||||
UInt32 fKeyIndex;
|
||||
plAnimTimeConvert *fAtc;
|
||||
|
||||
plControllerCacheInfo();
|
||||
~plControllerCacheInfo();
|
||||
|
||||
void SetATC(plAnimTimeConvert *atc);
|
||||
};
|
||||
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
// defines base methods
|
||||
//
|
||||
class plController : public plCreatable
|
||||
{
|
||||
public:
|
||||
CLASSNAME_REGISTER( plController );
|
||||
GETINTERFACE_ANY( plController, plCreatable );
|
||||
|
||||
virtual void Interp(hsScalar time, hsScalar* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsScaleValue* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsMatrix33* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsMatrix44* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const {}
|
||||
virtual void Interp(hsScalar time, hsAffineParts* parts, plControllerCacheInfo *cache = nil) const {}
|
||||
|
||||
virtual plControllerCacheInfo* CreateCache() const { return nil; } // Caller must handle deleting the pointer.
|
||||
virtual hsScalar GetLength() const = 0;
|
||||
virtual void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const = 0;
|
||||
virtual hsBool AllKeysMatch() const = 0;
|
||||
|
||||
// Checks each of our subcontrollers (if we have any) and deletes any that
|
||||
// are nothing but matching keys. Returns true if this controller itself
|
||||
// is redundant.
|
||||
virtual hsBool PurgeRedundantSubcontrollers() = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
class plLeafController : public plController
|
||||
{
|
||||
friend class plCompoundController;
|
||||
|
||||
protected:
|
||||
UInt8 fType;
|
||||
void *fKeys; // Need to pay attend to fType to determine what these actually are
|
||||
UInt32 fNumKeys;
|
||||
mutable UInt32 fLastKeyIdx;
|
||||
|
||||
public:
|
||||
plLeafController() : fType(hsKeyFrame::kUnknownKeyFrame), fKeys(nil), fNumKeys(0), fLastKeyIdx(0) {}
|
||||
virtual ~plLeafController();
|
||||
|
||||
CLASSNAME_REGISTER( plLeafController );
|
||||
GETINTERFACE_ANY( plLeafController, plController );
|
||||
|
||||
void Interp(hsScalar time, hsScalar* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScaleValue* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsMatrix33* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsMatrix44* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const;
|
||||
|
||||
virtual plControllerCacheInfo* CreateCache() const;
|
||||
hsScalar GetLength() const;
|
||||
UInt32 GetStride() const;
|
||||
|
||||
hsPoint3Key *GetPoint3Key(UInt32 i) const;
|
||||
hsBezPoint3Key *GetBezPoint3Key(UInt32 i) const;
|
||||
hsScalarKey *GetScalarKey(UInt32 i) const;
|
||||
hsBezScalarKey *GetBezScalarKey(UInt32 i) const;
|
||||
hsScaleKey *GetScaleKey(UInt32 i) const;
|
||||
hsBezScaleKey *GetBezScaleKey(UInt32 i) const;
|
||||
hsQuatKey *GetQuatKey(UInt32 i) const;
|
||||
hsCompressedQuatKey32 *GetCompressedQuatKey32(UInt32 i) const;
|
||||
hsCompressedQuatKey64 *GetCompressedQuatKey64(UInt32 i) const;
|
||||
hsG3DSMaxKeyFrame *Get3DSMaxKey(UInt32 i) const;
|
||||
hsMatrix33Key *GetMatrix33Key(UInt32 i) const;
|
||||
hsMatrix44Key *GetMatrix44Key(UInt32 i) const;
|
||||
|
||||
UInt8 GetType() const { return fType; }
|
||||
UInt32 GetNumKeys() const { return fNumKeys; }
|
||||
void *GetKeyBuffer() const { return fKeys; }
|
||||
void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const;
|
||||
void AllocKeys(UInt32 n, UInt8 type);
|
||||
void QuickScalarController(int numKeys, hsScalar* times, hsScalar* values, UInt32 valueStrides);
|
||||
hsBool AllKeysMatch() const;
|
||||
hsBool PurgeRedundantSubcontrollers();
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr);
|
||||
void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NON-LEAF (container) CONTROLLERS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
class plCompoundController : public plController
|
||||
{
|
||||
private:
|
||||
plController* fXController;
|
||||
plController* fYController;
|
||||
plController* fZController;
|
||||
|
||||
public:
|
||||
plCompoundController(); // allocs leaf controllers
|
||||
~plCompoundController();
|
||||
|
||||
CLASSNAME_REGISTER( plCompoundController );
|
||||
GETINTERFACE_ANY( plCompoundController, plController );
|
||||
|
||||
void Interp(hsScalar time, hsQuat* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsScalarTriple* result, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsAffineParts* parts, plControllerCacheInfo *cache = nil) const;
|
||||
void Interp(hsScalar time, hsColorRGBA* result, plControllerCacheInfo *cache = nil) const;
|
||||
|
||||
plControllerCacheInfo* CreateCache() const;
|
||||
plController *GetXController() const { return fXController; }
|
||||
plController *GetYController() const { return fYController; }
|
||||
plController *GetZController() const { return fZController; }
|
||||
plController *GetPosController() const { return fXController; }
|
||||
plController *GetRotController() const { return fYController; }
|
||||
plController *GetScaleController() const { return fZController; }
|
||||
plController *GetController(Int32 i) const;
|
||||
hsScalar GetLength() const;
|
||||
void GetKeyTimes(hsTArray<hsScalar> &keyTimes) const;
|
||||
hsBool AllKeysMatch() const;
|
||||
hsBool PurgeRedundantSubcontrollers();
|
||||
|
||||
void SetXController(plController *c) { delete fXController; fXController = c; }
|
||||
void SetYController(plController *c) { delete fYController; fYController = c; }
|
||||
void SetZController(plController *c) { delete fZController; fZController = c; }
|
||||
void SetPosController(plController *c) { delete fXController; fXController = c; }
|
||||
void SetRotController(plController *c) { delete fYController; fYController = c; }
|
||||
void SetScaleController(plController *c) { delete fZController; fZController = c; }
|
||||
void SetController(Int32 i, plController* c);
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr);
|
||||
void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,53 +1,53 @@
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plInterpCreatable_inc
|
||||
#define plInterpCreatable_inc
|
||||
|
||||
#include "pnFactory/plCreator.h"
|
||||
|
||||
#include "plController.h"
|
||||
|
||||
REGISTER_NONCREATABLE( plController );
|
||||
REGISTER_CREATABLE( plLeafController );
|
||||
REGISTER_CREATABLE( plCompoundController );
|
||||
|
||||
#include "plAnimTimeConvert.h"
|
||||
|
||||
REGISTER_CREATABLE( plAnimTimeConvert );
|
||||
REGISTER_NONCREATABLE( plATCEaseCurve );
|
||||
REGISTER_CREATABLE( plConstAccelEaseCurve );
|
||||
REGISTER_CREATABLE( plSplineEaseCurve );
|
||||
|
||||
#include "plAnimPath.h"
|
||||
|
||||
REGISTER_CREATABLE( plAnimPath );
|
||||
|
||||
#include "plModulator.h"
|
||||
|
||||
REGISTER_CREATABLE( plModulator );
|
||||
|
||||
#endif // plInterpCreatable_inc
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plInterpCreatable_inc
|
||||
#define plInterpCreatable_inc
|
||||
|
||||
#include "pnFactory/plCreator.h"
|
||||
|
||||
#include "plController.h"
|
||||
|
||||
REGISTER_NONCREATABLE( plController );
|
||||
REGISTER_CREATABLE( plLeafController );
|
||||
REGISTER_CREATABLE( plCompoundController );
|
||||
|
||||
#include "plAnimTimeConvert.h"
|
||||
|
||||
REGISTER_CREATABLE( plAnimTimeConvert );
|
||||
REGISTER_NONCREATABLE( plATCEaseCurve );
|
||||
REGISTER_CREATABLE( plConstAccelEaseCurve );
|
||||
REGISTER_CREATABLE( plSplineEaseCurve );
|
||||
|
||||
#include "plAnimPath.h"
|
||||
|
||||
REGISTER_CREATABLE( plAnimPath );
|
||||
|
||||
#include "plModulator.h"
|
||||
|
||||
REGISTER_CREATABLE( plModulator );
|
||||
|
||||
#endif // plInterpCreatable_inc
|
||||
|
@ -1,107 +1,107 @@
|
||||
/*==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 "hsTypes.h"
|
||||
#include "plModulator.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsBounds.h"
|
||||
|
||||
#include "plController.h"
|
||||
|
||||
#include "plIntersect/plVolumeIsect.h"
|
||||
|
||||
plModulator::plModulator()
|
||||
: fVolume(nil),
|
||||
fSoftDist(0)
|
||||
{
|
||||
}
|
||||
|
||||
plModulator::~plModulator()
|
||||
{
|
||||
delete fVolume;
|
||||
}
|
||||
|
||||
void plModulator::SetVolume(plVolumeIsect* vol)
|
||||
{
|
||||
delete fVolume;
|
||||
fVolume = vol;
|
||||
}
|
||||
|
||||
void plModulator::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
hsAssert(fVolume, "Modulator with no Volume is pretty useless");
|
||||
|
||||
fVolume->SetTransform(l2w, w2l);
|
||||
}
|
||||
|
||||
// Volume - Want to base this on the closest point on the bounds, instead of just the center.
|
||||
hsScalar plModulator::Modulation(const hsBounds3Ext& bnd) const
|
||||
{
|
||||
return Modulation(bnd.GetCenter());
|
||||
}
|
||||
|
||||
hsScalar plModulator::Modulation(const hsPoint3& pos) const
|
||||
{
|
||||
hsAssert(fVolume, "Modulator with no Volume is pretty useless");
|
||||
|
||||
hsScalar dist = fVolume->Test(pos);
|
||||
|
||||
hsScalar retVal;
|
||||
if( dist > 0 )
|
||||
{
|
||||
if( dist < fSoftDist )
|
||||
{
|
||||
dist /= fSoftDist;
|
||||
retVal = 1.f - dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = 1.f;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void plModulator::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
fVolume = plVolumeIsect::ConvertNoRef(mgr->ReadCreatable(s));
|
||||
fSoftDist = s->ReadSwapScalar();
|
||||
}
|
||||
|
||||
void plModulator::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
mgr->WriteCreatable(s, fVolume);
|
||||
s->WriteSwapScalar(fSoftDist);
|
||||
}
|
||||
|
||||
|
||||
/*==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 "hsTypes.h"
|
||||
#include "plModulator.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "hsStream.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsBounds.h"
|
||||
|
||||
#include "plController.h"
|
||||
|
||||
#include "plIntersect/plVolumeIsect.h"
|
||||
|
||||
plModulator::plModulator()
|
||||
: fVolume(nil),
|
||||
fSoftDist(0)
|
||||
{
|
||||
}
|
||||
|
||||
plModulator::~plModulator()
|
||||
{
|
||||
delete fVolume;
|
||||
}
|
||||
|
||||
void plModulator::SetVolume(plVolumeIsect* vol)
|
||||
{
|
||||
delete fVolume;
|
||||
fVolume = vol;
|
||||
}
|
||||
|
||||
void plModulator::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
hsAssert(fVolume, "Modulator with no Volume is pretty useless");
|
||||
|
||||
fVolume->SetTransform(l2w, w2l);
|
||||
}
|
||||
|
||||
// Volume - Want to base this on the closest point on the bounds, instead of just the center.
|
||||
hsScalar plModulator::Modulation(const hsBounds3Ext& bnd) const
|
||||
{
|
||||
return Modulation(bnd.GetCenter());
|
||||
}
|
||||
|
||||
hsScalar plModulator::Modulation(const hsPoint3& pos) const
|
||||
{
|
||||
hsAssert(fVolume, "Modulator with no Volume is pretty useless");
|
||||
|
||||
hsScalar dist = fVolume->Test(pos);
|
||||
|
||||
hsScalar retVal;
|
||||
if( dist > 0 )
|
||||
{
|
||||
if( dist < fSoftDist )
|
||||
{
|
||||
dist /= fSoftDist;
|
||||
retVal = 1.f - dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = 1.f;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void plModulator::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
fVolume = plVolumeIsect::ConvertNoRef(mgr->ReadCreatable(s));
|
||||
fSoftDist = s->ReadSwapScalar();
|
||||
}
|
||||
|
||||
void plModulator::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
mgr->WriteCreatable(s, fVolume);
|
||||
s->WriteSwapScalar(fSoftDist);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,65 +1,65 @@
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plModulator_inc
|
||||
#define plModulator_inc
|
||||
|
||||
#include "pnFactory/plCreatable.h"
|
||||
|
||||
struct hsMatrix44;
|
||||
struct hsPoint3;
|
||||
class plVolumeIsect;
|
||||
class hsBounds3Ext;
|
||||
|
||||
class plModulator : public plCreatable
|
||||
{
|
||||
protected:
|
||||
plVolumeIsect* fVolume;
|
||||
hsScalar fSoftDist;
|
||||
|
||||
public:
|
||||
plModulator();
|
||||
virtual ~plModulator();
|
||||
|
||||
CLASSNAME_REGISTER( plModulator );
|
||||
GETINTERFACE_ANY( plModulator, plCreatable );
|
||||
|
||||
const plVolumeIsect* GetVolume() const { return fVolume; }
|
||||
void SetVolume(plVolumeIsect* vol); // Takes ownership, so don't delete after handing it in.
|
||||
|
||||
hsScalar Modulation(const hsPoint3& pos) const;
|
||||
hsScalar Modulation(const hsBounds3Ext& bnd) const;
|
||||
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
hsScalar GetSoftDist() const { return fSoftDist; }
|
||||
void SetSoftDist(hsScalar s) { fSoftDist = s; }
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif // plModulator_inc
|
||||
/*==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==*/
|
||||
|
||||
#ifndef plModulator_inc
|
||||
#define plModulator_inc
|
||||
|
||||
#include "pnFactory/plCreatable.h"
|
||||
|
||||
struct hsMatrix44;
|
||||
struct hsPoint3;
|
||||
class plVolumeIsect;
|
||||
class hsBounds3Ext;
|
||||
|
||||
class plModulator : public plCreatable
|
||||
{
|
||||
protected:
|
||||
plVolumeIsect* fVolume;
|
||||
hsScalar fSoftDist;
|
||||
|
||||
public:
|
||||
plModulator();
|
||||
virtual ~plModulator();
|
||||
|
||||
CLASSNAME_REGISTER( plModulator );
|
||||
GETINTERFACE_ANY( plModulator, plCreatable );
|
||||
|
||||
const plVolumeIsect* GetVolume() const { return fVolume; }
|
||||
void SetVolume(plVolumeIsect* vol); // Takes ownership, so don't delete after handing it in.
|
||||
|
||||
hsScalar Modulation(const hsPoint3& pos) const;
|
||||
hsScalar Modulation(const hsBounds3Ext& bnd) const;
|
||||
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
hsScalar GetSoftDist() const { return fSoftDist; }
|
||||
void SetSoftDist(hsScalar s) { fSoftDist = s; }
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
};
|
||||
|
||||
#endif // plModulator_inc
|
||||
|
Reference in New Issue
Block a user