1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #define OSG_COMPILEMANIPULATORSLIB
48 #include "OSGConfig.h"
49 #include "OSGBaseFunctions.h"
50 #include "OSGSimpleMaterial.h"
51 #include "OSGTransform.h"
52 #include "OSGGeometry.h"
53 #include "OSGSimpleGeometry.h"
54 #include "OSGWindow.h"
55 #include "OSGNameAttachment.h"
56 #include "OSGCamera.h"
57 #include "OSGViewport.h"
59 #include "OSGManipulator.h"
60 #include "OSGSimpleGeometryExt.h"
64 /***************************************************************************\
66 \***************************************************************************/
68 /*! \class OSG::Manipulator
69 Baseclass for all Manipulators
72 /***************************************************************************\
74 \***************************************************************************/
76 /***************************************************************************\
78 \***************************************************************************/
80 //! initialize the static features of the class, e.g. action callbacks
82 void Manipulator::initMethod(InitPhase
)
86 /***************************************************************************\
88 \***************************************************************************/
90 /*-------------------------------------------------------------------------*\
92 \*-------------------------------------------------------------------------*/
94 /*----------------------- constructors & destructors ----------------------*/
96 Manipulator::Manipulator(void) :
99 _externalUpdateHandler(NULL
)
103 Manipulator::Manipulator(const Manipulator
&source
) :
105 _activeParent (NULL
),
106 _externalUpdateHandler(NULL
)
108 //TODO: empty copy constructor?!?!?!?
111 Manipulator::~Manipulator(void)
115 /*----------------------------- class specific ----------------------------*/
117 void Manipulator::setExternalUpdateHandler(ExternalUpdateHandler
* h
)
119 _externalUpdateHandler
= h
;
122 void Manipulator::callExternalUpdateHandler()
124 if ( NULL
!= _externalUpdateHandler
)
126 _externalUpdateHandler
->update(this->getTarget());
130 //! react to field changes
132 void Manipulator::changed(ConstFieldMaskArg whichField
,
136 Inherited::changed(whichField
, origin
, details
);
138 if ( (whichField
& TargetFieldMask
) == TargetFieldMask
)
140 updateHandleTransform();
142 if ( (whichField
& ParentsFieldMask
) == ParentsFieldMask
)
146 if ( !getParents().empty() )
148 //std::cout << "parent size= " << parents.getSize() << std::endl;
149 parent
= dynamic_cast<Node
*>(getParents()[0]); // Dangerous! multiple parents?
156 //std::cout << " Parent= " << parent << std::endl;
157 //std::cout << " activeParent= " << _activeParent << std::endl;
159 if ( parent
!= _activeParent
)
161 if ( NULL
!= parent
)
163 // remove old childs from a loaded osb file.
164 while(parent
->getNChildren() > 0)
166 parent
->subChild(parent
->getChild(0));
168 addHandleGeo(parent
);
171 if ( _activeParent
!= NULL
)
173 subHandleGeo(_activeParent
);
176 _activeParent
= parent
;
179 if ( (whichField
& EnablePivotFieldMask
) == EnablePivotFieldMask
)
181 if (getPivotNode() != 0) // Some manips don't support a pivot and don't create a node for it
183 if (!getEnablePivot())
185 getPivotNode()->setTravMask(0x0);
189 getPivotNode()->setTravMask(0xffffffff);
196 void Manipulator::addHandleGeo(Node
*n
)
198 n
->addChild(getTransXNode());
199 n
->addChild(getTransYNode());
200 n
->addChild(getTransZNode());
201 n
->addChild(getAxisLinesN());
202 n
->addChild(getPivotNode());
205 void Manipulator::subHandleGeo(Node
*n
)
207 n
->subChild(getTransXNode());
208 n
->subChild(getTransYNode());
209 n
->subChild(getTransZNode());
210 n
->subChild(getAxisLinesN());
211 n
->subChild(getPivotNode());
214 void Manipulator::updateHandleTransform()
216 if ( getTarget() != NULL
)
218 Transform
*t
= dynamic_cast<Transform
*>(getTarget()->getCore());
224 Quaternion scaleOrientation
;
227 m
.getTransform(translation
, rotation
, scaleFactor
, scaleOrientation
);
229 if( false == o
.invertFrom(m
) )
231 SWARNING
<< "Matrix is SINGULAR!!!\n";
235 Matrix n
,ma
,mb
,mc
,md
;
237 mb
.setTranslate(translation
);
238 ma
.setTranslate(Vec3f(getPivot()[0] * scaleFactor
[0],
239 getPivot()[1] * scaleFactor
[1],
240 getPivot()[2] * scaleFactor
[2])
242 mc
.setRotate(rotation
);
254 //! output the instance for debug purposes
256 void Manipulator::dump( UInt32
,
257 const BitVector
) const
259 SLOG
<< "Dump Manipulator NI" << std::endl
;
262 void Manipulator::onCreate()
266 void Manipulator::onCreate(const Manipulator
* source
)
268 Inherited::onCreate(source
);
270 SimpleMaterialUnrecPtr pMat
;
272 // SimpleMaterial *simpleMat;
275 setExternalUpdateHandler(NULL
);
277 // add a name attachment
278 NameUnrecPtr nameN
= Name::create();
279 nameN
->editFieldPtr()->setValue("XManipulator");
280 addAttachment(nameN
);
282 // make the axis lines
283 NodeUnrecPtr pNode
= makeCoordAxis(getLength()[0], 2.0, false);
284 setAxisLinesN(pNode
);
286 // make the red x-axis transform and handle
288 pNode
= Node::create();
289 setTransXNode(pNode
);
290 OSG::ComponentTransformUnrecPtr transHandleXC
= ComponentTransform::create();
292 pNode
= makeHandleGeo();
293 setHandleXNode(pNode
);
294 pMat
= SimpleMaterial::create();
295 setMaterialX (pMat
);
297 getTransXNode()->setCore (transHandleXC
);
298 getTransXNode()->addChild(getHandleXNode());
300 transHandleXC
->setTranslation(Vec3f(getLength()[0], 0, 0) );
301 transHandleXC
->setRotation (Quaternion(Vec3f(0, 0, 1), osgDegree2Rad(-90)));
303 pMat
->setDiffuse(Color3f(1, 0, 0));
304 pMat
->setLit (true );
306 geo
= dynamic_cast<Geometry
*>(getHandleXNode()->getCore());
307 geo
->setMaterial(pMat
);
310 // make the green y-axis transform and handle
312 pNode
= Node::create();
313 setTransYNode(pNode
);
314 OSG::ComponentTransformUnrecPtr transHandleYC
= ComponentTransform::create();
315 pNode
= makeHandleGeo();
316 setHandleYNode(pNode
);
317 pMat
= SimpleMaterial::create();
320 getTransYNode()->setCore (transHandleYC
);
321 getTransYNode()->addChild(getHandleYNode());
323 transHandleYC
->setTranslation(Vec3f(0, getLength()[1], 0) );
324 // transHandleYC->setRotation ( Quaternion(Vec3f(0, 0, 1), osgDegree2Rad(-90)));
326 pMat
->setDiffuse(Color3f(0, 1, 0));
327 pMat
->setLit (true );
329 geo
= dynamic_cast<Geometry
*>(getHandleYNode()->getCore());
330 geo
->setMaterial(pMat
);
333 // make the blue z-axis transform and handle
335 pNode
= Node::create();
336 setTransZNode(pNode
);
337 OSG::ComponentTransformUnrecPtr transHandleZC
= ComponentTransform::create();
338 pNode
= makeHandleGeo();
339 setHandleZNode(pNode
);
340 pMat
= SimpleMaterial::create();
343 getTransZNode()->setCore (transHandleZC
);
344 getTransZNode()->addChild(getHandleZNode());
346 transHandleZC
->setTranslation(Vec3f(0, 0, getLength()[2]) );
347 transHandleZC
->setRotation (Quaternion(Vec3f(1, 0, 0), osgDegree2Rad(90)));
349 pMat
->setDiffuse(Color3f(0, 0, 1));
350 pMat
->setLit (true );
352 geo
= dynamic_cast<Geometry
*>(getHandleZNode()->getCore());
353 geo
->setMaterial(pMat
);
356 // make the yellow pivot transform and handle
358 pNode
= Node::create();
360 OSG::ComponentTransformUnrecPtr transHandlePivotC
= ComponentTransform::create();
361 pNode
= makeSphere(2, 0.05f
);
362 setHandlePNode(pNode
);
363 pMat
= SimpleMaterial::create();
364 setMaterialPivot (pMat
);
366 getPivotNode()->setCore (transHandlePivotC
);
367 getPivotNode()->addChild(getHandlePNode());
369 transHandlePivotC
->setTranslation(Vec3f(0, 0, 0));
371 pMat
->setDiffuse(Color3f(1, 1, 0));
372 pMat
->setLit (true );
374 geo
= dynamic_cast<Geometry
*>(getHandlePNode()->getCore());
375 geo
->setMaterial(pMat
);
377 if (!getEnablePivot())
379 getPivotNode()->setTravMask(0x0);
385 void Manipulator::onDestroy()
389 void Manipulator::resolveLinks(void)
391 Inherited::resolveLinks();
393 _activeParent
= NULL
;
396 Pnt2f
Manipulator::calcScreenProjection(const Pnt3f
& p
,
397 Viewport
* const port
)
400 Matrix proj
, projtrans
, view
;
405 cam
= port
->getCamera();
407 cam
->getProjection(proj
,
408 port
->calcPixelWidth(),
409 port
->calcPixelHeight());
410 cam
->getProjectionTranslation(projtrans
,
411 port
->calcPixelWidth(),
412 port
->calcPixelHeight());
413 cam
->getViewing(view
,
414 port
->calcPixelWidth(),
415 port
->calcPixelHeight());
417 Matrix wctocc
= proj
;
418 wctocc
.mult(projtrans
);
421 wctocc
.multFull(p
, pnt
);
423 Real32 rx
= (pnt
[0] + 1.0) /2 * port
->calcPixelWidth();
424 Real32 ry
= (pnt
[1] + 1.0) /2 * port
->calcPixelHeight();
426 return Pnt2f(rx
, ry
);
430 SWARNING
<< "calcScreenProjection(const Pnt3f&, "
431 "Viewport * const port="
433 return Pnt2f(0.0f
, 0.0f
);
437 /*! The mouseMove is called by the viewer when the mouse is moved in the
438 viewer and this handle is the active one.
440 \param x the x-pos of the mouse (pixel)
441 \param y the y-pos of the mouse (pixel)
443 void Manipulator::mouseMove(const Int16 x
,
446 //SLOG << "Manipulator::mouseMove() enter\n" << std::flush;
448 // get the beacon's core (must be ComponentTransform) and it's center
449 if( getTarget() != NULL
)
451 // get transformation of beacon
452 Transform
*t
= dynamic_cast<Transform
*>(getTarget()->getCore());
456 UInt16
coord(0); // active coordinate: X=0, Y=1, Z=2
458 Int16 xDiff
; // the mousepos x delta
459 Int16 yDiff
; // the mousepos y delta
461 Vec3f centerV
; // center of beacon
462 Vec3f handleCenterV
; // center of subhandle
463 Vec2f mouseScreenV
; // mouse move vector
464 Vec2f handleScreenV
; // handle vec in (cc)
465 Real32 handleScreenVLen
; // len of handle vec in (cc)
467 Vec3f translation
; // for matrix decomposition
470 Quaternion scaleOrientation
;
472 // TODO: das ist ja schon ein wenig haesslich
473 static const Vec3f coordVector
[3] = {
474 Vec3f(1.0f
, 0.0f
, 0.0f
),
475 Vec3f(0.0f
, 1.0f
, 0.0f
),
476 Vec3f(0.0f
, 0.0f
, 1.0f
)
479 // check for the active handle
480 if( getActiveSubHandle() == getHandleXNode())
484 else if(getActiveSubHandle() == getHandleYNode())
488 else if(getActiveSubHandle() == getHandleZNode())
493 // TODO: only for debugging, -> FDEBUG
494 //SLOG << "moving " << ( coord == 0 ? "x\n" :
495 // coord == 1 ? "y\n" :
499 // calculate diffs between current and last mouse position
500 xDiff
= x
- Int16(getLastMousePos()[0]);
501 yDiff
= y
- Int16(getLastMousePos()[1]);
503 // set the vector resulting from user mouse movement and calc its length
504 mouseScreenV
.setValues(xDiff
, -yDiff
);
506 t
->getMatrix().getTransform(translation
, rotation
, scaleFactor
,
510 // calculate the camera coordinate of the center
511 centerV
= translation
;
512 Pnt2f centerPixPos
= calcScreenProjection(centerV
.addToZero(),
516 // calculate the camera coordinate of the handle center
517 handleCenterV
= centerV
+ coordVector
[coord
]*getLength()[coord
];
518 Pnt2f handleCenterPixPos
= calcScreenProjection(handleCenterV
.addToZero(),
521 handleScreenV
= handleCenterPixPos
- centerPixPos
;
522 handleScreenVLen
= handleScreenV
.length();
524 Real32 s
= handleScreenV
.dot(mouseScreenV
) / handleScreenVLen
;
526 doMovement(t
, coord
, s
* getLength()[coord
] * 0.01, translation
,
527 rotation
, scaleFactor
, scaleOrientation
);
531 SWARNING
<< "handled object has no parent transform!\n";
533 callExternalUpdateHandler();
537 SWARNING
<< "Handle has no target.\n";
540 setLastMousePos(Pnt2f(Real32(x
), Real32(y
)));
541 updateHandleTransform();
543 //SLOG << "Manipulator::mouseMove() leave\n" << std::flush;
546 /*! The mouseButtonPress is called by the viewer when the mouse is
547 pressed in the viewer above a subhandle of this handle.
549 \param button the button pressed
550 \param x the x-pos of the mouse (pixel)
551 \param y the y-pos of the mouse (pixel)
554 void Manipulator::mouseButtonPress(const UInt16 button
,
558 setLastMousePos(Pnt2f(Real32(x
), Real32(y
)));
562 void Manipulator::mouseButtonRelease(const UInt16 button
,
569 void Manipulator::doMovement( Transform
*t
,
572 const Vec3f
&translation
,
573 const Quaternion
&rotation
,
574 const Vec3f
&scaleFactor
,
575 const Quaternion
&scaleOrientation
)
577 SWARNING
<< "MoveManipulator::doMovement: called. Shouldn't happen!" << endLog
;
580 const Vec3f
& Manipulator::getActiveAxis(void) const
582 static const Vec3f coordVector
[] = {
583 Vec3f(1.0f
, 0.0f
, 0.0f
),
584 Vec3f(0.0f
, 1.0f
, 0.0f
),
585 Vec3f(0.0f
, 0.0f
, 1.0f
),
586 Vec3f(-1.0f
, -1.0f
, -1.0f
)
590 // check for the active handle
591 if( getActiveSubHandle() == getHandleXNode())
595 else if(getActiveSubHandle() == getHandleYNode())
599 else if(getActiveSubHandle() == getHandleZNode())
608 return coordVector
[coord
];