mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-14 01:10:11 -05:00
Minor cleanups
This commit is contained in:
@@ -45,59 +45,63 @@
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "AutoNavigationHandler";
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo DefaultCurveOptionInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo DefaultCurveOptionInfo = {
|
||||
"DefaultCurveOption",
|
||||
"Default Curve Option",
|
||||
"The defualt curve type chosen when generating a path, if none is specified."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo IncludeRollInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo IncludeRollInfo = {
|
||||
"IncludeRollInfo",
|
||||
"Include Roll",
|
||||
"If disabled, roll is removed from the interpolation of camera orientation."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo StopAtTargetsPerDefaultInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo StopAtTargetsPerDefaultInfo = {
|
||||
"StopAtTargetsPerDefault",
|
||||
"Stop At Targets Per Default",
|
||||
"Applied during path creation. If enabled, stops are automatically added between"
|
||||
" the path segments. The user must then choose to continue the path after reaching a target"
|
||||
"Applied during path creation. If enabled, stops are automatically added "
|
||||
"between the path segments. The user must then choose to continue the path "
|
||||
"after reaching a target"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo DefaultStopBehaviorInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo DefaultStopBehaviorInfo = {
|
||||
"DefaultStopBehavior",
|
||||
"Default Stop Behavior",
|
||||
"The default camera behavior that is applied when the camera reaches and stops at a target."
|
||||
"The default camera behavior that is applied when the camera reaches and stops "
|
||||
"at a target."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo ApplyStopBehaviorWhenIdleInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo ApplyStopBehaviorWhenIdleInfo = {
|
||||
"ApplyStopBehaviorWhenIdle",
|
||||
"Apply Stop Behavior When Idle",
|
||||
"If enabled, the camera is controlled using the default stop behavior even when no path is playing."
|
||||
"If enabled, the camera is controlled using the default stop behavior even when"
|
||||
"no path is playing."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo RelevantNodeTagsInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo RelevantNodeTagsInfo = {
|
||||
"RelevantNodeTags",
|
||||
"Relevant Node Tags",
|
||||
"List of tags for the nodes that are relevant for path creation, for example when avoiding collisions."
|
||||
"List of tags for the nodes that are relevant for path creation, for example "
|
||||
"when avoiding collisions."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo DefaultPositionOffsetAngleInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo DefaultPositionOffsetAngleInfo = {
|
||||
"DefaultPositionOffsetAngle",
|
||||
"Default Position Offset Angle",
|
||||
"Used for creating a default position at a target node. The angle (in degrees) "
|
||||
"specifies the deviation from the line connecting the target node and the sun, in "
|
||||
"the direction of the camera position at the start of the path."
|
||||
"specifies the deviation from the line connecting the target node and the sun, "
|
||||
"in the direction of the camera position at the start of the path."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo NumberSimulationStepsInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo NumberSimulationStepsInfo = {
|
||||
"NumberSimulationSteps",
|
||||
"Number Simulation Steps",
|
||||
"The number of steps used to simulate the camera motion, per frame. A larger number "
|
||||
"increases the precision, at the cost of reduced efficiency."
|
||||
"The number of steps used to simulate the camera motion, per frame. A larger "
|
||||
"number increases the precision, at the cost of reduced efficiency."
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo SpeedScaleInfo = {
|
||||
constexpr openspace::properties::Property::PropertyInfo SpeedScaleInfo = {
|
||||
"SpeedScale",
|
||||
"Speed Scale",
|
||||
"Scale factor that affects the default speed for a camera path."
|
||||
@@ -439,9 +443,12 @@ Waypoint AutoNavigationHandler::lastWayPoint() {
|
||||
}
|
||||
|
||||
void AutoNavigationHandler::removeRollRotation(CameraPose& pose, double deltaTime) {
|
||||
glm::dvec3 anchorPos = anchor()->worldPosition();
|
||||
const double notTooCloseDistance = deltaTime * glm::distance(anchorPos, pose.position);
|
||||
glm::dvec3 cameraDir = glm::normalize(pose.rotation * Camera::ViewDirectionCameraSpace);
|
||||
const glm::dvec3 anchorPos = anchor()->worldPosition();
|
||||
const glm::dvec3 cameraDir = glm::normalize(
|
||||
pose.rotation * Camera::ViewDirectionCameraSpace
|
||||
);
|
||||
const double anchorToPosDistance = glm::distance(anchorPos, pose.position);
|
||||
const double notTooCloseDistance = deltaTime * anchorToPosDistance;
|
||||
glm::dvec3 lookAtPos = pose.position + notTooCloseDistance * cameraDir;
|
||||
glm::dquat rollFreeRotation = helpers::getLookAtQuaternion(
|
||||
pose.position,
|
||||
@@ -623,7 +630,8 @@ Waypoint AutoNavigationHandler::computeDefaultWaypoint(const TargetNodeInstructi
|
||||
stepDirection = glm::normalize(nodePos - closeNode->worldPosition());
|
||||
}
|
||||
else {
|
||||
// Go to a point that is being lit up by the sun, slightly offsetted from sun direction
|
||||
// Go to a point that is being lit up by the sun, slightly offsetted from sun
|
||||
// direction
|
||||
const glm::dvec3 sunPos = glm::dvec3(0.0, 0.0, 0.0);
|
||||
const glm::dvec3 prevPos = lastWayPoint().position();
|
||||
const glm::dvec3 targetToPrev = prevPos - nodePos;
|
||||
|
||||
@@ -92,42 +92,47 @@ scripting::LuaLibrary AutoNavigationModule::luaLibrary() const {
|
||||
&autonavigation::luascriptfunctions::goTo,
|
||||
{},
|
||||
"string, [double]",
|
||||
"TODO: Description. Go to the node with the given name with optional duration."
|
||||
"Mov the camera to the node with the specified. The optional parameter "
|
||||
"specifies the duration of the motion."
|
||||
},
|
||||
{
|
||||
"generatePath",
|
||||
&autonavigation::luascriptfunctions::generatePath,
|
||||
{},
|
||||
"table",
|
||||
"Generate the path as described by the lua table input argument. TODO: Describe how a path instruction is defined?. "
|
||||
"Generate the path as described by the lua table input argument. "
|
||||
},
|
||||
{
|
||||
"generatePathFromFile",
|
||||
&autonavigation::luascriptfunctions::generatePathFromFile,
|
||||
{},
|
||||
"string",
|
||||
"Read an input file with lua instructions and use those to generate a camera path. TODO: Describe how a path instruction is defined?. "
|
||||
"Read an input file with lua instructions and use those to generate a camera "
|
||||
"path. "
|
||||
},
|
||||
{
|
||||
"getPathPositions",
|
||||
&autonavigation::luascriptfunctions::getPathPositions,
|
||||
{},
|
||||
"number",
|
||||
"FOR DEBUG. Sample positions along the path. The input argument is the number of samples per path segment. "
|
||||
"FOR DEBUG. Sample positions along the path. The input argument is the "
|
||||
"number of samples per path segment. "
|
||||
},
|
||||
{
|
||||
"getPathOrientations",
|
||||
&autonavigation::luascriptfunctions::getPathOrientations,
|
||||
{},
|
||||
"number",
|
||||
"FOR DEBUG. Sample orientations along the path. The input argument is the number of samples per path segment. "
|
||||
"FOR DEBUG. Sample orientations along the path. The input argument is the "
|
||||
"number of samples per path segment. "
|
||||
},
|
||||
{
|
||||
"getPathViewDirections",
|
||||
&autonavigation::luascriptfunctions::getPathViewDirections,
|
||||
{},
|
||||
"number",
|
||||
"FOR DEBUG. Sample view directions along the path. The input argument is the number of samples per path segment. "
|
||||
"FOR DEBUG. Sample view directions along the path. The input argument is "
|
||||
"the number of samples per path segment. "
|
||||
},
|
||||
{
|
||||
"getControlPoints",
|
||||
|
||||
@@ -39,275 +39,276 @@
|
||||
|
||||
namespace openspace::autonavigation::luascriptfunctions {
|
||||
|
||||
const double EPSILON = 1e-12;
|
||||
const double EPSILON = 1e-12;
|
||||
|
||||
int continuePath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath");
|
||||
int continuePath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath");
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.continuePath();
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.continuePath();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stopPath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath");
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.abortPath();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goTo(lua_State* L) {
|
||||
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::goTo");
|
||||
|
||||
const std::string& nodeIdentifier = ghoul::lua::value<std::string>(L, 1);
|
||||
|
||||
if (!sceneGraphNode(nodeIdentifier)) {
|
||||
lua_settop(L, 0);
|
||||
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
|
||||
}
|
||||
|
||||
int stopPath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath");
|
||||
ghoul::Dictionary insDict;
|
||||
insDict.setValue("Target", nodeIdentifier);
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.abortPath();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goTo(lua_State* L) {
|
||||
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::goTo");
|
||||
|
||||
const std::string& nodeIdentifier = ghoul::lua::value<std::string>(L, 1);
|
||||
|
||||
if (!sceneGraphNode(nodeIdentifier)) {
|
||||
if (nArguments > 1) {
|
||||
double duration = ghoul::lua::value<double>(L, 2);
|
||||
if (duration <= EPSILON) {
|
||||
lua_settop(L, 0);
|
||||
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
|
||||
return ghoul::lua::luaError(L, "Duration must be larger than zero.");
|
||||
}
|
||||
|
||||
ghoul::Dictionary insDict;
|
||||
insDict.setValue("Target", nodeIdentifier);
|
||||
|
||||
if (nArguments > 1) {
|
||||
double duration = ghoul::lua::value<double>(L, 2);
|
||||
if (duration <= EPSILON) {
|
||||
lua_settop(L, 0);
|
||||
return ghoul::lua::luaError(L, "Duration must be larger than zero.");
|
||||
}
|
||||
insDict.setValue("Duration", duration);
|
||||
}
|
||||
|
||||
PathSpecification spec = PathSpecification(TargetNodeInstruction{insDict});
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
|
||||
lua_settop(L, 0);
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
insDict.setValue("Duration", duration);
|
||||
}
|
||||
|
||||
int generatePath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePath");
|
||||
PathSpecification spec = PathSpecification(TargetNodeInstruction{insDict});
|
||||
|
||||
ghoul::Dictionary dictionary;
|
||||
ghoul::lua::luaDictionaryFromState(L, dictionary);
|
||||
PathSpecification spec(dictionary);
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
|
||||
if (spec.instructions()->empty()) {
|
||||
lua_settop(L, 0);
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("No instructions for camera path generation were provided.")
|
||||
);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
int generatePath(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePath");
|
||||
|
||||
ghoul::Dictionary dictionary;
|
||||
ghoul::lua::luaDictionaryFromState(L, dictionary);
|
||||
PathSpecification spec(dictionary);
|
||||
|
||||
if (spec.instructions()->empty()) {
|
||||
lua_settop(L, 0);
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("No instructions for camera path generation were provided.")
|
||||
);
|
||||
}
|
||||
|
||||
int generatePathFromFile(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePathFromFile");
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
|
||||
const std::string& filepath = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
|
||||
lua_settop(L, 0);
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filepath.empty()) {
|
||||
return ghoul::lua::luaError(L, "filepath string is empty");
|
||||
}
|
||||
int generatePathFromFile(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePathFromFile");
|
||||
|
||||
const std::string absolutePath = absPath(filepath);
|
||||
const std::string& filepath = ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::Yes);
|
||||
|
||||
LINFOC("AutoNavigationModule", fmt::format("Reading path instructions from file: {}", absolutePath));
|
||||
|
||||
if (!FileSys.fileExists(absolutePath)) {
|
||||
throw ghoul::FileNotFoundError(absolutePath, "PathSpecification");
|
||||
}
|
||||
|
||||
// Try to read the dictionary
|
||||
ghoul::Dictionary dictionary;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(absolutePath, dictionary);
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
PathSpecification::Documentation(),
|
||||
dictionary,
|
||||
"PathSpecification"
|
||||
);
|
||||
}
|
||||
catch (ghoul::RuntimeError& e) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("Unable to read dictionary from file: {}", e.message)
|
||||
);
|
||||
}
|
||||
|
||||
PathSpecification spec(dictionary);
|
||||
|
||||
if (spec.instructions()->empty()) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("No instructions for camera path generation were provided.")
|
||||
);
|
||||
}
|
||||
|
||||
LINFOC("AutoNavigationModule", "Reading succeeded. Creating path");
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
if (filepath.empty()) {
|
||||
return ghoul::lua::luaError(L, "filepath string is empty");
|
||||
}
|
||||
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathPositions(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathPositions");
|
||||
const std::string absolutePath = absPath(filepath);
|
||||
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
LINFOC("AutoNavigationModule", fmt::format(
|
||||
"Reading path instructions from file: {}", absolutePath
|
||||
));
|
||||
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> points = handler.getCurvePositions(pointsPerSegment);
|
||||
if (!FileSys.fileExists(absolutePath)) {
|
||||
throw ghoul::FileNotFoundError(absolutePath, "PathSpecification");
|
||||
}
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
// Try to read the dictionary
|
||||
ghoul::Dictionary dictionary;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(absolutePath, dictionary);
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
PathSpecification::Documentation(),
|
||||
dictionary,
|
||||
"PathSpecification"
|
||||
);
|
||||
}
|
||||
catch (ghoul::RuntimeError& e) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("Unable to read dictionary from file: {}", e.message)
|
||||
);
|
||||
}
|
||||
|
||||
PathSpecification spec(dictionary);
|
||||
|
||||
if (spec.instructions()->empty()) {
|
||||
return ghoul::lua::luaError(
|
||||
L, fmt::format("No instructions for camera path generation were provided.")
|
||||
);
|
||||
}
|
||||
|
||||
LINFOC("AutoNavigationModule", "Reading succeeded. Creating path");
|
||||
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
handler.createPath(spec);
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathPositions(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathPositions");
|
||||
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> points = handler.getCurvePositions(pointsPerSegment);
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
ghoul::lua::push(L, i+1);
|
||||
pushVector(L, points[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
ghoul::lua::push(L, i+1);
|
||||
pushVector(L, points[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathOrientations(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathPositions");
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathOrientations(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathPositions");
|
||||
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dquat> orientations = handler.getCurveOrientations(pointsPerSegment);
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
|
||||
// Push the rotation to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dquat& v) {
|
||||
lua_newtable(L);
|
||||
ghoul::lua::push(L, 1, v.w);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 2, v.x);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 3, v.y);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 4, v.z);
|
||||
lua_rawset(L, -4);
|
||||
};
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dquat> orientations = handler.getCurveOrientations(pointsPerSegment);
|
||||
|
||||
// Push the rotation to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dquat& v) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < orientations.size(); ++i) {
|
||||
ghoul::lua::push(L, i + 1);
|
||||
pushVector(L, orientations[i]);
|
||||
lua_rawset(L, -4);
|
||||
}
|
||||
ghoul::lua::push(L, 1, v.w);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 2, v.x);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 3, v.y);
|
||||
lua_rawset(L, -4);
|
||||
ghoul::lua::push(L, 4, v.z);
|
||||
lua_rawset(L, -4);
|
||||
};
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < orientations.size(); ++i) {
|
||||
ghoul::lua::push(L, i + 1);
|
||||
pushVector(L, orientations[i]);
|
||||
lua_rawset(L, -4);
|
||||
}
|
||||
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathViewDirections(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathViewDirections");
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendereable path
|
||||
int getPathViewDirections(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getPathViewDirections");
|
||||
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> viewDirections = handler.getCurveViewDirections(pointsPerSegment);
|
||||
const int pointsPerSegment = (int)ghoul::lua::value<lua_Number>(L, 1);
|
||||
|
||||
// Push the rotation to the Lua stack:
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> viewDirections = handler.getCurveViewDirections(pointsPerSegment);
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < viewDirections.size(); ++i) {
|
||||
ghoul::lua::push(L, i + 1);
|
||||
pushVector(L, viewDirections[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
// Push the rotation to the Lua stack:
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < viewDirections.size(); ++i) {
|
||||
ghoul::lua::push(L, i + 1);
|
||||
pushVector(L, viewDirections[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendering of control points
|
||||
int getControlPoints(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getControlPoints");
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> points = handler.getControlPoints();
|
||||
// TODO: remove when not needed
|
||||
// Created for debugging. Access info for rendering of control points
|
||||
int getControlPoints(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getControlPoints");
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
// Get sample positions from the current curve
|
||||
AutoNavigationModule* module = global::moduleEngine->module<AutoNavigationModule>();
|
||||
AutoNavigationHandler& handler = module->AutoNavigationHandler();
|
||||
std::vector<glm::dvec3> points = handler.getControlPoints();
|
||||
|
||||
// Push the points to the Lua stack:
|
||||
lua_settop(L, 0);
|
||||
const auto pushVector = [](lua_State* L, const glm::dvec3& v) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
ghoul::lua::push(L, i+1);
|
||||
pushVector(L, points[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
ghoul::lua::push(L, 1, v.x);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 2, v.y);
|
||||
lua_rawset(L, -3);
|
||||
ghoul::lua::push(L, 3, v.z);
|
||||
lua_rawset(L, -3);
|
||||
};
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < points.size(); ++i) {
|
||||
ghoul::lua::push(L, i+1);
|
||||
pushVector(L, points[i]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack");
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // namespace openspace::autonavigation::luascriptfunctions
|
||||
|
||||
@@ -84,7 +84,6 @@ AvoidCollisionCurve::AvoidCollisionCurve(const Waypoint& start, const Waypoint&
|
||||
double cosAngleToTarget = glm::dot(normalize(-startViewDirection), normalize(startToEnd));
|
||||
bool targetInOppositeDirection = cosAngleToTarget > 0.7;
|
||||
|
||||
// TODO: reduce magical numbers / create constants
|
||||
if (targetInOppositeDirection) {
|
||||
glm::dquat midleRotation = glm::slerp(start.rotation(), end.rotation(), 0.5);
|
||||
glm::dvec3 middleViewDirection = midleRotation * glm::dvec3(0.0, 0.0, -1.0);
|
||||
|
||||
@@ -98,9 +98,10 @@ namespace openspace::autonavigation::helpers {
|
||||
|
||||
namespace openspace::autonavigation::interpolation {
|
||||
|
||||
// Based on implementation by Mika Rantanen https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
|
||||
// Based on implementation by Mika Rantanen
|
||||
// https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
|
||||
glm::dvec3 catmullRom(double t, const glm::dvec3& p0, const glm::dvec3& p1,
|
||||
const glm::dvec3& p2, const glm::dvec3& p3, double alpha)
|
||||
const glm::dvec3& p2, const glm::dvec3& p3, double alpha)
|
||||
{
|
||||
glm::dvec3 m01, m02, m23, m13;
|
||||
|
||||
@@ -121,15 +122,14 @@ namespace openspace::autonavigation::interpolation {
|
||||
glm::dvec3 c = m1;
|
||||
glm::dvec3 d = p1;
|
||||
|
||||
return
|
||||
a * t * t * t +
|
||||
b * t * t +
|
||||
c * t +
|
||||
d;
|
||||
return a * t * t * t
|
||||
+ b * t * t
|
||||
+ c * t
|
||||
+ d;
|
||||
}
|
||||
|
||||
glm::dvec3 cubicBezier(double t, const glm::dvec3& cp1, const glm::dvec3& cp2,
|
||||
const glm::dvec3& cp3, const glm::dvec3& cp4)
|
||||
const glm::dvec3& cp3, const glm::dvec3& cp4)
|
||||
{
|
||||
ghoul_assert(t >= 0 && t <= 1.0, "Interpolation variable out of range [0, 1]");
|
||||
|
||||
@@ -157,9 +157,9 @@ namespace openspace::autonavigation::interpolation {
|
||||
const double t3 = t2 * t;
|
||||
|
||||
// calculate basis functions
|
||||
double const a0 = (2.0*t3) - (3.0*t2) + 1.0;
|
||||
double const a1 = (-2.0*t3) + (3.0*t2);
|
||||
double const b0 = t3 - (2.0*t2) + t;
|
||||
double const a0 = (2.0 * t3) - (3.0 * t2) + 1.0;
|
||||
double const a1 = (-2.0 * t3) + (3.0 * t2);
|
||||
double const b0 = t3 - (2.0 * t2) + t;
|
||||
double const b1 = t3 - t2;
|
||||
|
||||
return (a0 * p1) + (a1 * p2) + (b0 * tangent1) + (b1 * tangent2);
|
||||
@@ -167,7 +167,7 @@ namespace openspace::autonavigation::interpolation {
|
||||
|
||||
// uniform if tKnots are equally spaced, or else non uniform
|
||||
glm::dvec3 piecewiseCubicBezier(double t, const std::vector<glm::dvec3>& points,
|
||||
const std::vector<double>& tKnots)
|
||||
const std::vector<double>& tKnots)
|
||||
{
|
||||
ghoul_assert(points.size() > 4, "Minimum of four control points needed for interpolation!");
|
||||
ghoul_assert((points.size() - 1) % 3 == 0, "A vector containing 3n + 1 control points must be provided!");
|
||||
@@ -189,12 +189,17 @@ namespace openspace::autonavigation::interpolation {
|
||||
unsigned int idx = segmentIdx * 3;
|
||||
|
||||
// Interpolate using De Casteljau's algorithm
|
||||
return interpolation::cubicBezier(tScaled, points[idx], points[idx + 1],
|
||||
points[idx + 2], points[idx + 3]);
|
||||
return interpolation::cubicBezier(
|
||||
tScaled,
|
||||
points[idx],
|
||||
points[idx + 1],
|
||||
points[idx + 2],
|
||||
points[idx + 3]
|
||||
);
|
||||
}
|
||||
|
||||
glm::dvec3 piecewiseLinear(double t, const std::vector<glm::dvec3>& points,
|
||||
const std::vector<double>& tKnots)
|
||||
const std::vector<double>& tKnots)
|
||||
{
|
||||
ghoul_assert(points.size() == tKnots.size(), "Must have equal number of points and times!");
|
||||
ghoul_assert(points.size() > 2, "Minimum of two control points needed for interpolation!");
|
||||
|
||||
@@ -152,8 +152,8 @@ documentation::Documentation PathSpecification::Documentation() {
|
||||
|
||||
// create correct type of instruction and present and throw error with useful
|
||||
// error message if we failed.
|
||||
void PathSpecification::tryReadInstruction(int index, std::string type,
|
||||
ghoul::Dictionary& dictionary)
|
||||
void PathSpecification::tryReadInstruction(int index, const std::string& type,
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
if (type == KeyTypeTargetNode) {
|
||||
try {
|
||||
|
||||
@@ -52,13 +52,12 @@ public:
|
||||
const bool hasStartState() const;
|
||||
|
||||
private:
|
||||
void tryReadInstruction(int index, std::string type, ghoul::Dictionary& dictionary);
|
||||
void tryReadInstruction(int index, const std::string& type,
|
||||
const ghoul::Dictionary& dictionary);
|
||||
|
||||
std::vector<std::unique_ptr<Instruction>> _instructions;
|
||||
std::optional<bool> _stopAtTargets;
|
||||
std::optional<NavigationState> _startState;
|
||||
|
||||
// TODO: maxSpeed or speedFactor or something?
|
||||
};
|
||||
|
||||
} // namespace openspace::autonavigation
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace {
|
||||
|
||||
namespace openspace::autonavigation {
|
||||
|
||||
WaypointNodeDetails::WaypointNodeDetails(const std::string nodeIdentifier) {
|
||||
WaypointNodeDetails::WaypointNodeDetails(const std::string& nodeIdentifier) {
|
||||
const SceneGraphNode* node = sceneGraphNode(nodeIdentifier);
|
||||
if (!node) {
|
||||
LERROR(fmt::format("Could not find node '{}'.", nodeIdentifier));
|
||||
@@ -54,7 +54,6 @@ double WaypointNodeDetails::findValidBoundingSphere(const SceneGraphNode* node)
|
||||
global::moduleEngine->module<AutoNavigationModule>()->minValidBoundingSphere();
|
||||
|
||||
if (bs < minValidBoundingSphere) {
|
||||
|
||||
// If the bs of the target is too small, try to find a good value in a child node.
|
||||
// Only check the closest children, to avoid deep traversal in the scene graph.
|
||||
// Also, the possibility to find a bounding sphere represents the visual size of
|
||||
|
||||
@@ -39,12 +39,12 @@ struct CameraPose {
|
||||
// The waypoint node is the anchor or target node.
|
||||
struct WaypointNodeDetails {
|
||||
WaypointNodeDetails() = default;
|
||||
WaypointNodeDetails(const std::string nodeIdentifier);
|
||||
WaypointNodeDetails(const std::string& nodeIdentifier);
|
||||
|
||||
static double findValidBoundingSphere(const SceneGraphNode* node);
|
||||
|
||||
std::string identifier;
|
||||
double validBoundingSphere; // to be able to handle nodes with faulty bounding spheres
|
||||
double validBoundingSphere = 0.0; // to be able to handle nodes with faulty bounding spheres
|
||||
};
|
||||
|
||||
struct Waypoint {
|
||||
|
||||
Reference in New Issue
Block a user