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; }