| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- /*
- * PolyQuaternionCurve.cpp
- * Poly
- *
- * Created by Ivan Safrin on 9/15/08.
- * Copyright 2008 __MyCompanyName__. All rights reserved.
- *
- */
- #include "PolyQuaternionCurve.h"
- using namespace Polycode;
- QuaternionCurve::QuaternionCurve(BezierCurve *wCurve, BezierCurve *xCurve, BezierCurve *yCurve, BezierCurve *zCurve) {
- generatePointsFromCurves(wCurve, xCurve, yCurve, zCurve);
- }
- QuaternionCurve::~QuaternionCurve() {
- }
- void QuaternionCurve::generatePointsFromCurves(BezierCurve *wCurve, BezierCurve *xCurve, BezierCurve *yCurve, BezierCurve *zCurve) {
- for(int i=0; i < wCurve->getNumControlPoints(); i++) {
- /*
- Quaternion newQuat(wCurve->getControlPoint(i)->p2.y,
- xCurve->getControlPoint(i)->p2.y,
- yCurve->getControlPoint(i)->p2.y,
- zCurve->getControlPoint(i)->p2.y);
- points.push_back(newQuat);
- recalcTangents();
- */
- Quaternion quat1(wCurve->getControlPoint(i)->p1.y,
- xCurve->getControlPoint(i)->p1.y,
- yCurve->getControlPoint(i)->p1.y,
- zCurve->getControlPoint(i)->p1.y);
- Quaternion quat2(wCurve->getControlPoint(i)->p2.y,
- xCurve->getControlPoint(i)->p2.y,
- yCurve->getControlPoint(i)->p2.y,
- zCurve->getControlPoint(i)->p2.y);
- Quaternion quat3(wCurve->getControlPoint(i)->p3.y,
- xCurve->getControlPoint(i)->p3.y,
- yCurve->getControlPoint(i)->p3.y,
- zCurve->getControlPoint(i)->p3.y);
-
- QuatTriple newTriple;
- newTriple.q1 = quat1;
- newTriple.q2 = quat2;
- newTriple.q3 = quat3;
- tPoints.push_back(newTriple);
- }
- }
- Quaternion QuaternionCurve::interpolate(Number t, bool useShortestPath)
- {
- // Work out which segment this is in
- Number fSeg = t * (tPoints.size() - 1);
- unsigned int segIdx = (unsigned int)fSeg;
- // Apportion t
- t = fSeg - segIdx;
- return interpolate(segIdx, t, useShortestPath);
- }
- //---------------------------------------------------------------------
- Quaternion QuaternionCurve::interpolate(unsigned int fromIndex, Number t,
- bool useShortestPath)
- {
- // Bounds check
- assert (fromIndex >= 0 && fromIndex < tPoints.size() &&
- "fromIndex out of bounds");
- if ((fromIndex + 1) == tPoints.size() && tPoints[fromIndex].q2 != tPoints[0].q2)
- {
- Logger::log("size\n");
- // Duff request, cannot blend to nothing
- // Just return source
- return points[fromIndex];
- }
- // Fast special cases
- if (t == 0.0f)
- {
- return tPoints[fromIndex].q2;
- }
- else if(t == 1.0f)
- {
- return tPoints[fromIndex + 1].q2;
- }
-
- Quaternion &p = tPoints[fromIndex].q2;
- Quaternion &q = tPoints[fromIndex+1].q2;
- Quaternion &a = tPoints[fromIndex].q3;
- Quaternion &b = tPoints[fromIndex+1].q1;
-
- if ((fromIndex + 1) == tPoints.size() && tPoints[fromIndex].q2 == tPoints[0].q2) {
- q = tPoints[1].q2;
- b = tPoints[1].q1;
- }
- // NB interpolate to nearest rotation
- return Quaternion::Squad(t, p, a, b, q, useShortestPath);
- }
- void QuaternionCurve::recalcTangents(void)
- {
- unsigned int i, numPoints;
- bool isClosed;
- numPoints = (unsigned int)points.size();
- if (numPoints < 2) {
- return;
- }
- tangents.resize(numPoints);
- if (points[0] == points[numPoints-1])
- {
- isClosed = true;
- }
- else
- {
- isClosed = false;
- }
- Quaternion invp, part1, part2, preExp;
- for(i = 0; i < numPoints; ++i)
- {
- Quaternion &p = points[i];
- invp = p.Inverse();
- if (i ==0)
- {
- // special case start
- part1 = (invp * points[i+1]).Log();
- if (isClosed)
- {
- // Use numPoints-2 since numPoints-1 == end == start == this one
- part2 = (invp * points[numPoints-2]).Log();
- }
- else
- {
- part2 = (invp * p).Log();
- }
- }
- else if (i == numPoints-1)
- {
- // special case end
- if (isClosed)
- {
- // Wrap to [1] (not [0], this is the same as end == this one)
- part1 = (invp * points[1]).Log();
- }
- else
- {
- part1 = (invp * p).Log();
- }
- part2 = (invp * points[i-1]).Log();
- }
- else
- {
- part1 = (invp * points[i+1]).Log();
- part2 = (invp * points[i-1]).Log();
- }
- preExp =(part1 + part2) * -0.25 ;
- tangents[i] = p * preExp.Exp();
-
- }
- }
|