/**************************************************************************** Copyright (C) 2002-2006 Gilles Debunne (Gilles.Debunne@imag.fr) This file is part of the QGLViewer library. Version 2.2.4-1, released on December 12, 2006. http://artis.imag.fr/Members/Gilles.Debunne/QGLViewer libQGLViewer is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. libQGLViewer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with libQGLViewer; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ #include "constrainedFrame.h" using namespace qglviewer; using namespace std; static AxisPlaneConstraint::Type nextTranslationConstraintType(const AxisPlaneConstraint::Type& type) { switch (type) { case AxisPlaneConstraint::FREE : return AxisPlaneConstraint::PLANE; break; case AxisPlaneConstraint::PLANE : return AxisPlaneConstraint::AXIS; break; case AxisPlaneConstraint::AXIS : return AxisPlaneConstraint::FORBIDDEN; break; case AxisPlaneConstraint::FORBIDDEN : return AxisPlaneConstraint::FREE; break; default : return AxisPlaneConstraint::FREE; } } static AxisPlaneConstraint::Type nextRotationConstraintType(const AxisPlaneConstraint::Type& type) { switch (type) { case AxisPlaneConstraint::FREE : return AxisPlaneConstraint::AXIS; break; case AxisPlaneConstraint::AXIS : return AxisPlaneConstraint::FORBIDDEN; break; case AxisPlaneConstraint::PLANE : case AxisPlaneConstraint::FORBIDDEN : return AxisPlaneConstraint::FREE; break; default : return AxisPlaneConstraint::FREE; } } void Viewer::changeConstraint() { unsigned short previous = activeConstraint; activeConstraint = (activeConstraint+1)%3; constraints[activeConstraint]->setTranslationConstraintType(constraints[previous]->translationConstraintType()); constraints[activeConstraint]->setTranslationConstraintDirection(constraints[previous]->translationConstraintDirection()); constraints[activeConstraint]->setRotationConstraintType(constraints[previous]->rotationConstraintType()); constraints[activeConstraint]->setRotationConstraintDirection(constraints[previous]->rotationConstraintDirection()); frame->setConstraint(constraints[activeConstraint]); } void Viewer::init() { constraints[0] = new LocalConstraint(); constraints[1] = new WorldConstraint(); constraints[2] = new CameraConstraint(camera()); transDir = 0; // X direction rotDir = 0; // X direction activeConstraint = 0; frame = new ManipulatedFrame(); setManipulatedFrame(frame); frame->setConstraint(constraints[activeConstraint]); #if QT_VERSION < 0x040000 // Preserve CAMERA bindings, see setHandlerKeyboardModifiers documentation. setHandlerKeyboardModifiers(QGLViewer::CAMERA, Qt::AltButton); // The frames can be move without any key pressed setHandlerKeyboardModifiers(QGLViewer::FRAME, Qt::NoButton); // The camera can always be moved with the Control key. setHandlerKeyboardModifiers(QGLViewer::CAMERA, Qt::ControlButton); setMouseBinding(Qt::ShiftButton | Qt::LeftButton, QGLViewer::FRAME, QGLViewer::ROTATE, false); setMouseBinding(Qt::ShiftButton | Qt::RightButton, QGLViewer::FRAME, QGLViewer::TRANSLATE, false); setMouseBinding(Qt::ShiftButton | Qt::MidButton, QGLViewer::FRAME, QGLViewer::ZOOM, false); setWheelBinding(Qt::ShiftButton, QGLViewer::FRAME, QGLViewer::ZOOM, false); #else setHandlerKeyboardModifiers(QGLViewer::CAMERA, Qt::AltModifier); setHandlerKeyboardModifiers(QGLViewer::FRAME, Qt::NoModifier); setHandlerKeyboardModifiers(QGLViewer::CAMERA, Qt::ControlModifier); setMouseBinding(Qt::ShiftModifier | Qt::LeftButton, QGLViewer::FRAME, QGLViewer::ROTATE, false); setMouseBinding(Qt::ShiftModifier | Qt::RightButton, QGLViewer::FRAME, QGLViewer::TRANSLATE, false); setMouseBinding(Qt::ShiftModifier | Qt::MidButton, QGLViewer::FRAME, QGLViewer::ZOOM, false); setWheelBinding(Qt::ShiftModifier, QGLViewer::FRAME, QGLViewer::ZOOM, false); #endif setAxisIsDrawn(); setKeyDescription(Qt::Key_G, "Change translation constraint direction"); setKeyDescription(Qt::Key_D, "Change rotation constraint direction"); setKeyDescription(Qt::Key_Space, "Change constraint reference"); setKeyDescription(Qt::Key_T, "Change translation constraint type"); setKeyDescription(Qt::Key_R, "Change rotation constraint type"); restoreStateFromFile(); help(); } void Viewer::draw() { glMultMatrixd(frame->matrix()); drawAxis(0.4); const float scale = 0.3; glScalef(scale, scale, scale); const float nbSteps = 200.0; glBegin(GL_QUAD_STRIP); for (float i=0; ikey()) { case Qt::Key_G : transDir = (transDir+1)%3; break; case Qt::Key_D : rotDir = (rotDir+1)%3; break; case Qt::Key_Space: changeConstraint(); break; case Qt::Key_T : constraints[activeConstraint]->setTranslationConstraintType(nextTranslationConstraintType(constraints[activeConstraint]->translationConstraintType())); break; case Qt::Key_R : constraints[activeConstraint]->setRotationConstraintType(nextRotationConstraintType(constraints[activeConstraint]->rotationConstraintType())); break; default: QGLViewer::keyPressEvent(e); } Vec dir(0.0,0.0,0.0); dir[transDir] = 1.0; constraints[activeConstraint]->setTranslationConstraintDirection(dir); dir = Vec(0.0,0.0,0.0); dir[rotDir] = 1.0; constraints[activeConstraint]->setRotationConstraintDirection(dir); updateGL(); } void Viewer::displayType(const AxisPlaneConstraint::Type type, const int x, const int y, const char c) { QString text; switch (type) { case AxisPlaneConstraint::FREE: text = QString("FREE (%1)").arg(c); break; case AxisPlaneConstraint::PLANE: text = QString("PLANE (%1)").arg(c); break; case AxisPlaneConstraint::AXIS: text = QString("AXIS (%1)").arg(c); break; case AxisPlaneConstraint::FORBIDDEN: text = QString("FORBIDDEN (%1)").arg(c); break; } drawText(x, y, text); } void Viewer::displayDir(const unsigned short dir, const int x, const int y, const char c) { QString text; switch (dir) { case 0: text = QString("X (%1)").arg(c); break; case 1: text = QString("Y (%1)").arg(c); break; case 2: text = QString("Z (%1)").arg(c); break; } drawText(x, y, text); } void Viewer::displayText() { qglColor(foregroundColor()); glDisable(GL_LIGHTING); drawText(10, height()-30, "TRANSLATION :"); displayDir(transDir, 190, height()-30, 'G'); displayType(constraints[activeConstraint]->translationConstraintType(), 10, height()-60, 'T'); drawText(width()-220,height()-30, "ROTATION"); displayDir(rotDir, width()-100, height()-30, 'D'); displayType(constraints[activeConstraint]->rotationConstraintType(), width()-220, height()-60, 'R'); switch (activeConstraint) { case 0 : drawText(20,20, "Constraint direction defined w/r to LOCAL (SPACE)"); break; case 1 : drawText(20,20, "Constraint direction defined w/r to WORLD (SPACE)"); break; case 2 : drawText(20,20, "Constraint direction defined w/r to CAMERA (SPACE)"); break; } glEnable(GL_LIGHTING); } QString Viewer::helpString() const { QString text("

C o n s t r a i n e d F r a m e

"); text += "A manipulated frame can be constrained in its displacement.

"; text += "Try the different translation (press G and T) and rotation "; text += "(D and R) constraints while moving the frame with the mouse.

"; text += "The constraints can be defined with respect to various coordinates"; text += "systems : press Space to switch.

"; text += "Press the Control key while moving the mouse to move the camera.
"; text += "Press the Shift key to temporally disable the constraint.

"; text += "You can easily define your own constraints to create a specific frame behavior."; return text; }