mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-23 20:50:59 -05:00
Feature/gui for touch (#967)
Merging in feature gui for touch. Enable touch module to run. Currently only run on development mode with the "touch" scene.
This commit is contained in:
@@ -296,7 +296,6 @@ void parseLuaState(Configuration& configuration) {
|
||||
getValue(s, KeyMasterRotation, c.masterRotation);
|
||||
getValue(s, KeyDisableInGameConsole, c.isConsoleDisabled);
|
||||
getValue(s, KeyRenderingMethod, c.renderingMethod);
|
||||
|
||||
getValue(s, KeyLogging, c.logging);
|
||||
getValue(s, KeyDocumentation, c.documentation);
|
||||
getValue(s, KeyLoadingScreen, c.loadingScreen);
|
||||
|
||||
@@ -165,6 +165,15 @@ void NavigationHandler::deinitialize() {
|
||||
global::parallelPeer.connectionEvent().unsubscribe("NavigationHandler");
|
||||
}
|
||||
|
||||
void NavigationHandler::setFocusNode(SceneGraphNode* node) {
|
||||
_orbitalNavigator.setFocusNode(node);
|
||||
_camera->setPositionVec3(anchorNode()->worldPosition());
|
||||
}
|
||||
|
||||
void NavigationHandler::resetCameraDirection() {
|
||||
_orbitalNavigator.startRetargetAnchor();
|
||||
}
|
||||
|
||||
void NavigationHandler::setCamera(Camera* camera) {
|
||||
_camera = camera;
|
||||
_orbitalNavigator.setCamera(camera);
|
||||
@@ -299,6 +308,10 @@ void NavigationHandler::stopPlayback() {
|
||||
_playbackModeEnabled = false;
|
||||
}
|
||||
|
||||
const SceneGraphNode* NavigationHandler::anchorNode() const {
|
||||
return _orbitalNavigator.anchorNode();
|
||||
}
|
||||
|
||||
Camera* NavigationHandler::camera() const {
|
||||
return _camera;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/interaction/orbitalnavigator.h>
|
||||
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/query/query.h>
|
||||
@@ -35,6 +34,7 @@ namespace {
|
||||
|
||||
constexpr const double AngleEpsilon = 1E-7;
|
||||
constexpr const double DistanceRatioAimThreshold = 1E-4;
|
||||
constexpr const double FlightDestinationFactor = 1E-4;
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo AnchorInfo = {
|
||||
"Anchor",
|
||||
@@ -136,12 +136,31 @@ namespace {
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo StereoInterpolationTimeInfo =
|
||||
{
|
||||
"StereoInterpolationTime",
|
||||
"Stereo interpolation time",
|
||||
"The time to interpolate to a new stereoscopic depth "
|
||||
"when the anchor node is changed."
|
||||
constexpr openspace::properties::Property::PropertyInfo VelocityZoomControlInfo = {
|
||||
"VelocityZoomControl",
|
||||
"Velocity zoom control",
|
||||
"Controls the velocity of the camera motion when zooming in to the focus node. "
|
||||
"The higher the value the faster the camera will move towards the focus."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ApplyLinearFlightInfo = {
|
||||
"ApplyLinearFlight",
|
||||
"Apply Linear Flight",
|
||||
"This property makes the camera move to the specified distance 'FlightDestinationDistance' while facing the anchor"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FlightDestinationDistanceInfo = {
|
||||
"FlightDestinationDistance",
|
||||
"Flight Destination Distance",
|
||||
"The final distance we want to fly to, with regards to the anchor node."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
StereoInterpolationTimeInfo = {
|
||||
"StereoInterpolationTime",
|
||||
"Stereo interpolation time",
|
||||
"The time to interpolate to a new stereoscopic depth "
|
||||
"when the anchor node is changed."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo
|
||||
@@ -210,6 +229,9 @@ OrbitalNavigator::OrbitalNavigator()
|
||||
, _retargetAim(RetargetAimInfo)
|
||||
, _followAnchorNodeRotationDistance(FollowAnchorNodeInfo, 5.0f, 0.0f, 20.f)
|
||||
, _minimumAllowedDistance(MinimumDistanceInfo, 10.0f, 0.0f, 10000.f)
|
||||
, _velocitySensitivity(VelocityZoomControlInfo, 0.02f, 0.01f, 0.15f)
|
||||
, _applyLinearFlight(ApplyLinearFlightInfo, false)
|
||||
, _flightDestinationDistance(FlightDestinationDistanceInfo, 2e8f, 0.0f, 1e10f)
|
||||
, _mouseSensitivity(MouseSensitivityInfo, 15.0f, 1.0f, 50.f)
|
||||
, _joystickSensitivity(JoystickSensitivityInfo, 10.0f, 1.0f, 50.f)
|
||||
, _websocketSensitivity(WebsocketSensitivityInfo, 10.0f, 1.0f, 50.f)
|
||||
@@ -262,7 +284,8 @@ OrbitalNavigator::OrbitalNavigator()
|
||||
_retargetAim.onChange([this]() {
|
||||
if (_aimNode && _aimNode != _anchorNode) {
|
||||
startRetargetAim();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
startRetargetAnchor();
|
||||
}
|
||||
});
|
||||
@@ -337,6 +360,9 @@ OrbitalNavigator::OrbitalNavigator()
|
||||
addProperty(_retargetAim);
|
||||
addProperty(_followAnchorNodeRotationDistance);
|
||||
addProperty(_minimumAllowedDistance);
|
||||
addProperty(_velocitySensitivity);
|
||||
addProperty(_flightDestinationDistance);
|
||||
addProperty(_applyLinearFlight);
|
||||
|
||||
addProperty(_useAdaptiveStereoscopicDepth);
|
||||
addProperty(_staticViewScaleExponent);
|
||||
@@ -393,6 +419,9 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
}
|
||||
|
||||
const glm::dvec3 anchorPos = _anchorNode->worldPosition();
|
||||
|
||||
SurfacePositionHandle posHandle;
|
||||
|
||||
const glm::dvec3 prevCameraPosition = _camera->positionVec3();
|
||||
const glm::dvec3 anchorDisplacement = _previousAnchorNodePosition.has_value() ?
|
||||
(anchorPos - _previousAnchorNodePosition.value()) :
|
||||
@@ -403,6 +432,31 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
_camera->rotationQuaternion()
|
||||
};
|
||||
|
||||
if (_applyLinearFlight) {
|
||||
// Calculate a position handle based on the camera position in world space
|
||||
glm::dvec3 camPosToAnchorPosDiff = prevCameraPosition - anchorPos;
|
||||
// Use the boundingsphere to get an approximate distance to the surface of the node
|
||||
double nodeRadius = static_cast<double>(_anchorNode->boundingSphere());
|
||||
double distFromCameraToFocus = glm::distance(prevCameraPosition, anchorPos) - nodeRadius;
|
||||
|
||||
// Make the approximation delta size depending on the flight distance
|
||||
double arrivalThreshold = _flightDestinationDistance.value() * FlightDestinationFactor;
|
||||
|
||||
// Fly towards the flight destination distance. When getting closer than arrivalThreshold terminate the flight
|
||||
if (abs(distFromCameraToFocus - _flightDestinationDistance.value()) > arrivalThreshold) {
|
||||
|
||||
pose.position = moveCameraAlongVector(
|
||||
pose.position,
|
||||
distFromCameraToFocus,
|
||||
camPosToAnchorPosDiff,
|
||||
_flightDestinationDistance
|
||||
);
|
||||
}
|
||||
else {
|
||||
_applyLinearFlight.setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
const bool hasPreviousPositions =
|
||||
_previousAnchorNodePosition.has_value() &&
|
||||
_previousAimNodePosition.has_value();
|
||||
@@ -433,8 +487,7 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
_previousAnchorNodePosition = _anchorNode->worldPosition();
|
||||
|
||||
// Calculate a position handle based on the camera position in world space
|
||||
SurfacePositionHandle posHandle =
|
||||
calculateSurfacePositionHandle(*_anchorNode, pose.position);
|
||||
posHandle = calculateSurfacePositionHandle(*_anchorNode, pose.position);
|
||||
|
||||
// Decompose camera rotation so that we can handle global and local rotation
|
||||
// individually. Then we combine them again when finished.
|
||||
@@ -532,7 +585,8 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
if (_directlySetStereoDistance) {
|
||||
_currentCameraToSurfaceDistance = targetCameraToSurfaceDistance;
|
||||
_directlySetStereoDistance = false;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
_currentCameraToSurfaceDistance = interpolateCameraToSurfaceDistance(
|
||||
deltaTime,
|
||||
_currentCameraToSurfaceDistance,
|
||||
@@ -543,7 +597,8 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
|
||||
_stereoscopicDepthOfFocusSurface /
|
||||
static_cast<float>(_currentCameraToSurfaceDistance)
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
_camera->setScaling(glm::pow(10.f, _staticViewScaleExponent));
|
||||
}
|
||||
}
|
||||
@@ -972,6 +1027,7 @@ glm::dquat OrbitalNavigator::rotateLocally(double deltaTime,
|
||||
return localCameraRotation * joystickRotationDiff * mouseRotationDiff *
|
||||
websocketRotationDiff * scriptRotationDiff;
|
||||
}
|
||||
|
||||
glm::dquat OrbitalNavigator::interpolateLocalRotation(double deltaTime,
|
||||
const glm::dquat& localCameraRotation)
|
||||
{
|
||||
@@ -1173,6 +1229,27 @@ glm::dvec3 OrbitalNavigator::translateHorizontally(double deltaTime,
|
||||
return cameraPosition + rotationDiffVec3;
|
||||
}
|
||||
|
||||
glm::dvec3 OrbitalNavigator::moveCameraAlongVector(const glm::dvec3& camPos,
|
||||
double distFromCameraToFocus,
|
||||
const glm::dvec3& camPosToAnchorPosDiff,
|
||||
double destination) const
|
||||
{
|
||||
// This factor adapts the velocity so it slows down when getting closer
|
||||
// to our final destination
|
||||
double velocity = 0.0;
|
||||
|
||||
if (destination < distFromCameraToFocus) { // When flying towards anchor
|
||||
velocity = 1.0 - destination / distFromCameraToFocus;
|
||||
}
|
||||
else { // When flying away from anchor
|
||||
velocity = distFromCameraToFocus / destination - 1.0;
|
||||
}
|
||||
velocity *= _velocitySensitivity;
|
||||
|
||||
// Return the updated camera position
|
||||
return camPos - velocity * camPosToAnchorPosDiff;
|
||||
}
|
||||
|
||||
glm::dvec3 OrbitalNavigator::followAnchorNodeRotation(const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition,
|
||||
const glm::dquat& focusNodeRotationDiff) const
|
||||
|
||||
@@ -37,6 +37,12 @@ namespace {
|
||||
"If this value is 'false', this dashboard will be invisible, regardless of the "
|
||||
"state of the individual components"
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo StartPositionOffsetInfo = {
|
||||
"StartPositionOffset",
|
||||
"Start Position Offset",
|
||||
"A 2D vector controlling where the dashboard rendering starts."
|
||||
"Adding an offset in x and y-direction on screen"
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -44,8 +50,12 @@ namespace openspace {
|
||||
Dashboard::Dashboard()
|
||||
: properties::PropertyOwner({ "Dashboard" })
|
||||
, _isEnabled(EnabledInfo, true)
|
||||
, _startPositionOffset(
|
||||
properties::IVec2Property(StartPositionOffsetInfo, glm::ivec2(10, -10))
|
||||
)
|
||||
{
|
||||
addProperty(_isEnabled);
|
||||
addProperty(_startPositionOffset);
|
||||
}
|
||||
|
||||
void Dashboard::addDashboardItem(std::unique_ptr<DashboardItem> item) {
|
||||
@@ -128,6 +138,10 @@ void Dashboard::render(glm::vec2& penPosition) {
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 Dashboard::getStartPositionOffset() {
|
||||
return _startPositionOffset.value();
|
||||
};
|
||||
|
||||
scripting::LuaLibrary Dashboard::luaLibrary() {
|
||||
return {
|
||||
"dashboard",
|
||||
|
||||
@@ -54,6 +54,12 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Hidden
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
|
||||
"BoundingSphere",
|
||||
"Bounding Sphere",
|
||||
"The size of the bounding sphere radius."
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -109,6 +115,7 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
, _enabled(EnabledInfo, true)
|
||||
, _opacity(OpacityInfo, 1.f, 0.f, 1.f)
|
||||
, _renderableType(RenderableTypeInfo, "Renderable")
|
||||
, _boundingSphere(BoundingSphereInfo, 0.f, 0.f, 3e10f)
|
||||
{
|
||||
// I can't come up with a good reason not to do this for all renderables
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
@@ -144,6 +151,7 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
_renderableType = dictionary.value<std::string>(RenderableTypeInfo.identifier);
|
||||
}
|
||||
addProperty(_renderableType);
|
||||
addProperty(_boundingSphere);
|
||||
}
|
||||
|
||||
void Renderable::initialize() {}
|
||||
@@ -159,11 +167,12 @@ void Renderable::update(const UpdateData&) {}
|
||||
void Renderable::render(const RenderData&, RendererTasks&) {}
|
||||
|
||||
void Renderable::setBoundingSphere(float boundingSphere) {
|
||||
_boundingSphere = boundingSphere;
|
||||
|
||||
_boundingSphere.setValue(boundingSphere);
|
||||
}
|
||||
|
||||
float Renderable::boundingSphere() const {
|
||||
return _boundingSphere;
|
||||
return _boundingSphere.value();
|
||||
}
|
||||
|
||||
SurfacePositionHandle Renderable::calculateSurfacePositionHandle(
|
||||
|
||||
@@ -793,7 +793,7 @@ void RenderEngine::renderEndscreen() {
|
||||
);
|
||||
glm::vec2 penPosition = glm::vec2(
|
||||
fontResolution().x / 2 - size.boundingBox.x / 2,
|
||||
fontResolution().y / 2- size.boundingBox.y / 2
|
||||
fontResolution().y / 2 - size.boundingBox.y / 2
|
||||
);
|
||||
RenderFont(*_fontDate, penPosition, "Shutting down");
|
||||
}
|
||||
@@ -836,9 +836,11 @@ void RenderEngine::renderDashboard() {
|
||||
"Main Dashboard::render"
|
||||
);
|
||||
}
|
||||
|
||||
glm::vec2 dashboardStart = global::dashboard.getStartPositionOffset();
|
||||
glm::vec2 penPosition = glm::vec2(
|
||||
10.f,
|
||||
fontResolution().y - global::luaConsole.currentHeight()
|
||||
dashboardStart.x,
|
||||
dashboardStart.y + fontResolution().y - global::luaConsole.currentHeight()
|
||||
);
|
||||
|
||||
global::dashboard.render(penPosition);
|
||||
|
||||
@@ -27,13 +27,14 @@
|
||||
#include <modules/base/scale/staticscale.h>
|
||||
#include <modules/base/rotation/staticrotation.h>
|
||||
#include <modules/base/translation/statictranslation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/timeframe.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
|
||||
#include "scenegraphnode_doc.inl"
|
||||
|
||||
namespace {
|
||||
@@ -49,8 +50,48 @@ namespace {
|
||||
|
||||
constexpr const char* KeyTimeFrame = "TimeFrame";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ComputeScreenSpaceInfo =
|
||||
{
|
||||
"ComputeScreenSpaceData",
|
||||
"Screen Space Data",
|
||||
"If this value is set to 'true', the screenspace-based properties are calculated "
|
||||
"at regular intervals. If these values are set to 'false', they are not updated."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ScreenSpacePositionInfo = {
|
||||
"ScreenSpacePosition",
|
||||
"ScreenSpacePosition",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo ScreenVisibilityInfo = {
|
||||
"ScreenVisibility",
|
||||
"ScreenVisibility",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo DistanceFromCamToNodeInfo = {
|
||||
"DistanceFromCamToNode",
|
||||
"DistanceFromCamToNode",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo ScreenSizeRadiusInfo = {
|
||||
"ScreenSizeRadius",
|
||||
"ScreenSizeRadius",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo VisibilityDistanceInfo = {
|
||||
"VisibilityDistance",
|
||||
"VisibilityDistance",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
constexpr const char* KeyFixedBoundingSphere = "FixedBoundingSphere";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo BoundingSphereInfo = {
|
||||
"BoundingSphere",
|
||||
"Bounding Sphere",
|
||||
"The bounding sphere of the scene graph node. This can be the "
|
||||
"bounding sphere of a renderable or a fixed bounding sphere. "
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo GuiPathInfo = {
|
||||
"GuiPath",
|
||||
"Gui Path",
|
||||
@@ -235,6 +276,8 @@ std::unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
}
|
||||
|
||||
LDEBUG(fmt::format("Successfully created SceneGraphNode '{}'", result->identifier()));
|
||||
|
||||
result->_lastScreenSpaceUpdateTime = std::chrono::high_resolution_clock::now();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -248,7 +291,22 @@ SceneGraphNode::SceneGraphNode()
|
||||
std::make_unique<StaticRotation>(),
|
||||
std::make_unique<StaticScale>()
|
||||
}
|
||||
{}
|
||||
, _computeScreenSpaceValues(ComputeScreenSpaceInfo, false)
|
||||
, _screenSpacePosition(
|
||||
properties::IVec2Property(ScreenSpacePositionInfo, glm::ivec2(-1, -1))
|
||||
)
|
||||
, _screenVisibility(properties::BoolProperty(ScreenVisibilityInfo, false))
|
||||
, _distFromCamToNode(properties::DoubleProperty(DistanceFromCamToNodeInfo, -1.0))
|
||||
, _screenSizeRadius(properties::DoubleProperty(ScreenSizeRadiusInfo, 0))
|
||||
, _visibilityDistance(properties::FloatProperty(VisibilityDistanceInfo, 6e10f))
|
||||
{
|
||||
addProperty(_computeScreenSpaceValues);
|
||||
addProperty(_screenSpacePosition);
|
||||
addProperty(_screenVisibility);
|
||||
addProperty(_distFromCamToNode);
|
||||
addProperty(_screenSizeRadius);
|
||||
addProperty(_visibilityDistance);
|
||||
}
|
||||
|
||||
SceneGraphNode::~SceneGraphNode() {} // NOLINT
|
||||
|
||||
@@ -455,6 +513,9 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
_renderable->render(newData, tasks);
|
||||
if (_computeScreenSpaceValues) {
|
||||
computeScreenSpaceData(newData);
|
||||
}
|
||||
|
||||
glFinish();
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
@@ -462,6 +523,9 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
}
|
||||
else {
|
||||
_renderable->render(newData, tasks);
|
||||
if (_computeScreenSpaceValues) {
|
||||
computeScreenSpaceData(newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,6 +659,86 @@ void SceneGraphNode::setDependencies(const std::vector<SceneGraphNode*>& depende
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::computeScreenSpaceData(RenderData& newData) {
|
||||
// Purposely slow the update rate of screen space position in order to reduce the
|
||||
// effects of jittering in the position of information icon markers in web gui.
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
if ((now - _lastScreenSpaceUpdateTime) < std::chrono::milliseconds(100)) {
|
||||
return;
|
||||
}
|
||||
_lastScreenSpaceUpdateTime = now;
|
||||
|
||||
// Calculate ndc
|
||||
const Camera& cam = newData.camera;
|
||||
const glm::dvec3& worldPos = _worldPositionCached;
|
||||
const glm::dvec4 clipSpace = glm::dmat4(cam.projectionMatrix()) *
|
||||
cam.combinedViewMatrix() * glm::vec4(worldPos, 1.0);
|
||||
const glm::dvec2 worldPosNDC = glm::dvec2(clipSpace / clipSpace.w);
|
||||
|
||||
const bool visible = worldPosNDC.x >= -1.0 && worldPosNDC.x <= 1.0 &&
|
||||
worldPosNDC.y >= -1.0 && worldPosNDC.y <= 1.0 && clipSpace.z > 0;
|
||||
|
||||
// If not on the screen, we want to reset it or don't update it
|
||||
if (!visible) {
|
||||
_screenVisibility = false;
|
||||
return;
|
||||
}
|
||||
|
||||
glm::ivec2 res = global::windowDelegate.currentWindowSize();
|
||||
|
||||
// Get the radius of node
|
||||
double nodeRadius = static_cast<double>(this->boundingSphere());
|
||||
|
||||
// Distance from the camera to the node
|
||||
double distFromCamToNode = glm::distance(cam.positionVec3(), worldPos) - nodeRadius;
|
||||
|
||||
// Fix to limit the update of properties
|
||||
if (distFromCamToNode >= _visibilityDistance) {
|
||||
_screenVisibility = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_screenVisibility = true;
|
||||
|
||||
// Calculate the node radius to screensize pixels
|
||||
const glm::dvec3 lookUp = normalize(cam.lookUpVectorWorldSpace());
|
||||
const glm::dvec3 radiusPos = worldPos + (nodeRadius * lookUp);
|
||||
const glm::dvec4 clipSpaceRadius = glm::dmat4(cam.projectionMatrix()) *
|
||||
cam.combinedViewMatrix() * glm::vec4(radiusPos, 1.0);
|
||||
const glm::dvec3 radiusNDC = clipSpaceRadius / clipSpaceRadius.w;
|
||||
|
||||
const glm::ivec2 centerScreenSpace = glm::ivec2(
|
||||
(worldPosNDC.x + 1.0) * res.x / 2,
|
||||
(worldPosNDC.y + 1.0) * res.y / 2
|
||||
);
|
||||
const glm::ivec2 radiusScreenSpace = glm::ivec2(
|
||||
(radiusNDC.x + 1.0) * res.x / 2,
|
||||
(radiusNDC.y + 1.0) * res.y / 2
|
||||
);
|
||||
const double screenSpaceRadius = length(
|
||||
glm::vec2(centerScreenSpace) - glm::vec2(radiusScreenSpace)
|
||||
);
|
||||
|
||||
constexpr const double RadiusThreshold = 2.0;
|
||||
const double r = abs(_screenSizeRadius - screenSpaceRadius);
|
||||
if (r > RadiusThreshold) {
|
||||
_screenSizeRadius = screenSpaceRadius;
|
||||
}
|
||||
|
||||
constexpr const double ZoomThreshold = 0.1;
|
||||
const double d = abs(_distFromCamToNode - distFromCamToNode);
|
||||
if (d > (ZoomThreshold * distFromCamToNode)) {
|
||||
_distFromCamToNode = distFromCamToNode;
|
||||
}
|
||||
|
||||
constexpr const double MoveThreshold = 1.0;
|
||||
const glm::ivec2 ssp = _screenSpacePosition;
|
||||
const glm::dvec2 c = glm::abs(ssp - centerScreenSpace);
|
||||
if (c.x > MoveThreshold || c.y > MoveThreshold) {
|
||||
_screenSpacePosition = centerScreenSpace;
|
||||
}
|
||||
}
|
||||
|
||||
SurfacePositionHandle SceneGraphNode::calculateSurfacePositionHandle(
|
||||
const glm::dvec3& targetModelSpace) const
|
||||
{
|
||||
@@ -765,13 +909,13 @@ Renderable* SceneGraphNode::renderable() {
|
||||
return _renderable.get();
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraphNode::childNode(const std::string& identifier) {
|
||||
if (this->identifier() == identifier) {
|
||||
SceneGraphNode* SceneGraphNode::childNode(const std::string& id) {
|
||||
if (identifier() == id) {
|
||||
return this;
|
||||
}
|
||||
else {
|
||||
for (std::unique_ptr<SceneGraphNode>& it : _children) {
|
||||
SceneGraphNode* tmp = it->childNode(identifier);
|
||||
SceneGraphNode* tmp = it->childNode(id);
|
||||
if (tmp) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user