mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Integrated from CeeSol Perforce, changelist 203
AppFwk tests. Added rotation to locator. Caf::FrameAnimationControl : Set current frame to 0 if a framecount change makes the current frame invalid
This commit is contained in:
@@ -159,6 +159,7 @@ LocatorPanWalkRotate::LocatorPanWalkRotate(Camera* camera)
|
||||
: m_camera(camera),
|
||||
m_operation(PAN),
|
||||
m_pos(0, 0, 0),
|
||||
m_rotQuat(0, 0, 0, 1),
|
||||
m_lastPosX(0),
|
||||
m_lastPosY(0)
|
||||
{
|
||||
@@ -202,6 +203,24 @@ Vec3d LocatorPanWalkRotate::position() const
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void LocatorPanWalkRotate::setOrientation(const Mat3d& m)
|
||||
{
|
||||
m_rotQuat = Quatd::fromRotationMatrix(Mat4d(m));
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
cvf::Mat3d LocatorPanWalkRotate::orientation() const
|
||||
{
|
||||
return m_rotQuat.toMatrix3();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// The window coordinates are in OpenGL style coordinates, which means a right handed
|
||||
/// coordinate system with the origin in the lower left corner of the window.
|
||||
@@ -221,31 +240,39 @@ bool LocatorPanWalkRotate::update(int x, int y)
|
||||
{
|
||||
CVF_ASSERT(m_camera.notNull());
|
||||
|
||||
if (x == m_lastPosX && y == m_lastPosY) return false;
|
||||
if (x == m_lastPosX && y == m_lastPosY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const double vpPixSizeX = m_camera->viewport()->width();
|
||||
const double vpPixSizeY = m_camera->viewport()->height();
|
||||
if (vpPixSizeX <= 0 || vpPixSizeY <= 0) return false;
|
||||
// Need a non-zero viewport
|
||||
if (m_camera->viewport()->width() <= 0 ||
|
||||
m_camera->viewport()->height() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Normalized movement in screen plane
|
||||
const double tx = (x - m_lastPosX)/vpPixSizeX;
|
||||
const double ty = (y - m_lastPosY)/vpPixSizeY;
|
||||
|
||||
Vec3d oldPos = m_pos;
|
||||
Quatd oldRotQuat = m_rotQuat;
|
||||
|
||||
if (m_operation == PAN)
|
||||
{
|
||||
updatePan(tx, ty);
|
||||
updatePan(x, y);
|
||||
}
|
||||
else if (m_operation == WALK)
|
||||
{
|
||||
updateWalk(ty);
|
||||
updateWalk(y);
|
||||
}
|
||||
else if (m_operation == ROTATE)
|
||||
{
|
||||
updateRotation(x, y);
|
||||
}
|
||||
|
||||
m_lastPosX = x;
|
||||
m_lastPosY = y;
|
||||
|
||||
if (m_pos == oldPos)
|
||||
if (m_pos == oldPos && m_rotQuat == oldRotQuat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -259,10 +286,17 @@ bool LocatorPanWalkRotate::update(int x, int y)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void LocatorPanWalkRotate::updatePan(double tx, double ty)
|
||||
void LocatorPanWalkRotate::updatePan(int oglWinCoordX, int oglWinCoordY)
|
||||
{
|
||||
CVF_ASSERT(m_camera.notNull());
|
||||
|
||||
// Normalized movement in screen plane [0, 1]
|
||||
const double vpPixSizeX = m_camera->viewport()->width();
|
||||
const double vpPixSizeY = m_camera->viewport()->height();
|
||||
CVF_ASSERT(vpPixSizeX > 0 && vpPixSizeY > 0);
|
||||
const double tx = (oglWinCoordX - m_lastPosX)/vpPixSizeX;
|
||||
const double ty = (oglWinCoordY - m_lastPosY)/vpPixSizeY;
|
||||
|
||||
// Viewport size in world coordinates
|
||||
const double aspect = m_camera->aspectRatio();
|
||||
const double vpWorldSizeY = m_camera->frontPlaneFrustumHeight();
|
||||
@@ -303,10 +337,15 @@ void LocatorPanWalkRotate::updatePan(double tx, double ty)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void LocatorPanWalkRotate::updateWalk(double ty)
|
||||
void LocatorPanWalkRotate::updateWalk(int oglWinCoordY)
|
||||
{
|
||||
CVF_ASSERT(m_camera.notNull());
|
||||
|
||||
// Normalized movement in screen plane [0, 1]
|
||||
const double vpPixSizeY = m_camera->viewport()->height();
|
||||
CVF_ASSERT(vpPixSizeY > 0);
|
||||
const double ty = (oglWinCoordY - m_lastPosY)/vpPixSizeY;
|
||||
|
||||
const double vpWorldSizeY = m_camera->frontPlaneFrustumHeight();
|
||||
const Vec3d camDir = m_camera->direction();
|
||||
|
||||
@@ -337,5 +376,127 @@ void LocatorPanWalkRotate::updateWalk(double ty)
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void LocatorPanWalkRotate::updateRotation(int oglWinCoordX, int oglWinCoordY)
|
||||
{
|
||||
CVF_ASSERT(m_camera.notNull());
|
||||
|
||||
const double vpPixSizeX = m_camera->viewport()->width();
|
||||
const double vpPixSizeY = m_camera->viewport()->height();
|
||||
CVF_ASSERT(vpPixSizeX > 0 && vpPixSizeY > 0);
|
||||
|
||||
// Scale the new/last positions to the range [-1.0, 1.0]
|
||||
const double newPosX = 2.0*(oglWinCoordX/vpPixSizeX) - 1.0;
|
||||
const double newPosY = 2.0*((vpPixSizeY - oglWinCoordY)/vpPixSizeY) - 1.0;
|
||||
const double oldPosX = 2.0*(m_lastPosX/vpPixSizeX) - 1.0;
|
||||
const double oldPosY = 2.0*((vpPixSizeY - m_lastPosY)/vpPixSizeY) - 1.0;
|
||||
|
||||
// For now, use hard-coded value for trackball radius and sensitivity
|
||||
// Sensitivity could be exposed directly, but trackball rotation needs more consideration.
|
||||
// An idea would be for the user to be able to set an approximate size of the locator's visual representation in world coords,
|
||||
// and then we could estimate its current size relative to viewport, and then use that as trackball radius.
|
||||
// See trackballRotation() for some more info on trackballRadius (we've always used 0.8 as an approximation)
|
||||
const double trackballRadius = 0.8;
|
||||
const double rotateSensitivity = 1.0;
|
||||
Mat4d viewMat = m_camera->viewMatrix();
|
||||
Quatd incrementalRotationQuat = trackballRotation(oldPosX, -oldPosY, newPosX, -newPosY, viewMat, trackballRadius, rotateSensitivity);
|
||||
|
||||
// Update rotation quaternion
|
||||
Mat4d incRotationMatrix = incrementalRotationQuat.toMatrix4();
|
||||
incRotationMatrix.translatePostMultiply(-m_pos);
|
||||
incRotationMatrix.translatePreMultiply(m_pos);
|
||||
|
||||
Mat4d rotMat = m_rotQuat.toMatrix4();
|
||||
rotMat = incRotationMatrix*rotMat;
|
||||
|
||||
m_rotQuat = Quatd::fromRotationMatrix(rotMat);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Compute quaternion rotation
|
||||
///
|
||||
/// \param oldPosX x coordinate of the last position of the mouse, in the range [-1.0, 1.0]
|
||||
/// \param oldPosY y coordinate of the last position of the mouse, in the range [-1.0, 1.0]
|
||||
/// \param newPosX x coordinate of current position of the mouse, in the range [-1.0, 1.0]
|
||||
/// \param newPosY y coordinate of current position of the mouse, in the range [-1.0, 1.0]
|
||||
/// \param currViewMatrix Current transformation matrix. The inverse is used when calculating the rotation
|
||||
/// \param sensitivityFactor Mouse sensitivity factor
|
||||
///
|
||||
/// Simulate a track-ball. Project the points onto the virtual trackball, then figure out the axis
|
||||
/// of rotation. This is a deformed trackball-- is a trackball in the center, but is deformed into a
|
||||
/// hyperbolic sheet of rotation away from the center.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Quatd LocatorPanWalkRotate::trackballRotation(double oldPosX, double oldPosY, double newPosX, double newPosY, const Mat4d& currViewMatrix, double trackballRadius, double sensitivityFactor)
|
||||
{
|
||||
// This particular function was chosen after trying out several variations.
|
||||
// Implemented by Gavin Bell, lots of ideas from Thant Tessman and the August '88
|
||||
// issue of Siggraph's "Computer Graphics," pp. 121-129.
|
||||
|
||||
// This size should really be based on the distance from the center of rotation to the point on
|
||||
// the object underneath the mouse. That point would then track the mouse as closely as possible.
|
||||
//const double TRACKBALL_RADIUS = 0.8f;
|
||||
|
||||
// Clamp to valid range
|
||||
oldPosX = Math::clamp(oldPosX, -1.0, 1.0);
|
||||
oldPosY = Math::clamp(oldPosY, -1.0, 1.0);
|
||||
newPosX = Math::clamp(newPosX, -1.0, 1.0);
|
||||
newPosY = Math::clamp(newPosY, -1.0, 1.0);
|
||||
|
||||
// First, figure out z-coordinates for projection of P1 and P2 to deformed sphere
|
||||
Vec3d p1 = projectToSphere(trackballRadius, oldPosX, oldPosY);
|
||||
Vec3d p2 = projectToSphere(trackballRadius, newPosX, newPosY);
|
||||
|
||||
// Axis of rotation is the cross product of P1 and P2
|
||||
Vec3d a = p1 ^ p2;
|
||||
|
||||
// Figure out how much to rotate around that axis.
|
||||
Vec3d d = p1 - p2;
|
||||
double t = d.length()/(2.0*trackballRadius);
|
||||
|
||||
// Avoid problems with out-of-control values...
|
||||
t = Math::clamp(t, -1.0, 1.0);
|
||||
|
||||
double phi = 2.0*Math::asin(t);
|
||||
|
||||
// Scale by sensitivity factor
|
||||
phi *= sensitivityFactor;
|
||||
|
||||
// Use inverted matrix to find rotation axis
|
||||
Mat4d invMatr = currViewMatrix.getInverted();
|
||||
a.transformVector(invMatr);
|
||||
|
||||
// Get quaternion to be returned by pointer
|
||||
Quatd quat = Quatd::fromAxisAngle(a, phi);
|
||||
return quat;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d LocatorPanWalkRotate::projectToSphere(double radius, double posX, double posY)
|
||||
{
|
||||
double d = Math::sqrt(posX*posX + posY*posY);
|
||||
|
||||
if (d < radius*SQRT1_2_D)
|
||||
{
|
||||
// Inside sphere
|
||||
double projectedZ = Math::sqrt(radius*radius - d*d);
|
||||
|
||||
return Vec3d(posX, posY, projectedZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
// On hyperbola
|
||||
double t = radius/SQRT2_D;
|
||||
double projectedZ = t*t/d;
|
||||
|
||||
return Vec3d(posX, posY, projectedZ);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cvf
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "cvfPlane.h"
|
||||
#include "cvfQuat.h"
|
||||
|
||||
namespace cvf {
|
||||
|
||||
@@ -97,8 +98,8 @@ public:
|
||||
enum Operation
|
||||
{
|
||||
PAN,
|
||||
WALK
|
||||
//ROTATE // TODO
|
||||
WALK,
|
||||
ROTATE
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -106,20 +107,29 @@ public:
|
||||
~LocatorPanWalkRotate();
|
||||
|
||||
void setOperation(Operation op);
|
||||
|
||||
void setPosition(const Vec3d& position);
|
||||
virtual Vec3d position() const;
|
||||
void setOrientation(const Mat3d& m);
|
||||
Mat3d orientation() const;
|
||||
|
||||
virtual void start(int x, int y);
|
||||
virtual bool update(int x, int y);
|
||||
|
||||
private:
|
||||
void updatePan(double tx, double ty);
|
||||
void updateWalk(double ty);
|
||||
void updatePan(int oglWinCoordX, int oglWinCoordY);
|
||||
void updateWalk(int oglWinCoordY);
|
||||
void updateRotation(int oglWinCoordX, int oglWinCoordY);
|
||||
|
||||
static Quatd trackballRotation(double oldPosX, double oldPosY, double newPosX, double newPosY, const Mat4d& currViewMatrix, double trackballRadius, double sensitivityFactor);
|
||||
static Vec3d projectToSphere(double radius, double posX, double posY);
|
||||
|
||||
private:
|
||||
ref<Camera> m_camera;
|
||||
Operation m_operation; // Default operation is PAN
|
||||
Vec3d m_pos;
|
||||
int m_lastPosX;
|
||||
Quatd m_rotQuat;
|
||||
int m_lastPosX; // Last position, window coords, origin lower left (OpenGL style)
|
||||
int m_lastPosY;
|
||||
};
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include "cvfCamera.h"
|
||||
#include "cvfViewport.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace cvf {
|
||||
@@ -296,7 +295,7 @@ bool ManipulatorTrackball::zoom(int posX, int posY)
|
||||
Camera::ProjectionType projType = m_camera->projection();
|
||||
if (projType == Camera::PERSPECTIVE)
|
||||
{
|
||||
double fovY = 2*atan((newFrustumHeight/2)/nearPlane);
|
||||
double fovY = 2*Math::atan((newFrustumHeight/2)/nearPlane);
|
||||
if (fovY > 0)
|
||||
{
|
||||
m_camera->setProjectionAsPerspective(Math::toDegrees(fovY), nearPlane, farPlane);
|
||||
@@ -407,7 +406,7 @@ Quatd ManipulatorTrackball::trackballRotation(double oldPosX, double oldPosY, do
|
||||
// Avoid problems with out-of-control values...
|
||||
t = Math::clamp(t, -1.0, 1.0);
|
||||
|
||||
double phi = 2.0*asin(t);
|
||||
double phi = 2.0*Math::asin(t);
|
||||
|
||||
// Scale by sensitivity factor
|
||||
phi *= sensitivityFactor;
|
||||
@@ -437,12 +436,12 @@ Quatd ManipulatorTrackball::trackballRotation(double oldPosX, double oldPosY, do
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
Vec3d ManipulatorTrackball::projectToSphere(double radius, double posX, double posY)
|
||||
{
|
||||
double d = sqrt(posX*posX + posY*posY);
|
||||
double d = Math::sqrt(posX*posX + posY*posY);
|
||||
|
||||
if (d < radius*SQRT1_2_D)
|
||||
{
|
||||
// Inside sphere
|
||||
double projectedZ = sqrt(radius*radius - d*d);
|
||||
double projectedZ = Math::sqrt(radius*radius - d*d);
|
||||
|
||||
return Vec3d(posX, posY, projectedZ);
|
||||
}
|
||||
|
||||
@@ -231,9 +231,20 @@ void Manipulators::onPaintEvent(PostEventAction* postEventAction)
|
||||
m_camera->applyOpenGL();
|
||||
|
||||
GeometryBuilderDrawableGeo builder;
|
||||
GeometryUtils::createBox(Vec3f(m_activeLocator->position()), 0.2f, 0.2f, 0.2f, &builder);
|
||||
|
||||
GeometryUtils::createBox(Vec3f::ZERO, 0.2f, 0.2f, 0.2f, &builder);
|
||||
ref<DrawableGeo> boxGeo = builder.drawableGeo();
|
||||
|
||||
Mat4d transform;
|
||||
|
||||
if (dynamic_cast<LocatorPanWalkRotate*>(m_activeLocator.p()))
|
||||
{
|
||||
LocatorPanWalkRotate* loc = dynamic_cast<LocatorPanWalkRotate*>(m_activeLocator.p());
|
||||
transform.setFromMatrix3(loc->orientation());
|
||||
}
|
||||
|
||||
transform.translatePreMultiply(m_activeLocator->position());
|
||||
|
||||
boxGeo->transform(transform);
|
||||
boxGeo->computeNormals();
|
||||
|
||||
RenderStateLighting_FF lighting;
|
||||
@@ -262,15 +273,19 @@ void Manipulators::onMousePressEvent(MouseButton buttonPressed, MouseEvent* mous
|
||||
if (dynamic_cast<LocatorPanWalkRotate*>(m_activeLocator.p()))
|
||||
{
|
||||
LocatorPanWalkRotate* loc = dynamic_cast<LocatorPanWalkRotate*>(m_activeLocator.p());
|
||||
if (mouseEvent->buttons() == MiddleButton ||
|
||||
mouseEvent->buttons() == (LeftButton | RightButton))
|
||||
{
|
||||
loc->setOperation(LocatorPanWalkRotate::WALK);
|
||||
}
|
||||
else
|
||||
if (mouseEvent->buttons() == LeftButton)
|
||||
{
|
||||
loc->setOperation(LocatorPanWalkRotate::PAN);
|
||||
}
|
||||
else if (mouseEvent->buttons() == RightButton)
|
||||
{
|
||||
loc->setOperation(LocatorPanWalkRotate::ROTATE);
|
||||
}
|
||||
else if (mouseEvent->buttons() == MiddleButton ||
|
||||
mouseEvent->buttons() == (LeftButton | RightButton))
|
||||
{
|
||||
loc->setOperation(LocatorPanWalkRotate::WALK);
|
||||
}
|
||||
}
|
||||
|
||||
m_activeLocator->start(x, y);
|
||||
@@ -293,9 +308,10 @@ void Manipulators::onMouseMoveEvent(MouseEvent* mouseEvent)
|
||||
{
|
||||
int x = mouseEvent->x();
|
||||
int y = mouseEvent->y();
|
||||
m_activeLocator->update(x, y);
|
||||
|
||||
mouseEvent->setRequestedAction(REDRAW);
|
||||
if (m_activeLocator->update(x, y))
|
||||
{
|
||||
mouseEvent->setRequestedAction(REDRAW);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user