예제 #1
0
inline Quaternion<T> Squad(const Quaternion<T>& p, const Quaternion<T>& a, const Quaternion<T>& b, const Quaternion<T>& q, const T& time)
{
    Quaternion<T> qa = Slerp(p,q,time,0);
    Quaternion<T> qb = Slerp(a,b,time,0);
    T qtime = 2 * time * (1 - time);
    return Slerp(qa,qb,qtime,0);
}
예제 #2
0
	HawkQuaternion HawkQuaternion::Squad (Float fT,const HawkQuaternion& rkP, const HawkQuaternion& rkA,const HawkQuaternion& rkB, const HawkQuaternion& rkQ, bool shortestPath)
	{
		Float fSlerpT = 2.0f*fT*(1.0f-fT);
		HawkQuaternion kSlerpP = Slerp(fT, rkP, rkQ, shortestPath);
		HawkQuaternion kSlerpQ = Slerp(fT, rkA, rkB);
		return Slerp(fSlerpT, kSlerpP ,kSlerpQ);
	}
예제 #3
0
파일: quat.C 프로젝트: fluffels/straylight
void Squad (Quaternion* res, float t, Quaternion* p,
    Quaternion* a, Quaternion* b, Quaternion* q)
{
   Quaternion q1, q2;
   Slerp(&q1, t, p, q);
   Slerp(&q2, t, a, b);
   Slerp(res, 2 * t * (1 - t), &q1, &q2);
}
예제 #4
0
moQuaternion<Real>& moQuaternion<Real>::Squad (Real fT, const moQuaternion& rkQ0,
    const moQuaternion& rkA0, const moQuaternion& rkA1, const moQuaternion& rkQ1)
{
    Real fSlerpT = ((Real)2.0)*fT*((Real)1.0-fT);
    moQuaternion kSlerpP = Slerp(fT,rkQ0,rkQ1);
    moQuaternion kSlerpQ = Slerp(fT,rkA0,rkA1);
    return Slerp(fSlerpT,kSlerpP,kSlerpQ);
}
예제 #5
0
 //-----------------------------------------------------------------------
 Quaternion Quaternion::Squad (Real fT,
     const Quaternion& rkP, const Quaternion& rkA,
     const Quaternion& rkB, const Quaternion& rkQ, bool shortestPath)
 {
     Real fSlerpT = 2.0f*fT*(1.0f-fT);
     Quaternion kSlerpP = Slerp(fT, rkP, rkQ, shortestPath);
     Quaternion kSlerpQ = Slerp(fT, rkA, rkB);
     return Slerp(fSlerpT, kSlerpP ,kSlerpQ);
 }
예제 #6
0
 Quaternion Quaternion::Squad(
    float t, 
    const Quaternion &p,
    const Quaternion &a, 
    const Quaternion &b,
    const Quaternion &q, 
    bool shortestPath)
 {
    float slerpT = 2.0f * t * (1.0f - t);
    Quaternion slerpP = Slerp(t, p, q, shortestPath);
    Quaternion slerpQ = Slerp(t, a, b);
    return Slerp(slerpT, slerpP ,slerpQ);
 }
