OSGManipulator.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038
00039 //---------------------------------------------------------------------------
00040 //  Includes
00041 //---------------------------------------------------------------------------
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045
00046 #define OSG_COMPILEMANIPULATORSLIB
00047 
00048 #include "OSGConfig.h"
00049 #include "OSGBaseFunctions.h"
00050 #include "OSGSimpleMaterial.h"
00051 #include "OSGTransform.h"
00052 #include "OSGGeometry.h"
00053 #include "OSGSimpleGeometry.h"
00054 #include "OSGWindow.h"
00055 #include "OSGNameAttachment.h"
00056 #include "OSGCamera.h"
00057
00058 #include "OSGManipulator.h"
00059 #include "OSGSimpleGeometryExt.h"
00060
00061 OSG_USING_NAMESPACE
00062
00063 /***************************************************************************\
00064  *                            Description                                  *
00065 \***************************************************************************/
00066
00071 /***************************************************************************\
00072  *                           Class variables                               *
00073 \***************************************************************************/
00074
00075 /***************************************************************************\
00076  *                           Class methods                                 *
00077 \***************************************************************************/
00078
00080
00081 void Manipulator::initMethod(InitPhase)
00082 {
00083 }
00084
00085 /***************************************************************************\
00086  *                           Instance methods                              *
00087 \***************************************************************************/
00088
00089 /*-------------------------------------------------------------------------*\
00090  -  private                                                                 -
00091 \*-------------------------------------------------------------------------*/
00092
00093 /*----------------------- constructors & destructors ----------------------*/
00094
00095 Manipulator::Manipulator(void) :
00096     Inherited(),
00097     _activeParent( NULL ),
00098     _externalUpdateHandler( NULL )
00099 {
00100 }
00101
00102 Manipulator::Manipulator(const Manipulator &source) :
00103     Inherited(source)
00104 {
00105     //TODO: empty copy constructor?!?!?!?
00106 }
00107
00108 Manipulator::~Manipulator(void)
00109 {
00110 }
00111
00112 /*----------------------------- class specific ----------------------------*/
00113
00114 void Manipulator::setExternalUpdateHandler(ExternalUpdateHandler* h)
00115 {
00116     _externalUpdateHandler = h;
00117 }
00118
00119 void Manipulator::callExternalUpdateHandler()
00120 {
00121     if ( NULL != _externalUpdateHandler )
00122     {
00123         _externalUpdateHandler->update(this->getTarget());
00124     }
00125 }
00126
00128
00129 void Manipulator::changed(ConstFieldMaskArg whichField,
00130                           UInt32            origin,
00131                           BitVector         details    )
00132 {
00133     Inherited::changed(whichField, origin, details);
00134
00135     if ( (whichField & TargetFieldMask) == TargetFieldMask )
00136     {
00137         reverseTransform();
00138     }
00139     else if ( (whichField & ParentsFieldMask) == ParentsFieldMask )
00140     {
00141         Node *parent;
00142
00143         if ( !getParents().empty() )
00144         {
00145             //std::cout << "parent size= " << parents.getSize() << std::endl;
00146             parent = dynamic_cast<Node *>(getParents()[0]); // Dangerous! multiple parents?
00147         }
00148         else
00149         {
00150             parent = NULL;
00151         }
00152
00153         //std::cout << "  Parent=       " << parent << std::endl;
00154         //std::cout << "  activeParent= " << _activeParent << std::endl;
00155
00156         if ( parent != _activeParent )
00157         {
00158             if ( NULL != parent )
00159             {
00160                 // remove old childs from a loaded osb file.
00161                 while(parent->getNChildren() > 0)
00162                 {
00163                     parent->subChild(parent->getChild(0));
00164                 }
00165                 addHandleGeo(parent);
00166             }
00167
00168             if ( _activeParent != NULL )
00169             {
00170                 subHandleGeo(_activeParent);
00171             }
00172
00173             _activeParent = parent;
00174         }
00175     }
00176 }
00177
00178 void Manipulator::addHandleGeo(Node *n)
00179 {
00180     n->addChild(getTransXNode());
00181     n->addChild(getTransYNode());
00182     n->addChild(getTransZNode());
00183     n->addChild(getAxisLinesN());
00184 }
00185
00186 void Manipulator::subHandleGeo(Node *n)
00187 {
00188     n->subChild(getTransXNode());
00189     n->subChild(getTransYNode());
00190     n->subChild(getTransZNode());
00191     n->subChild(getAxisLinesN());
00192 }
00193
00194 void Manipulator::reverseTransform()
00195 {
00196     if ( getTarget() != NULL )
00197     {
00198         Transform *t = dynamic_cast<Transform *>(getTarget()->getCore());
00199         Matrix     m,n,o;
00200
00201         Vec3f      translation;
00202         Quaternion rotation;
00203         Vec3f      scaleFactor;
00204         Quaternion scaleOrientation;
00205
00206         m = t->getMatrix();
00207         m.getTransform(translation, rotation, scaleFactor, scaleOrientation);
00208
00209         if( false == o.invertFrom(m) )
00210         {
00211             SWARNING << "Matrix is SINGULAR!!!\n";
00212         }
00213         else
00214         {
00215             n.setIdentity (           );
00216             n.setTransform(translation);
00217             n.setRotate   (rotation   );
00218             n.multLeft    (o          );
00219
00220             setMatrix(n);
00221         }
00222     }
00223 }
00224
00226
00227 void Manipulator::dump(      UInt32    ,
00228                        const BitVector ) const
00229 {
00230     SLOG << "Dump Manipulator NI" << std::endl;
00231 }
00232
00233 void Manipulator::onCreate()
00234 {
00235 }
00236
00237 void Manipulator::onCreate(const Manipulator* source)
00238 {
00239     Inherited::onCreate(source);
00240
00241     SimpleMaterialUnrecPtr pMat = SimpleMaterial::create();
00242
00243     setMaterialX(pMat);
00244
00245     pMat = SimpleMaterial::create();
00246
00247     setMaterialY(pMat);
00248
00249     pMat = SimpleMaterial::create();
00250
00251     setMaterialZ(pMat);
00252
00253     SimpleMaterial *simpleMat;
00254     Geometry       *geo;
00255
00256     setExternalUpdateHandler(NULL);
00257
00258     // add a name attachment
00259     NameUnrecPtr nameN = Name::create();
00260     nameN->editFieldPtr()->setValue("XManipulator");
00261     addAttachment(nameN);
00262
00263     // make the axis lines
00264     NodeUnrecPtr pNode = makeCoordAxis(getLength()[0], 2.0, false);
00265     setAxisLinesN(pNode);
00266
00267     // make the red x-axis transform and handle
00268
00269     pNode = Node::create();
00270     setTransXNode(pNode);
00271     _transHandleXC = ComponentTransform::create();
00272
00273     pNode = makeHandleGeo();
00274     setHandleXNode(pNode);
00275     pMat = SimpleMaterial::create();
00276     setMaterialX  (pMat );
00277
00278     getTransXNode()->setCore (_transHandleXC  );
00279     getTransXNode()->addChild(getHandleXNode());
00280
00281     _transHandleXC->setTranslation(Vec3f(getLength()[0], 0, 0)                   );
00282     _transHandleXC->setRotation   (Quaternion(Vec3f(0, 0, 1), osgDegree2Rad(-90)));
00283
00284     simpleMat = dynamic_cast<SimpleMaterial *>(getMaterialX());
00285
00286     simpleMat->setDiffuse(Color3f(1, 0, 0));
00287     simpleMat->setLit    (true            );
00288
00289     geo = dynamic_cast<Geometry *>(getHandleXNode()->getCore());
00290     geo->setMaterial(simpleMat);
00291
00292     //
00293     // make the green y-axis transform and handle
00294
00295     pNode = Node::create();
00296     setTransYNode(pNode);
00297     _transHandleYC = ComponentTransform::create();
00298     pNode = makeHandleGeo();
00299     setHandleYNode(pNode);
00300     pMat = SimpleMaterial::create();
00301     setMaterialY(pMat);
00302
00303     getTransYNode()->setCore (_transHandleYC  );
00304     getTransYNode()->addChild(getHandleYNode());
00305
00306     _transHandleYC->setTranslation(Vec3f(0, getLength()[1], 0)                    );
00307 //    _transHandleYC->setRotation   ( Quaternion(Vec3f(0, 0, 1), osgDegree2Rad(-90)));
00308
00309     simpleMat = dynamic_cast<SimpleMaterial *>(getMaterialY());
00310     simpleMat->setDiffuse(Color3f(0, 1, 0));
00311     simpleMat->setLit    (true            );
00312
00313     geo = dynamic_cast<Geometry *>(getHandleYNode()->getCore());
00314     geo->setMaterial(simpleMat);
00315
00316     //
00317     // make the blue z-axis transform and handle
00318
00319     pNode = Node::create();
00320     setTransZNode(pNode);
00321     _transHandleZC = ComponentTransform::create();
00322     pNode = makeHandleGeo();
00323     setHandleZNode(pNode);
00324     pMat = SimpleMaterial::create();
00325     setMaterialZ  (pMat);
00326
00327     getTransZNode()->setCore (_transHandleZC);
00328     getTransZNode()->addChild(getHandleZNode());
00329
00330     _transHandleZC->setTranslation(Vec3f(0, 0, getLength()[2])                  );
00331     _transHandleZC->setRotation   (Quaternion(Vec3f(1, 0, 0), osgDegree2Rad(90)));
00332
00333     simpleMat = dynamic_cast<SimpleMaterial *>(getMaterialZ());
00334     simpleMat->setDiffuse(Color3f(0, 0, 1));
00335     simpleMat->setLit    (true            );
00336
00337     geo = dynamic_cast<Geometry *>(getHandleZNode()->getCore());
00338     geo->setMaterial(simpleMat);
00339
00340     commitChanges();
00341 }
00342
00343 void Manipulator::onDestroy()
00344 {
00345 }
00346
00347 void Manipulator::resolveLinks(void)
00348 {
00349     Inherited::resolveLinks();
00350
00351     _activeParent  = NULL;
00352
00353     _transHandleXC = NULL;
00354     _transHandleYC = NULL;
00355     _transHandleZC = NULL;
00356 }
00357
00358 Pnt2f Manipulator::calcScreenProjection(const Pnt3f    &       p,
00359                                               Viewport * const port)
00360 {
00361     Camera  *cam;
00362     Matrix   proj, projtrans, view;
00363     Pnt3f    pnt;
00364
00365     if( port != NULL )
00366     {
00367         cam = port->getCamera();
00368
00369         cam->getProjection(proj, port->getPixelWidth(),
00370                            port->getPixelHeight());
00371         cam->getProjectionTranslation(projtrans, port->getPixelWidth(),
00372                                       port->getPixelHeight());
00373         cam->getViewing(view, port->getPixelWidth(), port->getPixelHeight());
00374
00375         Matrix wctocc = proj;
00376         wctocc.mult(projtrans);
00377         wctocc.mult(view);
00378
00379         wctocc.multFull(p, pnt);
00380
00381         Real32 rx = (pnt[0] + 1.0) /2 * port->getPixelWidth();
00382         Real32 ry = (pnt[1] + 1.0) /2 * port->getPixelHeight();
00383
00384         return Pnt2f(rx, ry);
00385     }
00386     else
00387     {
00388         SWARNING << "calcScreenProjection(const Pnt3f&, "
00389                     "Viewport * const port="
00390                  << port << ")\n";
00391         return Pnt2f(0.0f, 0.0f);
00392     }
00393 }
00394
00401 void Manipulator::mouseMove(const Int16 x,
00402                             const Int16 y)
00403 {
00404     //SLOG << "Manipulator::mouseMove() enter\n" << std::flush;
00405
00406     // get the beacon's core (must be ComponentTransform) and it's center
00407     if( getTarget() != NULL )
00408     {
00409         // get transformation of beacon
00410         Transform *t = dynamic_cast<Transform *>(getTarget()->getCore());
00411
00412         if( t != NULL )
00413         {
00414             UInt16     coord(0);          // active coordinate: X=0, Y=1, Z=2
00415
00416             Int16      xDiff;             // the mousepos x delta
00417             Int16      yDiff;             // the mousepos y delta
00418
00419             Vec3f      centerV;           // center of beacon
00420             Vec3f      handleCenterV;     // center of subhandle
00421             Vec2f      mouseScreenV;      // mouse move vector
00422             Vec2f      handleScreenV;     // handle vec in (cc)
00423             Real32     handleScreenVLen;  // len of handle vec in (cc)
00424
00425             Vec3f      translation;       // for matrix decomposition
00426             Quaternion rotation;
00427             Vec3f      scaleFactor;
00428             Quaternion scaleOrientation;
00429
00430             // TODO: das ist ja schon ein wenig haesslich
00431             static const Vec3f coordVector[3] = {
00432                 Vec3f(1.0f, 0.0f, 0.0f),
00433                 Vec3f(0.0f, 1.0f, 0.0f),
00434                 Vec3f(0.0f, 0.0f, 1.0f)
00435             };
00436
00437             //  check for the active handle
00438             if(     getActiveSubHandle() == getHandleXNode())
00439             {
00440                 coord = 0;
00441             }
00442             else if(getActiveSubHandle() == getHandleYNode())
00443             {
00444                 coord = 1;
00445             }
00446             else if(getActiveSubHandle() == getHandleZNode())
00447             {
00448                 coord = 2;
00449             }
00450
00451             // TODO: only for debugging, -> FDEBUG
00452             //SLOG << "moving " << ( coord == 0 ? "x\n" :
00453             //                       coord == 1 ? "y\n" :
00454             //                       "z\n" )
00455             //     << std::flush;
00456
00457             // calculate diffs between current and last mouse position
00458             xDiff = x - Int16(getLastMousePos()[0]);
00459             yDiff = y - Int16(getLastMousePos()[1]);
00460
00461             // set the vector resulting from user mouse movement and calc its length
00462             mouseScreenV.setValues(xDiff, -yDiff);
00463
00464             t->getMatrix().getTransform(translation, rotation, scaleFactor,
00465                                         scaleOrientation);
00466
00467
00468             // calculate the camera coordinate of the center
00469             centerV            = translation;
00470             Pnt2f centerPixPos = calcScreenProjection(centerV.addToZero(),
00471                                                       getViewport());
00472
00473
00474             // calculate the camera coordinate of the handle center
00475             handleCenterV            = centerV + coordVector[coord]*getLength()[coord];
00476             Pnt2f handleCenterPixPos = calcScreenProjection(handleCenterV.addToZero(),
00477                                                             getViewport());
00478
00479             handleScreenV    = handleCenterPixPos - centerPixPos;
00480             handleScreenVLen = handleScreenV.length();
00481
00482             Real32 s = handleScreenV.dot(mouseScreenV) / handleScreenVLen;
00483
00484             doMovement(t, coord, s * getLength()[coord] * 0.01, translation,
00485                        rotation, scaleFactor, scaleOrientation);
00486         }
00487         else
00488         {
00489             SWARNING << "handled object has no parent transform!\n";
00490         }
00491         callExternalUpdateHandler();
00492     }
00493     else
00494     {
00495         SWARNING << "Handle has no target.\n";
00496     }
00497
00498     setLastMousePos(Pnt2f(Real32(x), Real32(y)));
00499     reverseTransform();
00500
00501     //SLOG << "Manipulator::mouseMove() leave\n" << std::flush;
00502 }
00503
00512 void Manipulator::mouseButtonPress(const UInt16 button,
00513                                    const Int16  x,
00514                                    const Int16  y     )
00515 {
00516     setLastMousePos(Pnt2f(Real32(x), Real32(y)));
00517     setActive(true);
00518 }
00519
00520 void Manipulator::mouseButtonRelease(const UInt16 button,
00521                                      const Int16  x,
00522                                      const Int16  y     )
00523 {
00524     setActive(false);
00525 }