-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
CameraManipulator.cpp
133 lines (110 loc) · 4.13 KB
/
CameraManipulator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <osg/GL>
#include <osg/Matrix>
#include <osg/io_utils>
#include <osg/ComputeBoundsVisitor>
#include <osgGA/CameraManipulator>
#include <string.h>
using namespace osg;
using namespace osgGA;
CameraManipulator::CameraManipulator()
{
_intersectTraversalMask = 0xffffffff;
_autoComputeHomePosition = true;
_homeEye.set(0.0,-1.0,0.0);
_homeCenter.set(0.0,0.0,0.0);
_homeUp.set(0.0,0.0,1.0);
}
CameraManipulator::CameraManipulator(const CameraManipulator& mm, const CopyOp& copyOp):
osg::Object(mm,copyOp),
osg::Callback(mm,copyOp),
inherited(mm, copyOp),
_intersectTraversalMask(mm._intersectTraversalMask),
_autoComputeHomePosition(mm._autoComputeHomePosition),
_homeEye(mm._homeEye),
_homeCenter(mm._homeCenter),
_homeUp(mm._homeUp),
_coordinateFrameCallback(dynamic_cast<CoordinateFrameCallback*>(copyOp(mm._coordinateFrameCallback.get())))
{
}
CameraManipulator::~CameraManipulator()
{
}
std::string CameraManipulator::getManipulatorName() const
{
const char* className = this->className();
const char* manipString = strstr(className, "Manipulator");
if (!manipString)
return std::string(className);
else
return std::string(className, manipString-className);
}
bool CameraManipulator::handle(const GUIEventAdapter&,GUIActionAdapter&)
{
return false;
}
/** Compute the home position.
*
* The computation considers camera's fov (field of view) and model size and
* positions camera far enough to fit the model to the screen.
*
* camera parameter enables computations of camera's fov. If camera is NULL,
* scene to camera distance can not be computed and default value is used,
* based on model size only.
*
* useBoundingBox parameter enables to use bounding box instead of bounding sphere
* for scene bounds. Bounding box provide more precise scene center that may be
* important for many applications.*/
void CameraManipulator::computeHomePosition(const osg::Camera *camera, bool useBoundingBox)
{
if (getNode())
{
osg::BoundingSphere boundingSphere;
OSG_INFO<<" CameraManipulator::computeHomePosition("<<camera<<", "<<useBoundingBox<<")"<<std::endl;
if (useBoundingBox)
{
// compute bounding box
// (bounding box computes model center more precisely than bounding sphere)
osg::ComputeBoundsVisitor cbVisitor;
getNode()->accept(cbVisitor);
osg::BoundingBox &bb = cbVisitor.getBoundingBox();
if (bb.valid()) boundingSphere.expandBy(bb);
else boundingSphere = getNode()->getBound();
}
else
{
// compute bounding sphere
boundingSphere = getNode()->getBound();
}
OSG_INFO<<" boundingSphere.center() = ("<<boundingSphere.center()<<")"<<std::endl;
OSG_INFO<<" boundingSphere.radius() = "<<boundingSphere.radius()<<std::endl;
double radius = osg::maximum(double(boundingSphere.radius()), 1e-6);
// set dist to default
double dist = 3.5f * radius;
if (camera)
{
// try to compute dist from frustum
double left,right,bottom,top,zNear,zFar;
if (camera->getProjectionMatrixAsFrustum(left,right,bottom,top,zNear,zFar))
{
double vertical2 = fabs(right - left) / zNear / 2.;
double horizontal2 = fabs(top - bottom) / zNear / 2.;
double dim = horizontal2 < vertical2 ? horizontal2 : vertical2;
double viewAngle = atan2(dim,1.);
dist = radius / sin(viewAngle);
}
else
{
// try to compute dist from ortho
if (camera->getProjectionMatrixAsOrtho(left,right,bottom,top,zNear,zFar))
{
dist = fabs(zFar - zNear) / 2.;
}
}
}
// set home position
setHomePosition(boundingSphere.center() + osg::Vec3d(0.0,-dist,0.0f),
boundingSphere.center(),
osg::Vec3d(0.0f,0.0f,1.0f),
_autoComputeHomePosition);
}
}