Commit 6fe89f58 authored by Mike Kremer's avatar Mike Kremer
Browse files

Implemented 3D-First-Person-Shooter navigation mode that still doesn't work too well.

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@7014 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 37a72c9e
......@@ -642,6 +642,9 @@ public:
/// Show / hide wheels
void slotSwitchWheels(bool _state);
/// Switch navigation mode
void slotSwitchNavigation(bool _egomode);
/// Set the snapShot name for all examiners
void slotSnapshotName();
......
......@@ -284,6 +284,17 @@ void CoreWidget::setupMenuBar()
viewMenu_->addSeparator();
QAction* navigationSwitchAction = new QAction( tr("Ego-shooter Navigation"), viewMenu_ );
navigationSwitchAction->setCheckable( true );
navigationSwitchAction->setStatusTip( tr("Switch between normal and ego-shooter navigation mode."));
navigationSwitchAction->setWhatsThis( tr("Switch between normal and ego-shooter navigation mode."));
navigationSwitchAction->setChecked( false );
connect( navigationSwitchAction, SIGNAL( toggled(bool) ), this, SLOT( slotSwitchNavigation(bool) ) );
viewMenu_->addAction( navigationSwitchAction);
viewMenu_->addSeparator();
connect( viewMenu_,SIGNAL( aboutToShow() ), this, SLOT( slotViewMenuAboutToShow() ) );
QAction* homeAction = new QAction(tr("Restore Home View"),viewMenu_);
......
......@@ -124,6 +124,16 @@ void CoreWidget::slotSwitchWheels(bool _state) {
_state ? (*it)->slotShowWheels() : (*it)->slotHideWheels();
}
/// Switch navigation mode
void CoreWidget::slotSwitchNavigation(bool _egomode) {
std::vector< glViewer* >::iterator it = examiner_widgets_.begin();
for(; it != examiner_widgets_.end(); it++) {
_egomode ? (*it)->navigationMode(glViewer::EGOSHOOTER_NAVIGATION) :
(*it)->navigationMode(glViewer::NORMAL_NAVIGATION);
}
}
/// Set the viewer to home position
void CoreWidget::slotGlobalHomeView() {
for ( int i = 0 ; i < PluginFunctions::viewers() ; ++i )
......
......@@ -169,6 +169,7 @@ glViewer::glViewer( QGraphicsScene* _scene,
normalsMode_ = DONT_TOUCH_NORMALS;
projectionMode_ = PERSPECTIVE_PROJECTION;
navigationMode_ = NORMAL_NAVIGATION;
light_matrix_.identity();
......@@ -332,6 +333,23 @@ void glViewer::projectionMode(ProjectionMode _p)
updateProjectionMatrix();
}
void glViewer::toggleNavigationMode()
{
if (navigationMode_ == NORMAL_NAVIGATION)
navigationMode(EGOSHOOTER_NAVIGATION);
else
navigationMode(NORMAL_NAVIGATION);
}
void glViewer::navigationMode(NavigationMode _n)
{
if ((navigationMode_ = _n) == NORMAL_NAVIGATION)
emit navigationModeChanged( true );
else
emit navigationModeChanged( false );
}
void glViewer::updateProjectionMatrix()
{
......@@ -1563,6 +1581,29 @@ void glViewer::mouseMoveEvent(QGraphicsSceneMouseEvent* _e)
}
}
//----------------------------------------------------------------------------------
void glViewer::keyPressEvent ( QKeyEvent* _event ) {
_event->accept();
switch (properties_.actionMode()) {
case Viewer::ExamineMode:
viewKeyEvent(_event);
break;
default: // avoid warning
break;
}
}
//----------------------------------------------------------------------------------
bool glViewer::viewKeyPressEvent(QKeyEvent* _event) {
_event->accept();
return true;
}
//-----------------------------------------------------------------------------
......@@ -1682,79 +1723,132 @@ void glViewer::dropEvent(QGraphicsSceneDragDropEvent* _e)
//-----------------------------------------------------------------------------
void
glViewer::viewMouseEvent(QMouseEvent* _event)
{
QPointF f (mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
QPoint pos (f.x(), f.y());
void glViewer::viewMouseEvent(QMouseEvent* _event) {
switch (_event->type())
{
case QEvent::MouseButtonPress:
{
if (navigationMode_ == NORMAL_NAVIGATION) {
treatNormalNavigation(_event);
} else if (navigationMode_ == EGOSHOOTER_NAVIGATION) {
treatEgoShooterNavigation(_event);
}
}
//----------------------------------------------------------------------------
void glViewer::treatEgoShooterNavigation( QMouseEvent* _event) {
// Ego-shooter navigation mode is selected
QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
QPoint pos(f.x(), f.y());
switch (_event->type()) {
case QEvent::MouseButtonDblClick: {
if (allowRotation_)
flyTo(_event->pos(), _event->button() == Qt::MidButton);
break;
}
case QEvent::MouseMove: {
// Considering center point of screen as origin
QPoint newpos = QPoint(pos.x() - glWidth() / 2, glHeight() / 2 - pos.y());
QPoint oldpos = QPoint(lastPoint2D_.x() - glWidth() / 2, glHeight() / 2 - lastPoint2D_.y());
double x = 2.0 * newpos.x() / glWidth();
double y = 2.0 * newpos.y() / glHeight();
double xo = 2.0 * oldpos.x() / glWidth();
double yo = 2.0 * oldpos.y() / glHeight();
double diffx = xo - x;
double diffy = yo - y;
ACG::Vec3d yaxis(0.0, 1.0, 0.0);
ACG::Vec3d xaxis(1.0, 0.0, 0.0);
ACG::Vec3d eye = glstate_->modelview().transform_point(glstate_->eye());
glstate_->rotate(-diffx * 90, 0.0, 1.0, 0.0);
glstate_->rotate(diffy * 90, 1.0, 0.0, 0.0);
rotate(yaxis, -diffx * 90, glstate_->eye());
rotate(xaxis, diffy * 90, glstate_->eye());
lastPoint2D_ = pos;
updateGL();
lastMoveTime_.restart();
break;
}
default: // avoid warning
break;
}
}
//----------------------------------------------------------------------------
void glViewer::treatNormalNavigation( QMouseEvent* _event ) {
// Normal navigation mode is selected
QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
QPoint pos(f.x(), f.y());
switch (_event->type()) {
case QEvent::MouseButtonPress: {
// shift key -> set rotation center
if (_event->modifiers() & Qt::ShiftModifier)
{
if (_event->modifiers() & Qt::ShiftModifier) {
ACG::Vec3d c;
if (fast_pick(pos, c))
{
if (fast_pick(pos, c)) {
trackball_center_ = c;
trackball_radius_ = std::max(scene_radius_, (c-glstate_->eye()).norm()*0.9f);
trackball_radius_ = std::max(scene_radius_, (c - glstate_->eye()).norm() * 0.9f);
}
}
lastPoint_hitSphere_ = mapToSphere( lastPoint2D_= pos,
lastPoint3D_ );
lastPoint_hitSphere_ = mapToSphere(lastPoint2D_ = pos, lastPoint3D_);
isRotating_ = true;
timer_->stop();
break;
}
case QEvent::MouseButtonDblClick:
{
case QEvent::MouseButtonDblClick: {
if (allowRotation_)
flyTo(_event->pos(), _event->button()==Qt::MidButton);
flyTo(_event->pos(), _event->button() == Qt::MidButton);
break;
}
case QEvent::MouseMove:
{
case QEvent::MouseMove: {
double factor = 1.0;
if (_event->modifiers() == Qt::ShiftModifier)
factor = properties_.wheelZoomFactorShift();
// mouse button should be pressed
if (_event->buttons() & (Qt::LeftButton | Qt::MidButton))
{
if (_event->buttons() & (Qt::LeftButton | Qt::MidButton)) {
QPoint newPoint2D = pos;
double value_x, value_y;
ACG::Vec3d newPoint3D;
bool newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D );
bool newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D);
makeCurrent();
// move in z direction
if ( (_event->buttons() & Qt::LeftButton) &&
(_event->buttons() & Qt::MidButton))
{
switch (projectionMode())
{
case PERSPECTIVE_PROJECTION:
{
if ((_event->buttons() & Qt::LeftButton) && (_event->buttons() & Qt::MidButton)) {
switch (projectionMode()) {
case PERSPECTIVE_PROJECTION: {
value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 3.0 / (double) glHeight();
translate( ACG::Vec3d(0.0, 0.0, value_y * factor ) );
translate(ACG::Vec3d(0.0, 0.0, value_y * factor));
updateGL();
break;
}
case ORTHOGRAPHIC_PROJECTION:
{
case ORTHOGRAPHIC_PROJECTION: {
value_y = ((newPoint2D.y() - lastPoint2D_.y())) * orthoWidth_ / (double) glHeight();
orthoWidth_ -= value_y * factor;
updateProjectionMatrix();
......@@ -1765,27 +1859,24 @@ glViewer::viewMouseEvent(QMouseEvent* _event)
}
// move in x,y direction
else if ( (_event->buttons() & Qt::MidButton) || (!allowRotation_ && (_event->buttons() & Qt::LeftButton)))
{
else if ((_event->buttons() & Qt::MidButton) || (!allowRotation_ && (_event->buttons() & Qt::LeftButton))) {
value_x = scene_radius_ * ((newPoint2D.x() - lastPoint2D_.x())) * 2.0 / (double) glWidth();
value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 2.0 / (double) glHeight();
translate( ACG::Vec3d(value_x * factor , -value_y * factor , 0.0) );
translate(ACG::Vec3d(value_x * factor, -value_y * factor, 0.0));
}
// rotate
else if (allowRotation_ && (_event->buttons() & Qt::LeftButton) )
{
ACG::Vec3d axis(1.0,0.0,0.0);
else if (allowRotation_ && (_event->buttons() & Qt::LeftButton)) {
ACG::Vec3d axis(1.0, 0.0, 0.0);
double angle(0.0);
if ( lastPoint_hitSphere_ ) {
if (lastPoint_hitSphere_) {
if ( ( newPoint_hitSphere = mapToSphere( newPoint2D,
newPoint3D ) ) ) {
if ((newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D))) {
axis = lastPoint3D_ % newPoint3D;
double cos_angle = ( lastPoint3D_ | newPoint3D );
if ( fabs(cos_angle) < 1.0 ) {
angle = acos( cos_angle ) * 180.0 / M_PI * factor ;
double cos_angle = (lastPoint3D_ | newPoint3D);
if (fabs(cos_angle) < 1.0) {
angle = acos(cos_angle) * 180.0 / M_PI * factor;
angle *= 2.0; // inventor rotation
}
}
......@@ -1808,17 +1899,12 @@ glViewer::viewMouseEvent(QMouseEvent* _event)
break;
}
case QEvent::MouseButtonRelease:
{
case QEvent::MouseButtonRelease: {
lastPoint_hitSphere_ = false;
// continue rotation ?
if ( isRotating_ &&
(_event->button() == Qt::LeftButton) &&
(!(_event->buttons() & Qt::MidButton)) &&
(lastMoveTime_.elapsed() < 50) && properties_.animation() )
if (isRotating_ && (_event->button() == Qt::LeftButton) && (!(_event->buttons() & Qt::MidButton))
&& (lastMoveTime_.elapsed() < 50) && properties_.animation())
timer_->start(0);
break;
}
......@@ -1826,14 +1912,19 @@ glViewer::viewMouseEvent(QMouseEvent* _event)
default: // avoid warning
break;
}
}
//-----------------------------------------------------------------------------
}
void glViewer::viewKeyEvent( QKeyEvent* _event) {
// Only react if in ego-shooter mode
if (navigationMode_ == EGOSHOOTER_NAVIGATION) {
}
}
//-----------------------------------------------------------------------------
void
glViewer::lightMouseEvent(QMouseEvent* _event)
{
......
......@@ -71,6 +71,7 @@
#include <QDragEnterEvent>
#include <QMouseEvent>
#include <QAction>
#include <QKeyEvent>
#include <QSize>
#include <QMap>
#include <QString>
......@@ -191,11 +192,21 @@ public:
PERSPECTIVE_PROJECTION //!< perspective
};
/// Navigation mode
enum NavigationMode {
NORMAL_NAVIGATION, //!< Normal mode
EGOSHOOTER_NAVIGATION //!< Egoshooter mode
};
/// Changes the projection mode and updates the projection matrix.
void projectionMode(ProjectionMode _p);
/// get current projection mode
ProjectionMode projectionMode() const { return projectionMode_; }
/// Changes the navigation mode
void navigationMode(NavigationMode _n);
/// get current navigation mode
NavigationMode navigationMode() const { return navigationMode_; }
/** Sets the center and dimension of the whole scene. This point is
used as fixpoint for rotations and to set the eye point far
......@@ -217,7 +228,6 @@ public:
*/
double scene_radius() const { return scene_radius_; }
/// set the viewing direction
void viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up );
......@@ -341,10 +351,13 @@ public slots:
virtual void orthographicProjection();
/// toggle projection mode
virtual void toggleProjectionMode();
/// toggle navigation mode
virtual void toggleNavigationMode();
signals:
void projectionModeChanged( bool _ortho );
void navigationModeChanged( bool _normal );
public slots:
......@@ -437,6 +450,8 @@ protected:
void viewMouseEvent( QMouseEvent* _event);
/// specialized viewer: handle wheel events
void viewWheelEvent(QWheelEvent* _event);
/// specialized viewer: hande key events
void viewKeyEvent( QKeyEvent* _event);
/// optional: hande mouse events to rotate light
void lightMouseEvent( QMouseEvent* /* _event */ );
......@@ -533,6 +548,7 @@ private:
// modi
NormalsMode normalsMode_;
ProjectionMode projectionMode_;
NavigationMode navigationMode_;
// helper
......@@ -651,7 +667,7 @@ private:
*
* This function is called by the internal gl widget when receiving a key press event.
*/
virtual void keyPressEvent(QKeyEvent* _event) { _event->ignore(); };
virtual void keyPressEvent(QKeyEvent* _event);
/** \brief Get keyRelease events from the glArea
*
......@@ -668,7 +684,7 @@ private:
*
* @return If the derived class handled the event it has to return true otherwise false
*/
virtual bool viewKeyPressEvent(QKeyEvent* /*_event*/) { return false; };
virtual bool viewKeyPressEvent(QKeyEvent* _event);
/** @} */
......@@ -834,6 +850,12 @@ private:
/// virtual trackball: map 2D screen point to unit sphere
bool mapToSphere(const QPoint& _p, ACG::Vec3d& _result) const;
/// Navigate through scene if ego-shooter mode has been selected
void treatEgoShooterNavigation( QMouseEvent* _event);
/// Navigate through scene if normal mode has been selected
void treatNormalNavigation( QMouseEvent* _event);
// mouse interaction
ACG::Vec3d lastPoint3D_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment