我要发帖 回复

管理员

735

主题

2万

积分

30

专家分

忠于职守杰出贡献鼓励

兴趣点(最多三项):

建模技术

私信
发表时间 : 2007-11-23 13:10:05 | 浏览 : 2737    评论 : 1
译者:竹林小舍
原文出处:http://www.nps.navy.mil/cs/sullivan/osgtutorials/osgText.htm



目标
添加文本到场景中——包括HUD风格的文本和作为场景一部分的文本。



摘要

文本类继承自Drawable类。也就是说文本实例可以加到Geode类实例上并且可以和其它几何体一样被渲染。与文本类相关的方法的全部列在*这里*。‘osgExample Text’工程示范了许多方法。这个教程提供了文本类的几个有限的函数。绘制一个HUD牵扯到下面两个概念:

1、生成一个子树,它的根节点有合适的投影及观察矩阵...

2、将HUD子树中的几何体指定到合适的RenderBin上,这样HUD几何体就会在场景的其他部分之后按正确地状态设置绘制。


渲染HUD的子树涉及到一个投影矩阵和一个观察矩阵。对于投影矩阵,我们会使用相当于屏幕维数水平和垂直扩展的正投影。根据这种模式,坐标相当于象素坐标。为了简单起见,观察矩阵使用单位矩阵。


为了渲染HUD,我们把它里面的几何体附加到一个指定的RenderBin上。RenderBin允许用户在几何体绘制过程中指定顺序。这对于HUD几何体需要最后绘制来说很有用。

代码

首先,声明我们需要的变量-osg::Text和osg::Projection。


osg::Group* root = NULL;


osg::Node* tankNode = NULL;


osg::Node* terrainNode = NULL;


osg::PositionAttitudeTransform* tankXform;


osgProducer::Viewer viewer;




// A geometry node for our HUD:


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


// Text instance that wil show up in the HUD:


osgText::Text* textOne = new osgText::Text();


// Text instance for a label that will follow the tank:


osgText::Text* tankLabel = new osgText::Text();


// Projection node for defining view frustrum for HUD:


osg::Projection* HUDProjectionMatrix = new osg::Projection;



从文件里加载模型,和前面的教程一样建立scene graph(这里没什么新东东)。



// Initialize root of scene:


root = new osg::Group();




osgDB::FilePathList pathList = osgDB::getDataFilePathList();


pathList.push_back


("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-Data\\NPSData\\Models\\T72-Tank\\");


pathList.push_back


("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-Data\\NPSData\\Models\\JoeDirt\\");


pathList.push_back


("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-Data\\NPSData\\Textures\\");


osgDB::setDataFilePathList(pathList);




// Load models from files and assign to nodes:


tankNode = osgDB::readNodeFile("t72-tank_des.flt");


terrainNode = osgDB::readNodeFile("JoeDirt.flt");




// Initialize transform to be used for positioning the tank


tankXform = new osg::PositionAttitudeTransform());


tankXform->setPosition( osg::Vec3d(5,5,8) );




// Build the scene - add the terrain node directly to the root,


// connect the tank node to the root via the transform node:


root->addChild(terrainNode);


root->addChild(tankXform);


tankXform->addChild(tankNode);




下一步,建立场景来显示HUD组件。添加一个子树,它的根节点有一个投影和观察矩阵。



// Initialize the projection matrix for viewing everything we


// will add as descendants of this node. Use screen coordinates


// to define the horizontal and vertical extent of the projection


// matrix. Positions described under this node will equate to


// pixel coordinates.


HUDProjectionMatrix->setMatrix(osg::Matrix::ortho2D(0,1024,0,768));





// For the HUD model view matrix use an identity matrix:


osg::MatrixTransform* HUDModelViewMatrix = new osg::MatrixTransform;


HUDModelViewMatrix->setMatrix(osg::Matrix::identity());




// Make sure the model view matrix is not affected by any transforms


// above it in the scene graph:


HUDModelViewMatrix->setReferenceFrame(osg::Transform::ABSOLUTE_RF);




// Add the HUD projection matrix as a child of the root node


// and the HUD model view matrix as a child of the projection matrix


// Anything under this node will be viewed using this projection matrix


// and positioned with this model view matrix.


root->addChild(HUDProjectionMatrix);


HUDProjectionMatrix->addChild(HUDModelViewMatrix);



现在建立几何体。我们根据屏幕坐标建立一个四边形,并设置颜色和纹理坐标。


// Add the Geometry node to contain HUD geometry as a child of the


// HUD model view matrix.


HUDModelViewMatrix->addChild( HUDGeode );




// Set up geometry for the HUD and add it to the HUD


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




osg::Vec3Array* HUDBackgroundVertices = new osg::Vec3Array;


HUDBackgroundVertices->push_back( osg::Vec3( 0,
0,-1) );