예제 #7
0
SkelMat4 skelBone_AvRot::GetDirtyTransform( const skelAnimStoreFrameList_c *frames )
{
	SkelQuat temp1, temp2;
	SkelMat4 temp;

	temp1 = m_reference1->GetTransform( frames );
	temp2 = m_reference2->GetTransform( frames );

	// lerp values
	Slerp( temp1, temp2, m_bone2weight, &m_cachedQuat );

	VectorCopy( m_basePos, m_cachedValue[ 3 ] );

	if( m_parent )
	{
		temp.Multiply( m_cachedValue, m_parent->GetTransform( frames ) );
		m_cachedValue = temp;
	}

	m_cachedQuat.GetMat4( m_cachedValue );

	m_isDirty = false;

	return m_cachedValue;
}
예제 #8
0
void AnimatedTransform::Interpolate(float time, Transform *t) const {
    // Handle boundary conditions for matrix interpolation
    if (!actuallyAnimated || time <= startTime) {
        *t = *startTransform;
        return;
    }
    if (time >= endTime) {
        *t = *endTransform;
        return;
    }
    float dt = (time - startTime) / (endTime - startTime);
    // Interpolate translation at _dt_
    Vector trans = (1.f - dt) * T[0] + dt * T[1];

    // Interpolate rotation at _dt_
    Quaternion rotate = Slerp(dt, R[0], R[1]);

    // Interpolate scale at _dt_
    Matrix4x4 scale;
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 3; ++j)
            scale.m[i][j] = Lerp(dt, S[0].m[i][j], S[1].m[i][j]);

    // Compute interpolated matrix as product of interpolated components
    *t = Translate(trans) * rotate.ToTransform() * Transform(scale);
}
예제 #9
0
bool Interpolator::LinearQuaternion(FlKeyCode keycode, FlKeyGroup* g1, FlKeyGroup* g2, double t, Quaternion &qval)
{
	qval = Quaternion(0, 0, 0, 1);
	if (!g1 || !g2) return false;
	FlKey *key1 = SearchKey(keycode, g1);
	FlKey *key2 = SearchKey(keycode, g2);
	if (!key1 || !key2) return false;
	if (key1->GetType()!=FLKEY_TYPE_QUATER ||
		key2->GetType()!=FLKEY_TYPE_QUATER)
		return false;
	double t1, t2;
	Quaternion q1, q2;
	q1 = ((FlKeyQuaternion*)key1)->GetValue();
	q2 = ((FlKeyQuaternion*)key2)->GetValue();
	t1 = g1->t;
	t2 = g2->t;
	if (t1 == t2)
	{
		qval = q1;
		return true;
	}
	double st = Smooth((t-t1)/(t2-t1), g1->type==1, g2->type==1);
	qval = Slerp(q1, q2, st);
	return true;
}
예제 #10
0
void QuatApp::SlerpArray( Quat *result, const Quat *source, const Quat *target, const float slerpFactor, const int numQuats )
{
	for (int i = 0; i < numQuats; i++)
	{
		Slerp(result[i], source[i], target[i], slerpFactor);
	}
}
예제 #11
0
파일: IAttribute.cpp 프로젝트: katik/naali
template<> void TUNDRACORE_API Attribute<Quat>::Interpolate(IAttribute* start, IAttribute* end, float t, AttributeChange::Type change)
{
    Attribute<Quat>* startQuat = dynamic_cast<Attribute<Quat>*>(start);
    Attribute<Quat>* endQuat = dynamic_cast<Attribute<Quat>*>(end);
    if (startQuat && endQuat)
        Set(Slerp(startQuat->Get(), endQuat->Get(), t), change);
}
예제 #12
0
void InterpolateRotation(Quat startRot, Quat endRot, AngAxis startSpin, float endSpin,
						 PreciseTimeValue startT, PreciseTimeValue endT, PreciseTimeValue curT,
						 float easyIn, bool targetConstant, Quat& resRot, AngAxis& resSpin)
{
	float timeDif = float(endT - startT);
	AngAxis totalSpin = startSpin;
	totalSpin.angle *= timeDif;
	Quat rot0 = startRot + Quat(totalSpin);
	AngAxis difSpin;
	difSpin.angle = QangAxis(rot0, endRot, difSpin.axis);
	AngAxis reverseSpin = difSpin;
	reverseSpin.angle = endSpin;
	AngAxis totalDifSpin = difSpin;
	totalDifSpin.angle = -endSpin*timeDif;
	Quat rot1 = endRot + Quat(totalDifSpin);
	AngAxis partialSpin = startSpin;
	partialSpin.angle *= float(curT - startT);
	Quat rot00 = startRot + Quat(partialSpin);
	AngAxis partialRevSpin = reverseSpin;
	partialRevSpin.angle *= float(curT - endT);
	Quat rot11 = endRot + Quat(partialRevSpin);
	if (!targetConstant)
		rot11.MakeClosest(rot00);
	float timeRatio = float(endT - curT)/timeDif;
	float adjRatio = timeRatio*(timeRatio*easyIn + 1.0f - easyIn);
	resRot = Slerp(rot11, rot00, adjRatio);

	curT.tick -= 1;
	partialSpin = startSpin;
	partialSpin.angle *= float(curT - startT);
	Quat rot20 = startRot + Quat(partialSpin);
	partialRevSpin = reverseSpin;
	partialRevSpin.angle *= float(curT - endT);
	Quat rot21 = endRot + Quat(partialRevSpin);
	if (!targetConstant)
		rot21.MakeClosest(rot20);
	timeRatio = float(endT - curT)/timeDif;
	float adjRatio2 = timeRatio*(timeRatio*easyIn + 1.0f - easyIn);
	Quat prevRot = Slerp(rot21, rot20, adjRatio2);
	resSpin.angle = QangAxis(prevRot, resRot, resSpin.axis);
	if (!targetConstant)
		resSpin.angle = timeRatio*startSpin.angle + (1.0f-timeRatio)*endSpin;
}
예제 #13
0
float3 MUST_USE_RESULT Quat::SlerpVector(const float3 &from, const float3 &to, float t)
{
	if (t <= 0.f)
		return from;
	if (t >= 1.f)
		return to;
	///\todo The following chain can be greatly optimized.
	Quat q = Quat::RotateFromTo(from, to);
	q = Slerp(Quat::identity, q, t);
	return q.Transform(from);
}
예제 #14
0
float3 MUST_USE_RESULT Quat::SlerpVectorAbs(const float3 &from, const float3 &to, float angleRadians)
{
	if (angleRadians <= 0.f)
		return from;
	Quat q = Quat::RotateFromTo(from, to);
	float a = q.Angle();
	if (a <= angleRadians)
		return to;
	float t = angleRadians / a;
	q = Slerp(Quat::identity, q, t);
	return q.Transform(from);
}
		glm::fquat GetOrient(const glm::fquat &initial, bool bSlerp) const
		{
			if(bSlerp)
			{
				return Slerp(initial, g_Orients[m_ixFinalOrient], m_currTimer.GetAlpha());
			}
			else
			{
				return Lerp(initial, g_Orients[m_ixFinalOrient], m_currTimer.GetAlpha());
			}

			return initial;
		}
