Merge branch 'feature/camera-path-fixes' into project/spaceship-installation

This commit is contained in:
Emma Broman
2021-12-09 13:36:46 +01:00
5 changed files with 58 additions and 34 deletions

View File

@@ -37,6 +37,7 @@
#include <openspace/query/query.h>
#include <openspace/util/collisionhelper.h>
#include <openspace/util/universalhelpers.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/interpolator.h>
@@ -235,51 +236,70 @@ glm::dquat Path::lookAtTargetsRotation(double t) const {
double Path::speedAlongPath(double traveledDistance) const {
const glm::dvec3 endNodePos = _end.node()->worldPosition();
const glm::dvec3 startNodePos = _start.node()->worldPosition();
const CameraPose prevPose = interpolatedPose(traveledDistance);
const double distanceToEndNode = glm::distance(prevPose.position, endNodePos);
const double distanceToStartNode = glm::distance(prevPose.position, startNodePos);
// Decide which is the closest node
SceneGraphNode* closestNode = _start.node();
glm::dvec3 closestPos = startNodePos;
if (distanceToEndNode < distanceToStartNode) {
closestPos = endNodePos;
closestNode = _end.node();
bool endNodeIsClosest = (distanceToEndNode < distanceToStartNode);
if (_start.nodeIdentifier() == _end.nodeIdentifier()) {
endNodeIsClosest = traveledDistance > (0.5 * pathLength());
}
const SceneGraphNode* closestNode = endNodeIsClosest ? _end.node() : _start.node();
const glm::dvec3 closestPos = closestNode->worldPosition();
const glm::dvec3 closestEdgePos =
endNodeIsClosest ? _end.position() : _start.position();
// Distance to the surface at the target position
const glm::dvec3 edgePosModelSpace = glm::dvec3(
glm::inverse(closestNode->modelTransform()) * glm::dvec4(closestEdgePos, 1.0)
);
const SurfacePositionHandle posHandle =
closestNode->calculateSurfacePositionHandle(edgePosModelSpace);
const glm::dvec3 centerToActualSurfaceModelSpace =
posHandle.centerToReferenceSurface +
posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface;
const glm::dvec3 centerToActualSurface =
glm::dmat3(closestNode->modelTransform()) * centerToActualSurfaceModelSpace;
// Compute speed based on distance to object surface
const double distanceToClosestNode = glm::distance(closestPos, prevPose.position);
double speed = distanceToClosestNode;
double distanceToSurface = distanceToClosestNode - glm::length(centerToActualSurface);
double speed = distanceToSurface;
// Dampen speed in beginning of path
double startUpDistance = 2.0 * _start.node()->boundingSphere();
if (startUpDistance < Epsilon) { // zero bounding sphere
startUpDistance = glm::distance(_start.position(), startNodePos);
const double edgePosToSurfaceDistance =
glm::distance(closestEdgePos, closestPos) - glm::length(centerToActualSurface);
// Dampen speed in beginning and end of path
double dampeningDistance = 2.0 * edgePosToSurfaceDistance;
// If the path is short, use another dampening approach, based on the boudningsphere
if (pathLength() < dampeningDistance) {
dampeningDistance = closestNode->boundingSphere();
}
if (traveledDistance < startUpDistance) {
speed *= traveledDistance / startUpDistance + 0.01;
}
// Buffer to prevent zero speed
constexpr const double buffer = 0.04;
// Dampen speed in end of path
// Note: this leads to problems when the full length of the path is really big
double closeUpDistance = 2.0 * _end.node()->boundingSphere();
if (closeUpDistance < Epsilon) { // zero bounding sphere
closeUpDistance = glm::distance(_end.position(), endNodePos);
if (traveledDistance < dampeningDistance) {
speed *= ghoul::sineEaseOut(traveledDistance / dampeningDistance) + buffer;
}
if (traveledDistance > (pathLength() - closeUpDistance)) {
const double remainingDistance = pathLength() - traveledDistance;
speed *= remainingDistance / closeUpDistance + 0.01;
else if (traveledDistance > (pathLength() - dampeningDistance)) {
double remainingDistance = pathLength() - traveledDistance;
// If the path length estimate is not completely correct, the remaining distance
// might be negative. Prevent that from causing problems with the speed.
if (remainingDistance < 0.0) {
remainingDistance = 0.1;
}
speed *= ghoul::sineEaseOut(remainingDistance / dampeningDistance) + buffer;
}
// TODO: also dampen speed based on curvature, or make sure the curve has a rounder
// shape
// TODO: check for when path is shorter than the starUpDistance or closeUpDistance
// variables
return _speedFactorFromDuration * speed;
}

View File

@@ -110,7 +110,7 @@ TEST_CASE("StringListProperty: Get Lua Value", "[stringlistproperty]") {
p.getLuaValue(L);
REQUIRE(ghoul::lua::luaValueToString(L, 1) ==
"{ 1.000000 = a, 2.000000 = b, 3.000000 = c }"
"{ [1] = \"a\", [2] = \"b\", [3] = \"c\" }"
);
}
@@ -221,7 +221,7 @@ TEST_CASE("IntListProperty: Get Lua Value", "[intlistproperty]") {
p.getLuaValue(L);
REQUIRE(ghoul::lua::luaValueToString(L, 1) ==
"{ 1.000000 = 1.000000, 2.000000 = 2.000000, 3.000000 = 3.000000 }"
"{ [1] = 1.000000, [2] = 2.000000, [3] = 3.000000 }"
);
}
@@ -332,7 +332,7 @@ TEST_CASE("DoubleListProperty: Get Lua Value", "[doublelistproperty]") {
p.getLuaValue(L);
REQUIRE(ghoul::lua::luaValueToString(L, 1) ==
"{ 1.000000 = 1.000000, 2.000000 = 2.000000, 3.000000 = 3.000000 }"
"{ [1] = 1.000000, [2] = 2.000000, [3] = 3.000000 }"
);
}

View File

@@ -60,7 +60,9 @@ TEST_CASE("CreateSingleColorImage: Faulty 1st input type", "[createsinglecolorim
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains("parameter 1 was not the expected type")
Catch::Matchers::Contains(
"Expected type 'String' for parameter 1 but got wrong type 'Table'"
)
);
}
@@ -71,7 +73,9 @@ TEST_CASE("CreateSingleColorImage: Faulty 2nd input type", "[createsinglecolorim
CHECK_THROWS_WITH(
openspace::luascriptfunctions::createSingleColorImage(L),
Catch::Matchers::Contains("parameter 2 was not the expected type")
Catch::Matchers::Contains(
"Expected type 'Table' for parameter 2 but got wrong type 'String'"
)
);
}