commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
179
include/engine/motion/quaternion_channel.cpp
Normal file
179
include/engine/motion/quaternion_channel.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "motion/quaternion_channel.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static float range(float v, float lo, float hi, int *i)
|
||||
{
|
||||
float r = hi - lo;
|
||||
|
||||
if (!r)
|
||||
{
|
||||
if (i)
|
||||
*i = 0;
|
||||
return lo;
|
||||
}
|
||||
|
||||
float v2 = v - lo;
|
||||
|
||||
if (v2 >= 0)
|
||||
v2 = lo + v2 - r * Math::Floor(v2 / r);
|
||||
else v2 = hi + v2 - r * Math::Ceil(v2 / r);
|
||||
|
||||
if (i)
|
||||
*i = - (int)((v2 - v) / r + (v2 > v ? 0.5f : -0.5f));
|
||||
return Types::Clamp(v2, lo, hi);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void QuaternionChannel::Evaluate(Time t, Quaternion &p, Curve::LoopMode loop, Time loop_start, Time loop_end) const
|
||||
{
|
||||
if (keys.GetCount() == 0)
|
||||
return;
|
||||
|
||||
QuaternionKey *skey = keys[0], *ekey = keys[keys.GetCount() - 1];
|
||||
|
||||
loop_start = (loop_start == Time::Inf) ? skey->t : Types::Clamp(loop_start, skey->t, ekey->t);
|
||||
loop_end = (loop_end == Time::Inf) ? ekey->t : Types::Clamp(loop_end, skey->t, ekey->t);
|
||||
|
||||
int noff = 0;
|
||||
if (t < loop_start)
|
||||
{
|
||||
switch (loop)
|
||||
{
|
||||
default:
|
||||
case Curve::Constant:
|
||||
Evaluate(loop_start, p, loop, loop_start, loop_end);
|
||||
return;
|
||||
case Curve::Reset:
|
||||
p.Set(0, 0, 0, 1);
|
||||
return;
|
||||
|
||||
case Curve::Repeat:
|
||||
case Curve::OffsetAndRepeat:
|
||||
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), NULL));
|
||||
break;
|
||||
case Curve::Oscillate:
|
||||
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
|
||||
if (noff % 2)
|
||||
t = loop_end + loop_start - t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (t > loop_end)
|
||||
{
|
||||
switch (loop)
|
||||
{
|
||||
default:
|
||||
case Curve::Constant:
|
||||
Evaluate(loop_end, p, loop, loop_start, loop_end);
|
||||
return;
|
||||
case Curve::Reset:
|
||||
p.Set(0, 0, 0, 1);
|
||||
return;
|
||||
|
||||
case Curve::Repeat:
|
||||
case Curve::OffsetAndRepeat:
|
||||
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), NULL));
|
||||
break;
|
||||
case Curve::Oscillate:
|
||||
t.setSec(range(t.toSec(), loop_start.toSec(), loop_end.toSec(), &noff));
|
||||
if (noff % 2)
|
||||
t = loop_end + loop_start - t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate (t is guaranteed to be in range).
|
||||
int ikey0;
|
||||
#if 1
|
||||
{
|
||||
uint lo = 0, hi = keys.GetCount() - 1;
|
||||
|
||||
forever
|
||||
{
|
||||
uint mid = (lo + hi) / 2;
|
||||
|
||||
if (keys[mid]->t > t)
|
||||
hi = mid;
|
||||
else
|
||||
{
|
||||
if (lo == mid)
|
||||
{
|
||||
ikey0 = lo;
|
||||
break;
|
||||
}
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (ikey0 = 1; ikey0 < int(keys.GetCount()); ikey0++)
|
||||
if (keys[ikey0]->t > t)
|
||||
break;
|
||||
--ikey0;
|
||||
#endif
|
||||
|
||||
// Slerp.
|
||||
if (ikey0 == (int(keys.GetCount()) - 1))
|
||||
p = keys[ikey0]->q;
|
||||
else
|
||||
{
|
||||
const float k = (t - keys[ikey0]->t).toSec() / (keys[ikey0 + 1]->t - keys[ikey0]->t).toSec();
|
||||
p = Quaternion::Slerp(k, keys[ikey0]->q, keys[ikey0 + 1]->q).Normalize();
|
||||
}
|
||||
}
|
||||
uint QuaternionChannel::Optimize(float threshold)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
TimeRange QuaternionChannel::GetTimeRange() const
|
||||
{
|
||||
Time min, max;
|
||||
if (keys.GetCount() > 0)
|
||||
{
|
||||
min = max = keys[0]->t;
|
||||
for (uint n = 1; n < keys.GetCount(); ++n)
|
||||
{
|
||||
min = Types::Min(min, keys[n]->t);
|
||||
max = Types::Max(max, keys[n]->t);
|
||||
}
|
||||
}
|
||||
return TimeRange(min, max);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool QuaternionChannel::Insert(const QuaternionKey &key)
|
||||
{
|
||||
uint n = 0;
|
||||
for (; n < keys.GetCount(); ++n)
|
||||
if (keys[n]->t > key.t)
|
||||
break;
|
||||
|
||||
return keys.Insert(new QuaternionKey(key), n);
|
||||
}
|
||||
void QuaternionChannel::Clear()
|
||||
{
|
||||
ArrayListDeleteAllPtr(QuaternionKey *, keys)
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
QuaternionChannel::QuaternionChannel()
|
||||
{}
|
||||
QuaternionChannel::~QuaternionChannel()
|
||||
{ Clear(); }
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user