A 'standard' Camera with fixed near and far planes.
A new StandardCamera
class is derived from Camera
.
Its near and far planes distances are set to fixed values (instead of being fit to
scene dimensions as is done in the QGLViewer::Camera
).
The orthographic frustum dimensions are fixed instead of depending on the distance
to the revolveAroundPoint()
. Since this may be needed for some applications,
you may want to use this standardCamera
class in your code.
#include <QGLViewer/camera.h> class StandardCamera : public qglviewer::Camera { public : StandardCamera(); virtual float zNear() const; virtual float zFar() const; void toggleMode() { standard = !standard; } bool isStandard() { return standard; } void changeOrthoFrustumSize(int delta); virtual void getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const; private : bool standard; float orthoSize; };
#include "standardCamera.h" #include <QWheelEvent> using namespace qglviewer; StandardCamera::StandardCamera() { standard = true; orthoSize = 1.0; } float StandardCamera::zNear() const { if (standard) return 0.001f; else return Camera::zNear(); } float StandardCamera::zFar() const { if (standard) return 1000.0; else return Camera::zFar(); } void StandardCamera::changeOrthoFrustumSize(int delta) { if (delta > 0) orthoSize *= 1.1f; else orthoSize /= 1.1f; } void StandardCamera::getOrthoWidthHeight(GLdouble &halfWidth, GLdouble &halfHeight) const { if (standard) { halfHeight = orthoSize; halfWidth = aspectRatio() * orthoSize; } else Camera::getOrthoWidthHeight(halfWidth, halfHeight); }
#include <QGLViewer/qglviewer.h> class CameraViewer : public QGLViewer { public : CameraViewer(qglviewer::Camera* camera); protected : virtual void draw(); virtual void init(); private : qglviewer::Camera* c; };
#include <QGLViewer/qglviewer.h> class StandardCamera; class Viewer : public QGLViewer { Q_OBJECT public : Viewer(StandardCamera* camera); public : Q_SIGNALS : void cameraChanged(); protected : virtual void draw(); virtual void init(); virtual QString helpString() const; virtual void keyPressEvent(QKeyEvent *e); virtual void wheelEvent (QWheelEvent *e); private : void showMessage(); };
#include "cameraViewer.h" using namespace qglviewer; CameraViewer::CameraViewer(Camera* camera) : c(camera) {}; void CameraViewer::draw() { // Exactly the same draw than for 'Viewer'. The two viewers could also share a 'Scene' instance. const float nbSteps = 200.0; glBegin(GL_QUAD_STRIP); for (int i=0; i<nbSteps; ++i) { const float ratio = i/nbSteps; const float angle = 21.0*ratio; const float c = cos(angle); const float s = sin(angle); const float r1 = 1.0 - 0.8f*ratio; const float r2 = 0.8f - 0.8f*ratio; const float alt = ratio - 0.5f; const float nor = 0.5f; const float up = sqrt(1.0-nor*nor); glColor3f(1.0-ratio, 0.2f , ratio); glNormal3f(nor*c, up, nor*s); glVertex3f(r1*c, alt, r1*s); glVertex3f(r2*c, alt+0.05f, r2*s); } glEnd(); // Draws the other viewer's camera glDisable(GL_LIGHTING); glLineWidth(4.0); glColor4f(1.0, 1.0, 1.0, 0.5); c->draw(); glEnable(GL_LIGHTING); } void CameraViewer::init() { // Places the cameraViewer's camera far away in order to see the (other viewer) camera. if (!restoreStateFromFile()) { // Make near and far planes much further from scene in order not to clip c's display. camera()->setZClippingCoefficient(50.0); camera()->setViewDirection(qglviewer::Vec(0.0, -1.0, 0.0)); showEntireScene(); } // Enable semi-transparent culling planes glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
#include "standardCamera.h" #include "viewer.h" #include "cameraViewer.h" #include <QApplication> #include <QGLViewer/manipulatedCameraFrame.h> int main(int argc, char** argv) { QApplication application(argc,argv); // Instantiate the two viewers. StandardCamera* sc = new StandardCamera(); Viewer viewer(sc); CameraViewer cviewer(sc); // Make sure every v camera movement updates the camera viewer QObject::connect(viewer.camera()->frame(), SIGNAL(manipulated()), &cviewer, SLOT(updateGL())); QObject::connect(viewer.camera()->frame(), SIGNAL(spun()), &cviewer, SLOT(updateGL())); // Also update on camera change (type or mode) QObject::connect(&viewer, SIGNAL(cameraChanged()), &cviewer, SLOT(updateGL())); viewer.setWindowTitle("standardCamera"); cviewer.setWindowTitle("Camera viewer"); cviewer.show(); viewer.show(); return application.exec(); }
#include "viewer.h" #include "standardCamera.h" #include <QKeyEvent> using namespace std; using namespace qglviewer; Viewer::Viewer(StandardCamera* nfc) { // Change the camera. Camera* c = camera(); setCamera(nfc); delete c; } // Draws a spiral void Viewer::draw() { const float nbSteps = 200.0; glBegin(GL_QUAD_STRIP); for (int i=0; i<nbSteps; ++i) { const float ratio = i/nbSteps; const float angle = 21.0*ratio; const float c = cos(angle); const float s = sin(angle); const float r1 = 1.0 - 0.8f*ratio; const float r2 = 0.8f - 0.8f*ratio; const float alt = ratio - 0.5f; const float nor = 0.5f; const float up = sqrt(1.0-nor*nor); glColor3f(1.0-ratio, 0.2f , ratio); glNormal3f(nor*c, up, nor*s); glVertex3f(r1*c, alt, r1*s); glVertex3f(r2*c, alt+0.05f, r2*s); } glEnd(); } void Viewer::init() { // Restore previous viewer state. if (!restoreStateFromFile()) showEntireScene(); setKeyDescription(Qt::Key_T, "Toggles camera type (perspective or orthographic)"); setKeyDescription(Qt::Key_M, "Toggles camera mode (standard or QGLViewer)"); setMouseBindingDescription(Qt::ShiftModifier, Qt::MidButton, "Change frustum size (for standard camera in orthographic mode)"); // Display help window. help(); } void Viewer::showMessage() { QString std = ((StandardCamera*)camera())->isStandard()?"Standard camera":"QGLViewer camera"; QString type = camera()->type() == Camera::PERSPECTIVE?"Perspective":"Orthographic"; displayMessage(std + " - " + type); Q_EMIT cameraChanged(); } void Viewer::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_M) { // 'M' changes mode : standard or QGLViewer camera ((StandardCamera*)camera())->toggleMode(); showMessage(); } else if (e->key() == Qt::Key_T) { // 'T' changes the projection type : perspective or orthogonal if (camera()->type() == Camera::ORTHOGRAPHIC) camera()->setType(Camera::PERSPECTIVE); else camera()->setType(Camera::ORTHOGRAPHIC); showMessage(); } else QGLViewer::keyPressEvent(e); } void Viewer::wheelEvent(QWheelEvent *e) { if ((camera()->type() == Camera::ORTHOGRAPHIC) && (((StandardCamera*)camera())->isStandard()) && (e->modifiers() & Qt::ShiftModifier)) { ((StandardCamera*)camera())->changeOrthoFrustumSize(e->delta()); Q_EMIT cameraChanged(); updateGL(); } else QGLViewer::wheelEvent(e); } QString Viewer::helpString() const { QString text("<h2>S t a n d a r d C a m e r a</h2>"); text += "An overloaded <code>Camera</code> class is used, that reproduces the 'standard' OpenGL settings.<br><br>"; text += "With this camera, the near and (resp. far) plane distance is set to a very small (resp. very large) value. "; text += "With the orthographic camera type, the frustum dimensions are fixed. Use <code>Shift</code> and the mouse wheel to change them.<br><br>"; text += "On the other hand, the QGLViewer camera fits the near and far distances to the scene radius. "; text += "Fine tuning is available using <code>zClippingCoefficient()</code> and <code>zNearCoefficient()</code>. "; text += "However, visual results do not seem to be impacted by this zBuffer fitted range.<br><br>"; text += "The QGLViewer camera also adapts the orthographic frustum dimensions to the distance to the <code>revolveAroundPoint()</code> to mimic a perspective camera. "; text += "Since this behavior may not be needed, this example shows how to override it.<br><br>"; text += "The second viewer displays the first one's camera to show its configuration.<br><br>"; text += "Use <b>M</b> to switch between 'standard' and QGLViewer camera behavior.<br>"; text += "Use <b>T</b> to switch between perspective and orthographic camera type.<br><br>"; text += "Use <b>Shift+wheel</b> to change standard camera orthographic size."; return text; }
Back to the examples main page.