예제 #16
0
// Spherical linear interpolation of two quaternion-transforms q0 and q1, with parameter t, 
// result in qt. Only the quaternion uses slerp, position and scaling use lerp
// Non-member function
void Slerp
(
	const CQuatTransform& q0,
	const CQuatTransform& q1,
	const TFloat32        t,
	CQuatTransform&       qt
)
{
	// Calculate lerp for position and scale
	qt.pos = q0.pos*(1.0f-t) + q1.pos*t;
	qt.scale = q0.scale*(1.0f-t) + q1.scale*t;

	// Call slerp function for quaternion rotation
	Slerp( q0.quat, q1.quat, t, qt.quat );
}
예제 #17
0
파일: IAttribute.cpp 프로젝트: katik/naali
template<> void TUNDRACORE_API Attribute<Transform>::Interpolate(IAttribute* start, IAttribute* end, float t, AttributeChange::Type change)
{
    Attribute<Transform>* startTrans = dynamic_cast<Attribute<Transform>*>(start);
    Attribute<Transform>* endTrans = dynamic_cast<Attribute<Transform>*>(end);
    if (startTrans && endTrans)
    {
        const Transform& startValue = startTrans->Get();
        const Transform& endValue = endTrans->Get();
        Transform newTrans;
        newTrans.pos = Lerp(startValue.pos, endValue.pos, t);
        newTrans.SetOrientation(Slerp(startValue.Orientation(), endValue.Orientation(), t));
        newTrans.scale = Lerp(startValue.scale, endValue.scale, t);
        Set(newTrans, change);
    }
}
예제 #18
0
// function for SLERP quaternion
void Interpolator::LinearInterpolationQuaternion(Motion * pInputMotion, Motion * pOutputMotion, int N)
{
  int inputLength = pInputMotion->GetNumFrames(); // frames are indexed 0, ..., inputLength-1

  int startKeyframe = 0;
  while (startKeyframe + N + 1 < inputLength)
  {
    int endKeyframe = startKeyframe + N + 1;

    Posture * startPosture = pInputMotion->GetPosture(startKeyframe);
    Posture * endPosture = pInputMotion->GetPosture(endKeyframe);

    // copy start and end keyframe
    pOutputMotion->SetPosture(startKeyframe, *startPosture);
    pOutputMotion->SetPosture(endKeyframe, *endPosture);

    // interpolate in between
    for(int frame=1; frame<=N; frame++)
    {
      Posture interpolatedPosture;
      double t = 1.0 * frame / (N+1);

      // interpolate root position
      interpolatedPosture.root_pos = startPosture->root_pos * (1-t) + endPosture->root_pos * t;

      // interpolate bone rotations
      for (int bone = 0; bone < MAX_BONES_IN_ASF_FILE; bone++)
	  {
		  // convert euler angles to quaternions
		  Quaternion<double> boneStartRot = Vector2Quaternion(startPosture->bone_rotation[bone]);
		  Quaternion<double> boneEndRot = Vector2Quaternion(endPosture->bone_rotation[bone]);

		  // do slerp for converted quaternions at t
		  double interpolatedAngles[3];
		  Quaternion2Euler(Slerp(t, boneStartRot, boneEndRot), interpolatedAngles);

		  interpolatedPosture.bone_rotation[bone].setValue(interpolatedAngles);
	  }

      pOutputMotion->SetPosture(startKeyframe + frame, interpolatedPosture);
    }

    startKeyframe = endKeyframe;
  }

  for(int frame=startKeyframe+1; frame<inputLength; frame++)
    pOutputMotion->SetPosture(frame, *(pInputMotion->GetPosture(frame)));
}
// Interpolate fractional arc between two wgs84 vectors.
// This models the earths ellipsoid.
geolocation Slerper::GeoSlerp(double frac)
{
    // Generate normalized ECEF vector
    xyz slerp = Slerp(frac);

    // Scale ecef unit vector so its roughly at earth surface
    double interpaltitudestep = m_altitude_delta * frac;
    slerp = slerp.scale(m_x0_magnitude + interpaltitudestep);

    // Convert ecef back to wgs84
    geolocation slerpgeo = slerp.togeolocation();

    // Set linear interpolated altitude on slerped wgs84 vector
    double interpaltitude = m_altitude_delta * frac;
    slerpgeo.Alt() = m_g0.Alt() + interpaltitude;

    return slerpgeo;
}
예제 #20
0
    void Evaluate()
    {
        float frame = GetFrame()->GetValue();

        int count = m_keys.GetCount();

        if (frame <= m_keys[0].m_frame) {
            //
            // Before first key
            //

            //  , add a SetRotate(const Quaternion&) to Matrix

            Vector vec;
            float angle = m_keys[0].m_quat.GetRotation(vec);
            GetValueInternal().SetRotate(vec, angle);
        } else if (frame >= m_keys[count - 1].m_frame) {
            //
            // After last key
            //

            Vector vec;
            float angle = m_keys[count - 1].m_quat.GetRotation(vec);
            GetValueInternal().SetRotate(vec, angle);
        } else {
            //
            // Between two keys
            //

            int index = 0;

            while (frame > m_keys[index + 1].m_frame) {
                index++;
            }

            float interpolant = (frame - m_keys[index].m_frame) / (m_keys[index + 1].m_frame - m_keys[index].m_frame);

            Quaternion quat = Slerp(m_keys[index].m_quat, m_keys[index + 1].m_quat, interpolant);
            Vector vec;
            float angle = quat.GetRotation(vec);
            GetValueInternal().SetRotate(vec, angle);
        }
    }
