40 using ScalarType = Scalar;
51 using MotionType = vcl::TrackBall<Scalar>::MotionType;
54 static constexpr double DISCRETE_TRANSLATION_STEP = 0.1;
55 static constexpr double DISCRETE_ROTATION_STEP =
M_PI_4 / 3.0;
63 float mDefaultTrackBallRadius = 1.0;
66 KeyModifiers mCurrentKeyModifiers = {KeyModifier::NO_MODIFIER};
69 MouseButton::Enum mCurrentMouseButton = MouseButton::NO_BUTTON;
71 std::map<std::pair<MouseButton::Enum, KeyModifiers>, MotionType>
74 {{MouseButton::LEFT, {KeyModifier::NO_MODIFIER}},
76 {{MouseButton::LEFT, {KeyModifier::CONTROL}}, TrackBallType::PAN },
77 {{MouseButton::LEFT, {KeyModifier::ALT}}, TrackBallType::ZMOVE},
78 {{MouseButton::LEFT, {KeyModifier::SHIFT}}, TrackBallType::SCALE},
79 {{MouseButton::MIDDLE, {KeyModifier::NO_MODIFIER}},
81 {{MouseButton::MIDDLE, {KeyModifier::CONTROL}},
82 TrackBallType::ROLL },
83 {{MouseButton::LEFT, {KeyModifier::SHIFT, KeyModifier::CONTROL}},
84 TrackBallType::DIR_LIGHT_ARC },
88 using Axis =
unsigned char;
89 std::map<std::pair<KeyModifiers, Axis>, MotionType> mScrollAtomicMap = {
90 {{{KeyModifier::NO_MODIFIER}, 1}, TrackBallType::SCALE},
91 {{{KeyModifier::CONTROL}, 1}, TrackBallType::ROLL },
92 {{{KeyModifier::SHIFT}, 1}, TrackBallType::FOV },
94 {{{KeyModifier::SHIFT}, 0}, TrackBallType::FOV },
99 std::pair<Key::Enum, KeyModifiers>,
102 {{Key::R, {KeyModifier::NO_MODIFIER}},
105 mDefaultTrackBallCenter, 1.5 / mDefaultTrackBallRadius);
107 {{Key::R, {KeyModifier::CONTROL, KeyModifier::SHIFT}},
109 t.resetDirectionalLight();
113 {{Key::NP_2, {KeyModifier::NO_MODIFIER}},
115 rotate(t, UNIT_X, DISCRETE_ROTATION_STEP);
117 {{Key::NP_4, {KeyModifier::NO_MODIFIER}},
119 rotate(t, UNIT_Y, -DISCRETE_ROTATION_STEP);
121 {{Key::NP_6, {KeyModifier::NO_MODIFIER}},
123 rotate(t, UNIT_Y, DISCRETE_ROTATION_STEP);
125 {{Key::NP_8, {KeyModifier::NO_MODIFIER}},
127 rotate(t, UNIT_X, -DISCRETE_ROTATION_STEP);
131 {{Key::UP, {KeyModifier::NO_MODIFIER}},
133 translate(t, UNIT_Y * DISCRETE_TRANSLATION_STEP);
135 {{Key::DOWN, {KeyModifier::NO_MODIFIER}},
137 translate(t, -UNIT_Y * DISCRETE_TRANSLATION_STEP);
139 {{Key::LEFT, {KeyModifier::NO_MODIFIER}},
141 translate(t, -UNIT_X * DISCRETE_TRANSLATION_STEP);
143 {{Key::RIGHT, {KeyModifier::NO_MODIFIER}},
145 translate(t, UNIT_X * DISCRETE_TRANSLATION_STEP);
149 {{Key::NP_1, {KeyModifier::NO_MODIFIER}},
153 {{Key::NP_7, {KeyModifier::NO_MODIFIER}},
156 rotate(t, UNIT_X,
M_PI_2);
158 {{Key::NP_3, {KeyModifier::NO_MODIFIER}},
161 rotate(t, UNIT_Y, -
M_PI_2);
163 {{Key::NP_1, {KeyModifier::CONTROL}},
166 rotate(t, UNIT_Y,
M_PI);
168 {{Key::NP_7, {KeyModifier::CONTROL}},
171 rotate(t, UNIT_X, -
M_PI_2);
173 {{Key::NP_3, {KeyModifier::CONTROL}},
176 rotate(t, UNIT_Y,
M_PI_2);
179 {{Key::NP_5, {KeyModifier::NO_MODIFIER}},
182 t.projectionMode() ==
186 t.setProjectionMode(v);
190 {{Key::NP_2, {KeyModifier::CONTROL, KeyModifier::SHIFT}},
192 rotateLight(t, UNIT_X, DISCRETE_ROTATION_STEP);
194 {{Key::NP_4, {KeyModifier::CONTROL, KeyModifier::SHIFT}},
196 rotateLight(t, UNIT_Y, -DISCRETE_ROTATION_STEP);
198 {{Key::NP_6, {KeyModifier::CONTROL, KeyModifier::SHIFT}},
200 rotateLight(t, UNIT_Y, DISCRETE_ROTATION_STEP);
202 {{Key::NP_8, {KeyModifier::CONTROL, KeyModifier::SHIFT}},
204 rotateLight(t, UNIT_X, -DISCRETE_ROTATION_STEP);
212 resizeViewer(width, height);
215 const Camera<Scalar>& camera()
const {
return mTrackball.camera(); }
221 return mTrackball.projectionMatrix();
227 mDefaultTrackBallCenter, 1.5 / mDefaultTrackBallRadius);
232 mTrackball.applyAtomicMotion(TrackBallType::FOCUS, center);
237 mDefaultTrackBallCenter = center;
238 mDefaultTrackBallRadius = radius;
247 return mTrackball.lightGizmoMatrix();
254 void onResize(
unsigned int width,
unsigned int height)
override
256 resizeViewer(width, height);
307 bool isDragging()
const {
return mTrackball.isDragging(); }
309 MotionType currentMotion()
const {
return mTrackball.currentMotion(); }
316 mTrackball.setScreenSize(w,
h);
319 void setKeyModifiers(
KeyModifiers keys) { mCurrentKeyModifiers = keys; }
321 void moveMouse(
int x,
int y)
324 auto it = mDragMotionMap.find(
325 std::make_pair(mCurrentMouseButton, mCurrentKeyModifiers));
326 if (
it != mDragMotionMap.end()) {
327 mTrackball.beginDragMotion(
it->second);
329 mTrackball.setMousePosition(x, y);
333 void pressMouse(MouseButton::Enum
button)
336 if (mTrackball.isDragging()) {
340 mCurrentMouseButton =
button;
343 mDragMotionMap.find(std::make_pair(
button, mCurrentKeyModifiers));
344 if (
it != mDragMotionMap.end()) {
345 mTrackball.beginDragMotion(
it->second);
352 void releaseMouse(MouseButton::Enum
button)
355 if (mTrackball.isDragging() && mCurrentMouseButton ==
button) {
356 mCurrentMouseButton = MouseButton::NO_BUTTON;
360 mDragMotionMap.find(std::make_pair(
button, mCurrentKeyModifiers));
361 if (
it != mDragMotionMap.end()) {
362 mTrackball.endDragMotion(
it->second);
374 auto it = mScrollAtomicMap.find({mCurrentKeyModifiers, Axis(0)});
375 if (
it != mScrollAtomicMap.end()) {
381 auto it = mScrollAtomicMap.find({mCurrentKeyModifiers, Axis(1)});
382 if (
it != mScrollAtomicMap.end()) {
388 void keyPress(Key::Enum key)
391 auto atomicOp = mKeyAtomicMap.find({key, mCurrentKeyModifiers});
392 if (
atomicOp != mKeyAtomicMap.end()) {
397 auto it = mDragMotionMap.find(
398 std::make_pair(mCurrentMouseButton, mCurrentKeyModifiers));
399 if (
it != mDragMotionMap.end()) {
400 mTrackball.beginDragMotion(
it->second);
403 mTrackball.endDragMotion(currentMotion());
408 void keyRelease(Key::Enum key)
411 if (!mTrackball.isDragging())
415 auto it = mDragMotionMap.find(
416 std::make_pair(mCurrentMouseButton, mCurrentKeyModifiers));
417 if (
it != mDragMotionMap.end()) {
418 mTrackball.beginDragMotion(
it->second);
421 mTrackball.endDragMotion(currentMotion());
429 Scalar angle =
M_PI / 6)
431 using Args =
typename TrackBallType::TransformArgs;
432 t.applyAtomicMotion(TrackBallType::ARC, Args(axis, angle));
435 static void rotateLight(
438 Scalar angle =
M_PI / 6)
440 using Args =
typename TrackBallType::TransformArgs;
441 t.applyAtomicMotion(TrackBallType::DIR_LIGHT_ARC, Args(axis, angle));
446 t.applyAtomicMotion(TrackBallType::PAN,
translation);