Skip to main content
added 109 characters in body
Source Link
Chaos
  • 153
  • 8

Hello everyone, I am trying to interpolate over a sequence of rotations represented by quaternions. I am currently employing Squad (Spherical and Quadrangle Interpolation). I successfully applied the function to 4 rotations and the results corresponded to the expected one.

RotationSequence( std::vector<Quaternion> rotations ) { if (rotations.size() < 4) throw std::runtime_error("Rotation sequence requires at least four rotations."); for (Quaternion rotation : rotations) this->rotations.push_back(rotation); /* Copy the last position to force the interpolation to behave correctly. */ this->rotations.push_back(rotations[rotations.size() - 1]); /* Preprocesses the sequence, selectively negating all quaternions. */ for (size_t ui = 1; ui < this->rotations.size(); ui++) if (this->rotations[ui].dot(this->rotations[ui - 1]) < 0.0) this->rotations[ui].negate(); /* Compute supports for the whole sequence, 0-th and n-th correspond to quaternions 0-th and n-th. */ supports.push_back(this->rotations[0]); for (size_t ui = 1; ui <= this->rotations.size()-2; ui++) supports.push_back( Support( this->rotations[ui - 1], this->rotations[ui + 0], this->rotations[ui + 1] ) ); supports.push_back(rotations[rotations.size() - 1]); 
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_tfloat uiprogress = size_t(float(rotations.size() - 12) * t; size_t ui = size_t(floor(progress));  t = progress - float(ui); assert(ui + 10 < rotations.size() - 1);   t = modassert(t,ui + 1.0 /< rotations.size()) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 1], supports[ui], supports[ui + 1], t ); } 

Hello everyone, I am trying to interpolate over a sequence of rotations represented by quaternions. I am currently employing Squad (Spherical and Quadrangle Interpolation). I successfully applied the function to 4 rotations and the results corresponded to the expected one.

RotationSequence( std::vector<Quaternion> rotations ) { if (rotations.size() < 4) throw std::runtime_error("Rotation sequence requires at least four rotations."); for (Quaternion rotation : rotations) this->rotations.push_back(rotation); /* Preprocesses the sequence, selectively negating all quaternions. */ for (size_t ui = 1; ui < this->rotations.size(); ui++) if (this->rotations[ui].dot(this->rotations[ui - 1]) < 0.0) this->rotations[ui].negate(); /* Compute supports for the whole sequence, 0-th and n-th correspond to quaternions 0-th and n-th. */ supports.push_back(this->rotations[0]); for (size_t ui = 1; ui <= this->rotations.size()-2; ui++) supports.push_back( Support( this->rotations[ui - 1], this->rotations[ui + 0], this->rotations[ui + 1] ) ); supports.push_back(rotations[rotations.size() - 1]); 
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1);   t = mod(t, 1.0 / rotations.size()) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 1], supports[ui], supports[ui + 1], t ); } 

I am trying to interpolate over a sequence of rotations represented by quaternions. I am currently employing Squad (Spherical and Quadrangle Interpolation). I successfully applied the function to 4 rotations and the results corresponded to the expected one.

RotationSequence( std::vector<Quaternion> rotations ) { if (rotations.size() < 4) throw std::runtime_error("Rotation sequence requires at least four rotations."); for (Quaternion rotation : rotations) this->rotations.push_back(rotation); /* Copy the last position to force the interpolation to behave correctly. */ this->rotations.push_back(rotations[rotations.size() - 1]); /* Preprocesses the sequence, selectively negating all quaternions. */ for (size_t ui = 1; ui < this->rotations.size(); ui++) if (this->rotations[ui].dot(this->rotations[ui - 1]) < 0.0) this->rotations[ui].negate(); /* Compute supports for the whole sequence, 0-th and n-th correspond to quaternions 0-th and n-th. */ supports.push_back(this->rotations[0]); for (size_t ui = 1; ui <= this->rotations.size()-2; ui++) supports.push_back( Support( this->rotations[ui - 1], this->rotations[ui + 0], this->rotations[ui + 1] ) ); supports.push_back(rotations[rotations.size() - 1]); 
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ float progress = float(rotations.size() - 2) * t; size_t ui = size_t(floor(progress));  t = progress - float(ui); assert(ui + 0 < rotations.size()); assert(ui + 1 < rotations.size()); return Squad( rotations[ui], rotations[ui + 1], supports[ui], supports[ui + 1], t ); } 
Became Hot Network Question
edited body
Source Link
Chaos
  • 153
  • 8
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1); t = mod(t, static_cast(1.0 / rotations.size())) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 3]1], supports[ui], supports[ui + 1], t ); } 
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1); t = mod(t, static_cast(1.0 / rotations.size())) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 3], supports[ui], supports[ui + 1], t ); } 
Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1); t = mod(t, 1.0 / rotations.size()) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 1], supports[ui], supports[ui + 1], t ); } 
added 3576 characters in body
Source Link
Chaos
  • 153
  • 8