예제 #21
0
void TAnimContainer::PrepareModel()
{ // tutaj zostawi� tylko ustawienie submodelu, przeliczanie ma by� w UpdateModel()
    if (pSubModel) // pozby� si� tego - sprawdza� wcze�niej
    {
        // nanoszenie animacji na wzorzec
        if (iAnim & 1) // zmieniona pozycja wzgl�dem pocz�tkowej
            pSubModel->SetRotateXYZ(vRotateAngles); // ustawia typ animacji
        if (iAnim & 2) // zmieniona pozycja wzgl�dem pocz�tkowej
            pSubModel->SetTranslate(vTranslation);
        if (iAnim & 4) // zmieniona pozycja wzgl�dem pocz�tkowej
        {
            if (fAngleSpeed > 0.0f)
            {
                fAngleCurrent +=
                    fAngleSpeed * Timer::GetDeltaTime(); // aktualny parametr interpolacji
                if (fAngleCurrent >= 1.0f)
                { // interpolacja zako�czona, ustawienie na pozycj� ko�cow�
                    qCurrent = qDesired;
                    fAngleSpeed = 0.0; // wy��czenie przeliczania wektora
                    if (evDone)
                        Global::AddToQuery(evDone,
                                           NULL); // wykonanie eventu informuj�cego o zako�czeniu
                }
                else
                { // obliczanie pozycji po�redniej
                    // normalizacja jest wymagana do interpolacji w nast�pnej animacji
                    qCurrent = Normalize(
                        Slerp(qStart, qDesired, fAngleCurrent)); // interpolacja sferyczna k�ta
                    // qCurrent=Slerp(qStart,qDesired,fAngleCurrent); //interpolacja sferyczna k�ta
                    if (qCurrent.w ==
                        1.0) // rozpozna� brak obrotu i wy��czy� w iAnim w takim przypadku
                        iAnim &= ~4; // k�ty s� zerowe
                }
            }
            mAnim->Quaternion(&qCurrent); // wype�nienie macierzy (wymaga normalizacji?)
            pSubModel->mAnimMatrix = mAnim; // u�yczenie do submodelu (na czas renderowania!)
        }
    }
    // if (!strcmp(pSubModel->pName,"?Z?�?^?[")) //jak g��wna ko��
    // WriteLog(AnsiString(pMovementData->iFrame)+": "+AnsiString(iAnim)+"
    // "+AnsiString(vTranslation.x)+" "+AnsiString(vTranslation.y)+" "+AnsiString(vTranslation.z));
}
예제 #22
0
// Decasteljau Quaternion formula to find value at t
Quaternion<double> Interpolator::DeCasteljauQuaternion(double t, Quaternion<double> p0, Quaternion<double> p1, Quaternion<double> p2, Quaternion<double> p3)
{
  // students should implement this
  Quaternion<double> result;

  Quaternion<double> q0 = Slerp(t, p0, p1);
  Quaternion<double> q1 = Slerp(t, p1, p2);
  Quaternion<double> q2 = Slerp(t, p2, p3);

  Quaternion<double> r0 = Slerp(t, q0, q1);
  Quaternion<double> r1 = Slerp(t, q1, q2);

  result = Slerp(t, r0, r1);

  return result;
}
예제 #23
0
CQuaternion  DeCasteljau(CQuaternion const& q1, CQuaternion const& q2,CQuaternion const& q3, CQuaternion const& q4,float t)
{
// simplified version
//	CQuaternion pp = Slerp(Slerp(q1,q4,t),Slerp(q2,q3,t),2*t*(1-t));

	CQuaternion p1,p2,p3,p12,p23,p;
	
	p1 = Slerp(q1,q2,t);
	p2 = Slerp(q2,q3,t);
	p3 = Slerp(q3,q4,t);

	p12 = Slerp(p1,p2,t);
	p23 = Slerp(p2,p3,t);

	p= Slerp(p12,p23,t);

	return p;
}
void OrientConstRotation::Update(TimeValue t){
	Interval iv = FOREVER;
	ivalid = FOREVER;
	
	int ct = pblock->Count(orientation_target_list);
	int ctf = pblock->Count(orientation_target_weight);

	float total_orient_target_weight_prev = 0.0f, total_orient_target_weight_current = 0.0f;
	float orient_targ_Wt_current = 0.0f;
	Quat quat_prev, quat_current, lCurRot;
	INode *orient_target_prev= NULL, *orient_target_current= NULL;
	Matrix3 targetTM(1);
	Point3 trans, scaleP;

	quat_prev.Identity();
	quat_current.Identity();
	lCurRot.Identity();

		if (ct == 1){
			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}
		}
		else if (ct > 1){

			pblock->GetValue(orientation_target_list, t, orient_target_prev, iv, 0);
			pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, 0);
