101 lines
3.5 KiB
C++
101 lines
3.5 KiB
C++
#ifndef ARCBALL_H
|
|
#define ARCBALL_H
|
|
|
|
#include <Magnum/Magnum.h>
|
|
#include <Magnum/Math/DualQuaternion.h>
|
|
#include <Magnum/Math/Functions.h>
|
|
#include <Magnum/Math/Vector2.h>
|
|
#include <Magnum/Math/Vector3.h>
|
|
|
|
using namespace Magnum;
|
|
|
|
Quaternion ndcToArcBall(const Vector2 &p);
|
|
|
|
/* Implementation of Ken Shoemake's arcball camera with smooth navigation
|
|
feature: https://www.talisman.org/~erlkonig/misc/shoemake92-arcball.pdf */
|
|
class ArcBall {
|
|
public:
|
|
ArcBall(const Vector3 &cameraPosition, const Vector3 &viewCenter,
|
|
const Vector3 &upDir, Deg fov, const Vector2i &windowSize);
|
|
|
|
/* Set the camera view parameters: eye position, view center, up
|
|
direction */
|
|
void setViewParameters(const Vector3 &eye, const Vector3 &viewCenter,
|
|
const Vector3 &upDir);
|
|
|
|
/* Reset the camera to its initial position, view center, and up dir */
|
|
void reset();
|
|
|
|
/* Update screen size after the window has been resized */
|
|
void reshape(const Vector2i &windowSize) { m_windowSize = windowSize; }
|
|
|
|
/* Update any unfinished transformation due to lagging, return true if
|
|
the camera matrices have changed */
|
|
bool updateTransformation();
|
|
|
|
/* Get/set the amount of lagging such that the camera will (slowly)
|
|
smoothly navigate. Lagging must be in [0, 1) */
|
|
Float lagging() const { return m_lagging; }
|
|
void setLagging(Float lagging);
|
|
|
|
/* Initialize the first (screen) mouse position for camera
|
|
transformation. This should be called in mouse pressed event. */
|
|
void initTransformation(const Vector2i &mousePos);
|
|
|
|
/* Rotate the camera from the previous (screen) mouse position to the
|
|
current (screen) position */
|
|
void rotate(const Vector2i &mousePos);
|
|
|
|
/* Translate the camera from the previous (screen) mouse position to
|
|
the current (screen) mouse position */
|
|
void translate(const Vector2i &mousePos);
|
|
|
|
/* Translate the camera by the delta amount of (NDC) mouse position.
|
|
Note that NDC position must be in [-1, -1] to [1, 1]. */
|
|
void translateDelta(const Vector2 &translationNDC);
|
|
|
|
/* Zoom the camera (positive delta = zoom in, negative = zoom out) */
|
|
void zoom(Float delta);
|
|
|
|
/* Get the camera's view transformation as a qual quaternion */
|
|
const DualQuaternion &view() const { return m_view; }
|
|
|
|
/* Get the camera's view transformation as a matrix */
|
|
Matrix4 viewMatrix() const { return m_view.toMatrix(); }
|
|
|
|
/* Get the camera's inverse view matrix (which also produces
|
|
transformation of the camera) */
|
|
Matrix4 inverseViewMatrix() const { return m_inverseView.toMatrix(); }
|
|
|
|
/* Get the camera's transformation as a dual quaternion */
|
|
const DualQuaternion &transformation() const { return m_inverseView; }
|
|
|
|
/* Get the camera's transformation matrix */
|
|
Matrix4 transformationMatrix() const { return m_inverseView.toMatrix(); }
|
|
|
|
/* Return the distance from the camera position to the center view */
|
|
Float viewDistance() const { return Math::abs(m_targetZooming); }
|
|
|
|
protected:
|
|
/* Update the camera transformations */
|
|
void updateInternalTransformations();
|
|
|
|
/* Transform from screen coordinate to NDC - normalized device
|
|
coordinate. The top-left of the screen corresponds to [-1, 1] NDC,
|
|
and the bottom right is [1, -1] NDC. */
|
|
Vector2 screenCoordToNDC(const Vector2i &mousePos) const;
|
|
|
|
Deg m_fov;
|
|
Vector2i m_windowSize;
|
|
|
|
Vector2 m_prevMousePosNDC;
|
|
Float m_lagging{};
|
|
|
|
Vector3 m_targetPosition, m_currentPosition, m_positionT0;
|
|
Quaternion m_targetQRotation, m_currentQRotation, m_qRotationT0;
|
|
Float m_targetZooming, m_currentZooming, m_zoomingT0;
|
|
DualQuaternion m_view, m_inverseView;
|
|
};
|
|
|
|
#endif
|