osg渲染一个房子的四壁(有纹理)
1 /* -*-c++-*- Copyright (C) 2009 Wang Rui <wangray84 at gmail dot com> 2 * OpenSceneGraph Engine Book - Design and Implementation 3 * How to create a geometric house 4 */ 5 6 #include <osg/Texture2D> 7 #include <osg/Geometry> 8 #include <osg/Geode> 9 #include <osgDB/ReadFile> 10 #include <osgUtil/SmoothingVisitor> 11 #include <osgViewer/Viewer> 12 13 osg::Drawable* createHouseWall() 14 { 15 // House vertices 16 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; 17 //前面 18 vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) ); // 0 19 vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) ); // 1 20 vertices->push_back( osg::Vec3( 6.0, 0.0, 4.0) ); // 2 21 vertices->push_back( osg::Vec3( 6.0, 0.0, 0.0) ); // 3 22 //右面 23 vertices->push_back( osg::Vec3( 6.0, 4.0, 4.0) ); // 4 24 vertices->push_back( osg::Vec3( 6.0, 4.0, 0.0) ); // 5 25 //后面 26 vertices->push_back( osg::Vec3( 0.0, 4.0, 4.0) ); // 6 27 vertices->push_back( osg::Vec3( 0.0, 4.0, 0.0) ); // 7 28 //左面 29 vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) ); // 8 30 vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) ); // 9 31 32 // House normals 33 osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array( 10 ); 34 //左前 35 (*normals)[0].set(-1.0,1.0, 0.0 ); 36 (*normals)[1].set(-1.0,1.0, 0.0 ); 37 //右前 38 // (*normals)[2].set( 1.0,-1.0, 0.0 ); 39 // (*normals)[3].set( 1.0,-1.0, 0.0 ); 40 //右后 41 (*normals)[4].set( 1.0, 1.0, 0.0 ); 42 (*normals)[5].set( 1.0, 1.0, 0.0 ); 43 //左后 44 //(*normals)[6].set(-1.0, 1.0, 0.0 ); 45 //(*normals)[7].set(-1.0, 1.0, 0.0 ); 46 //左前 47 //(*normals)[8].set(-1.0,-1.0, 0.0 ); 48 //(*normals)[9].set(-1.0,-1.0, 0.0 ); 49 50 // House texture coordinates 51 osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array( 10 ); 52 //前面的左0.3 53 (*texcoords)[0].set( 0.0, 1.0 ); 54 (*texcoords)[1].set( 0.0, 0.0 ); 55 (*texcoords)[2].set( 0.3, 1.0 ); 56 (*texcoords)[3].set( 0.3, 0.0 ); 57 58 //右面0.2 59 (*texcoords)[4].set( 0.5, 1.0 ); 60 (*texcoords)[5].set( 0.5, 0.0 ); 61 62 //后面0.3 63 (*texcoords)[6].set( 0.8, 1.0 ); 64 (*texcoords)[7].set( 0.8, 0.0 ); 65 //左边0.2 66 (*texcoords)[8].set( 1.0, 1.0 ); 67 (*texcoords)[9].set( 1.0, 0.0 ); 68 69 // Create wall geometry 70 osg::ref_ptr<osg::Geometry> houseWall = new osg::Geometry; 71 houseWall->setVertexArray( vertices.get() ); 72 houseWall->setTexCoordArray( 0, texcoords.get() ); 73 houseWall->setNormalArray( normals.get() ); 74 houseWall->setNormalBinding( osg::Geometry::BIND_PER_VERTEX ); 75 houseWall->addPrimitiveSet( new osg::DrawArrays(osg::DrawArrays::QUAD_STRIP, 0, 10) ); 76 77 houseWall->getOrCreateStateSet()->setTextureAttributeAndModes( 0, 78 new osg::Texture2D(osgDB::readImageFile("C:\\wall.png")) ); 79 return houseWall.release(); 80 } 81 82 int main( int argc, char** argv ) 83 { 84 osg::ref_ptr<osg::Geode> geode = new osg::Geode; 85 geode->addDrawable( createHouseWall() ); 86 // geode->addDrawable( createHouseRoof() ); 87 88 osgViewer::Viewer viewer; 89 viewer.setSceneData( geode.get() ); 90 return viewer.run(); 91 }
所用的纹理:
运行效果(为了观察法线对灯光的影响,注释掉30行到40行相应的代码。改掉左前的法线方向,其影响是房子的里面亮了,如下图):
运行效果(没有纹理):
带有环境光、散射光,指定光源位置,有多个纹理
效果:
代码实现:
/* -*-c++-*- Copyright (C) 2009 Wang Rui <wangray84 at gmail dot com> * OpenSceneGraph Engine Book - Design and Implementation * How to create a geometric house */ #include <osg/Texture2D> #include <osg/Geometry> #include <osg/Geode> #include <osgDB/ReadFile> #include <osgUtil/SmoothingVisitor> #include <osgViewer/Viewer> #include <osg/PositionAttitudeTransform> #include <osg/MatrixTransform> //回调函数,让其不断的旋转 class RotateCallback : public osg::NodeCallback { public: RotateCallback() : _rotateZ(0.0) {} virtual void operator()( osg::Node* node, osg::NodeVisitor* nv ) { osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>( node ); if ( pat ) { osg::Quat quat( osg::DegreesToRadians(_rotateZ), osg::Z_AXIS ); pat->setAttitude( quat ); _rotateZ += 1.0; } traverse( node, nv );//访问器的下一个节点 } protected: double _rotateZ; }; //向场景中添加光源 osg::ref_ptr<osg::Group> createLight(osg::ref_ptr<osg::Node> node) { osg::ref_ptr<osg::Group> lightRoot= new osg::Group(); //lightRoot->addChild(node); //开启光照 osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet(); stateset = lightRoot->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON); stateset->setMode(GL_LIGHT0,osg::StateAttribute::ON); //创建一个Light对象 osg::ref_ptr<osg::Light> light = new osg::Light(); light->setLightNum(0); //设置方向 light->setDirection(osg::Vec3(0.0f,1.0f,-1.0f)); //设置位置 light->setPosition(osg::Vec4(0,-10,8,1.0f)); //设置环境光的颜色 light->setAmbient(osg::Vec4(0.1f,0.1f,0.1f,1.0f)); //设置散射光的颜色 light->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); ////设置恒衰减指数 //light->setConstantAttenuation(1.0f); ////设置线形衰减指数 //light->setLinearAttenuation(0.0f); ////设置二次方衰减指数 //light->setQuadraticAttenuation(0.0f); //创建光源 osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource(); lightSource->setLight(light.get()); lightRoot->addChild(lightSource.get()); return lightRoot.get() ; } osg::Drawable* createHouseWall() { // House vertices osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; //前面 vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) ); // 0 vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) ); // 1 vertices->push_back( osg::Vec3( 4.0, 0.0, 4.0) ); // 2 vertices->push_back( osg::Vec3( 4.0, 0.0, 0.0) ); // 3 //右面 vertices->push_back( osg::Vec3( 4.0, 4.0, 4.0) ); // 4 vertices->push_back( osg::Vec3( 4.0, 4.0, 0.0) ); // 5 //后面 vertices->push_back( osg::Vec3( 0.0, 4.0, 4.0) ); // 6 vertices->push_back( osg::Vec3( 0.0, 4.0, 0.0) ); // 7 //左面 vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) ); // 8 vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) ); // 9 // House normals osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array( 10 ); //左前 (*normals)[0].set(-1.0,-1.0, 0.0 ); (*normals)[1].set(-1.0,-1.0, 0.0 ); //右前 (*normals)[2].set( 1.0,-1.0, 0.0 ); (*normals)[3].set( 1.0,-1.0, 0.0 ); //右后 (*normals)[4].set( 1.0, 1.0, 0.0 ); (*normals)[5].set( 1.0, 1.0, 0.0 ); //左后 (*normals)[6].set(-1.0, 1.0, 0.0 ); (*normals)[7].set(-1.0, 1.0, 0.0 ); //左前 (*normals)[8].set(-1.0,-1.0, 0.0 ); (*normals)[9].set(-1.0,-1.0, 0.0 ); // House texture coordinates osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array( 10 ); //前面的左0.3 (*texcoords)[0].set( 0.0, 1.0 ); (*texcoords)[1].set( 0.0, 0.0 ); (*texcoords)[2].set( 1.0, 1.0 ); (*texcoords)[3].set( 1.0, 0.0 ); //右面0.2 /* (*texcoords)[4].set( 0.0, 1.0 ); (*texcoords)[5].set( 0.0, 0.0 ); //后面0.3 (*texcoords)[6].set( 1.0, 1.0 ); (*texcoords)[7].set( 1.0, 0.0 ); //左边0.2 (*texcoords)[8].set( 0.0, 1.0 ); (*texcoords)[9].set( 0.0, 0.0 );*/ // House texture coordinates osg::ref_ptr<osg::Vec2Array> texcoords2 = new osg::Vec2Array( 10 ); //右面0.2 (*texcoords2)[4].set( 0.0, 1.0 ); (*texcoords2)[5].set( 0.0, 0.0 ); //后面0.3 (*texcoords2)[6].set( 1.0, 1.0 ); (*texcoords2)[7].set( 1.0, 0.0 ); //左边0.2 (*texcoords2)[8].set( 0.0, 1.0 ); (*texcoords2)[9].set( 0.0, 0.0 ); // Create wall geometry osg::ref_ptr<osg::Geometry> houseWall = new osg::Geometry; houseWall->setVertexArray( vertices.get() ); houseWall->setTexCoordArray( 0, texcoords.get() ); houseWall->setTexCoordArray( 1, texcoords2.get() ); houseWall->setNormalArray( normals.get() ); houseWall->setNormalBinding( osg::Geometry::BIND_PER_VERTEX ); houseWall->addPrimitiveSet( new osg::DrawArrays(osg::DrawArrays::QUAD_STRIP, 0, 10) ); houseWall->getOrCreateStateSet()->setTextureAttributeAndModes( 0,new osg::Texture2D(osgDB::readImageFile("C:\\22.jpg")) ); houseWall->getOrCreateStateSet()->setTextureAttributeAndModes( 1,new osg::Texture2D(osgDB::readImageFile("C:\\55.jpg")) ); return houseWall.release(); } int main( int argc, char** argv ) { osg::Group *root = new osg::Group; osg::ref_ptr<osg::Geode> geode = new osg::Geode; geode->addDrawable( createHouseWall() ); osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform; pat->addChild( geode ); pat->setUpdateCallback( new RotateCallback ); root->addChild(pat); root->addChild(createLight(geode.get())); osgViewer::Viewer viewer; viewer.setUpViewInWindow(20,20,400,400); viewer.setSceneData(root); return viewer.run(); }
.