//			if (orient_target_prev != NULL)
//			{
				ivalid &= iv;

				if (orient_target_prev == NULL){
					targetTM.IdentityMatrix();
				}
				else {
					targetTM = orient_target_prev->GetNodeTM(t, &ivalid);
				}

				if (IsLocal() && orient_target_prev != NULL) {
					targetTM = targetTM * Inverse(orient_target_prev->GetParentTM(t));
				}
				AffineParts comps;		// Requires header decomp.h
				decomp_affine(targetTM, &comps);
				quat_current = comps.q;
				quat_current.Normalize();
				quat_current.MakeClosest(quat_prev);

				lCurRot = quat_current;

				quat_prev = lCurRot;
				total_orient_target_weight_prev += orient_targ_Wt_current;
//			}

			for (int i = 0; i < ct -1; i++) {
//				ct = pblock->Count(orientation_target_list);
				pblock->GetValue(orientation_target_list, t, orient_target_current, iv, i+1);
				pblock->GetValue(orientation_target_weight, t, orient_targ_Wt_current, iv, i+1);
//				if (orient_target_current != NULL){
					ivalid &= iv;

					if (orient_target_current == NULL){
						targetTM.IdentityMatrix();
					}
					else {
						targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					}

//					Matrix3 targetTM = orient_target_current->GetNodeTM(t, &ivalid);
					if (IsLocal() && orient_target_current != NULL) {
						targetTM = targetTM * Inverse(orient_target_current->GetParentTM(t));
					}
					AffineParts comps;		// Requires header decomp.h
					decomp_affine(targetTM, &comps);
					quat_current = comps.q;
					quat_current.Normalize();
					quat_current.MakeClosest(quat_prev);

					float slerp_wt = 0.0f;
					if ((total_orient_target_weight_prev + orient_targ_Wt_current) != 0.0){
						slerp_wt = orient_targ_Wt_current / (total_orient_target_weight_prev + orient_targ_Wt_current);
					}

					lCurRot = Slerp(quat_prev, quat_current, slerp_wt);
					lCurRot.Normalize();

					quat_prev = lCurRot;
					total_orient_target_weight_prev += orient_targ_Wt_current;
//				}
			}			//for (int i = 0; i < ct -1; i++)
		}				//else if (ct > 1)

		if (oldTargetNumber != ct) {
			InitialOrientQuat = lCurRot;
		}

		curRot = lCurRot;
		if (total_orient_target_weight_prev > 0.0){
			if (Relative()){
				if(IsLocal()){
					curRot =   baseRotQuatLocal * (lCurRot /InitialOrientQuat);
				}
				else{
					curRot =   baseRotQuatWorld * (lCurRot /InitialOrientQuat);
				}
			}
		}
		else {
			curRot = baseRotQuatLocal;
		}
		curRot.MakeClosest(IdentQuat());
		curRot.Normalize();
		oldTargetNumber = ct;
//	if (ivalid.Empty()) ivalid.SetInstant(t);
}
예제 #25
0
	//-----------------------------------------------------------------------
	Quaternion Quaternion::Slerp(const Quaternion& rkP,
		const Quaternion& rkQ, Real fT)
	{
		return Slerp(fT, rkP, rkQ, false);
	}
