root/OpenSceneGraph/trunk/src/osgGA/NodeTrackerManipulator.cpp @ 12157

Revision 12157, 9.4 kB (checked in by robert, 3 years ago)

Added check against the NodePath? being empty.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgGA/NodeTrackerManipulator>
15#include <osg/Quat>
16#include <osg/Notify>
17#include <osg/Transform>
18#include <iterator>
19
20using namespace osg;
21using namespace osgGA;
22
23
24NodeTrackerManipulator::NodeTrackerManipulator( int flags )
25    : inherited( flags ),
26      _trackerMode(NODE_CENTER_AND_ROTATION)
27{
28    setVerticalAxisFixed(false);
29}
30
31
32NodeTrackerManipulator::NodeTrackerManipulator( const NodeTrackerManipulator& m, const CopyOp& copyOp )
33    : inherited( m, copyOp ),
34      _trackNodePath( m._trackNodePath ),
35      _trackerMode( m._trackerMode )
36{
37}
38
39
40void NodeTrackerManipulator::setTrackNodePath(const osg::NodePath& nodePath)
41{
42    _trackNodePath.setNodePath(nodePath);
43}
44
45
46void NodeTrackerManipulator::setTrackerMode(TrackerMode mode)
47{
48    _trackerMode = mode;
49}
50
51/// Sets rotation mode. \sa setVerticalAxisFixed
52void NodeTrackerManipulator::setRotationMode(RotationMode mode)
53{
54    setVerticalAxisFixed(mode!=TRACKBALL);
55
56    if (getAutoComputeHomePosition())
57        computeHomePosition();
58}
59
60/// Gets rotation mode. \sa getVerticalAxisFixed
61NodeTrackerManipulator::RotationMode NodeTrackerManipulator::getRotationMode() const
62{
63    return getVerticalAxisFixed() ? ELEVATION_AZIM : TRACKBALL;
64}
65
66void NodeTrackerManipulator::setNode(Node* node)
67{
68    inherited::setNode( node );
69
70    // update model size
71    if (_flags & UPDATE_MODEL_SIZE)
72    {
73        if (_node.valid())
74        {
75            setMinimumDistance(clampBetween(_modelSize*0.001, 0.00001, 1.0));
76            OSG_INFO << "NodeTrackerManipulator: setting minimum distance to "
77                         << _minimumDistance << std::endl;
78        }
79    }
80}
81
82void NodeTrackerManipulator::setTrackNode(osg::Node* node)
83{
84    if (!node)
85    {
86        OSG_NOTICE<<"NodeTrackerManipulator::setTrackNode(Node*):  Unable to set tracked node due to null Node*"<<std::endl;
87        return;
88    }
89
90    osg::NodePathList nodePaths = node->getParentalNodePaths();
91    if (!nodePaths.empty())
92    {
93        if (nodePaths.size()>1)
94        {
95            OSG_NOTICE<<"osgGA::NodeTrackerManipualtor::setTrackNode(..) taking first parent path, ignoring others."<<std::endl;
96        }
97
98        for(unsigned int i=0; i<nodePaths.size(); ++i)
99        {
100            OSG_NOTICE<<"NodePath "<<i<<std::endl;
101            for(NodePath::iterator itr = nodePaths[i].begin();
102                itr != nodePaths[i].end();
103                ++itr)
104            {
105                OSG_NOTICE<<"     "<<(*itr)->className()<<std::endl;
106            }
107        }
108       
109
110        OSG_INFO<<"NodeTrackerManipulator::setTrackNode(Node*"<<node<<" "<<node->getName()<<"): Path set"<<std::endl;
111        setTrackNodePath( nodePaths[0] );
112    }
113    else
114    {
115        OSG_NOTICE<<"NodeTrackerManipulator::setTrackNode(Node*): Unable to set tracked node due to empty parental path."<<std::endl;
116    }
117
118
119}
120
121
122void NodeTrackerManipulator::computeHomePosition()
123{
124    osg::Node* node = getTrackNode();
125    if(node)
126    {
127        const osg::BoundingSphere& boundingSphere=node->getBound();
128
129        setHomePosition(boundingSphere._center+osg::Vec3d( 0.0,-3.5f * boundingSphere._radius,0.0f),
130                        boundingSphere._center,
131                        osg::Vec3d(0.0f,0.0f,1.0f),
132                        _autoComputeHomePosition);
133    }
134}
135
136
137void NodeTrackerManipulator::setByMatrix(const osg::Matrixd& matrix)
138{
139    osg::Vec3d eye,center,up;
140    matrix.getLookAt(eye,center,up,_distance);
141    computePosition(eye,center,up);
142}
143
144void NodeTrackerManipulator::computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const
145{
146    osg::NodePath nodePath;
147    if (_trackNodePath.getNodePath(nodePath))
148    {
149        worldToLocal = osg::computeWorldToLocal(nodePath);
150    }
151}
152
153void NodeTrackerManipulator::computeNodeLocalToWorld(osg::Matrixd& localToWorld) const
154{
155    osg::NodePath nodePath;
156    if (_trackNodePath.getNodePath(nodePath))
157    {
158        localToWorld = osg::computeLocalToWorld(nodePath);
159    }
160
161}
162
163void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter, osg::Quat& nodeRotation) const
164{
165    osg::Matrixd localToWorld, worldToLocal;
166    computeNodeLocalToWorld(localToWorld);
167    computeNodeWorldToLocal(worldToLocal);
168
169    osg::NodePath nodePath;
170    if (_trackNodePath.getNodePath(nodePath) && !nodePath.empty())
171        nodeCenter = osg::Vec3d(nodePath.back()->getBound().center())*localToWorld;
172    else
173        nodeCenter = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld;
174
175
176    switch(_trackerMode)
177    {
178        case(NODE_CENTER_AND_AZIM):
179        {
180            CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter);
181            osg::Matrixd localToFrame(localToWorld*osg::Matrixd::inverse(coordinateFrame));
182
183            double azim = atan2(-localToFrame(0,1),localToFrame(0,0));
184            osg::Quat nodeRotationRelToFrame, rotationOfFrame;
185            nodeRotationRelToFrame.makeRotate(-azim,0.0,0.0,1.0);
186            rotationOfFrame = coordinateFrame.getRotate();
187            nodeRotation = nodeRotationRelToFrame*rotationOfFrame;
188            break;
189        }
190        case(NODE_CENTER_AND_ROTATION):
191        {
192            // scale the matrix to get rid of any scales before we extract the rotation.
193            double sx = 1.0/sqrt(localToWorld(0,0)*localToWorld(0,0) + localToWorld(1,0)*localToWorld(1,0) + localToWorld(2,0)*localToWorld(2,0));
194            double sy = 1.0/sqrt(localToWorld(0,1)*localToWorld(0,1) + localToWorld(1,1)*localToWorld(1,1) + localToWorld(2,1)*localToWorld(2,1));
195            double sz = 1.0/sqrt(localToWorld(0,2)*localToWorld(0,2) + localToWorld(1,2)*localToWorld(1,2) + localToWorld(2,2)*localToWorld(2,2));
196            localToWorld = localToWorld*osg::Matrixd::scale(sx,sy,sz);
197
198            nodeRotation = localToWorld.getRotate();
199            break;
200        }
201        case(NODE_CENTER):
202        default:
203        {
204            CoordinateFrame coordinateFrame = getCoordinateFrame(nodeCenter);
205            nodeRotation = coordinateFrame.getRotate();
206            break;
207        }
208    }
209
210}
211
212
213osg::Matrixd NodeTrackerManipulator::getMatrix() const
214{
215    osg::Vec3d nodeCenter;
216    osg::Quat nodeRotation;
217    computeNodeCenterAndRotation(nodeCenter,nodeRotation);
218    return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::rotate(nodeRotation)*osg::Matrix::translate(nodeCenter);
219}
220
221osg::Matrixd NodeTrackerManipulator::getInverseMatrix() const
222{
223    osg::Vec3d nodeCenter;
224    osg::Quat nodeRotation;
225    computeNodeCenterAndRotation(nodeCenter,nodeRotation);
226    return osg::Matrixd::translate(-nodeCenter)*osg::Matrixd::rotate(nodeRotation.inverse())*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
227}
228
229void NodeTrackerManipulator::computePosition(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up)
230{
231    if (!_node) return;
232
233    // compute rotation matrix
234    osg::Vec3d lv(center-eye);
235    _distance = lv.length();
236
237    osg::Matrixd lookat;
238    lookat.makeLookAt(eye,center,up);
239
240    _rotation = lookat.getRotate().inverse();
241}
242
243
244// doc in parent
245bool NodeTrackerManipulator::performMovementLeftMouseButton( const double eventTimeDelta, const double dx, const double dy )
246{
247    osg::Vec3d nodeCenter;
248    osg::Quat nodeRotation;
249    computeNodeCenterAndRotation(nodeCenter, nodeRotation);
250
251    // rotate camera
252    if( getVerticalAxisFixed() ) {
253
254         osg::Matrix rotation_matrix;
255         rotation_matrix.makeRotate(_rotation);
256
257         osg::Vec3d lookVector = -getUpVector(rotation_matrix);
258         osg::Vec3d sideVector = getSideVector(rotation_matrix);
259         osg::Vec3d upVector = getFrontVector(rotation_matrix);
260
261         osg::Vec3d localUp(0.0f,0.0f,1.0f);
262
263         osg::Vec3d forwardVector = localUp^sideVector;
264         sideVector = forwardVector^localUp;
265
266         forwardVector.normalize();
267         sideVector.normalize();
268
269         osg::Quat rotate_elevation;
270         rotate_elevation.makeRotate(dy,sideVector);
271
272         osg::Quat rotate_azim;
273         rotate_azim.makeRotate(-dx,localUp);
274
275         _rotation = _rotation * rotate_elevation * rotate_azim;
276
277    } else
278        rotateTrackball( _ga_t0->getXnormalized(), _ga_t0->getYnormalized(),
279                         _ga_t1->getXnormalized(), _ga_t1->getYnormalized(),
280                         _thrown ? float( _delta_frame_time / eventTimeDelta ) : 1.f );
281
282    return true;
283}
284
285
286// doc in parent
287bool NodeTrackerManipulator::performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy )
288{
289    osg::Vec3d nodeCenter;
290    osg::Quat nodeRotation;
291    computeNodeCenterAndRotation(nodeCenter, nodeRotation);
292
293    return true;
294}
295
296
297// doc in parent
298bool NodeTrackerManipulator::performMovementRightMouseButton( const double eventTimeDelta, const double dx, const double dy )
299{
300    osg::Vec3d nodeCenter;
301    osg::Quat nodeRotation;
302    computeNodeCenterAndRotation(nodeCenter, nodeRotation);
303
304    return inherited::performMovementRightMouseButton(eventTimeDelta, dx, dy);
305}
Note: See TracBrowser for help on using the browser.