This commit is contained in:
2020-06-18 18:25:03 -06:00
commit e01c09fbcc
17 changed files with 2689 additions and 0 deletions

100
src/arc_ball.h Normal file
View File

@@ -0,0 +1,100 @@
#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