Edit: I am sharing part of the code, perhaps the problem is strictly practical.

Slerp:

static Quaternion Slerp(Quaternion &lhs, Quaternion &rhs, float t, TM_BOOL invert = true) { t = Unit(t); // Clamps in range 0..1. if (t < 1e-20) return lhs; if (t > 1.0 - 1e-20) return rhs; if (lhs == rhs) return lhs; if (lhs == -rhs) return lhs; float dot = lhs.dot(rhs); if (abs(dot) >= 0.9999999) { if (dot >= 0.0) return Lerp(lhs, rhs, t).normalize(); else return Lerp(lhs, -rhs, t).normalize(); } else { float tetha = acos(dot); if (!invert) return (lhs * sin(tetha * (1.0 - t)) + rhs * sin(tetha * t)) / sin(tetha); else { if (dot >= 0.0) return (lhs * sin(tetha * (1.0 - t)) + rhs * sin(tetha * t)) / sin(tetha); else return (lhs * sin(tetha * (1.0 - t)) + (-rhs) * sin(tetha * t)) / sin(tetha); } } } 

Squad:

static Quaternion Squad( Quaternion &start, Quaternion &end, Quaternion &firstSupport, Quaternion &secondSupport, float t ) { t = Unit(t); return Slerp( Slerp(start, end, t, false), Slerp(firstSupport, secondSupport, t, false), 2.0 * t * (1.0 - t), false ); } 

Squad with support:

static Quaternion Squad( Quaternion &q0, Quaternion &q1, Quaternion &q2, Quaternion &q3, float t ) { q1 = (q0 + q1).squaredMagnitude() < (q0 - q1).squaredMagnitude() ? -q1 : q1; q2 = (q1 + q2).squaredMagnitude() < (q1 - q2).squaredMagnitude() ? -q2 : q2; q3 = (q2 + q3).squaredMagnitude() < (q2 - q3).squaredMagnitude() ? -q3 : q3; Quaternion firstSupport = Support(q0, q1, q2), secondSupport = Support(q1, q2, q3); return Squad(q0, q3, firstSupport, secondSupport, t); } 

Support:

inline static Quaternion Support( Quaternion &previous, Quaternion &current, Quaternion &next ) { Quaternion inverseOfQuat = current.inverse(), leftProduct = inverseOfQuat * previous, rightProduct = inverseOfQuat * next, leftLog = leftProduct.log(), rightLog = rightProduct.log(), sum = leftLog + rightLog, param = -sum / 4.0, result = current * param.exp(); return result; } 

Rotation Sequence C'tor:

RotationSequence( std::vector<Quaternion> rotations ) { if (rotations.size() < 4) throw std::runtime_error("Rotation sequence requires at least four rotations."); for (Quaternion rotation : rotations) this->rotations.push_back(rotation); /* Preprocesses the sequence, selectively negating all quaternions. */ for (size_t ui = 1; ui < this->rotations.size(); ui++) if (this->rotations[ui].dot(this->rotations[ui - 1]) < 0.0) this->rotations[ui].negate(); /* Compute supports for the whole sequence, 0-th and n-th correspond to quaternions 0-th and n-th. */ supports.push_back(this->rotations[0]); for (size_t ui = 1; ui <= this->rotations.size()-2; ui++) supports.push_back( Support( this->rotations[ui - 1], this->rotations[ui + 0], this->rotations[ui + 1] ) ); supports.push_back(rotations[rotations.size() - 1]); 

Interpolation:

Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1); t = mod(t, static_cast(1.0 / rotations.size())) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 3], supports[ui], supports[ui + 1], t ); } 

