mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-10 13:40:08 -06:00
Merging Master
This commit is contained in:
@@ -27,14 +27,17 @@
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/interaction/orbitalnavigator.h>
|
||||
#include <openspace/interaction/keyframenavigator.h>
|
||||
#include <openspace/interaction/inputstate.h>
|
||||
#include <openspace/network/parallelpeer.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionaryluaformatter.h>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
@@ -43,7 +46,11 @@ namespace {
|
||||
constexpr const char* KeyAnchor = "Anchor";
|
||||
constexpr const char* KeyAim = "Aim";
|
||||
constexpr const char* KeyPosition = "Position";
|
||||
constexpr const char* KeyRotation = "Rotation";
|
||||
constexpr const char* KeyUp = "Up";
|
||||
constexpr const char* KeyYaw = "Yaw";
|
||||
constexpr const char* KeyPitch = "Pitch";
|
||||
constexpr const char* KeyReferenceFrame = "ReferenceFrame";
|
||||
const double Epsilon = 1E-7;
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo KeyFrameInfo = {
|
||||
"UseKeyFrameInteraction",
|
||||
@@ -51,24 +58,101 @@ namespace {
|
||||
"If this is set to 'true' the entire interaction is based off key frames rather "
|
||||
"than using the mouse interaction."
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "navigationhandler_lua.inl"
|
||||
|
||||
namespace openspace::interaction {
|
||||
|
||||
|
||||
ghoul::Dictionary
|
||||
openspace::interaction::NavigationHandler::NavigationState::dictionary() const
|
||||
{
|
||||
ghoul::Dictionary cameraDict;
|
||||
cameraDict.setValue(KeyPosition, position);
|
||||
cameraDict.setValue(KeyAnchor, anchor);
|
||||
|
||||
if (anchor != referenceFrame) {
|
||||
cameraDict.setValue(KeyReferenceFrame, referenceFrame);
|
||||
}
|
||||
if (!aim.empty()) {
|
||||
cameraDict.setValue(KeyAim, aim);
|
||||
}
|
||||
if (up.has_value()) {
|
||||
cameraDict.setValue(KeyUp, up.value());
|
||||
|
||||
if (std::abs(yaw) > Epsilon) {
|
||||
cameraDict.setValue(KeyYaw, yaw);
|
||||
}
|
||||
if (std::abs(pitch) > Epsilon) {
|
||||
cameraDict.setValue(KeyPitch, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
return cameraDict;
|
||||
}
|
||||
|
||||
openspace::interaction::NavigationHandler::NavigationState::NavigationState(
|
||||
const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
const bool hasAnchor = dictionary.hasValue<std::string>(KeyAnchor);
|
||||
const bool hasPosition = dictionary.hasValue<glm::dvec3>(KeyPosition);
|
||||
if (!hasAnchor || !hasPosition) {
|
||||
throw ghoul::RuntimeError(
|
||||
"Position and Anchor need to be defined for navigation dictionary."
|
||||
);
|
||||
}
|
||||
|
||||
anchor = dictionary.value<std::string>(KeyAnchor);
|
||||
position = dictionary.value<glm::dvec3>(KeyPosition);
|
||||
|
||||
if (dictionary.hasValue<std::string>(KeyReferenceFrame)) {
|
||||
referenceFrame = dictionary.value<std::string>(KeyReferenceFrame);
|
||||
}
|
||||
else {
|
||||
referenceFrame = anchor;
|
||||
}
|
||||
if (dictionary.hasValue<std::string>(KeyAim)) {
|
||||
aim = dictionary.value<std::string>(KeyAim);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<glm::dvec3>(KeyUp)) {
|
||||
up = dictionary.value<glm::dvec3>(KeyUp);
|
||||
|
||||
if (dictionary.hasValue<double>(KeyYaw)) {
|
||||
yaw = dictionary.value<double>(KeyYaw);
|
||||
}
|
||||
if (dictionary.hasValue<double>(KeyPitch)) {
|
||||
pitch = dictionary.value<double>(KeyPitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openspace::interaction::NavigationHandler::NavigationState::NavigationState(
|
||||
std::string anchor,
|
||||
std::string aim,
|
||||
std::string referenceFrame,
|
||||
glm::dvec3 position,
|
||||
std::optional<glm::dvec3> up,
|
||||
double yaw,
|
||||
double pitch)
|
||||
: anchor(std::move(anchor))
|
||||
, aim(std::move(aim))
|
||||
, referenceFrame(std::move(referenceFrame))
|
||||
, position(std::move(position))
|
||||
, up(std::move(up))
|
||||
, yaw(yaw)
|
||||
, pitch(pitch)
|
||||
{}
|
||||
|
||||
NavigationHandler::NavigationHandler()
|
||||
: properties::PropertyOwner({ "NavigationHandler" })
|
||||
, _useKeyFrameInteraction(KeyFrameInfo, false)
|
||||
{
|
||||
|
||||
_inputState = std::make_unique<InputState>();
|
||||
_orbitalNavigator = std::make_unique<OrbitalNavigator>();
|
||||
_keyframeNavigator = std::make_unique<KeyframeNavigator>();
|
||||
|
||||
// Add the properties
|
||||
addProperty(_useKeyFrameInteraction);
|
||||
addPropertySubOwner(*_orbitalNavigator);
|
||||
addPropertySubOwner(_orbitalNavigator);
|
||||
}
|
||||
|
||||
NavigationHandler::~NavigationHandler() {} // NOLINT
|
||||
@@ -90,19 +174,25 @@ void NavigationHandler::deinitialize() {
|
||||
|
||||
void NavigationHandler::setCamera(Camera* camera) {
|
||||
_camera = camera;
|
||||
_orbitalNavigator->setCamera(camera);
|
||||
_orbitalNavigator.setCamera(camera);
|
||||
}
|
||||
|
||||
const OrbitalNavigator& NavigationHandler::orbitalNavigator() const {
|
||||
return *_orbitalNavigator;
|
||||
void NavigationHandler::setNavigationStateNextFrame(
|
||||
NavigationHandler::NavigationState state)
|
||||
{
|
||||
_pendingNavigationState = std::move(state);
|
||||
}
|
||||
|
||||
OrbitalNavigator& NavigationHandler::orbitalNavigator() {
|
||||
return *_orbitalNavigator;
|
||||
return _orbitalNavigator;
|
||||
}
|
||||
|
||||
KeyframeNavigator& NavigationHandler::keyframeNavigator() const {
|
||||
return *_keyframeNavigator;
|
||||
const OrbitalNavigator& NavigationHandler::orbitalNavigator() const {
|
||||
return _orbitalNavigator;
|
||||
}
|
||||
|
||||
KeyframeNavigator& NavigationHandler::keyframeNavigator() {
|
||||
return _keyframeNavigator;
|
||||
}
|
||||
|
||||
bool NavigationHandler::isKeyFrameInteractionEnabled() const {
|
||||
@@ -110,33 +200,93 @@ bool NavigationHandler::isKeyFrameInteractionEnabled() const {
|
||||
}
|
||||
|
||||
float NavigationHandler::interpolationTime() const {
|
||||
return _orbitalNavigator->retargetInterpolationTime();
|
||||
return _orbitalNavigator.retargetInterpolationTime();
|
||||
}
|
||||
|
||||
void NavigationHandler::setInterpolationTime(float durationInSeconds) {
|
||||
_orbitalNavigator->setRetargetInterpolationTime(durationInSeconds);
|
||||
_orbitalNavigator.setRetargetInterpolationTime(durationInSeconds);
|
||||
}
|
||||
|
||||
void NavigationHandler::updateCamera(double deltaTime) {
|
||||
ghoul_assert(_inputState != nullptr, "InputState must not be nullptr");
|
||||
ghoul_assert(_camera != nullptr, "Camera must not be nullptr");
|
||||
|
||||
if (_cameraUpdatedFromScript) {
|
||||
_cameraUpdatedFromScript = false;
|
||||
}
|
||||
else {
|
||||
if (!_playbackModeEnabled && _camera) {
|
||||
if (_useKeyFrameInteraction) {
|
||||
_keyframeNavigator->updateCamera(*_camera, _playbackModeEnabled);
|
||||
}
|
||||
else {
|
||||
_orbitalNavigator->updateStatesFromInput(*_inputState, deltaTime);
|
||||
_orbitalNavigator->updateCameraStateFromStates(deltaTime);
|
||||
}
|
||||
if (_pendingNavigationState.has_value()) {
|
||||
applyNavigationState(_pendingNavigationState.value());
|
||||
_orbitalNavigator.resetVelocities();
|
||||
_pendingNavigationState.reset();
|
||||
} else if (!_playbackModeEnabled && _camera) {
|
||||
if (_useKeyFrameInteraction) {
|
||||
_keyframeNavigator.updateCamera(*_camera, _playbackModeEnabled);
|
||||
}
|
||||
else {
|
||||
_orbitalNavigator.updateStatesFromInput(_inputState, deltaTime);
|
||||
_orbitalNavigator.updateCameraStateFromStates(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationHandler::applyNavigationState(const NavigationHandler::NavigationState& ns)
|
||||
{
|
||||
const SceneGraphNode* referenceFrame = sceneGraphNode(ns.referenceFrame);
|
||||
const SceneGraphNode* anchor = sceneGraphNode(ns.anchor);
|
||||
|
||||
if (!anchor) {
|
||||
LERROR(fmt::format(
|
||||
"Could not find scene graph node '{}' used as anchor.", ns.referenceFrame
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (!ns.aim.empty() && !sceneGraphNode(ns.aim)) {
|
||||
LERROR(fmt::format(
|
||||
"Could not find scene graph node '{}' used as aim.", ns.referenceFrame
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (!referenceFrame) {
|
||||
LERROR(fmt::format(
|
||||
"Could not find scene graph node '{}' used as reference frame.",
|
||||
ns.referenceFrame)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::dvec3 anchorWorldPosition = anchor->worldPosition();
|
||||
const glm::dmat3 referenceFrameTransform = referenceFrame->worldRotationMatrix();
|
||||
|
||||
_orbitalNavigator.setAnchorNode(ns.anchor);
|
||||
_orbitalNavigator.setAimNode(ns.aim);
|
||||
|
||||
const SceneGraphNode* anchorNode = _orbitalNavigator.anchorNode();
|
||||
const SceneGraphNode* aimNode = _orbitalNavigator.aimNode();
|
||||
if (!aimNode) {
|
||||
aimNode = anchorNode;
|
||||
}
|
||||
|
||||
const glm::dvec3 cameraPositionWorld = anchorWorldPosition +
|
||||
glm::dvec3(referenceFrameTransform * glm::dvec4(ns.position, 1.0));
|
||||
|
||||
glm::dvec3 up = ns.up.has_value() ?
|
||||
glm::normalize(referenceFrameTransform * ns.up.value()) :
|
||||
glm::dvec3(0.0, 1.0, 0.0);
|
||||
|
||||
// Construct vectors of a "neutral" view, i.e. when the aim is centered in view.
|
||||
glm::dvec3 neutralView =
|
||||
glm::normalize(aimNode->worldPosition() - cameraPositionWorld);
|
||||
|
||||
glm::dquat neutralCameraRotation = glm::inverse(glm::quat_cast(glm::lookAt(
|
||||
glm::dvec3(0.0),
|
||||
neutralView,
|
||||
up
|
||||
)));
|
||||
|
||||
glm::dquat pitchRotation = glm::angleAxis(ns.pitch, glm::dvec3(1.f, 0.f, 0.f));
|
||||
glm::dquat yawRotation = glm::angleAxis(ns.yaw, glm::dvec3(0.f, -1.f, 0.f));
|
||||
|
||||
_camera->setPositionVec3(cameraPositionWorld);
|
||||
_camera->setRotation(neutralCameraRotation * yawRotation * pitchRotation);
|
||||
_orbitalNavigator.clearPreviousState();
|
||||
}
|
||||
|
||||
void NavigationHandler::setEnableKeyFrameInteraction() {
|
||||
_useKeyFrameInteraction = true;
|
||||
}
|
||||
@@ -150,8 +300,8 @@ void NavigationHandler::triggerPlaybackStart() {
|
||||
}
|
||||
|
||||
void NavigationHandler::stopPlayback() {
|
||||
_orbitalNavigator->resetVelocities();
|
||||
_orbitalNavigator->resetNodeMovements();
|
||||
_orbitalNavigator.resetVelocities();
|
||||
_orbitalNavigator.resetNodeMovements();
|
||||
_playbackModeEnabled = false;
|
||||
}
|
||||
|
||||
@@ -160,131 +310,120 @@ Camera* NavigationHandler::camera() const {
|
||||
}
|
||||
|
||||
const InputState& NavigationHandler::inputState() const {
|
||||
return *_inputState;
|
||||
return _inputState;
|
||||
}
|
||||
|
||||
void NavigationHandler::mouseButtonCallback(MouseButton button, MouseAction action) {
|
||||
_inputState->mouseButtonCallback(button, action);
|
||||
_inputState.mouseButtonCallback(button, action);
|
||||
}
|
||||
|
||||
void NavigationHandler::mousePositionCallback(double x, double y) {
|
||||
_inputState->mousePositionCallback(x, y);
|
||||
_inputState.mousePositionCallback(x, y);
|
||||
}
|
||||
|
||||
void NavigationHandler::mouseScrollWheelCallback(double pos) {
|
||||
_inputState->mouseScrollWheelCallback(pos);
|
||||
_inputState.mouseScrollWheelCallback(pos);
|
||||
}
|
||||
|
||||
void NavigationHandler::keyboardCallback(Key key, KeyModifier modifier, KeyAction action)
|
||||
{
|
||||
_inputState->keyboardCallback(key, modifier, action);
|
||||
_inputState.keyboardCallback(key, modifier, action);
|
||||
}
|
||||
|
||||
void NavigationHandler::setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict)
|
||||
NavigationHandler::NavigationState NavigationHandler::navigationState(
|
||||
const SceneGraphNode& referenceFrame) const
|
||||
{
|
||||
bool readSuccessful = true;
|
||||
const SceneGraphNode* anchor = _orbitalNavigator.anchorNode();
|
||||
const SceneGraphNode* aim = _orbitalNavigator.aimNode();
|
||||
|
||||
std::string anchor;
|
||||
std::string aim;
|
||||
glm::dvec3 cameraPosition;
|
||||
glm::dvec4 cameraRotation; // Need to read the quaternion as a vector first.
|
||||
|
||||
readSuccessful &= cameraDict.getValue(KeyAnchor, anchor);
|
||||
readSuccessful &= cameraDict.getValue(KeyPosition, cameraPosition);
|
||||
readSuccessful &= cameraDict.getValue(KeyRotation, cameraRotation);
|
||||
cameraDict.getValue(KeyAim, aim); // Aim is not required
|
||||
|
||||
if (!readSuccessful) {
|
||||
throw ghoul::RuntimeError(
|
||||
"Position, Rotation and Focus need to be defined for camera dictionary."
|
||||
);
|
||||
if (!aim) {
|
||||
aim = anchor;
|
||||
}
|
||||
|
||||
// Set state
|
||||
_orbitalNavigator->setAnchorNode(anchor);
|
||||
_orbitalNavigator->setAimNode(aim);
|
||||
const glm::dquat invNeutralRotation = glm::quat_cast(glm::lookAt(
|
||||
glm::dvec3(0.0, 0.0, 0.0),
|
||||
aim->worldPosition() - _camera->positionVec3(),
|
||||
glm::normalize(_camera->lookUpVectorWorldSpace())
|
||||
));
|
||||
|
||||
_camera->setPositionVec3(cameraPosition);
|
||||
_camera->setRotation(glm::dquat(
|
||||
cameraRotation.x, cameraRotation.y, cameraRotation.z, cameraRotation.w));
|
||||
glm::dquat localRotation = invNeutralRotation * _camera->rotationQuaternion();
|
||||
glm::dvec3 eulerAngles = glm::eulerAngles(localRotation);
|
||||
|
||||
const double pitch = eulerAngles.x;
|
||||
const double yaw = -eulerAngles.y;
|
||||
|
||||
// Need to compensate by redisual roll left in local rotation:
|
||||
const glm::dquat unroll = glm::angleAxis(eulerAngles.z, glm::dvec3(0, 0, 1));
|
||||
const glm::dvec3 neutralUp =
|
||||
glm::inverse(invNeutralRotation) * unroll * _camera->lookUpVectorCameraSpace();
|
||||
|
||||
const glm::dmat3 invReferenceFrameTransform =
|
||||
glm::inverse(referenceFrame.worldRotationMatrix());
|
||||
|
||||
const glm::dvec3 position = invReferenceFrameTransform *
|
||||
(glm::dvec4(_camera->positionVec3() - anchor->worldPosition(), 1.0));
|
||||
|
||||
return NavigationState(
|
||||
_orbitalNavigator.anchorNode()->identifier(),
|
||||
_orbitalNavigator.aimNode() ?
|
||||
_orbitalNavigator.aimNode()->identifier() : "",
|
||||
referenceFrame.identifier(),
|
||||
position,
|
||||
invReferenceFrameTransform * neutralUp, yaw, pitch
|
||||
);
|
||||
}
|
||||
|
||||
ghoul::Dictionary NavigationHandler::cameraStateDictionary() {
|
||||
glm::dvec3 cameraPosition;
|
||||
glm::dquat quat;
|
||||
glm::dvec4 cameraRotation;
|
||||
void NavigationHandler::saveNavigationState(const std::string& filepath,
|
||||
const std::string& referenceFrameIdentifier)
|
||||
{
|
||||
const SceneGraphNode* referenceFrame = _orbitalNavigator.followingNodeRotation() ?
|
||||
_orbitalNavigator.anchorNode() :
|
||||
sceneGraph()->root();
|
||||
|
||||
cameraPosition = _camera->positionVec3();
|
||||
quat = _camera->rotationQuaternion();
|
||||
cameraRotation = glm::dvec4(quat.w, quat.x, quat.y, quat.z);
|
||||
|
||||
ghoul::Dictionary cameraDict;
|
||||
cameraDict.setValue(KeyPosition, cameraPosition);
|
||||
cameraDict.setValue(KeyRotation, cameraRotation);
|
||||
cameraDict.setValue(KeyAnchor, _orbitalNavigator->anchorNode()->identifier());
|
||||
if (_orbitalNavigator->aimNode()) {
|
||||
cameraDict.setValue(KeyAim, _orbitalNavigator->aimNode()->identifier());
|
||||
}
|
||||
|
||||
return cameraDict;
|
||||
}
|
||||
|
||||
void NavigationHandler::saveCameraStateToFile(const std::string& filepath) {
|
||||
if (!filepath.empty()) {
|
||||
std::string fullpath = absPath(filepath);
|
||||
LINFO(fmt::format("Saving camera position: {}", filepath));
|
||||
|
||||
ghoul::Dictionary cameraDict = cameraStateDictionary();
|
||||
|
||||
// TODO(abock): Should get the camera state as a dictionary and save the
|
||||
// dictionary to a file in form of a lua state and not use ofstreams here.
|
||||
|
||||
std::ofstream ofs(fullpath.c_str());
|
||||
|
||||
glm::dvec3 p = _camera->positionVec3();
|
||||
glm::dquat q = _camera->rotationQuaternion();
|
||||
|
||||
ofs << "return {" << std::endl;
|
||||
ofs << " " << KeyAnchor << " = " << "\"" <<
|
||||
_orbitalNavigator->anchorNode()->identifier() << "\""
|
||||
<< "," << std::endl;
|
||||
|
||||
if (_orbitalNavigator->aimNode()) {
|
||||
ofs << " " << KeyAim << " = " << "\"" <<
|
||||
_orbitalNavigator->aimNode()->identifier() << "\""
|
||||
<< "," << std::endl;
|
||||
if (!referenceFrameIdentifier.empty()) {
|
||||
referenceFrame = sceneGraphNode(referenceFrameIdentifier);
|
||||
if (!referenceFrame) {
|
||||
LERROR(fmt::format(
|
||||
"Could not find node '{}' to use as reference frame",
|
||||
referenceFrameIdentifier
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ofs << " " << KeyPosition << " = {"
|
||||
<< std::to_string(p.x) << ", "
|
||||
<< std::to_string(p.y) << ", "
|
||||
<< std::to_string(p.z) << "}," << std::endl;
|
||||
ofs << " " << KeyRotation << " = {"
|
||||
<< std::to_string(q.w) << ", "
|
||||
<< std::to_string(q.x) << ", "
|
||||
<< std::to_string(q.y) << ", "
|
||||
<< std::to_string(q.z) << "}," << std::endl;
|
||||
ofs << "}"<< std::endl;
|
||||
if (!filepath.empty()) {
|
||||
std::string absolutePath = absPath(filepath);
|
||||
LINFO(fmt::format("Saving camera position: {}", absolutePath));
|
||||
|
||||
ghoul::Dictionary cameraDict = navigationState(*referenceFrame).dictionary();
|
||||
ghoul::DictionaryLuaFormatter formatter;
|
||||
|
||||
std::ofstream ofs(absolutePath.c_str());
|
||||
ofs << "return " << formatter.format(cameraDict);
|
||||
ofs.close();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigationHandler::restoreCameraStateFromFile(const std::string& filepath) {
|
||||
LINFO(fmt::format("Reading camera state from file: {}", filepath));
|
||||
if (!FileSys.fileExists(filepath)) {
|
||||
throw ghoul::FileNotFoundError(filepath, "CameraFilePath");
|
||||
void NavigationHandler::loadNavigationState(const std::string& filepath) {
|
||||
const std::string absolutePath = absPath(filepath);
|
||||
LINFO(fmt::format("Reading camera state from file: {}", absolutePath));
|
||||
|
||||
if (!FileSys.fileExists(absolutePath)) {
|
||||
throw ghoul::FileNotFoundError(absolutePath, "NavigationState");
|
||||
}
|
||||
|
||||
ghoul::Dictionary cameraDict;
|
||||
ghoul::Dictionary navigationStateDictionary;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(filepath, cameraDict);
|
||||
setCameraStateFromDictionary(cameraDict);
|
||||
_cameraUpdatedFromScript = true;
|
||||
ghoul::lua::loadDictionaryFromFile(absolutePath, navigationStateDictionary);
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
NavigationState::Documentation(),
|
||||
navigationStateDictionary,
|
||||
"NavigationState"
|
||||
);
|
||||
setNavigationStateNextFrame(NavigationState(navigationStateDictionary));
|
||||
}
|
||||
catch (ghoul::RuntimeError& e) {
|
||||
LWARNING("Unable to set camera position");
|
||||
LWARNING(e.message);
|
||||
LERROR(fmt::format("Unable to set camera position: {}", e.message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +432,7 @@ void NavigationHandler::setJoystickAxisMapping(int axis,
|
||||
JoystickCameraStates::AxisInvert shouldInvert,
|
||||
JoystickCameraStates::AxisNormalize shouldNormalize)
|
||||
{
|
||||
_orbitalNavigator->joystickStates().setAxisMapping(
|
||||
_orbitalNavigator.joystickStates().setAxisMapping(
|
||||
axis,
|
||||
mapping,
|
||||
shouldInvert,
|
||||
@@ -304,15 +443,15 @@ void NavigationHandler::setJoystickAxisMapping(int axis,
|
||||
JoystickCameraStates::AxisInformation
|
||||
NavigationHandler::joystickAxisMapping(int axis) const
|
||||
{
|
||||
return _orbitalNavigator->joystickStates().axisMapping(axis);
|
||||
return _orbitalNavigator.joystickStates().axisMapping(axis);
|
||||
}
|
||||
|
||||
void NavigationHandler::setJoystickAxisDeadzone(int axis, float deadzone) {
|
||||
_orbitalNavigator->joystickStates().setDeadzone(axis, deadzone);
|
||||
_orbitalNavigator.joystickStates().setDeadzone(axis, deadzone);
|
||||
}
|
||||
|
||||
float NavigationHandler::joystickAxisDeadzone(int axis) const {
|
||||
return _orbitalNavigator->joystickStates().deadzone(axis);
|
||||
return _orbitalNavigator.joystickStates().deadzone(axis);
|
||||
}
|
||||
|
||||
void NavigationHandler::bindJoystickButtonCommand(int button, std::string command,
|
||||
@@ -320,7 +459,7 @@ void NavigationHandler::bindJoystickButtonCommand(int button, std::string comman
|
||||
JoystickCameraStates::ButtonCommandRemote remote,
|
||||
std::string documentation)
|
||||
{
|
||||
_orbitalNavigator->joystickStates().bindButtonCommand(
|
||||
_orbitalNavigator.joystickStates().bindButtonCommand(
|
||||
button,
|
||||
std::move(command),
|
||||
action,
|
||||
@@ -330,11 +469,68 @@ void NavigationHandler::bindJoystickButtonCommand(int button, std::string comman
|
||||
}
|
||||
|
||||
void NavigationHandler::clearJoystickButtonCommand(int button) {
|
||||
_orbitalNavigator->joystickStates().clearButtonCommand(button);
|
||||
_orbitalNavigator.joystickStates().clearButtonCommand(button);
|
||||
}
|
||||
|
||||
std::vector<std::string> NavigationHandler::joystickButtonCommand(int button) const {
|
||||
return _orbitalNavigator->joystickStates().buttonCommand(button);
|
||||
return _orbitalNavigator.joystickStates().buttonCommand(button);
|
||||
}
|
||||
|
||||
documentation::Documentation NavigationHandler::NavigationState::Documentation() {
|
||||
using namespace documentation;
|
||||
|
||||
return {
|
||||
"Navigation State",
|
||||
"core_navigation_state",
|
||||
{
|
||||
{
|
||||
KeyAnchor,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"The identifier of the anchor node."
|
||||
},
|
||||
{
|
||||
KeyAim,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"The identifier of the aim node, if used."
|
||||
},
|
||||
{
|
||||
KeyReferenceFrame,
|
||||
new StringVerifier,
|
||||
Optional::Yes,
|
||||
"The identifier of the scene graph node to use as reference frame. "
|
||||
"If not specified, this will be the same as the anchor."
|
||||
},
|
||||
{
|
||||
KeyPosition,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
"The position of the camera relative to the anchor node, "
|
||||
"expressed in meters in the specified reference frame."
|
||||
},
|
||||
{
|
||||
KeyUp,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::Yes,
|
||||
"The up vector expressed in the coordinate system of the reference frame."
|
||||
},
|
||||
{
|
||||
KeyYaw,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"The yaw angle in radians. "
|
||||
"Positive angle means yawing camera to the right."
|
||||
},
|
||||
{
|
||||
KeyPitch,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
"The pitch angle in radians. "
|
||||
"Positive angle means pitching camera upwards."
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
scripting::LuaLibrary NavigationHandler::luaLibrary() {
|
||||
@@ -342,25 +538,33 @@ scripting::LuaLibrary NavigationHandler::luaLibrary() {
|
||||
"navigation",
|
||||
{
|
||||
{
|
||||
"setCameraState",
|
||||
&luascriptfunctions::setCameraState,
|
||||
"setNavigationState",
|
||||
&luascriptfunctions::setNavigationState,
|
||||
{},
|
||||
"object",
|
||||
"Set the camera state"
|
||||
"table",
|
||||
"Set the navigation state. "
|
||||
"The argument must be a valid Navigation State."
|
||||
},
|
||||
{
|
||||
"saveCameraStateToFile",
|
||||
&luascriptfunctions::saveCameraStateToFile,
|
||||
"saveNavigationState",
|
||||
&luascriptfunctions::saveNavigationState,
|
||||
{},
|
||||
"string",
|
||||
"Save the current camera state to file"
|
||||
"string, [string]",
|
||||
"Save the current navigation state to a file with the path given by the "
|
||||
"first argument. The optoinal second argument is the scene graph node to "
|
||||
"use as reference frame. By default, the reference frame will picked "
|
||||
"based on whether the orbital navigator is currently following the "
|
||||
"anchor node rotation. If it is, the anchor will be chosen as reference "
|
||||
"frame. If not, the reference frame will be set to the scene graph root."
|
||||
},
|
||||
{
|
||||
"restoreCameraStateFromFile",
|
||||
&luascriptfunctions::restoreCameraStateFromFile,
|
||||
"loadNavigationState",
|
||||
&luascriptfunctions::loadNavigationState,
|
||||
{},
|
||||
"string",
|
||||
"Restore the camera state from file"
|
||||
"Load a navigation state from file. The file should be a lua file "
|
||||
"returning the navigation state as a table formatted as a "
|
||||
"Navigation State, such as the output files of saveNavigationState."
|
||||
},
|
||||
{
|
||||
"retargetAnchor",
|
||||
|
||||
Reference in New Issue
Block a user