예제 #26
0
// not 'static', because used in ExportPsa()
void CAnimTrack::GetBonePosition(float Frame, float NumFrames, bool Loop, CVec3 &DstPos, CQuat &DstQuat) const
{
	guard(CAnimTrack::GetBonePosition);

	// fast case: 1 frame only
	if (KeyTime.Num() == 1 || NumFrames == 1 || Frame == 0)
	{
		if (KeyPos.Num())  DstPos  = KeyPos[0];
		if (KeyQuat.Num()) DstQuat = KeyQuat[0];
		return;
	}

	// data for lerping
	int posX, rotX;			// index of previous frame
	int posY, rotY;			// index of next frame
	float posF, rotF;		// fraction between X and Y for lerping

	int NumTimeKeys = KeyTime.Num();
	int NumPosKeys  = KeyPos.Num();
	int NumRotKeys  = KeyQuat.Num();

	if (NumTimeKeys)
	{
		// here: KeyPos and KeyQuat sizes either equals to 1 or equals to KeyTime size
		assert(NumPosKeys <= 1 || NumPosKeys == NumTimeKeys);
		assert(NumRotKeys == 1 || NumRotKeys == NumTimeKeys);

		GetKeyParams(KeyTime, Frame, NumFrames, Loop, posX, posY, posF);
		rotX = posX;
		rotY = posY;
		rotF = posF;

		if (NumPosKeys <= 1)
		{
			posX = posY = 0;
			posF = 0;
		}
		if (NumRotKeys == 1)
		{
			rotX = rotY = 0;
			rotF = 0;
		}
	}
	else
	{
		// empty KeyTime array - keys are evenly spaced on a time line
		// note: KeyPos and KeyQuat sizes can be different
		if (KeyPosTime.Num())
		{
			GetKeyParams(KeyPosTime, Frame, NumFrames, Loop, posX, posY, posF);
		}
		else if (NumPosKeys > 1)
		{
			float Position = Frame / NumFrames * NumPosKeys;
			posX = appFloor(Position);
			posF = Position - posX;
			posY = posX + 1;
			if (posY >= NumPosKeys)
			{
				if (!Loop)
				{
					posY = NumPosKeys - 1;
					posF = 0;
				}
				else
					posY = 0;
			}
		}
		else
		{
			posX = posY = 0;
			posF = 0;
		}

		if (KeyQuatTime.Num())
		{
			GetKeyParams(KeyQuatTime, Frame, NumFrames, Loop, rotX, rotY, rotF);
		}
		else if (NumRotKeys > 1)
		{
			float Position = Frame / NumFrames * NumRotKeys;
			rotX = appFloor(Position);
			rotF = Position - rotX;
			rotY = rotX + 1;
			if (rotY >= NumRotKeys)
			{
				if (!Loop)
				{
					rotY = NumRotKeys - 1;
					rotF = 0;
				}
				else
					rotY = 0;
			}
		}
		else
		{
			rotX = rotY = 0;
			rotF = 0;
		}
	}

	// get position
	if (posF > 0)
		Lerp(KeyPos[posX], KeyPos[posY], posF, DstPos);
	else if (NumPosKeys)		// do not change DstPos when no keys
		DstPos = KeyPos[posX];
	// get orientation
	if (rotF > 0)
		Slerp(KeyQuat[rotX], KeyQuat[rotY], rotF, DstQuat);
	else if (NumRotKeys)		// do not change DstQuat when no keys
		DstQuat = KeyQuat[rotX];

	unguard;
}
예제 #27
0
SkelMat4 skelBone_HoseRot::GetDirtyTransform( SkelMat4& myParentTM, SkelMat4& targetTM )
{
	SkelMat4 m;
	SkelMat4 invParentTM;
	SkelMat4 temp;
	SkelVec3 rotaxis;
	SkelVec3 targetup, targetaim;
	SkelVec3 upaxis, aimaxis;
	SkelVec3 tmp;
	SkelQuat targetQuat;
	float l, s, c;
	float angle, vScale;

	aimaxis = myParentTM[ 0 ];
	targetaim = targetTM[ 0 ];

	CrossProduct( targetaim, aimaxis, rotaxis );

	s = VectorLengthSquared( rotaxis );

	if( s == 0.0 ) {
		rotaxis.x = 1.0;
	} else if( s != 1.0 ) {
		l = 1.0 / sqrt( s );
		VectorScale( rotaxis, l, rotaxis );
	}

	s = DotProduct( aimaxis, targetaim );
	if( s < 1.0 ) {
		if( s > -0.999 ) {
			angle = acos( s );
		} else {
			angle = 6.2831855f;
		}
	} else {
		angle = 0.0;
	}

	vScale = angle * m_bendRatio;
	if( vScale > m_bendMax ) {
		vScale = m_bendMax;
	}

	temp[ 0 ][ 0 ] = myParentTM[ 0 ][ 0 ];
	temp[ 0 ][ 1 ] = myParentTM[ 1 ][ 0 ];
	temp[ 0 ][ 2 ] = myParentTM[ 2 ][ 0 ];
	temp[ 1 ][ 0 ] = myParentTM[ 0 ][ 1 ];
	temp[ 1 ][ 1 ] = myParentTM[ 1 ][ 1 ];
	temp[ 1 ][ 2 ] = myParentTM[ 2 ][ 1 ];
	temp[ 2 ][ 0 ] = myParentTM[ 0 ][ 2 ];
	temp[ 2 ][ 1 ] = myParentTM[ 1 ][ 2 ];
	temp[ 2 ][ 2 ] = myParentTM[ 2 ][ 2 ];
	temp[ 3 ][ 0 ] = -( myParentTM[ 0 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 0 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 0 ][ 2 ] * myParentTM[ 3 ][ 2 ] );
	temp[ 3 ][ 1 ] = -( myParentTM[ 1 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 1 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 1 ][ 2 ] * myParentTM[ 3 ][ 2 ] );
	temp[ 3 ][ 2 ] = -( myParentTM[ 2 ][ 0 ] * myParentTM[ 3 ][ 0 ] + myParentTM[ 2 ][ 1 ] * myParentTM[ 3 ][ 1 ] + myParentTM[ 2 ][ 2 ] * myParentTM[ 3 ][ 2 ] );

	m.Multiply( temp, myParentTM );

	VectorCopy( rotaxis, tmp );
	rotaxis[ 0 ] = tmp[ 0 ] * temp[ 0 ][ 0 ] + tmp[ 1 ] * temp[ 1 ][ 0 ] + tmp[ 2 ] * temp[ 2 ][ 0 ];
	rotaxis[ 1 ] = tmp[ 0 ] * temp[ 0 ][ 1 ] + tmp[ 1 ] * temp[ 1 ][ 1 ] + tmp[ 2 ] * temp[ 2 ][ 1 ];
	rotaxis[ 2 ] = tmp[ 0 ] * temp[ 0 ][ 2 ] + tmp[ 1 ] * temp[ 1 ][ 2 ] + tmp[ 2 ] * temp[ 2 ][ 2 ];

	targetaim.y = cos( vScale * 0.5 );
	targetup.y = rotaxis.x * targetaim.y;
	targetup.z = rotaxis.y * targetaim.y;
	targetaim.x = rotaxis.z * targetaim.y;

	c = cos( vScale * 0.5 );
	l = sqrt( 1.0 - c * c );

	m_cachedQuat[ 0 ] = rotaxis[ 0 ] * l;
	m_cachedQuat[ 1 ] = rotaxis[ 1 ] * l;
	m_cachedQuat[ 2 ] = rotaxis[ 2 ] * l;
	m_cachedQuat[ 3 ] = c;

	if( m_spinRatio < 1.0 )
	{
		m.Multiply( targetTM, temp );
		MatToQuat( m.val, targetQuat.val );
		Slerp( targetQuat, m_cachedQuat, m_spinRatio, &m_cachedQuat );
	}

	m_cachedQuat.GetMat4( m_cachedValue );
	VectorCopy( m_basePos, m_cachedValue[ 3 ] );

	m.Multiply( m_cachedValue, myParentTM );
	m_cachedValue = m;

	m_isDirty = false;

	return m_cachedValue;
}
예제 #28
0
//-------------------------------------------------------------------------------
// @ Player::Update()
//-------------------------------------------------------------------------------
// Main update loop
//-------------------------------------------------------------------------------
void
Player::Update( float dt )
{
    IvMatrix33 rotateX, rotateY, rotateZ;
    IvMatrix33 rotate;
    float heading = 0.0f, pitch = 0.0f, roll = 0.0f;

    // clear transform
    if (IvGame::mGame->mEventHandler->IsKeyPressed(' '))
    {
        if (mRun)
        {
            // reset animations
            mTime = 0.0f;
            mRun = false;
            heading = mStartHeading;
            pitch = mStartPitch;
            roll = mStartRoll;
            mSlerpRotate = mStartRotate;
            mNumPoints = 0;
            mRotate.Rotation( heading, pitch, roll );
        }
        else
        {
            // start 'er up again
            mRun = true;
        }
    }

    // swap orientation reps
    if (IvGame::mGame->mEventHandler->IsKeyPressed('x'))
    {
        mUseQuat = !mUseQuat;

        mNumPoints = 0;
    }


    if (mRun)
    {
        // get the next time step
        mTime += dt;
        if ( mTime > 8.0f )
            mTime = 8.0f;
        float alpha = mTime/8.0f;

        // interpolate
        heading = mStartHeading*(1.0f - alpha) + mEndHeading*alpha;
        pitch = mStartPitch*(1.0f - alpha) + mEndPitch*alpha;
        roll = mStartRoll*(1.0f - alpha) + mEndRoll*alpha;
        Slerp(mSlerpRotate, mStartRotate, mEndRotate, alpha);

        // set rotation matrix based on current orientation rep
        if (mUseQuat)
        {
            mRotate.Rotation(mSlerpRotate);
        }
        else
        {
            mRotate.Rotation( heading, pitch, roll );
        }

        // add new path points
        if (mNumPoints < 1280 && mFrameCounter == 0)
        {
            mStoredPoints[0][mNumPoints] = mRotate*IvVector3(1.0f, -1.0f, 1.0f);
            mStoredPoints[1][mNumPoints++] = mRotate*IvVector3(-1.0f, 0.0f, -1.0f);
        }
        mFrameCounter = (mFrameCounter + 1) % 10;
    }


}   // End of Player::Update()
예제 #29
0
// function for SLERP bezier quaternion interpolation
void Interpolator::BezierInterpolationQuaternion(Motion * pInputMotion, Motion * pOutputMotion, int N)
{
  // students should implement this
  int inputLength = pInputMotion->GetNumFrames(); // frames are indexed 0, ..., inputLength-1

  int startKeyframe = 0;
  // default and next 'a' values for bezier are stored in memory
  Quaternion<double> aDef[MAX_BONES_IN_ASF_FILE];
  Quaternion<double> aNext[MAX_BONES_IN_ASF_FILE];

  double bezRatio = 1.0/3.0;
  vector aNextRoot;
  // use a0 for the first frame by backtracking from next 2 known frames
  vector v1 = pInputMotion->GetPosture(0)->root_pos;
  vector v2 = pInputMotion->GetPosture(N+1)->root_pos;
  vector v3 = pInputMotion->GetPosture(N+1+N+1)->root_pos;
  vector aDefRoot = v1*(1-bezRatio) + (v3 * (-1) + v2 * 2) * bezRatio;

  for (int i = 0; i < MAX_BONES_IN_ASF_FILE; i++)
  {
	Quaternion<double> q1 = Vector2Quaternion(pInputMotion->GetPosture(0)->bone_rotation[i]);
	Quaternion<double> q2 = Vector2Quaternion(pInputMotion->GetPosture(N+1)->bone_rotation[i]);
	Quaternion<double> q3 = Vector2Quaternion(pInputMotion->GetPosture(N+1+N+1)->bone_rotation[i]);
	aDef[i] = Slerp(bezRatio, q1, Slerp(2.0, q3, q2));
  }

  while (startKeyframe + N + 1 < inputLength)
  {
    int endKeyframe = startKeyframe + N + 1;

    Posture * startPosture = pInputMotion->GetPosture(startKeyframe);
    Posture * endPosture = pInputMotion->GetPosture(endKeyframe);
	Posture * nextPosture;
	if (endKeyframe + N + 1 >= inputLength)	nextPosture = pInputMotion->GetPosture(inputLength-1);
	else nextPosture = pInputMotion->GetPosture(endKeyframe + (N+1));
	
    // copy start and end keyframe
    pOutputMotion->SetPosture(startKeyframe, *startPosture);
    pOutputMotion->SetPosture(endKeyframe, *endPosture);

    // interpolate in between
    for(int frame=1; frame<=N; frame++)
    {
      Posture interpolatedPosture;
      double t = 1.0 * frame / (N+1);

	  // bez interpolate root position
	  vector rootStartPos = startPosture->root_pos;
  	  vector rootEndPos = endPosture->root_pos;
	  vector rootNextPos = nextPosture->root_pos;
	  vector p1 = startKeyframe == 0? aDefRoot : aNextRoot; // use a0 if first frame, otherwise use a calculated in previous iteration
	  vector aN = rootEndPos*(1-bezRatio) + ((rootStartPos*-1+ rootEndPos*2)*0.5+ rootNextPos*0.5)*bezRatio;
	  vector p2 = aN*-1+rootEndPos*2; // bn

	  interpolatedPosture.root_pos = DeCasteljauEuler(t, rootStartPos, p1, p2, rootEndPos);

	  // interpolate bone rotations
      for (int bone = 0; bone < MAX_BONES_IN_ASF_FILE; bone++)
	  {
		  Quaternion<double> boneStartRot = Vector2Quaternion(startPosture->bone_rotation[bone]); // qn
		  Quaternion<double> boneEndRot = Vector2Quaternion(endPosture->bone_rotation[bone]); // qn+1
		  Quaternion<double> boneNextRot = Vector2Quaternion(nextPosture->bone_rotation[bone]); // qn+2

		  Quaternion<double> p1 = startKeyframe == 0? aDef[bone] : aNext[bone]; // use a0 if first frame, otherwise use a calculated in previous iteration

		  Quaternion<double> aBar = Slerp(0.5, Slerp(2.0, boneStartRot, boneEndRot), boneNextRot);
		  Quaternion<double> p2 = Slerp(-bezRatio, boneEndRot, aBar);

		  double interpolatedAngles[3];
		  Quaternion2Euler(DeCasteljauQuaternion(t, boneStartRot, p1, p2, boneEndRot), interpolatedAngles);

		  interpolatedPosture.bone_rotation[bone].setValue(interpolatedAngles);
	  }
	  pOutputMotion->SetPosture(startKeyframe + frame, interpolatedPosture);
    }

	// set the aN values for the next N frames (bezier)
	vector rootStartPos = startPosture->root_pos;
  	vector rootEndPos = endPosture->root_pos;
	vector rootNextPos = nextPosture->root_pos;
	aNextRoot = rootEndPos*(1-bezRatio) + ((rootStartPos*-1+ rootEndPos*2)*0.5+ rootNextPos*0.5)*bezRatio;

	for (int bone = 0; bone < MAX_BONES_IN_ASF_FILE; bone++)
    {
	   Quaternion<double>  boneStartRot = Vector2Quaternion(startPosture->bone_rotation[bone]); // qn
	   Quaternion<double> boneEndRot = Vector2Quaternion(endPosture->bone_rotation[bone]); // qn+1
	   Quaternion<double> boneNextRot = Vector2Quaternion(nextPosture->bone_rotation[bone]); // qn+2
	   aNext[bone] = Slerp(bezRatio, boneEndRot, Slerp(0.5, Slerp(2.0, boneStartRot, boneEndRot), boneNextRot)); // an+1
	}

    startKeyframe = endKeyframe;
  }

  for(int frame=startKeyframe+1; frame<inputLength; frame++)
    pOutputMotion->SetPosture(frame, *(pInputMotion->GetPosture(frame)));
}