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
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org