我要发帖 回复

管理员

735

主题

2万

积分

30

专家分

忠于职守杰出贡献鼓励

兴趣点(最多三项):

建模技术

私信
发表时间 : 2007-11-23 13:01:31 | 浏览 : 2652    评论 : 0
译者:竹林小舍




原文出处:http://www.nps.navy.mil/cs/sullivan/osgtutorials/osgTexturedGeometry.htm


目标:

为教程1中介绍的由OpenGL基本绘制单位定义的几何体添加纹理。
背景:

前一节教程介绍了包含由OpenGL基本单位产生的基本形状的视景。本节讲解如何为这些形状添加纹理。为了使代码更方便使用,我们将pyramid的代码放到一个函数中,产生geode并返回它的指针。下面的代码来自教程1。

osg::Geode* createPyramid()

{


osg::Geode* pyramidGeode = new osg::Geode();


osg::Geometry* pyramidGeometry = new osg::Geometry();


pyramidGeode->addDrawable(pyramidGeometry);




// Specify the vertices:


osg::Vec3Array* pyramidVertices = new osg::Vec3Array;


pyramidVertices->push_back( osg::Vec3(0, 0, 0) ); // front left


pyramidVertices->push_back( osg::Vec3(2, 0, 0) ); // front right


pyramidVertices->push_back( osg::Vec3(2, 2, 0) ); // back right


pyramidVertices->push_back( osg::Vec3( 0,2, 0) ); // back left


pyramidVertices->push_back( osg::Vec3( 1, 1,2) ); // peak




// Associate this set of vertices with the geometry associated with the


// geode we added to the scene.


pyramidGeometry->setVertexArray( pyramidVertices );




// Create a QUAD primitive for the base by specifying the


// vertices from our vertex list that make up this QUAD:


osg::DrawElementsUInt* pyramidBase =


new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);


pyramidBase->push_back(3);


pyramidBase->push_back(2);


pyramidBase->push_back(1);


pyramidBase->push_back(0);




//Add this primitive to the geometry:

pyramidGeometry->addPrimitiveSet(pyramidBase);


// code to create other faces goes here!


// (removed to save space, see tutorial two)


osg::Vec4Array* colors = new osg::Vec4Array;


colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red


colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //index 1 green


colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //index 2 blue


colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 3 white




osg::TemplateIndexArray


<unsigned int, osg::Array::UIntArrayType,4,4> *colorIndexArray;


colorIndexArray =


new osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType,4,4>;


colorIndexArray->push_back(0); // vertex 0 assigned color array element 0


colorIndexArray->push_back(1); // vertex 1 assigned color array element 1


colorIndexArray->push_back(2); // vertex 2 assigned color array element 2


colorIndexArray->push_back(3); // vertex 3 assigned color array element 3


colorIndexArray->push_back(0); // vertex 4 assigned color array element 0




pyramidGeometry->setColorArray(colors);


pyramidGeometry->setColorIndices(colorIndexArray);


pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);




// Since the mapping from vertices to texture coordinates is 1:1,


// we don't need to use an index array to map vertices to texture


// coordinates. We can do it directly with the 'setTexCoordArray'


// method of the Geometry class.


// This method takes a variable that is an array of two dimensional


// vectors (osg::Vec2). This variable needs to have the same


// number of elements as our Geometry has vertices. Each array element


// defines the texture coordinate for the cooresponding vertex in the


// vertex array.


osg::Vec2Array* texcoords = new osg::Vec2Array(5);


(*texcoords)[0].set(0.00f,0.0f); // tex coord for vertex 0



(*texcoords)[1].set(0.25f,0.0f); // tex coord for vertex 1


(*texcoords)[2].set(0.50f,0.0f); // ""


(*texcoords)[3].set(0.75f,0.0f); // ""


(*texcoords)[4].set(0.50f,1.0f); // ""


pyramidGeometry->setTexCoordArray(0,texcoords);




return pyramidGeode;

}

加载纹理,生成状态集合并将他们附加到节点上
       渲染基本单位的方法是使用StateSet。这节代码演示了怎样从文件中加载纹理,产生此纹理起作用的一个StateSet,并将这个StateSet附加到场景中的一个节点上。前面开始的代码和上一节教程中的一样,初始化一个viewer并建立有一个pyramid的场景。

int main()

{


osgProducer::Viewer viewer;




// Declare a group to act as root node of a scene:


osg::Group* root = new osg::Group();


osg::Geode* pyramidGeode = createPyramid();


root->addChild(pyramidGeode);


现在,准备加纹理。这里我们会声明一个纹理实例并将它的数据不一致性设为'DYNAMIC'。(如果不把纹理声明为dynamic,osg的一些优化程序会删除它。)这个texture类包装了OpenGL纹理模式(wrap,filter,等等)和一个osg::Image。下面的代码说明了如何从文件里读取osg::Image实例并把这个图像和纹理关联起来。


osg::Texture2D* KLN89FaceTexture = new osg::Texture2D;




// protect from being optimized away as static state:


KLN89FaceTexture->setDataVariance(osg::Object::DYNAMIC);




// load an image by reading a file:


osg::Image* klnFace = osgDB::readImageFile("KLN89FaceB.tga");


if (!klnFace)


{


std::cout << " couldn't find texture, quiting." << std::endl;


return -1;


}




// Assign the texture to the image we read from file:


KLN89FaceTexture->setImage(klnFace);


       纹理 可以和渲染StateSet关联起来。下一步就产生一个StateSet,关联并启动我们的纹理,并将这个StateSet附加到我们的geometry上。


// Create a new StateSet with default settings:


osg::StateSet* stateOne = new osg::StateSet();




// Assign texture unit 0 of our new StateSet to the texture


// we just created and enable the texture.


stateOne->setTextureAttributeAndModes


(0,KLN89FaceTexture,osg::StateAttribute::ON);


// Associate this state set with the Geode that contains


// the pyramid:


pyramidGeode->setStateSet(stateOne);


最后一步是仿真循环:


//The final step is to set up and enter a simulation loop.


viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);


viewer.setSceneData( root );


viewer.realize();




while( !viewer.done() )


{


viewer.sync();


viewer.update();


viewer.frame();


}


return 0;

}

编码愉快!


[ 本帖最后由 obuil 于 2007-11-23 01:31 PM 编辑 ]

最近VR访客

手机版|VR开发网 统计 津ICP备18009691号
网安备12019202000257

GMT+8, 2021-9-18 05:42 AM

返回顶部