source: trunk/packages/vizservers/nanovis/NvCamera.cpp @ 3502

Last change on this file since 3502 was 3502, checked in by ldelgass, 12 years ago

Add basic VTK structured points reader to nanovis, update copyright dates.

  • Property svn:eol-style set to native
File size: 7.5 KB
RevLine 
[2798]1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
[953]2/*
3 * ----------------------------------------------------------------------
4 * NvCamera.cpp : NvCamera class
5 *
6 * ======================================================================
7 *  AUTHOR:  Wei Qiao <qiaow@purdue.edu>
8 *           Purdue Rendering and Perceptualization Lab (PURPL)
9 *
[3502]10 *  Copyright (c) 2004-2013  HUBzero Foundation, LLC
[953]11 *
12 *  See the file "license.terms" for information on usage and
13 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * ======================================================================
15 */
[2836]16#include <stdio.h>
[2854]17#include <math.h>
[3362]18#include <float.h>
[953]19
[2836]20#include <GL/glew.h>
[953]21#include <GL/glu.h>
[2836]22
[3467]23#include <vrmath/Quaternion.h>
24#include <vrmath/Rotation.h>
[3492]25#include <vrmath/Matrix4x4d.h>
26#include <vrmath/Vector3f.h>
27#include <vrmath/Vector4f.h>
[2877]28
[3492]29#include "nanovis.h"
[953]30#include "NvCamera.h"
[2836]31#include "Trace.h"
[953]32
[3492]33using namespace vrmath;
34
35static inline double deg2rad(double deg)
[2854]36{
37    return ((deg * M_PI) / 180.);
38}
39
[3492]40static inline double rad2deg(double rad)
[2854]41{
42    return ((rad * 180.) / M_PI);
43}
44
[953]45NvCamera::NvCamera(int startx, int starty, int w, int h,
[3362]46                   float loc_x, float loc_y, float loc_z) :
[2836]47    _location(loc_x, loc_y, loc_z),
[3362]48    _fov(30.0),
49    _near(0.1),
50    _far(50.0),
[2836]51    _width(w),
52    _height(h),
53    _startX(startx),
54    _startY(starty)
55{
[953]56}
57
[3362]58void
[3492]59NvCamera::getUpDirMatrix(Matrix4x4d& upMat)
[3362]60{
[3492]61    switch (NanoVis::updir) {
62    case NanoVis::X_POS: {
63        upMat.makeRotation(0, 0, 1, deg2rad(90));
64        Matrix4x4d tmp;
65        tmp.makeRotation(1, 0, 0, deg2rad(90));
66        upMat.multiply(tmp);
67    }
68        break;
69    case NanoVis::Y_POS:
70        upMat.makeIdentity();
71        break;
72    case NanoVis::Z_POS: {
73        upMat.makeRotation(1, 0, 0, deg2rad(-90));
74        Matrix4x4d tmp;
75        tmp.makeRotation(0, 0, 1, deg2rad(-90));
76        upMat.multiply(tmp);
77    }
78        break;
79    case NanoVis::X_NEG:
80        upMat.makeRotation(0, 0, 1, deg2rad(-90));
81        break;
82    case NanoVis::Y_NEG: {
83        upMat.makeRotation(0, 0, 1, deg2rad(180));
84        Matrix4x4d tmp;
85        tmp.makeRotation(0, 1, 0, deg2rad(-90));
86        upMat.multiply(tmp);
87    }
88        break;
89    case NanoVis::Z_NEG:
90        upMat.makeRotation(1, 0, 0, deg2rad(90));
91        break;
92    }
93}
94
95/**
96 * \brief Reset zoom to include extents
97 */
98void
99NvCamera::reset(const Vector3f& bboxMin,
100                const Vector3f& bboxMax,
101                bool resetOrientation)
102{
103    TRACE("Enter");
104
105    if (resetOrientation) {
106        _cameraMatrix.makeIdentity();
107    }
108
109    Vector3f center(bboxMin + bboxMax);
110    center.scale(0.5);
111
112    Matrix4x4d mat, upMat;
113    getUpDirMatrix(upMat);
114    mat.makeTranslation(-center);
115    mat.multiply(_cameraMatrix, mat);
116    mat.multiply(upMat);
117
118    Vector3f emin(FLT_MAX, FLT_MAX, FLT_MAX), emax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
119
120    // Transform bounds by camera matrix
121    Vector4f bboxEye[8];
122    bboxEye[0] = Vector4f(bboxMin.x, bboxMin.y, bboxMin.z, 1);
123    bboxEye[1] = Vector4f(bboxMax.x, bboxMin.y, bboxMin.z, 1);
124    bboxEye[2] = Vector4f(bboxMin.x, bboxMax.y, bboxMin.z, 1);
125    bboxEye[3] = Vector4f(bboxMin.x, bboxMin.y, bboxMax.z, 1);
126    bboxEye[4] = Vector4f(bboxMax.x, bboxMax.y, bboxMin.z, 1);
127    bboxEye[5] = Vector4f(bboxMax.x, bboxMin.y, bboxMax.z, 1);
128    bboxEye[6] = Vector4f(bboxMin.x, bboxMax.y, bboxMax.z, 1);
129    bboxEye[7] = Vector4f(bboxMax.x, bboxMax.y, bboxMax.z, 1);
130
[3362]131    for (int i = 0; i < 8; i++) {
[3492]132        Vector4f eyeVert = mat.transform(bboxEye[i]);
133        if (eyeVert.x < emin.x) emin.x = eyeVert.x;
134        if (eyeVert.x > emax.x) emax.x = eyeVert.x;
135        if (eyeVert.y < emin.y) emin.y = eyeVert.y;
136        if (eyeVert.y > emax.y) emax.y = eyeVert.y;
137        if (eyeVert.z < emin.z) emin.z = eyeVert.z;
138        if (eyeVert.z > emax.z) emax.z = eyeVert.z;
[3362]139    }
[3492]140
141    TRACE("Eye bounds: (%g,%g,%g) - (%g,%g,%g)",
142          emin.x, emin.y, emin.z,
143          emax.x, emax.y, emax.z);
144
145    double bwidth = emax.x - emin.x;
146    double bheight = emax.y - emin.y;
147    double bdepth = emax.z - emin.z;
148
149    TRACE("bwidth: %g, bheight: %g, bdepth: %g", bwidth, bheight, bdepth);
150
151    double angle = deg2rad(_fov);
152    double distance;
153
154    // Deal with vertical aspect window
155    double winAspect = (double)(_width - _startX)/(double)(_height - _startY);
156    double sceneAspect = 1.0;;
157    if (bheight > 0.0)
158        sceneAspect = bwidth / bheight;
159
160    if (sceneAspect >= winAspect) {
161        angle = 2.0 * atan(tan(angle*0.5)*winAspect);
162        _near = bwidth / (2.0 * tan(angle*0.5));
163    } else {
164        _near = bheight / (2.0 * tan(angle*0.5));
[3362]165    }
[3492]166
167    distance = _near + bdepth * 0.5;
168    _far = _near + bdepth;
169
170    _location.set(center.x, center.y, center.z + distance);
171
172    TRACE("win aspect: %g scene aspect: %g", winAspect, sceneAspect);
173    TRACE("c: %g,%g,%g, d: %g", center.x, center.y, center.z, distance);
174    TRACE("near: %g, far: %g", _near, _far);
175
176    initialize();
177    resetClippingRange(bboxMin, bboxMax);
178}
179
180void
181NvCamera::resetClippingRange(const Vector3f& bboxMin, const Vector3f& bboxMax)
182{
183    Vector3f emin(bboxMin.x, bboxMin.y, bboxMin.z), emax(bboxMax.x, bboxMax.y, bboxMax.z);
184
185    Vector3f center(emin + emax);
186    center.scale(0.5);
187
188    // Compute the radius of the enclosing sphere,
189    // which is half the bounding box diagonal
190    Vector3f diagonal(emax - emin);
191    double radius = diagonal.length() * 0.5;
192
193    // If we have just a single point, pick a radius of 1.0
194    radius = (radius == 0) ? 1.0 : radius;
195
196    TRACE("c: %g,%g,%g, r: %g cam z: %g", center.x, center.y, center.z, radius, _location.z);
197
198    _near = _location.z - radius;
199    _far = _location.z + radius;
200
201    if (_near < 0.0) {
202        _near = 0.001;
[3362]203    }
[3492]204    if (_far < 0.0) {
205        _far = 1.0;
206    }
[3362]207
[3452]208    TRACE("Resetting camera clipping range to: near: %g, far: %g", _near, _far);
[3362]209
210    glMatrixMode(GL_PROJECTION);
211    glLoadIdentity();
212    gluPerspective(_fov,
213                   (GLdouble)(_width - _startX)/(GLdouble)(_height - _startY),
214                   _near, _far);
215    glMatrixMode(GL_MODELVIEW);
[3492]216
217    print();
[3362]218}
219
[953]220void
[1431]221NvCamera::initialize()
[953]222{
[3492]223    TRACE("Enter");
224    print();
225
[2836]226    glViewport(_startX, _startY, _width, _height);
[953]227    glMatrixMode(GL_PROJECTION);
228    glLoadIdentity();
[3362]229    gluPerspective(_fov,
[2854]230                   (GLdouble)(_width - _startX)/(GLdouble)(_height - _startY),
[3362]231                   _near, _far);
[953]232
233    glMatrixMode(GL_MODELVIEW);
234    glLoadIdentity();
235
[2877]236    glTranslatef(-_location.x, -_location.y, -_location.z);
[3492]237    glMultMatrixd((const GLdouble *)_cameraMatrix.get());
[953]238}
[2877]239
240void NvCamera::rotate(double *quat)
241{
[3492]242    Quaternion q(quat[0], quat[1], quat[2], quat[3]);
243    Rotation rot;
[2877]244    rot.set(q);
245    _cameraMatrix.makeRotation(rot);
246    _cameraMatrix.transpose();
[3452]247    TRACE("Set rotation to quat: %g %g %g %g",
[2877]248          quat[0], quat[1], quat[2], quat[3]);
249}
250
[3362]251void NvCamera::rotate(float angleX, float angleY, float angleZ)
[2877]252{
[3362]253    angleX = -angleX;
254    angleY = angleY - 180.;
[2877]255
[3362]256    _cameraMatrix.makeRotation(1, 0, 0, deg2rad(angleX));
[3492]257    Matrix4x4d mat;
[3362]258    mat.makeRotation(0, 1, 0, deg2rad(angleY));
[2877]259    _cameraMatrix.multiply(mat);
[3362]260    mat.makeRotation(0, 0, 1, deg2rad(angleZ));
[2877]261    _cameraMatrix.multiply(mat);
262    //_cameraMatrix.transpose();
263
[3452]264    TRACE("Set rotation to angles: %g %g %g",
[3362]265          angleX, angleY, angleZ);
[2877]266}
[3492]267
268void NvCamera::print() const
269{
270    TRACE("x: %d y: %d w: %d h: %d", _startX, _startY, _width, _height);
271    TRACE("loc: %g %g %g",
272          _location.x, _location.y, _location.z);
273    TRACE("Camera matrix: ");
274    _cameraMatrix.print();
275    TRACE("fov: %g near: %g far: %g", _fov, _near, _far);
276}
Note: See TracBrowser for help on using the repository browser.