1
/**************************************************************************\
3
* This file is part of the Coin 3D visualization library.
4
* Copyright (C) 1998-2007 by Systems in Motion. All rights reserved.
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* ("GPL") version 2 as published by the Free Software Foundation.
9
* See the file LICENSE.GPL at the root directory of this source
10
* distribution for additional information about the GNU GPL.
12
* For using Coin with software that can not be combined with the GNU
13
* GPL, and for taking advantage of the additional benefits of our
14
* support services, please contact Systems in Motion about acquiring
15
* a Coin Professional Edition License.
17
* See http://www.coin3d.org/ for more information.
19
* Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY.
20
* http://www.sim.no/ sales@sim.no coin-support@coin3d.org
22
\**************************************************************************/
25
\class SoFrustumCamera SoFrustumCamera.h Inventor/nodes/SoFrustumCamera.h
26
\brief The SoFrustumCamera class defines a camera with a generic frustum..
28
The SoFrustumCamera class makes it possible to specify a frustum in
29
the same manner as the OpenGL glFrustum() function. It has four new
30
fields (left, right, top, bottom), and will use
31
SoCamera::nearDistance and SoCamera::farDistance for the two last
32
glFrustum() parameters.
34
This camera can be useful in applications that require full control
35
over the view frustum, such as in CAVE or other multipipe
42
\var SoSFFloat SoFrustumCamera::left
44
The left clipping plane position. Default value is -0.5.
48
\var SoSFFloat SoFrustumCamera::right
50
The right clipping plane position. Default value is 0.5
54
\var SoSFFloat SoFrustumCamera::bottom
56
The bottom clipping plane position. Default value is -0.5.
60
\var SoSFFloat SoFrustumCamera::top
62
The top clipping plane position. Default value is 0.5.
65
#include <Inventor/nodes/SoFrustumCamera.h>
66
#include <Inventor/nodes/SoSubNodeP.h>
67
#include <Inventor/errors/SoDebugError.h>
68
#include <Inventor/SbSphere.h>
71
SO_NODE_SOURCE(SoFrustumCamera);
76
SoFrustumCamera::SoFrustumCamera(void)
78
SO_NODE_INTERNAL_CONSTRUCTOR(SoFrustumCamera);
80
SO_NODE_ADD_FIELD(top, (0.5f));
81
SO_NODE_ADD_FIELD(bottom, (-0.5f));
82
SO_NODE_ADD_FIELD(left, (-0.5f));
83
SO_NODE_ADD_FIELD(right, (0.5f));
89
SoFrustumCamera::~SoFrustumCamera(void)
95
SoFrustumCamera::initClass(void)
97
SO_NODE_INTERNAL_INIT_CLASS(SoFrustumCamera, SoNode::COIN_2_5);
100
// Doc in superclass.
102
SoFrustumCamera::scaleHeight(float scalefactor)
104
this->top = this->top.getValue() * scalefactor;
105
this->bottom = this->bottom.getValue() * scalefactor;
108
// Doc in superclass.
110
SoFrustumCamera::getViewVolume(float useaspectratio) const
114
if (useaspectratio == 0.0f) { // LEAVE_ALONE viewportMapping
115
vv.frustum(this->left.getValue(),
116
this->right.getValue(),
117
this->bottom.getValue(),
118
this->top.getValue(),
119
this->nearDistance.getValue(),
120
this->farDistance.getValue());
123
// calculate left and right based on height
124
float cx = (this->left.getValue() + this->right.getValue()) * 0.5f;
125
float h_2 = (this->top.getValue() - this->bottom.getValue()) * 0.5f;
127
vv.frustum(cx - h_2 * useaspectratio,
128
cx + h_2 * useaspectratio,
129
this->bottom.getValue(),
130
this->top.getValue(),
131
this->nearDistance.getValue(),
132
this->farDistance.getValue());
134
vv.rotateCamera(this->orientation.getValue());
135
vv.translateCamera(this->position.getValue());
139
// Doc in superclass.
141
SoFrustumCamera::viewBoundingBox(const SbBox3f & box, float aspect, float slack)
145
// Only check for "flagged" emptiness, and don't use
146
// SbBox3f::hasVolume(), as we *can* handle flat boxes.
148
SoDebugError::postWarning("Frustum::viewBoundingBox",
149
"bounding box is empty");
154
// First, we want to move the camera in such a way that it is
155
// pointing straight at the center of the scene bounding box -- but
156
// without modifiying the rotation value (so we can't use
157
// SoCamera::pointAt()).
158
SbVec3f cameradirection;
159
this->orientation.getValue().multVec(SbVec3f(0, 0, -1), cameradirection);
160
this->position.setValue(box.getCenter() + -cameradirection);
162
// Get the radius of the bounding sphere.
164
bs.circumscribe(box);
165
float radius = bs.getRadius();
167
// Make sure that everything will still be inside the viewing volume
168
// even if the aspect ratio "favorizes" width over height.
169
float aspectradius = radius / (aspect < 1.0f ? aspect : 1.0f);
171
// just calculate a heightangle so that we can reuse code from
172
// SoPerspectiveCamera
173
float nearv = this->nearDistance.getValue();
174
SbVec3f tvec = SbVec3f(0.0f, this->top.getValue(), nearv);
175
SbVec3f bvec = SbVec3f(0.0f, this->bottom.getValue(), nearv);
177
(void) tvec.normalize();
178
(void) bvec.normalize();
180
float heightangle = (float) acos((double)SbClamp(tvec.dot(bvec), 0.0f, 1.0f));
182
// Move the camera to the edge of the bounding sphere, while still
183
// pointing at the scene.
184
SbVec3f direction = this->position.getValue() - box.getCenter();
185
direction.normalize();
187
aspectradius + (aspectradius/float(atan(heightangle)));
188
this->position.setValue(box.getCenter() + direction * movelength);
190
// Set up the far clipping plane according to the slack value (a
191
// value of 1.0 will yield a far clipping plane that is tangent to
192
// the bounding sphere of the scene).
193
float distance_to_midpoint =
194
(this->position.getValue() - box.getCenter()).length();
195
this->farDistance = distance_to_midpoint + radius * slack;
197
// The focal distance is simply the distance from the camera to the
198
// scene midpoint. This field is not used in rendering, its just
199
// provided to make it easier for the user to do calculations based
200
// on the distance between the camera and the scene.
201
this->focalDistance = distance_to_midpoint;