<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>libQGLViewer constrainedFrame example</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link href="../qglviewer.css" rel="stylesheet" type="text/css" /> <link rel="shortcut icon" href="../images/qglviewer.ico" type="image/x-icon" /> <link rel="icon" href="../images/qglviewer.icon.png" type="image/png" /> </head> <body> <table class="banner"> <tr> <td align="center"><a href="../index.html"><b>Home</b></a></td> <td align="center"><a href="../refManual/hierarchy.html"><b>Documentation</b></a></td> <td align="center"><a href="../download.html"><b>Download</b></a></td> <td align="center" class="qindexHL"><a href="index.html"><b>Screenshots</b></a></td> <td align="center"><a href="../developer.html"><b>Developer</b></a></td> </tr> </table> <h1>The constrainedFrame example</h1> <center> <img src="../images/constrainedFrame.jpg" width="300" height="200" alt="constrainedFrame"/> </center> <p> Constraints can limit the translation and/or rotation of a (Manipulated)Frame. </p> <p> Try the different possible constraints using the T (translate) and R (rotate) keys. G and D change the constraint directions. Press Space to change the coordinate system (World, Camera or Local) which defines the constraint directions. </p> <p> Press the Control key while moving the mouse to move the camera. </p> <h2>constrainedFrame.h</h2> <pre> <span class="dir">#include <QGLViewer/qglviewer.h> </span> <span class="key">class </span>Viewer : <span class="key">public </span>QGLViewer { <span class="key">protected</span>: <span class="key">virtual </span><span class="typ">void </span>init(); <span class="key">virtual </span><span class="typ">void </span>draw(); <span class="key">virtual </span>QString helpString() <span class="typ">const</span>; <span class="key">virtual </span><span class="typ">void </span>keyPressEvent(QKeyEvent *); <span class="typ">void </span>displayText(); <span class="typ">void </span>displayType(<span class="typ">const </span>qglviewer::AxisPlaneConstraint::Type type, <span class="typ">const int </span>x, <span class="typ">const int </span>y, <span class="typ">const char </span>c); <span class="typ">void </span>displayDir(<span class="typ">const unsigned short </span>dir, <span class="typ">const int </span>x, <span class="typ">const int </span>y, <span class="typ">const char </span>c); <span class="key">private</span>: <span class="typ">int </span>transDir; <span class="typ">int </span>rotDir; qglviewer::ManipulatedFrame* frame; <span class="typ">void </span>changeConstraint(); qglviewer::AxisPlaneConstraint* constraints[<span class="num">3</span>]; <span class="typ">unsigned short </span>activeConstraint; };</pre> <h2>constrainedFrame.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"constrainedFrame.h"</span><span class="dir"> </span> <span class="key">using namespace </span>qglviewer; <span class="key">using namespace </span>std; <span class="typ">static </span>AxisPlaneConstraint::Type nextTranslationConstraintType(<span class="typ">const </span>AxisPlaneConstraint::Type& type) { <span class="key">switch </span>(type) { <span class="key">case </span>AxisPlaneConstraint::FREE : <span class="key">return </span>AxisPlaneConstraint::PLANE; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::PLANE : <span class="key">return </span>AxisPlaneConstraint::AXIS; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::AXIS : <span class="key">return </span>AxisPlaneConstraint::FORBIDDEN; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::FORBIDDEN : <span class="key">return </span>AxisPlaneConstraint::FREE; <span class="key">break</span>; <span class="key">default </span>: <span class="key">return </span>AxisPlaneConstraint::FREE; } } <span class="typ">static </span>AxisPlaneConstraint::Type nextRotationConstraintType(<span class="typ">const </span>AxisPlaneConstraint::Type& type) { <span class="key">switch </span>(type) { <span class="key">case </span>AxisPlaneConstraint::FREE : <span class="key">return </span>AxisPlaneConstraint::AXIS; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::PLANE : <span class="key">return </span>AxisPlaneConstraint::FREE; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::AXIS : <span class="key">return </span>AxisPlaneConstraint::FORBIDDEN; <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::FORBIDDEN : <span class="key">return </span>AxisPlaneConstraint::FREE; <span class="key">break</span>; <span class="key">default </span>: <span class="key">return </span>AxisPlaneConstraint::FREE; } } <span class="typ">void </span>Viewer::changeConstraint() { <span class="typ">unsigned short </span>previous = activeConstraint; activeConstraint = (activeConstraint+<span class="num">1</span>)%<span class="num">3</span>; constraints[activeConstraint]->setTranslationConstraintType(constraints[previous]->translationConstraintType()); constraints[activeConstraint]->setTranslationConstraintDir (constraints[previous]->translationConstraintDir()); constraints[activeConstraint]->setRotationConstraintType (constraints[previous]->rotationConstraintType()); constraints[activeConstraint]->setRotationConstraintDir (constraints[previous]->rotationConstraintDir()); frame->setConstraint(constraints[activeConstraint]); } <span class="typ">void </span>Viewer::init() { constraints[<span class="num">0</span>] = <span class="key">new </span>LocalConstraint(); constraints[<span class="num">1</span>] = <span class="key">new </span>WorldConstraint(); constraints[<span class="num">2</span>] = <span class="key">new </span>CameraConstraint(camera()); transDir = <span class="num">0</span>; <span class="com">// X direction </span> rotDir = <span class="num">0</span>; <span class="com">// X direction </span> activeConstraint = <span class="num">0</span>; frame = <span class="key">new </span>ManipulatedFrame(); setManipulatedFrame(frame); frame->setConstraint(constraints[activeConstraint]); <span class="com">// Preserve CAMERA bindings, see setMouseStateKey documentation. </span> setMouseStateKey(QGLViewer::CAMERA, Qt::AltButton); <span class="com">// The frames can be move without any key pressed </span> setMouseStateKey(QGLViewer::FRAME, Qt::NoButton); <span class="com">// The camera can always be moved with the Control key. </span> setMouseStateKey(QGLViewer::CAMERA, Qt::ControlButton); setDrawAxis(); restoreFromFile(); help(); } <span class="typ">void </span>Viewer::draw() { glMultMatrixd(frame->matrix()); drawAxis(<span class="num">0.4</span>); <span class="typ">const float </span>scale = <span class="num">0.3</span>; glScalef(scale, scale, scale); <span class="typ">const float </span>nbSteps = <span class="num">500.0</span>; glBegin(GL_QUAD_STRIP); <span class="key">for </span>(<span class="typ">float </span>i=<span class="num">0</span>; i<nbSteps; ++i) { <span class="typ">float </span>ratio = i/nbSteps; <span class="typ">float </span>angle = <span class="num">21.0</span>*ratio; <span class="typ">float </span>c = cos(angle); <span class="typ">float </span>s = sin(angle); <span class="typ">float </span>r1 = <span class="num">1.0 </span>- <span class="num">0.8</span>*ratio; <span class="typ">float </span>r2 = <span class="num">0.8 </span>- <span class="num">0.8</span>*ratio; <span class="typ">float </span>alt = ratio <span class="num">- 0.5</span>; <span class="typ">const float </span>nor = .<span class="num">5</span>; <span class="typ">const float </span>up = sqrt(<span class="num">1.0</span>-nor*nor); glColor3f(<span class="num">1</span>-ratio, .<span class="num">2 </span>, ratio); glNormal3f(nor*c*scale, up*scale, nor*s*scale); glVertex3f(r1*c, alt, r1*s); glVertex3f(r2*c, alt+<span class="num">0.05</span>, r2*s); } glEnd(); displayText(); } <span class="typ">void </span>Viewer::keyPressEvent(QKeyEvent *e) { <span class="key">switch </span>(e->key()) { <span class="key">case </span>Qt::Key_G : transDir = (transDir+<span class="num">1</span>)%<span class="num">3</span>; <span class="key">break</span>; <span class="key">case </span>Qt::Key_D : rotDir = (rotDir+<span class="num">1</span>)%<span class="num">3</span>; <span class="key">break</span>; <span class="key">case </span>Qt::Key_Space: changeConstraint(); <span class="key">break</span>; <span class="key">case </span>Qt::Key_T : constraints[activeConstraint]->setTranslationConstraintType(nextTranslationConstraintType(constraints[activeConstraint]->translationConstraintType())); <span class="key">break</span>; <span class="key">case </span>Qt::Key_R : constraints[activeConstraint]->setRotationConstraintType(nextRotationConstraintType(constraints[activeConstraint]->rotationConstraintType())); <span class="key">break</span>; <span class="key">default</span>: QGLViewer::keyPressEvent(e); } Vec dir(<span class="num">0.0</span>,<span class="num">0.0</span>,<span class="num">0.0</span>); dir[transDir] = <span class="num">1.0</span>; constraints[activeConstraint]->setTranslationConstraintDir(dir); dir = Vec(<span class="num">0.0</span>,<span class="num">0.0</span>,<span class="num">0.0</span>); dir[rotDir] = <span class="num">1.0</span>; constraints[activeConstraint]->setRotationConstraintDir(dir); updateGL(); } <span class="typ">void </span>Viewer::displayType(<span class="typ">const </span>AxisPlaneConstraint::Type type, <span class="typ">const int </span>x, <span class="typ">const int </span>y, <span class="typ">const char </span>c) { <span class="typ">char </span>text[<span class="num">12</span>]; <span class="key">switch </span>(type) { <span class="key">case </span>AxisPlaneConstraint::FREE: sprintf(text, <span class="str">"FREE (%c)"</span>, c); <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::PLANE: sprintf(text, <span class="str">"PLANE (%c)"</span>, c); <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::AXIS: sprintf(text, <span class="str">"AXIS (%c)"</span>, c); <span class="key">break</span>; <span class="key">case </span>AxisPlaneConstraint::FORBIDDEN: sprintf(text, <span class="str">"FORBIDDEN (%c)"</span>, c); <span class="key">break</span>; } drawText(x, y, text); } <span class="typ">void </span>Viewer::displayDir(<span class="typ">const unsigned short </span>dir, <span class="typ">const int </span>x, <span class="typ">const int </span>y, <span class="typ">const char </span>c) { <span class="typ">char </span>text[<span class="num">6</span>]; <span class="key">switch </span>(dir) { <span class="key">case </span><span class="num">0</span>: sprintf(text, <span class="str">"X (%c)"</span>, c); <span class="key">break</span>; <span class="key">case </span><span class="num">1</span>: sprintf(text, <span class="str">"Y (%c)"</span>, c); <span class="key">break</span>; <span class="key">case </span><span class="num">2</span>: sprintf(text, <span class="str">"Z (%c)"</span>, c); <span class="key">break</span>; } drawText(x, y, text); } <span class="typ">void </span>Viewer::displayText() { glColor3fv(foregroundColor().address()); glDisable(GL_LIGHTING); drawText(<span class="num">10</span>, height()<span class="num">-30</span>, <span class="str">"TRANSLATION :"</span>); displayDir(transDir, <span class="num">190</span>, height()<span class="num">-30</span>, <span class="str">'G'</span>); displayType(constraints[activeConstraint]->translationConstraintType(), <span class="num">10</span>, height()<span class="num">-60</span>, <span class="str">'T'</span>); drawText(width()<span class="num">-220</span>,height()<span class="num">-30</span>, <span class="str">"ROTATION"</span>); displayDir(rotDir, width()<span class="num">-100</span>, height()<span class="num">-30</span>, <span class="str">'D'</span>); displayType(constraints[activeConstraint]->rotationConstraintType(), width()<span class="num">-220</span>, height()<span class="num">-60</span>, <span class="str">'R'</span>); <span class="key">switch </span>(activeConstraint) { <span class="key">case </span><span class="num">0 </span>: drawText(<span class="num">20</span>,<span class="num">20</span>, <span class="str">"Constraint direction defined w/r to LOCAL (SPACE)"</span>); <span class="key">break</span>; <span class="key">case </span><span class="num">1 </span>: drawText(<span class="num">20</span>,<span class="num">20</span>, <span class="str">"Constraint direction defined w/r to WORLD (SPACE)"</span>); <span class="key">break</span>; <span class="key">case </span><span class="num">2 </span>: drawText(<span class="num">20</span>,<span class="num">20</span>, <span class="str">"Constraint direction defined w/r to CAMERA (SPACE)"</span>); <span class="key">break</span>; } } QString Viewer::helpString() <span class="typ">const </span>{ QString text(<span class="str">"<h2>C o n s t r a i n e d F r a m e</h2>"</span>); text += <span class="str">"A manipulated frame can be constrained in its displacement.<br>"</span>; text += <span class="str">"Try the different translation (press <b>G</b> and <b>T</b>) and rotation "</span>; text += <span class="str">"(<b>D</b> and <b>R</b>) constraints while moving the frame with the mouse.<br>"</span>; text += <span class="str">"The constraints can be defined with respect to various coordinates"</span>; text += <span class="str">"systems : press <b>Space</b> to switch.<br>"</span>; text += <span class="str">"Press the <b>Control</b> key while moving the mouse to move the camera.<br>"</span>; text += <span class="str">"You can easily define your own constraints to create a specific frame behavior."</span>; <span class="key">return </span>text; } </pre> <h2>main.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"constrainedFrame.h"</span><span class="dir"> </span><span class="dir">#include <qapplication.h> </span> <span class="typ">int </span>main(<span class="typ">int </span>argc, <span class="typ">char</span>** argv) { <span class="com">// Read command lines arguments. </span> QApplication application(argc,argv); <span class="com">// Instantiate the viewer. </span> Viewer v; <span class="com">// Make the viewer window visible on screen. </span> v.show(); <span class="com">// Set the viewer as the application main widget. </span> application.setMainWidget(&v); <span class="com">// Run main loop. </span> <span class="key">return </span>application.exec(); }</pre> <p> <a href="index.html">Go back</a> to the examples main page </p> <p> <a href="http://validator.w3.org/check/referer"><img src="../images/xhtml.png" alt="Valid XHTML 1.0!" height="31" width="88" border="0"/></a> <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../images/css.png" width="88" height="31" alt="Valid CSS!" border="0"/></a> <i>Last modified on Thursday, February 5, 2004.</i> </p> </body> </html>