Refactor piecewise slerp a bit

This commit is contained in:
Emma Broman
2020-02-11 11:35:56 -05:00
parent 426b2006c2
commit ffe417823f
3 changed files with 33 additions and 29 deletions
+26 -29
View File
@@ -98,49 +98,46 @@ glm::dquat PathSegment::getRotationAt(double t) const {
}
}
// Interpolate between a number of keyframes for orientation using SLERP
const glm::dquat PathSegment::piecewiseSlerpRotation(double t) const {
// breakpoints for subintervals
const double t1 = 0.3;
const double t2 = 0.8; // TODO: these should probably be based on distance
glm::dvec3 posAtT1 = getPositionAt(t1);
glm::dvec3 posAtT2 = getPositionAt(t2);
std::vector<double> times{ 0.0, t1, t2, 1.0 };
glm::dvec3 startNodePos = sceneGraphNode(_start.referenceNode)->worldPosition();
glm::dvec3 endNodePos = sceneGraphNode(_end.referenceNode)->worldPosition();
glm::dvec3 startUpVec = _start.rotation * glm::dvec3(0.0, 1.0, 0.0);
glm::dmat4 lookAtStartMat = glm::lookAt(posAtT1, startNodePos, startUpVec);
glm::dquat lookAtStartQuad = glm::normalize(glm::inverse(glm::quat_cast(lookAtStartMat)));
glm::dvec3 endUpVec = _end.rotation * glm::dvec3(0.0, 1.0, 0.0);
glm::dmat4 lookAtEndMat = glm::lookAt(posAtT2, endNodePos, endUpVec);
glm::dquat lookAtEndQuad = glm::normalize(glm::inverse(glm::quat_cast(lookAtEndMat)));
// Interpolate based on the subintervals
double tScaled;
glm::dquat startQuad, endQuad;
glm::dquat lookAtStartQ =
helpers::getLookAtQuaternion(getPositionAt(t1), startNodePos, startUpVec);
if (t < t1) {
tScaled = t / t1;
startQuad = _start.rotation;
endQuad = lookAtStartQuad;
}
else if (t < t2) {
tScaled = (t - t1) / (t2 - t1);
startQuad = lookAtStartQuad;
endQuad = lookAtEndQuad;
}
else { // t <= 1.0
tScaled = (t - t2) / (1.0 - t2);
startQuad = lookAtEndQuad;
endQuad = _end.rotation;
glm::dquat lookAtEndQ =
helpers::getLookAtQuaternion(getPositionAt(t2), endNodePos, endUpVec);
std::vector<glm::dquat> keyframes{
_start.rotation,
lookAtStartQ,
lookAtEndQ,
_end.rotation
};
ghoul_assert(keyframes.size() == times.size(), "Must have one time value per keyframe.");
// Find the current segment and compute interpolation
glm::dquat result;
for (int i = 0; i < keyframes.size() - 1; ++i) {
if (t <= times[i + 1]) {
double tScaled = (t - times[i]) / (times[i + 1] - times[i]);
tScaled = ghoul::quadraticEaseInOut(tScaled);
result = glm::slerp(keyframes[i], keyframes[i + 1], tScaled);
break;
}
}
// TODO: experiment with easing functions
tScaled = ghoul::quadraticEaseInOut(tScaled);
return glm::slerp(startQuad, endQuad, tScaled);
return result;
}
// Initialise the curve, based on the start, end state and curve type