Let me fix broken formatting in former post:

osg::Matrixd ModelPositionCallback::calculatePositionMatrix(
  const osg::EllipsoidModel* ellipsoid,
  // in global coords (origin in ellipsod center)
  const osg::Vec3d &newPosition,
  // in global coords (origin in ellipsod center)
  const osg::Vec3d &oldPosition)

{
   // Math below may fail in Polar areas
   // ( I hope you don't care about them now)

   // First compute movement in coord system
   // tangent to ellipsoid in newPosition
   // Axes of this local coordinate system match world directions:

   //+X points towards east direction
   //+Y points towards north direction
   //+Z points toward  up direction
   osg::Matrixd localToWorld, worldToLocal;

  ellipsoid->computeLocalToWorldTransformFromXYZ
         ( newPosition[0],newPosition[1],newPosition[2],
           localToWorld );

   worldToLocal = Matrix::inverse( localToWorld );

   osg::Vec3d newPosInNewPosLocalCoordSystem =
      osg::Vec3d( 0,0,0 ); // == newPosition * worldToLocal;

   osg::Vec3d oldPosInNewPosLocalCoordSystem =
      oldPosition * worldToLocal;

   osg::Vec3d moveInNewPosLocalCoordSystem =
                         newPosInNewPosLocalCoordSystem -
                         oldPosInNewPosLocalCoordSystem;

   // now the question is how your model is oriented ?
   // does model nose point towards X+ or Y+ or (i hope its not Z+)?
   // I will further assume towards Y+
#if 0
   // compass geographical heading measured clockwise
   // from north is this (radians):
   double heading = atan2( moveInNewPosLocalCoordSystem[0],
                                          moveInNewPosLocalCoordSystem[1] );
#else
   // but we rather need heading angle measured
   // anticlockwise from X+ and it would be (note swapped coords)
   double heading = atan2( moveInNewPosLocalCoordSystem[1],
                                          moveInNewPosLocalCoordSystem[0] );
#endif

   // usually pitch in local tangent space can be computed
   // like this (radians):
   double pitch = atan2( moveInNewPosLocalCoordSystem[2],
                               hypot( moveInNewPosLocalCoordSystem[0],
moveInNewPosLocalCoordSystem[1] ));

#if 1
   // I recommend to start initially with 0 pitch
   // to be on safer side at the beginig - undef it later
   pitch = 0.0;
#endif

   // roll cannot be computed using odlPos and newPos only
   // so I assume 0 degrees
   double roll = 0.0;

   // Now it all depends on your model coordinate frame:
   // I am assuming your model nose points toward Y+ and
   // its roof points toward Z+
   // Above means we need first to rotate its nose around Z+
   // by -90 degrees from Y+ to match X+ orientation

   osg::Matrix turnRight90DegreesClockwise =
       osg::Matrix::rotate( osg::DegreesToRadians( -90.0 ),
                            osg::Vec3d( 0,0,1 ) );

   osg::Matrix rotateToMatchLocalHeading =
                osg::Matrix::rotate( heading,
                                     osg::Vec3d( 0,0,1 ) );

   osg::Matrix rotateToMatchLocalPitch =
                osg::Matrix::rotate( pitch,
                                     osg::Vec3d( 1,0,0 ) );

   osg::Matrix rotateToMatchLocalRoll =
                osg::Matrix::rotate( roll,
                                     osg::Vec3d( 0,1,0 ) );

   // So the matrix would be like this:
   osg::Matrixd matrix = turnRight90DegreesClockwise *
                                    rotateToMatchLocalRoll *
                                    rotateToMatchLocalPitch *
                                    rotateToMatchLocalHeading *
                                    localToWorld;

   return matrix;
}


WL

----- Original Message ----- From: "Wojciech Lewandowski" <[email protected]>
To: <[email protected]>
Sent: Thursday, October 29, 2009 6:41 PM
Subject: Re: [osg-users] Rotating models with respect
toCoordinateSystemNode/ EllipsoidModel


Hi Michael,

I met at least few people who were using models in different coordinate
frames so your results may vary. But assuming that your model is pretty
standard: where forward points toward Y+, right points toward X+ and top
points toward Z+, this piece of code could work for you.


osg::Matrixd ModelPositionCallback::calculatePositionMatrix(
  const osg::EllipsoidModel* ellipsoid,
  const osg::Vec3d &newPosition, // in global coords (origin in ellipsod
center)
  const osg::Vec3d &oldPosition) // in global coords (origin in ellipsod
