mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-22 19:29:04 -05:00
Refactor piecewise slerp a bit
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user