[osg-users] [vpb] geographic to geocentric coordinate transformation

Christian Schulte christian.schulte at onera.fr
Fri Jun 19 08:05:53 PDT 2015


Hello Elias,

underneath you will find your corrected and commented example (sorry, I 
had to change the lat,lon and models :-) ).

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgDB/ReadFile>
#include <osg/PositionAttitudeTransform>

int main( int argc, char** argv ) {

      osg::ref_ptr<osg::GraphicsContext::Traits> traits;
     if(!(traits = new osg::GraphicsContext::Traits()).valid()) {
         // print
         osg::notify(osg::WARN)
             << " - traits = new osg::GraphicsContext::Traits() -> 
invalid : abandon" << std::endl;
         // error
         return NULL;
     }

     // set traits properties
     traits->screenNum            = 0;
     traits->x                     = 40;
     traits->y                     = 40;
     traits->width                 = 1024;
     traits->height                 = 768;
     traits->doubleBuffer         = true;
     traits->windowDecoration     = true;
     traits->vsync                = true;

     osg::ref_ptr<osg::GraphicsContext> gc = 
osg::GraphicsContext::createGraphicsContext(traits);

     osg::ref_ptr<osg::Group> root = new osg::Group;
     osg::ref_ptr<osg::Node> cessna = osgDB::readNodeFile("EC225.ive");
     osg::ref_ptr<osg::Node> map = 
osgDB::readNodeFile("y:/Bdt/Marseille/marseillemipmaphard09dds.ive");
     osg::ref_ptr<osg::Camera> camera = new osg::Camera;
     osg::Vec3d center, eye, up;

     //Getting XYZ position for cessna
     osg::Matrix cessnaLocation;
     osg::EllipsoidModel ellipsoid;
     double x,y,z;
ellipsoid.convertLatLongHeightToXYZ(osg::DegreesToRadians(43.449310), 
osg::DegreesToRadians(5.197525), 200.0, x, y, z);
     osg::Vec3 positionForCessna = osg::Vec3d(x,y,z);

     //Placing cessna
     osg::ref_ptr<osg::PositionAttitudeTransform> moveCessna = new 
osg::PositionAttitudeTransform;
     moveCessna->setPosition(positionForCessna);
     // Calculating attitude (heading north)
     double phi = 0.0;
     double psi = 0.0;
     double theta = 0.0;
     osg::Matrixd localToWorld;
     osg::Matrixd attitude;
ellipsoid.computeLocalToWorldTransformFromXYZ(osg::DegreesToRadians(43.449310), 
osg::DegreesToRadians(5.197525), 200.0,    localToWorld);
     attitude.makeRotate(
             osg::DegreesToRadians(phi),     osg::Y_AXIS,
             osg::DegreesToRadians(theta),     osg::X_AXIS,
             osg::DegreesToRadians(-psi),     osg::Z_AXIS);
     attitude *= localToWorld;
     osg::Quat quat = attitude.getRotate();
     moveCessna->setAttitude(quat);

     moveCessna->addChild(cessna.get());

     osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

     // Create camera as shallow copy of theo ne of the view
     camera = 
dynamic_cast<osg::Camera*>(viewer->getCamera()->clone(osg::CopyOp::SHALLOW_COPY));
     camera->setGraphicsContext(gc);
camera->setProjectionMatrixAsPerspective(40.0,1.33,0.1,10000.0);
     camera->setViewport(new osg::Viewport(0, 0, gc->getTraits()->width, 
gc->getTraits()->height));
     camera->setClearColor(osg::Vec4f(0.5f,0.5f,0.0f,0.0f));
     camera->setCullingActive(false);

     //Getting XYZ position for camera
     //Lat Lon are the same, height is 500.0
     // The eye : position of the camera
ellipsoid.convertLatLongHeightToXYZ(osg::DegreesToRadians(43.449310), 
osg::DegreesToRadians(5.197525), 500.0, x, y, z);
     eye = osg::Vec3d(x,y,z);
     // The center : position where you look at (same position a little 
bit underneath...
ellipsoid.convertLatLongHeightToXYZ(osg::DegreesToRadians(43.449310), 
osg::DegreesToRadians(5.197525), 499.9, x, y, z);
     center = osg::Vec3d(x,y,z);
     // The up : a little more tricky...
     // It is the up vector of your screen (ie what is the bottom top 
axis of your screen)
     // If you want it to be north up
     up = osg::Vec3d    ( -std::cos(osg::DegreesToRadians(43.449310)) * 
std::sin( osg::DegreesToRadians(5.197525)),
-std::sin(osg::DegreesToRadians(43.449310)) * std::sin( 
osg::DegreesToRadians(5.197525)),
std::cos(osg::DegreesToRadians(5.197525)));
     // If you want it to be east up
     up = osg::Vec3d    ( -std::cos(osg::DegreesToRadians(43.449310)),
std::cos(osg::DegreesToRadians(43.449310)),
                         0.0);
     // Now you can set your view matrix
     camera->setViewMatrixAsLookAt(eye,center,up);

     // Some light for the scene...
     osg::ref_ptr<osg::Light> light = new osg::Light();
     light->setLightNum(0);
     light->setDataVariance(osg::Object::DYNAMIC);
     osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
     lightSource->setLight(light);
