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

 

posted @ 2018-10-13 19:15  一梦、  阅读(1295)  评论(0编辑  收藏  举报