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