今天学习回调,回调分为更新回调、拣选回调、绘制。自以为顺序是从左到右的,即更新>拣选>绘制。根据海军教程里的内容,我今天将回调用到之前博客中的地球上,之前的那篇博客只是将球体贴上了世界地图的纹理,现在我们让它自转起来,当然能自转也一定能公转(这个就先不做了,不过一定能够实现)。
1.定义一个用户自定义数据类,当然,这个类一定要从osg::Referenced类派生。
2.定义回调类,重写操作符()。
3.安装回调类。
4.循环仿真。
userData.h
#pragma once
#include <osg/Node>
#include <osg/MatrixTransform>
#include <iostream>
#include <osgText/Text>
#include "myFindNodeVisitor.h"
#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgTextd.lib")
#else
#pragma comment(lib,"osg.lib")
#pragma commnet(lib,"osgText.lib")
#endif
class UserData : public osg::Referenced
{
public:
//构造函数,需要设定从哪个点查找,并设置地球自转速度
UserData(osg::Node* node,double speed)
{
if (node)
{
m_earth = NULL;
m_text = NULL;
m_rotation = 0.0f;
m_speed = speed;
//这个类是前一个博客中的查找结点的类
myFindNodeVisitor findNode("earthRotation");
node->accept(findNode);
osg::MatrixTransform* earth = dynamic_cast<osg::MatrixTransform*>(findNode.getFirst());
if (earth)
{
m_earth = earth;
}
}
}
void upateRotation()
{
if (!m_earth)
{
std::cout<<"UserData::m_earth is NULL!"<<std::endl;
return;
}
m_rotation += m_speed;
if (m_rotation>osg::DegreesToRadians(360.0f))
{
m_rotation = 0.0f;
}
m_earth->setMatrix(osg::Matrix::rotate(m_rotation,osg::Vec3(0,0,1)));
}
protected:
osg::MatrixTransform* m_earth;
double m_rotation;
double m_speed;
};
class callBack : public osg::NodeCallback
{
public:
//重写操作符()在这里调用用户定义的功能
virtual void operator ()(osg::Node* node, osg::NodeVisitor* nv)
{
osg::ref_ptr<UserData> userData = dynamic_cast<UserData*>(node->getUserData());
if (userData)
{
userData->upateRotation();
}
traverse(node,nv);
}
};
main.cpp
//By smells2 at Lab 2012-02-21
#include <osg/Group>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osgViewer/Viewer>
#include <osgDB/readfile>
#include <osgDB/WriteFile>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/TexEnv>
#include <osg/Texture2D>
#include <iostream>
#include "UserData.h"
int main()
{
osg::ref_ptr<osg::Group> root = new osg::Group;
osgViewer::Viewer myViewer;
//Declear Sphere instance,the constructor takes an osg::vec3 to define
//center and a float to define the radius.
//Then we declear the ShapDrawable instance that derive from Drawable .We should
//initalize it with the shape we create above .
osg::ref_ptr<osg::Geode> unitSphere = new osg::Geode;
osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(osg::Vec3(0,0,0), 1.0f);
osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable(sphere.get());
unitSphere->addDrawable(shapeDrawable.get());
osg::ref_ptr<osg::PositionAttitudeTransform> sphereForm = new osg::PositionAttitudeTransform;
sphereForm->setPosition(osg::Vec3(2.5,0.0,0.0));
//sphereForm->addChild(unitSphere.get());
osg::MatrixTransform* rot = new osg::MatrixTransform;
rot->setName("earthRotation");
rot->addChild(unitSphere.get());
//root->addChild(rot);
sphereForm->addChild(rot);
root->addChild(sphereForm.get());
//load image from the file
osg::ref_ptr<osg::Texture2D> earthTexture = new osg::Texture2D;
earthTexture->setDataVariance(osg::Object::DYNAMIC);
osg::ref_ptr<osg::Image> earthImage = osgDB::readImageFile("D:\\OSG\\osg2.9\\OpenSceneGraph2.9.5\\data\\Images\\land_shallow_topo_2048.jpg");
if (!earthImage.get())
{
std::cout<<"load texture failed !"<<std::endl;
return -1;
}
//assign the texture from the image file
earthTexture->setImage(earthImage.get());
//set the stateset for decal texture
osg::ref_ptr<osg::TexEnv> texenv = new osg::TexEnv;
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
texenv->setMode(osg::TexEnv::DECAL);
stateset->setTextureAttributeAndModes(0,earthTexture.get(),osg::StateAttribute::ON);
stateset->setTextureAttribute(0,texenv.get());
//这里设置回调函数
UserData* userData = new UserData(root.get(),0.001);
root->setUserData(userData);
root->setUpdateCallback(new callBack);
//realize
root->setStateSet(stateset.get());
myViewer.setSceneData(root.get());
myViewer.realize();
myViewer.run();
}