Home | Documentation | Download | Screenshots | Developper |
A TriangleSetConstraint
constrains the camera displacement.
The camera is constrained to stay above a given 'road' defined by triangles. Camera is in FLY mode.
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.
#include "qglviewer.h" class Viewer : public QGLViewer { protected : void init(); void draw(); void displayConstraint(qglviewer::Vec); };
#include "triSetConstraint.h" #include <qapplication.h> int main(int argc, char** argv) { // Read command lines arguments. QApplication application(argc,argv); // Instantiate the viewer. Viewer v; // Make the viewer window visible on screen. v.show(); // Set the viewer as the application main widget. application.setMainWidget(&v); // Run main loop. return application.exec(); }
#include "triSetConstraint.h" #include <triangleSetConstraint.h> #include <math.h> using namespace qglviewer; static bool segmentIntersection(const Vec& p, const Vec& dir1, const Vec& norm, const Vec& s1, const Vec& s2, Vec& inter) { // dir1 is supposed to be normalized. Vec perp = cross(dir1, norm); // Check for near-parallel lines float n = perp.norm(); // Degenerated case : parallel lines if (n < 1.E-10) return false; perp /= n; float proj = (s2 - s1) * perp; float alpha = ((p-s1)*perp) / proj; if ( (alpha < 0.0) || (alpha > 1.0) ) return false; // else inter = s1 + (s2-s1) * alpha; return true; } /*! Constrain the translation \p trans with respect to a path defined by a triangle set. See addTriangle() and addPoint(). */ void Viewer::displayConstraint(Vec trans) { TriangleSetConstraint* tsc = (TriangleSetConstraint*)(camera.constraint()); unsigned int currentTriangle = tsc->currentTriangle(); trans = camera.frame.inverseTransformOf(trans); Vec pos, nextPos, start; start = camera.position(); pos = start; unsigned short nextEdge; const float dist = trans.norm(); if (dist < 1E-8) return; trans /= dist; // Draw the current triangle glColor3f(.6,.2,6); glLineWidth(4.0); glBegin(GL_TRIANGLES); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,0)).address()); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,1)).address()); glVertex3fv(tsc->point(tsc->trianglePoint(currentTriangle,2)).address()); glEnd(); glColor3f(.8,.5,0); glPointSize(10.0); glBegin(GL_POINTS); glVertex3fv(start.address()); glEnd(); glLineWidth(1.0); glBegin(GL_LINES); glVertex3fv(start.address()); glVertex3fv((start+trans).address()); glEnd(); glColor3f(.4,.6,.7); glPointSize(5.0); while (true) { float step = -1.0E9f; nextEdge = 3; Vec e1 = tsc->point(tsc->trianglePoint(currentTriangle,0)) - tsc->point(tsc->trianglePoint(currentTriangle,1)); Vec e2 = tsc->point(tsc->trianglePoint(currentTriangle,0)) - tsc->point(tsc->trianglePoint(currentTriangle,2)); Vec norm = cross(e1, e2); Vec res; for (unsigned short edge=0; edge<3; edge++) { if (segmentIntersection(pos, trans, norm, tsc->point(tsc->trianglePoint(currentTriangle,(edge+1)%3)), tsc->point(tsc->trianglePoint(currentTriangle,(edge+2)%3)), res)) { if ((res-pos)*trans > step) { step = (res-pos)*trans; nextPos = res; nextEdge = edge; } } } glBegin(GL_POINTS); glVertex3fv(nextPos.address()); glEnd(); float soFar = (nextPos-start)*trans; if ((soFar > dist) || (tsc->neighTriangle(currentTriangle,nextEdge) == -1)) return; currentTriangle = tsc->neighTriangle(currentTriangle,nextEdge); pos = nextPos; } } static const float nbSteps = 20.0; static const float r = 0.7; void Viewer::init() { setSceneRadius(3.0); camera.setFlySpeed(0.001); camera.setMode(ManipulatedFrame::FLY); glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); TriangleSetConstraint* tsc = new TriangleSetConstraint(); camera.setConstraint(tsc); tsc->addPoint(Vec(1.0,0.0,0.0)); tsc->addPoint(Vec(r ,0.0,0.0)); for (int i=1; i<nbSteps; ++i) { float angle = 2.0 * M_PI * i / nbSteps; tsc->addPoint(Vec(cos(angle) , sin(angle) , 0.0)); // index 2i tsc->addPoint(Vec(r*cos(angle), r*sin(angle), 0.0)); // index 2i+1 tsc->addTriangle(2*i-1, 2*i, 2*i+1); tsc->addTriangle(2*i-1, 2*i-2, 2*i); } tsc->addTriangle(0, 2*(int)nbSteps-2, 2*(int)nbSteps-1); tsc->addTriangle(0, 1, 2*(int)nbSteps-1); tsc->setCurrentTriangle(1); camera.setOrientation(Quaternion(Vec(1,0,0), M_PI/2.0)); camera.setPosition(0.85, 0.05, 0.0); } void Viewer::draw() { // The camera is made visible by reseting the modelview matrix glLoadIdentity(); glTranslatef(0.0,0.0,-2.5); // Draw Road glNormal3f(0.0, 0.0, 1.0); glColor3f(.2,.6,.8); glBegin(GL_QUAD_STRIP); for (float i=0; i<=nbSteps; ++i) { float angle = 2.0 * M_PI * i / nbSteps; glVertex3f(cos(angle), sin(angle), 0.0); glVertex3f(r*cos(angle), r*sin(angle), 0.0); } glEnd(); // Draw camera position Vec pos = camera.position(); glPointSize(5.0); glBegin(GL_POINTS); glVertex3fv(pos.address()); glEnd(); displayConstraint(Vec(0,0,-1)); }
Back to the main page