HUDBackgroundVertices->push_back( osg::Vec3(1024,
0,-1) );


HUDBackgroundVertices->push_back( osg::Vec3(1024,200,-1) );


HUDBackgroundVertices->push_back( osg::Vec3(
0,200,-1) );




osg::DrawElementsUInt* HUDBackgroundIndices =


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


HUDBackgroundIndices->push_back(0);


HUDBackgroundIndices->push_back(1);


HUDBackgroundIndices->push_back(2);


HUDBackgroundIndices->push_back(3);




osg::Vec4Array* HUDcolors = new osg::Vec4Array;


HUDcolors->push_back(osg::Vec4(0.8f,0.8f,0.8f,0.8f));




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


(*texcoords)[0].set(0.0f,0.0f);


(*texcoords)[1].set(1.0f,0.0f);


(*texcoords)[2].set(1.0f,1.0f);


(*texcoords)[3].set(0.0f,1.0f);




HUDBackgroundGeometry->setTexCoordArray(0,texcoords);


osg::Texture2D* HUDTexture = new osg::Texture2D;


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


osg::Image* hudImage;


hudImage = osgDB::readImageFile("HUDBack2.tga");


HUDTexture->setImage(hudImage);


osg::Vec3Array* HUDnormals = new osg::Vec3Array;


HUDnormals->push_back(osg::Vec3(0.0f,0.0f,1.0f));


HUDBackgroundGeometry->setNormalArray(HUDnormals);


HUDBackgroundGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);


HUDBackgroundGeometry->addPrimitiveSet(HUDBackgroundIndices);


HUDBackgroundGeometry->setVertexArray(HUDBackgroundVertices);


HUDBackgroundGeometry->setColorArray(HUDcolors);



HUDBackgroundGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);




HUDGeode->addDrawable(HUDBackgroundGeometry);



为了正确的渲染HUD,我们建立带有深度检测和透明度混合的osg::stateSet。我们也要保证HUD几何体最后绘制。几何体在裁剪遍历时通过指定一个已编号的渲染箱可以控制渲染顺序。最后一行演示了这些:


// Create and set up a state set using the texture from above:


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


HUDGeode->setStateSet(HUDStateSet);


HUDStateSet->


setTextureAttributeAndModes(0,HUDTexture,osg::StateAttribute::ON);




// For this state set, turn blending on (so alpha texture looks right)


HUDStateSet->setMode(GL_BLEND,osg::StateAttribute::ON);




// Disable depth testing so geometry is draw regardless of depth values


// of geometry already draw.


HUDStateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);


HUDStateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );




// Need to make sure this geometry is draw last. RenderBins are handled


// in numerical order so set bin number to 11


HUDStateSet->setRenderBinDetails( 11, "RenderBin");




最后,使用文本时,由于osg::Text是继承自osg::Drawable的,osg::Text实例可以作为孩子加到osg::Geode类实例上。



// Add the text (Text class is derived from drawable) to the geode:


HUDGeode->addDrawable( textOne );




// Set up the parameters for the text we'll add to the HUD:


textOne->setCharacterSize(25);


textOne->setFont("C:/WINDOWS/Fonts/impact.ttf");


textOne->setText("Not so good");


textOne->setAxisAlignment(osgText::Text::SCREEN);


textOne->setPosition( osg::Vec3(360,165,-1.5) );


textOne->setColor( osg::Vec4(199, 77, 15, 1) );




// Declare a geode to contain the tank's text label:


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




// Add the tank label to the scene:


tankLabelGeode->addDrawable(tankLabel);


tankXform->addChild(tankLabelGeode);




// Set up the parameters for the text label for the tank


// align text with tank's SCREEN.


// (for Onder: use XZ_PLANE to align text with tank's XZ plane.)


tankLabel->setCharacterSize(5);


tankLabel->setFont("/fonts/arial.ttf");


tankLabel->setText("Tank #1");


tankLabel->setAxisAlignment(osgText::Text::XZ_PLANE);




// Set the text to render with alignment anchor and bounding box around it:


tankLabel->setDrawMode(osgText::Text::TEXT |


osgText::Text::ALIGNMENT |


osgText::Text::BOUNDINGBOX);


tankLabel->setAlignment(osgText::Text::CENTER_TOP);


tankLabel->setPosition( osg::Vec3(0,0,8) );


tankLabel->setColor( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );





最后,建立viewer并进入仿真循环:



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


viewer.setSceneData( root );




viewer.realize();




while( !viewer.done() )


{


viewer.sync();


viewer.update();


viewer.frame();


}


好运!


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

最近VR访客

jungle_shaw 评论于2008-1-23 21:07:03

回复 #1 obuil 的帖子

谢谢!

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

GMT+8, 2021-9-29 09:54 AM

返回顶部