Edit: I am sharing part of the code, perhaps the problem is strictly practical.

Slerp:

static Quaternion Slerp(Quaternion &lhs, Quaternion &rhs, float t, TM_BOOL invert = true) { t = Unit(t); // Clamps in range 0..1. if (t < 1e-20) return lhs; if (t > 1.0 - 1e-20) return rhs; if (lhs == rhs) return lhs; if (lhs == -rhs) return lhs; float dot = lhs.dot(rhs); if (abs(dot) >= 0.9999999) { if (dot >= 0.0) return Lerp(lhs, rhs, t).normalize(); else return Lerp(lhs, -rhs, t).normalize(); } else { float tetha = acos(dot); if (!invert) return (lhs * sin(tetha * (1.0 - t)) + rhs * sin(tetha * t)) / sin(tetha); else { if (dot >= 0.0) return (lhs * sin(tetha * (1.0 - t)) + rhs * sin(tetha * t)) / sin(tetha); else return (lhs * sin(tetha * (1.0 - t)) + (-rhs) * sin(tetha * t)) / sin(tetha); } } } 

Squad:

static Quaternion Squad( Quaternion &start, Quaternion &end, Quaternion &firstSupport, Quaternion &secondSupport, float t ) { t = Unit(t); return Slerp( Slerp(start, end, t, false), Slerp(firstSupport, secondSupport, t, false), 2.0 * t * (1.0 - t), false ); } 

Squad with support:

static Quaternion Squad( Quaternion &q0, Quaternion &q1, Quaternion &q2, Quaternion &q3, float t ) { q1 = (q0 + q1).squaredMagnitude() < (q0 - q1).squaredMagnitude() ? -q1 : q1; q2 = (q1 + q2).squaredMagnitude() < (q1 - q2).squaredMagnitude() ? -q2 : q2; q3 = (q2 + q3).squaredMagnitude() < (q2 - q3).squaredMagnitude() ? -q3 : q3; Quaternion firstSupport = Support(q0, q1, q2), secondSupport = Support(q1, q2, q3); return Squad(q0, q3, firstSupport, secondSupport, t); } 

Support:

inline static Quaternion Support( Quaternion &previous, Quaternion &current, Quaternion &next ) { Quaternion inverseOfQuat = current.inverse(), leftProduct = inverseOfQuat * previous, rightProduct = inverseOfQuat * next, leftLog = leftProduct.log(), rightLog = rightProduct.log(), sum = leftLog + rightLog, param = -sum / 4.0, result = current * param.exp(); return result; } 

Rotation Sequence C'tor:

RotationSequence( std::vector<Quaternion> rotations ) { if (rotations.size() < 4) throw std::runtime_error("Rotation sequence requires at least four rotations."); for (Quaternion rotation : rotations) this->rotations.push_back(rotation); /* Preprocesses the sequence, selectively negating all quaternions. */ for (size_t ui = 1; ui < this->rotations.size(); ui++) if (this->rotations[ui].dot(this->rotations[ui - 1]) < 0.0) this->rotations[ui].negate(); /* Compute supports for the whole sequence, 0-th and n-th correspond to quaternions 0-th and n-th. */ supports.push_back(this->rotations[0]); for (size_t ui = 1; ui <= this->rotations.size()-2; ui++) supports.push_back( Support( this->rotations[ui - 1], this->rotations[ui + 0], this->rotations[ui + 1] ) ); supports.push_back(rotations[rotations.size() - 1]); 

Interpolation:

Quaternion Interpolate( float t ) { t = Unit(t); /* Here, I identify the corresponding rotation by the $t$ factor. */ size_t ui = size_t(float(rotations.size() - 1) * t); assert(ui + 1 < rotations.size() - 1); t = mod(t, static_cast(1.0 / rotations.size())) * rotations.size();/* Computes mod(). */ return Squad( rotations[ui], rotations[ui + 3], supports[ui], supports[ui + 1], t ); } 
Source Link
Chaos
  • 153
  • 8
Loading