osg中有一種結點叫做告示板結點,其從osg::Geode類派生,它與其他的osg::Geode類相似,但它有一個特點就是能夠讓自己的一面朝向觀察屏幕。這樣就可以有很多的應用,比如說,可以用多個這種結點做成一片森林。
osg::Billboard類有兩種朝向方式,一種是平行於觀察平面,一種是垂直與觀察點。
#include <osg/Image>
#include <osg/Geometry>
#include <osg/Billboard>
#include <osg/StateSet>
#include <osg/Group>
#include <osg/Texture2D>
#include <osg/PositionAttitudeTransform>
#include <osgDB/readfile>
#include <osgViewer/Viewer>
#include <iostream>
#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgViewerd.lib")
#else
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgDB.lib")
#pragma comment(lib,"osgViewer.lib")
#endif
//生成一個矩形
osg::ref_ptr<osg::Geometry> createTree()
{
//繪製四邊形
osg::ref_ptr<osg::Geometry> rect = new osg::Geometry;
//頂點座標
osg::ref_ptr<osg::Vec3Array> vectexArray = new osg::Vec3Array;
vectexArray->push_back(osg::Vec3(-0.5f,0.0f,-0.5f));
vectexArray->push_back(osg::Vec3(0.5f,0.0f,-0.5f));
vectexArray->push_back(osg::Vec3(0.5f,0.0f,0.5f));
vectexArray->push_back(osg::Vec3(-0.5f,0.0f,0.5f));
rect->setVertexArray(vectexArray.get());
//法向
osg::ref_ptr<osg::Vec3Array> normalArray = new osg::Vec3Array;
normalArray->push_back(osg::Vec3(1.0f,0.0f,0.0f)^osg::Vec3(0.0f,0.0f,1.0f));
rect->setNormalArray(normalArray.get());
rect->setNormalBinding(osg::Geometry::BIND_OVERALL);
//紋理映射
osg::ref_ptr<osg::Vec2Array> coordArray = new osg::Vec2Array;
coordArray->push_back(osg::Vec2(0.0f,0.0f));
coordArray->push_back(osg::Vec2(1.0f,0.0f));
coordArray->push_back(osg::Vec2(1.0f,1.0f));
coordArray->push_back(osg::Vec2(0.0f,1.0f));
rect->setTexCoordArray(0,coordArray.get());
rect->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
return rect;
}
int main(int args,char** argv)
{
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Image> treeImage = osgDB::readImageFile("Images/tree0.rgba");
//定義三種不同的告示板結點
osg::ref_ptr<osg::Billboard> treeBillboard_rot_world = new osg::Billboard;
treeBillboard_rot_world->setMode(osg::Billboard::POINT_ROT_WORLD);
treeBillboard_rot_world->addDrawable(createTree().get());
osg::ref_ptr<osg::Billboard> treeBillboard_rot_eye = new osg::Billboard;
treeBillboard_rot_eye->setMode(osg::Billboard::POINT_ROT_EYE);
treeBillboard_rot_eye->addDrawable(createTree().get());
osg::ref_ptr<osg::Billboard> treeBillboard_rot_axial = new osg::Billboard;
treeBillboard_rot_axial->setMode(osg::Billboard::AXIAL_ROT);
treeBillboard_rot_axial->addDrawable(createTree().get());
//普通結點
osg::ref_ptr<osg::Geode> tree = new osg::Geode;
tree->addDrawable(createTree().get());
//分別貼上大樹紋理
if (treeImage.get())
{
osg::ref_ptr<osg::Texture2D> treeTexture = new osg::Texture2D;
treeTexture->setDataVariance(osg::Object::DYNAMIC);
treeTexture->setImage(treeImage.get());
osg::ref_ptr<osg::StateSet> treeStateSet = new osg::StateSet;
treeStateSet->setTextureAttributeAndModes(0,treeTexture.get());
treeStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
treeStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);
treeBillboard_rot_world->setStateSet(treeStateSet.get());
treeBillboard_rot_eye->setStateSet(treeStateSet.get());
treeBillboard_rot_axial->setStateSet(treeStateSet.get());
tree->setStateSet(treeStateSet.get());
}
treeBillboard_rot_eye->setPosition(0,osg::Vec3(10.0f,5.0f,5.0f));
treeBillboard_rot_world->setPosition(0,osg::Vec3(5.0f,5.0f,5.0f));
treeBillboard_rot_axial->setPosition(0,osg::Vec3(15.0f,0.0f,0.0f));
osg::ref_ptr<osg::PositionAttitudeTransform> treePos = new osg::PositionAttitudeTransform;
treePos->setPosition(osg::Vec3(0.0f,0.0f,0.0f));
treePos->addChild(tree.get());
root->addChild(treeBillboard_rot_axial.get());
root->addChild(treeBillboard_rot_world.get());
root->addChild(treeBillboard_rot_eye.get());
root->addChild(treePos.get());
osgViewer::Viewer myViewer;
myViewer.setSceneData(root.get());
myViewer.realize();
myViewer.run();
return 0;
}