1 #include <Gui/Viewer/FlightCameraManipulator.hpp>
3 #include <Core/Asset/Camera.hpp>
4 #include <Core/Math/Math.hpp>
5 #include <Core/Utils/Log.hpp>
6 #include <Engine/Scene/Light.hpp>
7 #include <Gui/Utils/Keyboard.hpp>
9 #include <Gui/Utils/KeyMappingManager.hpp>
11 #include <Engine/Scene/CameraComponent.hpp>
12 #include <QApplication>
13 #include <QMessageBox>
23 using namespace Core::Utils;
28 #define KMA_VALUE( XX ) Gui::KeyMappingManager::KeyMappingAction Gui::FlightCameraManipulator::XX;
29 KeyMappingFlightManipulator
32 void FlightCameraManipulator::configureKeyMapping_impl() {
34 FlightCameraKeyMapping::setContext(
35 Gui::KeyMappingManager::getInstance()->getContext(
"FlightManipulatorContext" ) );
37 if ( KeyMapping::getContext().isInvalid() ) {
39 <<
"CameraContext not defined (maybe the configuration file do not contains "
40 "it). Add it for default key mapping.";
41 FlightCameraKeyMapping::setContext(
42 Gui::KeyMappingManager::getInstance()->addContext(
"FlightManipulatorContext" ) );
45 #define KMA_VALUE( XX ) \
46 XX = Gui::KeyMappingManager::getInstance()->getAction( FlightCameraKeyMapping::getContext(), \
48 KeyMappingFlightManipulator
51 auto mgr = Gui::KeyMappingManager::getInstance();
52 auto context = FlightCameraKeyMapping::getContext();
55 using ActionBindingPair = std::pair<std::reference_wrapper<KeyMappingManager::KeyMappingAction>,
56 KeyMappingManager::EventBinding>;
59 std::map<std::string, ActionBindingPair> defaultBinding;
61 defaultBinding.insert(
62 std::make_pair( std::string {
"FLIGHTMODECAMERA_PAN" },
63 ActionBindingPair { FLIGHTMODECAMERA_PAN,
64 mgr->createEventBindingFromStrings(
65 "LeftButton",
"ShiftModifier" ) } ) );
67 defaultBinding.insert( std::make_pair(
68 std::string {
"FLIGHTMODECAMERA_ROTATE" },
69 ActionBindingPair { FLIGHTMODECAMERA_ROTATE,
70 mgr->createEventBindingFromStrings(
"LeftButton" ) } ) );
72 defaultBinding.insert(
73 std::make_pair( std::string {
"FLIGHTMODECAMERA_ZOOM" },
74 ActionBindingPair { FLIGHTMODECAMERA_ZOOM,
75 mgr->createEventBindingFromStrings(
76 "LeftButton",
"ControlModifier" ) } ) );
78 for (
auto& [actionName, actionBinding] : defaultBinding ) {
79 if ( actionBinding.first.get().isInvalid() ) {
80 LOG( logWARNING ) <<
"FlightManipulator action " << actionName
81 <<
" not defined in configuration file. Adding default keymapping.";
82 actionBinding.first.get() = mgr->addAction( context, actionBinding.second, actionName );
88 void FlightCameraManipulator::setupKeyMappingCallbacks() {
90 m_keyMappingCallbackManager.addEventCallback( FLIGHTMODECAMERA_PAN,
91 [=]( QEvent* event ) { panCallback( event ); } );
92 m_keyMappingCallbackManager.addEventCallback(
93 FLIGHTMODECAMERA_ROTATE, [=]( QEvent* event ) { rotateCallback( event ); } );
95 m_keyMappingCallbackManager.addEventCallback( FLIGHTMODECAMERA_ZOOM,
96 [=]( QEvent* event ) { zoomCallback( event ); } );
99 void FlightCameraManipulator::panCallback( QEvent* event ) {
100 if ( event->type() == QEvent::MouseMove ) {
101 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
102 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
103 handleCameraPan( dx, dy );
107 void FlightCameraManipulator::rotateCallback( QEvent* event ) {
108 if ( event->type() == QEvent::MouseMove ) {
109 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
110 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
111 handleCameraRotate( dx, dy );
115 void FlightCameraManipulator::zoomCallback( QEvent* event ) {
116 if ( event->type() == QEvent::MouseMove ) {
117 auto mouseEvent =
reinterpret_cast<QMouseEvent*
>( event );
118 auto [dx, dy] = computeDeltaMouseMove( mouseEvent );
119 handleCameraZoom( dx, dy );
121 if ( event->type() == QEvent::Wheel ) {
122 auto wheelEvent =
reinterpret_cast<QWheelEvent*
>( event );
124 ( wheelEvent->angleDelta().y() * 0.01_ra + wheelEvent->angleDelta().x() * 0.01_ra ) *
125 m_wheelSpeedModifier );
130 return FlightCameraKeyMapping::getContext();
133 FlightCameraManipulator::FlightCameraManipulator() :
136 setupKeyMappingCallbacks();
144 initializeFixedUpVector();
145 setupKeyMappingCallbacks();
154 initializeFixedUpVector();
157 m_flightSpeed = 0.2_ra;
165 void FlightCameraManipulator::resetCamera() {
168 initializeFixedUpVector();
171 m_flightSpeed = 0.2_ra;
180 const Qt::MouseButtons&,
181 const Qt::KeyboardModifiers&,
190 const Qt::MouseButtons& ,
191 const Qt::KeyboardModifiers& ,
212 const Qt::MouseButtons&,
213 const Qt::KeyboardModifiers&,
232 void FlightCameraManipulator::setCameraPosition(
const Core::Vector3& position ) {
234 QMessageBox::warning(
nullptr,
"Error",
"Position cannot be set to target point" );
246 void FlightCameraManipulator::setCameraTarget(
const Core::Vector3& target ) {
248 QMessageBox::warning(
nullptr,
"Error",
"Target cannot be set to current camera position" );
258 void FlightCameraManipulator::fitScene(
const Core::Aabb& aabb ) {
264 const Scalar r = ( aabb.max() - aabb.min() ).norm() / 2_ra;
265 const Scalar x = r / std::sin( f / 2_ra );
266 const Scalar y = r / std::sin( f * a / 2_ra );
267 Scalar d = std::max( std::max( x, y ), 0.001_ra );
270 Core::Vector3( aabb.center().x(), aabb.center().y(), aabb.center().z() + d ) );
272 initializeFixedUpVector();
275 m_flightSpeed = d / 10_ra;
277 Scalar zfar = std::max( d + ( aabb.max().z() - aabb.min().z() ) * 2_ra,
m_camera->
getZFar() );
286 void FlightCameraManipulator::handleCameraRotate( Scalar dx, Scalar dy ) {
290 Core::Transform R( Core::Transform::Identity() );
291 if ( std::abs( dphi ) > std::abs( dtheta ) ) {
292 R = Core::AngleAxis( -dphi, m_fixUpVector );
294 else { R = Core::AngleAxis( -dtheta, -
m_camera->getRightVector().normalized() ); }
302 void FlightCameraManipulator::handleCameraPan( Scalar dx, Scalar dy ) {
306 Core::Vector3 R = -
m_camera->getRightVector();
307 Core::Vector3 U = m_fixUpVector;
309 Core::Transform T( Core::Transform::Identity() );
310 Core::Vector3 t = x * R + y * U;
317 void FlightCameraManipulator::handleCameraZoom( Scalar dx, Scalar dy ) {
321 void FlightCameraManipulator::handleCameraZoom( Scalar z ) {
323 Core::Transform T( Core::Transform::Identity() );
330 void FlightCameraManipulator::initializeFixedUpVector() {
334 if ( std::abs(upVector[0]) > std::abs(upVector[1]) )
336 if ( std::abs(upVector[0]) > std::abs(upVector[2]) ) { m_fixUpVector = Ra::Core::Vector3( 1, 0, 0 ); }
338 { m_fixUpVector = Ra::Core::Vector3( 0, 0, 1 ); }
340 else if ( std::abs(upVector[1]) > std::abs(upVector[2]) )
341 { m_fixUpVector = Ra::Core::Vector3( 0, 1, 0 ); }
343 { m_fixUpVector = Ra::Core::Vector3( 0, 0, 1 ); }
345 m_fixUpVector = Ra::Core::Vector3( 0_ra, 1_ra, 0_ra );
Scalar getZFar() const
Return the Z Far plane distance from the camera.
void setPosition(const Core::Vector3 &position)
Set the position of the camera to position.
void setDirection(const Core::Vector3 &direction)
void setZFar(Scalar zFar)
Set the Z Far plane distance to zFar.
Core::Vector3 getPosition() const
Return the position.
Core::Vector3 getUpVector() const
Return the up vector.
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::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.
Engine::Scene::Light * m_light
The light attached to the Camera.
Scalar m_cameraSensitivity
the Camera sensitivity to manipulation.
bool handleKeyPressEvent(QKeyEvent *event, const KeyMappingManager::KeyMappingAction &action) override
bool handleWheelEvent(QWheelEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
virtual ~FlightCameraManipulator()
[Constructor]
bool handleMousePressEvent(QMouseEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
bool handleMouseReleaseEvent(QMouseEvent *event) override
void updateCamera() override
bool handleMouseMoveEvent(QMouseEvent *event, const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &modifiers, int key) override
KeyMappingManager::Context mappingContext() override
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
constexpr int sign(const T &val)
Returns the sign of any numeric type as { -1, 0, 1}.