<!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 triSetConstraint 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 triSetConstraint example</h1> <center> <img src="../images/triSetConstraint.jpg" width="300" height="200" alt="triSetConstraint"/> </center> <p> A <code>TriangleSetConstraint</code> constrains the camera displacement. </p> <p> The camera is constrained to stay above a given 'road' defined by triangles. Camera is in FLY mode. </p> <p> The example is a little bit complex : the computations needed to get the intersection of the Z-direction and the triangle are cut and pasted from the triangleSetConstraint class, in order to draw interesting debugging informations. </p> <h2>triSetConstraint.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="typ">void </span>init(); <span class="typ">void </span>draw(); <span class="typ">void </span>displayConstraint(qglviewer::Vec); };</pre> <h2>triSetConstraint.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"triSetConstraint.h"</span><span class="dir"> </span><span class="dir">#include <QGLViewer/triangleSetConstraint.h> </span><span class="dir">#include <math.h> </span> <span class="key">using namespace </span>qglviewer; <span class="typ">static bool </span>segmentIntersection(<span class="typ">const </span>Vec& p, <span class="typ">const </span>Vec& dir1, <span class="typ">const </span>Vec& norm, <span class="typ">const </span>Vec& s1, <span class="typ">const </span>Vec& s2, Vec& inter) { <span class="com">// dir1 is supposed to be normalized. </span> Vec perp = cross(dir1, norm); <span class="com">// Check for near-parallel lines </span> <span class="typ">float </span>n = perp.norm(); <span class="com">// Degenerated case : parallel lines </span> <span class="key">if </span>(n < <span class="num">1.E</span>-<span class="num">10</span>) <span class="key">return false</span>; perp /= n; <span class="typ">float </span>proj = (s2 - s1) * perp; <span class="typ">float </span>alpha = ((p-s1)*perp) / proj; <span class="key">if </span>( (alpha < <span class="num">0.0</span>) || (alpha > <span class="num">1.0</span>) ) <span class="key">return false</span>; <span class="com">// else </span> inter = s1 + (s2-s1) * alpha; <span class="key">return true</span>; } <span class="com">/* Constrain the translation \p trans with respect to a path defined by a triangle set. See addTriangle() and addPoint(). */</span> <span class="typ">void </span>Viewer::displayConstraint(Vec trans) { TriangleSetConstraint* tsc = (TriangleSetConstraint*)(camera()->frame()->constraint()); <span class="typ">unsigned int </span>currentTriangle = tsc->currentTriangle(); trans = camera()->frame()->inverseTransformOf(trans); Vec pos, nextPos, start; start = camera()->position(); pos = start; <span class="typ">unsigned short </span>nextEdge; <span class="typ">const float </span>dist = trans.norm(); <span class="key">if </span>(dist < <span class="num">1E</span>-<span class="num">8</span>) <span class="key">return</span>; trans /= dist; <span class="com">// Draw the current triangle </span> glColor3f(.<span class="num">6</span>,.<span class="num">2</span>,<span class="num">6</span>); glLineWidth(<span class="num">4.0</span>); glBegin(GL_TRIANGLES); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">0</span>)).address()); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">1</span>)).address()); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">2</span>)).address()); glEnd(); glColor3f(.<span class="num">8</span>,.<span class="num">5</span>,<span class="num">0</span>); glPointSize(<span class="num">10.0</span>); glBegin(GL_POINTS); glVertex3fv(start.address()); glEnd(); glLineWidth(<span class="num">1.0</span>); glBegin(GL_LINES); glVertex3fv(start.address()); glVertex3fv((start+trans).address()); glEnd(); glColor3f(.<span class="num">4</span>,.<span class="num">6</span>,.<span class="num">7</span>); glPointSize(<span class="num">5.0</span>); <span class="key">while </span>(<span class="key">true</span>) { <span class="typ">float </span>step = <span class="num">-1.0E9f</span>; nextEdge = <span class="num">3</span>; Vec e1 = tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">0</span>)) - tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">1</span>)); Vec e2 = tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">0</span>)) - tsc->point(tsc->trianglePoint(currentTriangle,<span class="num">2</span>)); Vec norm = cross(e1, e2); Vec res; <span class="key">for </span>(<span class="typ">unsigned short </span>edge=<span class="num">0</span>; edge<<span class="num">3</span>; edge++) { <span class="key">if </span>(segmentIntersection(pos, trans, norm, tsc->point(tsc->trianglePoint(currentTriangle,(edge+<span class="num">1</span>)%<span class="num">3</span>)), tsc->point(tsc->trianglePoint(currentTriangle,(edge+<span class="num">2</span>)%<span class="num">3</span>)), res)) { <span class="key">if </span>((res-pos)*trans > step) { step = (res-pos)*trans; nextPos = res; nextEdge = edge; } } } glBegin(GL_POINTS); glVertex3fv(nextPos.address()); glEnd(); <span class="typ">float </span>soFar = (nextPos-start)*trans; <span class="key">if </span>((soFar > dist) || (tsc->neighTriangle(currentTriangle,nextEdge) == <span class="num">-1</span>)) <span class="key">return</span>; currentTriangle = tsc->neighTriangle(currentTriangle,nextEdge); pos = nextPos; } } <span class="typ">static const float </span>nbSteps = <span class="num">20.0</span>; <span class="typ">static const float </span>r = <span class="num">0.7</span>; <span class="typ">void </span>Viewer::init() { setSceneRadius(<span class="num">3.0</span>); camera()->setFlySpeed(<span class="num">0.001</span>); <span class="com">// Use fly mode mouse bindings </span> toggleCameraMode(); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); TriangleSetConstraint* tsc = <span class="key">new </span>TriangleSetConstraint(); camera()->frame()->setConstraint(tsc); tsc->addPoint(Vec(<span class="num">1.0</span>,<span class="num">0.0</span>,<span class="num">0.0</span>)); tsc->addPoint(Vec(r ,<span class="num">0.0</span>,<span class="num">0.0</span>)); <span class="key">for </span>(<span class="typ">int </span>i=<span class="num">1</span>; i<nbSteps; ++i) { <span class="typ">float </span>angle = <span class="num">2.0 </span>* M_PI * i / nbSteps; tsc->addPoint(Vec(cos(angle) , sin(angle) , <span class="num">0.0</span>)); <span class="com">// index 2i </span> tsc->addPoint(Vec(r*cos(angle), r*sin(angle), <span class="num">0.0</span>)); <span class="com">// index 2i+1 </span> tsc->addTriangle(<span class="num">2</span>*i-1, <span class="num">2</span>*i, <span class="num">2</span>*i+<span class="num">1</span>); tsc->addTriangle(<span class="num">2</span>*i-1, <span class="num">2</span>*i-2, <span class="num">2</span>*i); } tsc->addTriangle(<span class="num">0</span>, <span class="num">2</span>*(<span class="typ">int</span>)nbSteps-2, <span class="num">2</span>*(<span class="typ">int</span>)nbSteps-1); tsc->addTriangle(<span class="num">0</span>, <span class="num">1</span>, <span class="num">2</span>*(<span class="typ">int</span>)nbSteps-1); tsc->setCurrentTriangle(<span class="num">1</span>); camera()->setOrientation(Quaternion(Vec(<span class="num">1</span>,<span class="num">0</span>,<span class="num">0</span>), M_PI/<span class="num">2.0</span>)); camera()->setPosition(<span class="num">0.85</span>, <span class="num">0.05</span>, <span class="num">0.0</span>); } <span class="typ">void </span>Viewer::draw() { <span class="com">// The camera is made visible by reseting the modelview matrix </span> glLoadIdentity(); glTranslatef(<span class="num">0.0</span>,<span class="num">0.0</span>,<span class="num">-2.5</span>); <span class="com">// Draw Road </span> glNormal3f(<span class="num">0.0</span>, <span class="num">0.0</span>, <span class="num">1.0</span>); glColor3f(.<span class="num">2</span>,.<span class="num">6</span>,.<span class="num">8</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>angle = <span class="num">2.0 </span>* M_PI * i / nbSteps; glVertex3f(cos(angle), sin(angle), <span class="num">0.0</span>); glVertex3f(r*cos(angle), r*sin(angle), <span class="num">0.0</span>); } glEnd(); <span class="com">// Draw camera position </span> Vec pos = camera()->position(); glPointSize(<span class="num">5.0</span>); glBegin(GL_POINTS); glVertex3fv(pos.address()); glEnd(); displayConstraint(Vec(<span class="num">0</span>,<span class="num">0</span>,<span class="num">-1</span>)); } </pre> <h2>main.cpp</h2> <pre> <span class="dir">#include </span><span class="dstr">"triSetConstraint.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 Friday, November 7, 2003.</i> </p> </body> </html>