1#include <Gui/Viewer/TrackballCameraManipulator.hpp>
3#include <Core/Asset/Camera.hpp>
4#include <Core/Math/Math.hpp>
5#include <Core/Utils/Log.hpp>
6#include <Engine/RadiumEngine.hpp>
7#include <Engine/Rendering/RenderObject.hpp>
8#include <Engine/Rendering/RenderObjectManager.hpp>
9#include <Engine/Scene/Light.hpp>
11#include <Gui/Utils/KeyMappingManager.hpp>
12#include <Gui/Utils/Keyboard.hpp>
14#include <Engine/Scene/CameraComponent.hpp>
15#include <QApplication>
23using namespace Ra::Core::Utils;
27#define KMA_VALUE( XX ) KeyMappingManager::KeyMappingAction TrackballCameraManipulator::XX;
31void TrackballCameraManipulator::configureKeyMapping_impl() {
33 KeyMapping::setContext( KeyMappingManager::getInstance()->getContext(
"CameraContext" ) );
34 if ( KeyMapping::getContext().isInvalid() ) {
36 <<
"CameraContext not defined (maybe the configuration file do not contains it)";
37 LOG( logERROR ) <<
"CameraContext all keymapping invalide !";
41#define KMA_VALUE( XX ) \
42 XX = KeyMappingManager::getInstance()->getAction( KeyMapping::getContext(), #XX );
47void TrackballCameraManipulator::setupKeyMappingCallbacks() {
50 TRACKBALLCAMERA_ROTATE, [=]( QEvent* event ) { rotateCallback( event ); } );
52 [=]( QEvent* event ) { panCallback( event ); } );
54 [=]( QEvent* event ) { zoomCallback( event ); } );
56 TRACKBALLCAMERA_MOVE_FORWARD, [=]( QEvent* event ) { moveForwardCallback( event ); } );
58 m_keyMappingCallbackManager.
addEventCallback( TRACKBALLCAMERA_PROJ_MODE, [=]( QEvent* ) {
61 : ProjType::ORTHOGRAPHIC );
64 m_keyMappingCallbackManager.
addEventCallback( CAMERA_TOGGLE_QUICK, [=]( QEvent* ) {
65 static bool quick =
false;
75 setupKeyMappingCallbacks();
88 setupKeyMappingCallbacks();
142 return KeyMapping::getContext();
145void TrackballCameraManipulator::mousePressSaveData(
const QMouseEvent* mouseEvent ) {
151void TrackballCameraManipulator::rotateCallback( QEvent* event ) {
152 if ( event->type() == QEvent::MouseMove ) {
153 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
154 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
155 handleCameraRotate( dx, dy );
159void TrackballCameraManipulator::panCallback( QEvent* event ) {
160 if ( event->type() == QEvent::MouseMove ) {
161 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
162 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
163 handleCameraPan( dx, dy );
167void TrackballCameraManipulator::zoomCallback( QEvent* event ) {
168 if ( event->type() == QEvent::MouseMove ) {
169 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
170 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
171 handleCameraZoom( dx, dy );
173 else if ( event->type() == QEvent::Wheel ) {
174 auto wheelEvent =
reinterpret_cast<QWheelEvent*
>( event );
176 ( wheelEvent->angleDelta().y() * 0.01_ra + wheelEvent->angleDelta().x() * 0.01_ra ) *
181void TrackballCameraManipulator::moveForwardCallback( QEvent* event ) {
183 if ( event->type() == QEvent::MouseMove ) {
184 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
185 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
186 handleCameraMoveForward( dx, dy );
188 else if ( event->type() == QEvent::Wheel ) {
189 auto wheelEvent =
reinterpret_cast<QWheelEvent*
>( event );
191 handleCameraMoveForward(
192 ( wheelEvent->angleDelta().y() * 0.01_ra + wheelEvent->angleDelta().x() * 0.01_ra ) *
198 const Qt::MouseButtons&,
199 const Qt::KeyboardModifiers&,
212 const Qt::MouseButtons&,
213 const Qt::KeyboardModifiers&,
234 const Qt::MouseButtons&,
235 const Qt::KeyboardModifiers&,
255void TrackballCameraManipulator::setCameraPosition(
const Core::Vector3& position ) {
257 QMessageBox::warning(
nullptr,
"Error",
"Position cannot be set to target point" );
271void TrackballCameraManipulator::setCameraTarget(
const Core::Vector3& target ) {
273 QMessageBox::warning(
nullptr,
"Error",
"Target cannot be set to current camera position" );
286void TrackballCameraManipulator::fitScene(
const Core::Aabb& aabb ) {
290 const Scalar r = ( aabb.max() - aabb.min() ).norm() / 2_ra;
291 const Scalar x = r /
std::sin( f / 2_ra );
292 const Scalar y = r /
std::sin( f * a / 2_ra );
296 Core::Vector3 camPos { aabb.center().x(), aabb.center().y(), aabb.center().z() + d };
298 Core::Vector3 camDir { aabb.center() - camPos };
314void TrackballCameraManipulator::handleCameraRotate( Scalar dx, Scalar dy ) {
318 Scalar phi =
m_phi + dphi;
319 Scalar theta = m_theta + dtheta;
324 Core::Vector3
right { -dir[2], 0, dir[0] };
329 Core::Vector3 up = dir.cross( right ).normalized();
337 m <<
right[0], up[0], dir[0],
338 right[1], up[1], dir[1],
339 right[2], up[2], dir[2];
346 t.translation() = pos;
355void TrackballCameraManipulator::handleCameraPan( Scalar dx, Scalar dy ) {
359 Core::Vector3 R = -
m_camera->getRightVector();
362 Core::Transform T( Core::Transform::Identity() );
363 Core::Vector3 t = x * R + y * U;
370void TrackballCameraManipulator::handleCameraMoveForward( Scalar dx, Scalar dy ) {
374void TrackballCameraManipulator::handleCameraMoveForward( Scalar z ) {
378 Core::Transform T( Core::Transform::Identity() );
386void TrackballCameraManipulator::handleCameraZoom( Scalar dx, Scalar dy ) {
390void TrackballCameraManipulator::handleCameraZoom( Scalar z ) {
404 if ( UNLIKELY( areApproxEqual( R.z(), 0_ra ) && areApproxEqual( R.x(), 0_ra ) ) ) {
417void TrackballCameraManipulator::clampThetaPhi() {
421 if ( m_theta < -Pi ) { m_theta += 2_ra * Pi; }
422 if ( m_theta > Pi ) { m_theta -= 2_ra * Pi; }
425bool TrackballCameraManipulator::checkIntegrity(
const std::string& mess )
const {
428 if ( d > 0.001_ra ) {
429 LOG( logWARNING ) <<
"TrackballCameraManipulator Integrity problem : " << mess;
431 LOG( logWARNING ) <<
"\t Ref "
436 LOG( logWARNING ) <<
"\t Center " << c.transpose();
437 LOG( logWARNING ) <<
"\t Distance " << d;
438 LOG( logWARNING ) <<
"\t angles " <<
m_phi <<
" " << m_theta;
ProjType
Define the projection type.
void setPosition(const Core::Vector3 &position)
Set the position of the camera to position.
void setDirection(const Core::Vector3 &direction)
Core::Vector3 getPosition() const
Return the position.
void setZoomFactor(const Scalar &zoomFactor)
Set the zoom factor to zoomFactor.
Core::Vector3 getUpVector() const
Return the up vector.
void setType(const ProjType &projectionType)
Set the projection type to projectionType.
Scalar getZoomFactor() const
Return the zoom factor.
void setFrame(const Core::Transform &frame)
Set the frame of the camera to frame.
ProjType getType() const
Return the projection type.
Scalar getAspect() const
Return the aspect ratio of the viewport.
Core::Transform getFrame() const
Core::Vector3 getDirection() const
Return the direction the camera is looking at.
virtual void setDirection(const Eigen::Matrix< Scalar, 3, 1 > &)
virtual void setPosition(const Eigen::Matrix< Scalar, 3, 1 > &)
The CameraManipulator class is the generic class for camera manipulators.
Scalar m_lastMouseX
x-position of the mouse on the screen at the manipulation start.
Scalar m_quickCameraModifier
Additional factor for camera sensitivity.
Core::Asset::Camera * m_camera
The Camera.
Scalar m_lastMouseY
y-position of the mouse on the screen at the manipulation start.
Scalar m_wheelSpeedModifier
Speed modifier on mouse wheel events.
Engine::Scene::Light * m_light
The light attached to the Camera.
Scalar m_cameraSensitivity
the Camera sensitivity to manipulation.
bool triggerEventCallback(QEvent *event, int key, bool wheel=false)
void addEventCallback(KeyMappingAction action, Callback callback)
Ra::Core::Utils::Index KeyMappingAction
handle to an action
Ra::Core::Utils::Index Context
handle to a Context
const Core::Transform::ConstTranslationPart getTrackballCenter() const
virtual ~TrackballCameraManipulator()
Destructor.
KeyMappingManager::Context mappingContext() override
bool handleWheelEvent(QWheelEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
Scalar getTrackballRadius() const
Return the distance from the camera to the target point.
bool handleKeyPressEvent(QKeyEvent *event, const KeyMappingManager::KeyMappingAction &action) override
void updateCamera() override
bool handleMouseReleaseEvent(QMouseEvent *event) override
Scalar m_phiDir
sign of m_theta at mousePressEvent, to guide the phi rotation direction.
TrackballCameraManipulator()
Default constructor.
bool handleMousePressEvent(QMouseEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
void resetCamera() override
Core::Transform m_referenceFrame
initial frame of the camera, centered on target, to compute angles.
bool handleMouseMoveEvent(QMouseEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
void setTrackballRadius(Scalar rad)
void updatePhiTheta()
Update the polar coordinates of the Camera w.r.t. the trackball center.
Scalar m_distFromCenter
The distance from the camera to the trackball center.
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type areApproxEqual(T x, T y, T espilonBoostFactor=T(10))
Compare two numbers such that |x-y| < espilon*epsilonBoostFactor.
constexpr T signNZ(const T &val)
constexpr int sign(const T &val)
Returns the sign of any numeric type as { -1, 0, 1}.
hepler function to manage enum as underlying types in VariableSet