Since you're navigating on a sphere, you always need to calculate the
bearing based off the local "up" vector of the sphere (ground
stabilized) and not the "up" vector of the ownship. The reason why your
code works from the birds eye view is because the "up" vectors between
the two are the same in this case. When you introduce pitch and roll,
the "up" vector of the ownship diverges from the sphere "up" vector
which probably explains why your code below no longer works.

Once you calculate the bearing correctly, your compass heading can then
be calculated by using the bearing angle to rotate around the z-axis
(0,0,1).

-Shayne 

-----Original Message-----
From: osg-users-boun...@lists.openscenegraph.org
[mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of onur
akkaya
Sent: Thursday, June 28, 2012 1:20 AM
To: osg-users@lists.openscenegraph.org
Subject: [osg-users] ECEF Oriented Compass Implementation

Hi,

I have an ECEF terrain and I want to implement a compass node to show
the true north to the user.

I tried the code below but at some angles it does not work correctly.
When the camera is vertical (birds eye view) to the terrain, it works
perfect but if you rotate the camera (elevation or roll) it does not
show the correct value.

thanks,

class Compass : public osg::Camera
{
public:
    Compass(void)
    {
    }

    Compass( const Compass& copy, osg::CopyOp copyop =
osg::CopyOp::SHALLOW_COPY ):
                    osg::Camera(copy, copyop),
                        _plateTransform(copy._plateTransform),
                        _needleTransform(copy._needleTransform),
                        _mainCamera(copy._mainCamera),
                        m_bIsFirst(false)
    {
    }

    Compass::~Compass(void)
    {
    }

    META_Node( osg, Compass );
    void setPlate( osg::MatrixTransform* plate )
    {
        _plateTransform = plate; 
    }

    void setNeedle( osg::MatrixTransform* needle ) 
    {
        _needleTransform = needle; 
    }

    void setMainCamera( osg::Camera* camera ) 
    {
        _mainCamera = camera;
    }

    virtual void traverse( osg::NodeVisitor& nv )
    {
        if ( _mainCamera.valid() &&
nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR )
        {
            osg::Matrix matrix = _mainCamera->getViewMatrix();
            matrix.setTrans( osg::Vec3() );
            osg::Vec3 northVec = osg::Z_AXIS * matrix;  
            northVec.z()= 0.0;

            northVec.normalize();
            osg::Vec3 axis = osg::Y_AXIS ^ northVec;
            float angle = atan2(axis.length(), osg::Y_AXIS*northVec);
            axis.normalize();

            if ( _plateTransform.valid() )
            {
                _plateTransform->setMatrix( osg::Matrix::rotate(angle,
axis) );
            }

            _plateTransform->accept( nv );
            _needleTransform->accept( nv );
            osg::Camera::traverse( nv );
        }
    }

    osg::MatrixTransform* createCompassPlate( const std::string& image,
float radius, float height)
    {
        osg::Vec3 center(-radius, -radius, height);
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->addDrawable(createTexturedQuadGeometry(center,
osg::Vec3(radius*2.0f,0.0f,0.0f),
            osg::Vec3(0.0f,radius*2.0f,0.0f)) );
        osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;      
        texture->setImage(osgDB::readImageFile(image));

        osg::ref_ptr<osg::MatrixTransform> part =new
osg::MatrixTransform();
        part->getOrCreateStateSet()->setTextureAttributeAndModes(0,
texture.get() );
 
part->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT
_BIN ); 

        part->addChild(geode.get());

        return part.release();
    }
    osg::MatrixTransform* createCompassNeedle( const std::string& image,
float radius, float height)
    {
        osg::Vec3 center(-radius/4, -radius, height);
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->addDrawable(createTexturedQuadGeometry(center,
osg::Vec3(radius/2,0.0f,0.0f),
            osg::Vec3(0.0f,radius*2,0.0f)) );
        osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;      
        texture->setImage(osgDB::readImageFile(image));

        osg::ref_ptr<osg::MatrixTransform> part =new
osg::MatrixTransform();
        part->getOrCreateStateSet()->setTextureAttributeAndModes(0,
texture.get() );
 
part->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT
_BIN ); 

        part->addChild(geode.get());

        return part.release();
    }

protected:
    osg::ref_ptr<osg::MatrixTransform> _plateTransform;
    osg::ref_ptr<osg::MatrixTransform> _needleTransform;
    osg::observer_ptr<osg::Camera> _mainCamera;
    bool m_bIsFirst;
};

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





_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.or
g
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to