center)
{
   // Math below may fail in Polar areas ( I hope you don't care bout them
now)

   // First compute movement in coord system tangent to ellipsoid in
oldPosition
   // Axes of this local coordinate system match world directions:
   //+X points towards east direction
   //+Y points towards north direction
   //+Z points toward  up direction
   osg::Matrixd localToWorld, worldToLocal;

  ellipsoid->computeLocalToWorldTransformFromXYZ(
newPosition[0],newPosition[1],newPosition[2], localToWorld );
   worldToLocal = Matrix::inverse( localToWorld );

   osg::Vec3d newPosInNewPosLocalCoordSystem = osg::Vec3d( 0,0,0 ); // ==
newPosition * worldToLocal;
   osg::Vec3d oldPosInNewPosLocalCoordSystem = oldPosition * worldToLocal;

   osg::Vec3d moveInNewPosLocalCoordSystem =
newPosInNewPosLocalCoordSystem - oldPosInNewPosLocalCoordSystem;

   // now the question is how your model is oriented does model nose point
toward X+ or Y+ or (i hope its not Z+)?
#if 0
   // compass geographical heading measured clockwise from north is
(radians):
   double heading = atan2( moveInNewPosLocalCoordSystem[0],
moveInNewPosLocalCoordSystem[1] );
#else
   // but we rather need heading angle measured anticlockwise from X+ and
it would be (note swapped coords )
   double heading = atan2( moveInNewPosLocalCoordSystem[1],
moveInNewPosLocalCoordSystem[0] );
#endif

   // usually pitch in local tangent space can be computed like this
(radians):
   double pitch = atan2( moveInNewPosLocalCoordSystem[2],
                          hypot( moveInNewPosLocalCoordSystem[0],
moveInNewPosLocalCoordSystem[1] ) );

#if 1 // I recommend to start initially with 0 pitch to be on safer side
at the beginig - undef it later
   pitch = 0.0;
#endif

   // roll cannot be computed using odlPos and newPos only so I assume 0
degrees
   double roll = 0.0;

   // Now it all depends on your model coordinate frame:
   // I am assuming your model nose points toward Y+ and its roof points
toward Z+
   // Above means we need first to rotate its nose around Z+ by -90
degrees from Y+ to match X+ orientation

   osg::Matrix turnRight90DegreesClockwise =
       osg::Matrix::rotate( osg::DegreesToRadians( -90.0 ), osg::Vec3d(
0,0,1 ) );

   osg::Matrix rotateToMatchLocalHeading =
                osg::Matrix::rotate( heading, osg::Vec3d( 0,0,1 ) );//
around Z+

   osg::Matrix rotateToMatchLocalPitch =
                osg::Matrix::rotate( pitch, osg::Vec3d( 1,0,0 ) ); //
around X+

   osg::Matrix rotateToMatchLocalRoll =
                osg::Matrix::rotate( roll, osg::Vec3d( 0,1,0 ) );// around
Y+

   // So the matrix without pitch and roll would be like this:
   osg::Matrixd matrix = turnRight90DegreesClockwise *
                                    rotateToMatchLocalRoll *
                                    rotateToMatchLocalPitch *
                                    rotateToMatchLocalHeading *
                                    localToWorld;

   return matrix;
}

HTH,  It comes from my head, I have not tested this. There is a chance I
forgot something really important ;-)  But it should be clear eanough to
understand the steps.
Wojtek Lewandowski

----- Original Message ----- From: "Michael Weber" <[email protected]>
To: <[email protected]>
Sent: Thursday, October 29, 2009 2:45 PM
Subject: Re: [osg-users] Rotating models with respect
toCoordinateSystemNode / EllipsoidModel


Well, my programm is pretty much like the osgsimulation example. But
instead of a aircraft which flies a constant route I use a model which
flies an arbitrary trajectory.

For the positioning of the model I just use makeTranslate with the new
X,Y,Z coordinates, which works as expected.

Now I try to rotate my model that way that it heads towards the direction
it is "flying". For the rotation I use makeRotate with the new position
and the previous position (taken from here
(http://forum.openscenegraph.org/viewtopic.php?p=16587#16587)).

But somehow it works not as expected. The model always looks somewhere
else. So I suppose either I use the makeRotate in a wrong way or the
rotation somehow depends on the position within the EllipsoidModel (maybe
some conversion from world to local coordinates or vice versa?)

Any ideas?

Michael

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=18856#18856





_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to