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>
10 #include <Engine/Scene/SystemDisplay.hpp>
11 #include <Gui/Utils/KeyMappingManager.hpp>
12 #include <Gui/Utils/Keyboard.hpp>
14 #include <Engine/Scene/CameraComponent.hpp>
15 #include <QApplication>
16 #include <QMessageBox>
23 using namespace Ra::Core::Utils;
27 #define KMA_VALUE( XX ) KeyMappingManager::KeyMappingAction TrackballCameraManipulator::XX;
31 void 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 );
47 void TrackballCameraManipulator::setupKeyMappingCallbacks() {
49 m_keyMappingCallbackManager.addEventCallback(
50 TRACKBALLCAMERA_ROTATE, [=]( QEvent* event ) { rotateCallback( event ); } );
51 m_keyMappingCallbackManager.addEventCallback( TRACKBALLCAMERA_PAN,
52 [=]( QEvent* event ) { panCallback( event ); } );
53 m_keyMappingCallbackManager.addEventCallback( TRACKBALLCAMERA_ZOOM,
54 [=]( QEvent* event ) { zoomCallback( event ); } );
55 m_keyMappingCallbackManager.addEventCallback(
56 TRACKBALLCAMERA_MOVE_FORWARD, [=]( QEvent* event ) { moveForwardCallback( event ); } );
58 m_keyMappingCallbackManager.addEventCallback( TRACKBALLCAMERA_PROJ_MODE, [=]( QEvent* ) {
60 m_camera->setType( m_camera->getType() == ProjType::ORTHOGRAPHIC ? ProjType::PERSPECTIVE
61 : ProjType::ORTHOGRAPHIC );
64 m_keyMappingCallbackManager.addEventCallback( CAMERA_TOGGLE_QUICK, [=]( QEvent* ) {
65 static bool quick =
false;
67 if ( quick ) { m_quickCameraModifier = 10.0_ra; }
68 else { m_quickCameraModifier = 1.0_ra; }
75 setupKeyMappingCallbacks();
88 setupKeyMappingCallbacks();
142 return KeyMapping::getContext();
145 void TrackballCameraManipulator::mousePressSaveData(
const QMouseEvent* mouseEvent ) {
151 void 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 );
159 void 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 );
167 void 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 ) *
181 void 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&,
255 void TrackballCameraManipulator::setCameraPosition(
const Core::Vector3& position ) {
257 QMessageBox::warning(
nullptr,
"Error",
"Position cannot be set to target point" );
271 void TrackballCameraManipulator::setCameraTarget(
const Core::Vector3& target ) {
273 QMessageBox::warning(
nullptr,
"Error",
"Target cannot be set to current camera position" );
286 void 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 );
293 Scalar d = std::max( std::max( x, y ), 0.001_ra );
296 Core::Vector3 camPos { aabb.center().x(), aabb.center().y(), aabb.center().z() + d };
298 Core::Vector3 camDir { aabb.center() - camPos };
314 void TrackballCameraManipulator::handleCameraRotate( Scalar dx, Scalar dy ) {
318 Scalar phi =
m_phi + dphi;
319 Scalar theta = m_theta + dtheta;
320 Core::Vector3 dir { std::sin( phi ) * std::sin( theta ),
322 std::cos( phi ) * std::sin( theta ) };
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;
355 void 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;
370 void TrackballCameraManipulator::handleCameraMoveForward( Scalar dx, Scalar dy ) {
374 void TrackballCameraManipulator::handleCameraMoveForward( Scalar z ) {
378 Core::Transform T( Core::Transform::Identity() );
386 void TrackballCameraManipulator::handleCameraZoom( Scalar dx, Scalar dy ) {
390 void TrackballCameraManipulator::handleCameraZoom( Scalar z ) {
399 m_theta = std::acos( R.y() );
404 if ( UNLIKELY( areApproxEqual( R.z(), 0_ra ) && areApproxEqual( R.x(), 0_ra ) ) ) {
407 m_phi = std::atan2( fx, fy );
409 else {
m_phi = std::atan2( R.x(), R.z() ); }
414 CORE_ASSERT( std::isfinite( m_theta ) && std::isfinite(
m_phi ),
"Error in trackball camera" );
417 void TrackballCameraManipulator::clampThetaPhi() {
421 if ( m_theta < -Pi ) { m_theta += 2_ra * Pi; }
422 if ( m_theta > Pi ) { m_theta -= 2_ra * Pi; }
425 bool 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.
Scalar getZoomFactor() const
Return the zoom factor.
void setFrame(const Core::Transform &frame)
Set the frame of the camera to frame.
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)
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}.