lightSource->setLocalStateSetModes(osg::StateAttribute::ON);

     // Adding the elements
     root->addChild( map.get() );
     root->addChild( moveCessna.get() );
     root->addChild( lightSource.get());

     // Setting up the view
     viewer->setCamera( camera.get() );
     viewer->setSceneData( root.get() );

     osg::ref_ptr<osgViewer::StatsHandler> stats = new 
osgViewer::StatsHandler();
     viewer->addEventHandler(stats.get());

     while (!viewer->done())
     {
         viewer->frame();
     }

     return 1;
}


Hope it helps out !

Cheers,

Christian

Le 18/06/2015 20:23, Elias Tarasov a écrit :
> Hello, Christian!
>
> Again, your comments helped me:)
> And again, i can't understand it from the first time.
>
> The root of the problem here is how to move and rotate camera.
> And the root of it is how to calculate needed matrices.
>
> So, i looked for it:
>
> 1. Looked into general OSG forum.
> 2. Looked into vpb forum.
> 3. Stackoverflow.
>
> There are a lot of info but to indicate what kind of problem i have, here is the pattern of what i found:
>
> Vec3d eye( 1000.0, 1000.0, 0.0 );
> Vec3d center( 0.0, 0.0, 0.0 );
> Vec3d up( 0.0, 0.0, 1.0 );
> viewer.getCamera()->setViewMatrixAsLookAt( eye, center, up );
>
> Assumption:
> Vectors must be defined with respect to some choosen coordinate frame.
> So, with respect to what frame eye, center, up are defined?
> How can i calculate them?
> I presume, that without knowing in what frame vectors are expressed, and how to move to that frame from already defined frame (for instance from ECEF),
> variables like Vec3d eye( 1000.0, 1000.0, 0.0 ) are useless.
>
> Here is the code i changed according to your recomendations.
> In the comments, there are at least three issues:
> 1. How to correctly define rotation?
> 2. How to define Up vector.
> 3. How to correctly add moved camera.
>
> int main( int argc, char** argv ) {
>
> 	osg::ref_ptr<osg::Group> root = new osg::Group;
> 	osg::ref_ptr<osg::Node> cessna = osgDB::readNodeFile("c:/OpenSceneGraph/data/cessnafire.osg");
> 	osg::ref_ptr<osg::Node> map = osgDB::readNodeFile("c:/Terrain/FromUSGS/output/out.osgb");
> 	osg::ref_ptr<osg::Camera> camera = new osg::Camera;
>
> 	//Getting XYZ position for cessna
> 	//-85.4877762 is terrain's center lat
> 	//30.5292506 is terrain's center lon
> 	//100 m - height above terrain we want to place the cessna.
> 	osg::Matrix cessnaLocation;
> 	osg::EllipsoidModel ellipsoid;
> 	ellipsoid.computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(-85.4877762), osg::DegreesToRadians(30.5292506), 100, cessnaLocation);
> 	osg::Vec3 positionForCessna = cessnaLocation.getTrans();
> 	
> 	//Placing cessna
> 	osg::ref_ptr<osg::PositionAttitudeTransform> moveCessna = new osg::PositionAttitudeTransform;
> 	moveCessna->setPosition(positionForCessna);
> 	moveCessna->addChild(cessna.get());
> 		
> 	//Getting XYZ position for camera
> 	//Lat Lon are the same, height is 150
> 	osg::Matrix cameraLocation;
> 	ellipsoid.computeLocalToWorldTransformFromLatLongHeight(osg::DegreesToRadians(-85.4877762), osg::DegreesToRadians(30.5292506), 150, cameraLocation);
> 	osg::Vec3 positionForCamera = cameraLocation.getTrans();
> 	
> 	//Placing camera
> 	osg::ref_ptr<osg::PositionAttitudeTransform> moveCamera = new osg::PositionAttitudeTransform;
> 	moveCamera->setPosition(positionForCamera);
> 	moveCamera->addChild(camera.get());
> 	
> 	//rotation and Y up
> 	//How to setup rotation matrix? with respect to what coordinate frame? I presume View frame with respect to ECEF?
> 	osg::Matrix rotation;
> 	rotation.makeRotate(osg::PI_2, osg::Vec3f(1.0, 0.0, 0.0)); //Here we rotate around X on the angle pi/2. But rotate around what?
> 	
> 	//How to define that matrix and why does it need?
> 	osg::Matrix ToYUP;  //Maybe here we can define a direction around of which we make our rotation?
> 	
> 	//View = translation * YUP * rotation;
> 	osg::Matrix viewMatrix;
> 	viewMatrix = cameraLocation * ToYUP * rotation;
> 	camera->setViewMatrix(viewMatrix);
> 		
> 	//How to add moved camera?
> 	root->addChild(camera.get() );
> 	//Or maybe even camera->addChild( root.get() ); ?
> 	root->addChild( moveCessna.get() );
> 	root->addChild( map.get() );
> 	
> 	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
> 	viewer->setCamera( camera.get() );
> 	viewer->setSceneData( root.get() );
> 	
> 	return viewer->run();
> }
>
>
> Thank you!
>
> Cheers,
> Elias
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=64123#64123
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>


-- 
SCHULTE Christian
Ingénieur Recherche
Responsable du Laboratoire de Simulation
ONERA - DCSD/PSEV
Département Commande des Systèmes et Dynamique du Vol
ONERA - Centre de Salon de Provence
BA 701
13661 SALON AIR Cedex - France
Tel :04.90.17.01.45




More information about the osg-users mailing list