2
3
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:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -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})

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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