openscenegraph
Dragger
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.
14
15#ifndef OSGMANIPULATOR_DRAGGER
16#define OSGMANIPULATOR_DRAGGER 1
17
18#include <osgManipulator/Constraint>
19#include <osgManipulator/Command>
20
21#include <osg/BoundingSphere>
22#include <osg/MatrixTransform>
23#include <osgUtil/SceneView>
24#include <osgGA/GUIEventAdapter>
25#include <osgGA/GUIActionAdapter>
26
27namespace osgManipulator
28{
29
30class CompositeDragger;
31class MotionCommand;
32class TranslateInLineCommand;
33class TranslateInPlaneCommand;
34class Scale1DCommand;
35class Scale2DCommand;
36class ScaleUniformCommand;
37class Rotate3DCommand;
38
39/** Computes the nodepath from the given node all the way up to the root. */
40extern OSGMANIPULATOR_EXPORT void computeNodePathToRoot(osg::Node& node, osg::NodePath& np);
41
42
43class OSGMANIPULATOR_EXPORT DraggerTransformCallback : public DraggerCallback
44{
45 public:
46
47 enum HandleCommandMask
48 {
49 HANDLE_TRANSLATE_IN_LINE = 1<<0,
50 HANDLE_TRANSLATE_IN_PLANE = 1<<1,
51 HANDLE_SCALED_1D = 1<<2,
52 HANDLE_SCALED_2D = 1<<3,
53 HANDLE_SCALED_UNIFORM = 1<<4,
54 HANDLE_ROTATE_3D = 1<<5,
55 HANDLE_ALL = 0x8ffffff
56 };
57
58 DraggerTransformCallback(osg::MatrixTransform* transform, int handleCommandMask = HANDLE_ALL);
59
60 virtual bool receive(const MotionCommand&);
61 virtual bool receive(const TranslateInLineCommand& command);
62 virtual bool receive(const TranslateInPlaneCommand& command);
63 virtual bool receive(const Scale1DCommand& command);
64 virtual bool receive(const Scale2DCommand& command);
65 virtual bool receive(const ScaleUniformCommand& command);
66 virtual bool receive(const Rotate3DCommand& command);
67
68 osg::MatrixTransform* getTransform() { return _transform.get(); }
69 const osg::MatrixTransform* getTransform() const { return _transform.get(); }
70
71 protected:
72
73 unsigned int _handleCommandMask;
74
75 osg::observer_ptr<osg::MatrixTransform> _transform;
76 osg::Matrix _startMotionMatrix;
77
78 osg::Matrix _localToWorld;
79 osg::Matrix _worldToLocal;
80};
81
82
83class OSGMANIPULATOR_EXPORT PointerInfo
84{
85 public:
86
87 PointerInfo();
88
89 PointerInfo(const PointerInfo& rhs):
90 _hitList(rhs._hitList),
91 _nearPoint(rhs._nearPoint),
92 _farPoint(rhs._farPoint),
93 _eyeDir(rhs._eyeDir)
94 {
95 _hitIter = _hitList.begin();
96 }
97
98 void reset()
99 {
100 _hitList.clear();
101 _hitIter = _hitList.begin();
102 setCamera(0);
103 }
104
105
106 bool completed() const { return _hitIter==_hitList.end(); }
107
108 void next()
109 {
110 if (!completed()) ++_hitIter;
111 }
112
113 typedef std::pair<osg::NodePath, osg::Vec3d> NodePathIntersectionPair;
114 typedef std::list< NodePathIntersectionPair> IntersectionList;
115
116
117 osg::Vec3d getLocalIntersectPoint() const { return _hitIter->second; }
118
119
120
121 void setNearFarPoints (osg::Vec3d nearPoint, osg::Vec3d farPoint) {
122 _nearPoint = nearPoint;
123 _farPoint=farPoint;
124 _eyeDir = farPoint - nearPoint;
125 }
126
127 const osg::Vec3d& getEyeDir() const {return _eyeDir;}
128
129 void getNearFarPoints( osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const {
130 nearPoint = _nearPoint;
131 farPoint = _farPoint;
132 }
133
134 bool contains(const osg::Node* node) const;
135
136 void setCamera(osg::Camera* camera)
137 {
138
139 if (camera)
140 {
141 _MVPW = camera->getViewMatrix() * camera->getProjectionMatrix();
142 if (camera->getViewport()) _MVPW.postMult(camera->getViewport()->computeWindowMatrix());
143 _inverseMVPW.invert(_MVPW);
144 osg::Vec3d eye, center, up;
145 camera->getViewMatrix().getLookAt(eye, center, up);
146 _eyeDir = eye - center;
147
148 }
149 else
150 {
151 _MVPW.makeIdentity();
152 _inverseMVPW.makeIdentity();
153 _eyeDir = osg::Vec3d(0,0,1);
154 }
155
156 }
157
158 void addIntersection(const osg::NodePath& nodePath, const osg::Vec3d& intersectionPoint)
159 {
160 bool needToResetHitIter = _hitList.empty();
161 _hitList.push_back(NodePathIntersectionPair(nodePath, intersectionPoint));
162 if (needToResetHitIter) _hitIter = _hitList.begin();
163 }
164
165 void setMousePosition(float pixel_x, float pixel_y)
166 {
167 projectWindowXYIntoObject(osg::Vec2d(pixel_x, pixel_y), _nearPoint, _farPoint);
168 }
169
170 protected:
171 bool projectWindowXYIntoObject(const osg::Vec2d& windowCoord, osg::Vec3d& nearPoint, osg::Vec3d& farPoint) const;
172
173 public:
174 IntersectionList _hitList;
175 IntersectionList::const_iterator _hitIter;
176
177 protected:
178
179 osg::Vec3d _nearPoint,_farPoint;
180 osg::Vec3d _eyeDir;
181
182 osg::Matrix _MVPW;
183 osg::Matrix _inverseMVPW;
184
185};
186
187/**
188 * Base class for draggers. Concrete draggers implement the pick event handler
189 * and generate motion commands (translate, rotate, ...) and sends these
190 * command to all the DraggerCallbacks & Transforms that are connected to the Dragger that generates the
191 * commands.
192 */
193class OSGMANIPULATOR_EXPORT Dragger : public osg::MatrixTransform
194{
195 public:
196
197
198 META_Node(osgManipulator,Dragger);
199
200 /**
201 * Set/Get parent dragger. For simple draggers parent points to itself.
202 * For composite draggers parent points to the parent dragger that uses
203 * this dragger.
204 */
205 virtual void setParentDragger(Dragger* parent) { _parentDragger = parent; }
206
207 Dragger* getParentDragger() { return _parentDragger; }
208 const Dragger* getParentDragger() const { return _parentDragger; }
209
210 /** Returns 0 if this Dragger is not a CompositeDragger. */
211 virtual const CompositeDragger* getComposite() const { return 0; }
212
213 /** Returns 0 if this Dragger is not a CompositeDragger. */
214 virtual CompositeDragger* getComposite() { return 0; }
215
216
217 void setHandleEvents(bool flag);
218 bool getHandleEvents() const { return _handleEvents; }
219
220 void setActivationModKeyMask(unsigned int mask) { _activationModKeyMask = mask; }
221 unsigned int getActivationModKeyMask() const { return _activationModKeyMask; }
222
223 void setActivationMouseButtonMask(unsigned int mask) { _activationMouseButtonMask = mask; }
224 unsigned int getActivationMouseButtonMask() const { return _activationMouseButtonMask; }
225
226 void setActivationKeyEvent(int key) { _activationKeyEvent = key; }
227 int getActivationKeyEvent() const { return _activationKeyEvent; }
228
229
230 virtual void traverse(osg::NodeVisitor& nv);
231
232 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
233 virtual bool handle(const PointerInfo&, const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) { return false; }
234
235
236 typedef std::vector< osg::ref_ptr<Constraint> > Constraints;
237
238 void addConstraint(Constraint* constraint);
239 template<class T> void addConstraint(const osg::ref_ptr<T>& c) { addConstraint(c.get()); }
240
241 void removeConstraint(Constraint* constraint);
242 template<class T> void removeConstraint(const osg::ref_ptr<T>& c) { removeConstraint(c.get()); }
243
244 Constraints& getConstraints() { return _constraints; }
245 const Constraints& getConstraints() const { return _constraints; }
246
247
248 typedef std::vector< osg::ref_ptr<DraggerCallback> > DraggerCallbacks;
249
250 void addDraggerCallback(DraggerCallback* dc);
251 template<class T> void addDraggerCallback(const osg::ref_ptr<T>& dc) { addDraggerCallback(dc.get()); }
252
253 void removeDraggerCallback(DraggerCallback* dc);
254 template<class T> void removeDraggerCallback(const osg::ref_ptr<T>& dc) { removeDraggerCallback(dc.get()); }
255
256 DraggerCallbacks& getDraggerCallbacks() { return _draggerCallbacks; }
257 const DraggerCallbacks& getDraggerCallbacks() const { return _draggerCallbacks; }
258
259 void addTransformUpdating(MatrixTransform* transform, int handleCommandMask = DraggerTransformCallback::HANDLE_ALL);
260 void removeTransformUpdating(MatrixTransform* transform);
261
262 /** Setup default geometry for dragger. */
263 virtual void setupDefaultGeometry() {}
264
265 virtual bool receive(const MotionCommand& command);
266 virtual void dispatch(MotionCommand& command);
267
268 void setDraggerActive(bool active) { _draggerActive = active; }
269 bool getDraggerActive() const { return _draggerActive; }
270
271 /**
272 * Set/Get the traversal mask used by this dragger when looking for intersections during event handling.
273 * This is useful to "hide" some geometry during event handling.
274 */
275 virtual void setIntersectionMask(osg::Node::NodeMask intersectionMask) { _intersectionMask = intersectionMask; }
276 osg::Node::NodeMask getIntersectionMask() const { return _intersectionMask; }
277
278 /** Return true if the axis of the Locator are inverted requiring the faces of any cubes used from rendering to be flipped to ensure the correct front/back face is used.*/
279 bool inverted() const;
280
281 /** apply the appropriate FrontFace setting to provided StateSet to ensure that the rendering of hull of the volume is the correct orientation.*/
282 void applyAppropriateFrontFace(osg::StateSet* ss) const;
283
284protected:
285
286 Dragger();
287 Dragger(const Dragger& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
288
289 virtual ~Dragger();
290
291
292 bool _handleEvents;
293 bool _draggerActive;
294
295 unsigned int _activationModKeyMask;
296 unsigned int _activationMouseButtonMask;
297 int _activationKeyEvent;
298 bool _activationPermittedByModKeyMask;
299 bool _activationPermittedByMouseButtonMask;
300 bool _activationPermittedByKeyEvent;
301
302 osgManipulator::PointerInfo _pointer;
303
304 Dragger* _parentDragger;
305
306 osg::ref_ptr<DraggerCallback> _selfUpdater;
307 Constraints _constraints;
308 DraggerCallbacks _draggerCallbacks;
309 osg::Node::NodeMask _intersectionMask;
310
311};
312
313
314/**
315 * CompositeDragger allows to create complex draggers that are composed of a
316 * hierarchy of Draggers.
317 */
318class OSGMANIPULATOR_EXPORT CompositeDragger : public Dragger
319{
320 public:
321
322 META_Node(osgManipulator,CompositeDragger);
323
324 typedef std::vector< osg::ref_ptr<Dragger> > DraggerList;
325
326 virtual const CompositeDragger* getComposite() const { return this; }
327 virtual CompositeDragger* getComposite() { return this; }
328
329 virtual void setParentDragger(Dragger* parent);
330
331 virtual bool handle(const PointerInfo& pi, const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
332
333 // Composite-specific methods below
334 virtual bool addDragger(Dragger* dragger);
335 template<class T> bool addDragger(const osg::ref_ptr<T>& dc) { return addDragger(dc.get()); }
336
337 virtual bool removeDragger(Dragger* dragger);
338 template<class T> bool removeDragger(const osg::ref_ptr<T>& dc) { return removeDragger(dc.get()); }
339
340 unsigned int getNumDraggers() const { return _draggerList.size(); }
341
342 Dragger* getDragger(unsigned int i) { return _draggerList[i].get(); }
343 const Dragger* getDragger(unsigned int i) const { return _draggerList[i].get(); }
344
345 bool containsDragger(const Dragger* dragger) const;
346 template<class T> bool containsDragger(const osg::ref_ptr<T>& dc) const { return containsDragger(dc.get()); }
347
348 DraggerList::iterator findDragger(const Dragger* dragger);
349
350 virtual void setIntersectionMask(osg::Node::NodeMask intersectionMask);
351
352 protected:
353
354 CompositeDragger() {}
355 CompositeDragger(const CompositeDragger& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
356
357 virtual ~CompositeDragger() {}
358
359 DraggerList _draggerList;
360};
361
362/**
363 * Culls the drawable all the time. Used by draggers to have invisible geometry
364 * around lines and points so that they can be picked. For example, a dragger
365 * could have a line with an invisible cylinder around it to enable picking on
366 * that line.
367 */
368void OSGMANIPULATOR_EXPORT setDrawableToAlwaysCull(osg::Drawable& drawable);
369
370/**
371 * Convenience function for setting the material color on a node.
372 */
373void OSGMANIPULATOR_EXPORT setMaterialColor(const osg::Vec4& color, osg::Node& node);
374
375}
376
377#endif