我要发帖 回复

高级会员

109

主题

1589

积分

0

专家分

OSG-VR-GIS

忠于职守杰出贡献

:

私信
发表时间 : 2007-12-21 14:17:21 | 浏览 : 1682    评论 : 0
Navy15 - 向场景中添加告示牌(Billboard)节点 (1)
目的:
4.jpg
向场景中添加告示牌节点,以模拟沙漠中灌木的效果。
-----------------------------

概述:
告示牌(Billboard)节点的特性是围绕用户定义的轴(或者点)进行旋转,从而始终面向一个指定的方向。典型的告示牌可以绕Z轴正向旋转,同时面向视口方向,以实现树林的模拟。OSG发行版本的示例程序osgBillboard中通过指定旋转轴和法线(朝向方向)的方式,演示了各种模式的告示牌节点。本教程将创建多个树木样式的告示牌,它们环绕Z轴正向旋转并始终朝向视口。

Billboard类(osg::Billboard)包括可以绕一个轴或者参考点旋转并朝向指定方向的几何体。Billboard类继承自Geode类。也就是说,继承自Drawable类(包括Geometry类)的实例可以被添加给Billboard对象。我们可以将几何体关联给告示牌节点。因为Billboard类是继承自Geode类的,我们也可以将StateSet关联给告示牌节点。

除了继承自Geode类的方法和成员外,告示牌类还包括了用于控制其自身特性的成员和方法:告示牌是否环绕参考点或者轴;如果绕某个轴旋转的话,它应该朝向什么方向。为了控制告示牌的类型,可以使用其中的setMode(osg::Billboard::Mode)方法。其合法参数有:POINT_ROT_EYE(绕一个点旋转,相对于眼睛位置),POINT_ROT_WORLD(绕一个点旋转,相对于世界坐标),AXIAL_ROT(绕一个轴旋转)。如果指定了AXIAL_ROT模式,用户就可以使用setAxis(osg::Vec3)方法来设置告示牌绕之旋转的轴。用户还可以使用setNormal(osg::Vec3)方法定义告示牌朝向的法线。为了放置告示牌,用户还需重载osg::Geode的addGeometry方法。这个方法有两个参数:一个Drawable实例,以及一个标识位置的osg::Vec3实例。

创建告示牌还需要最后一步工作:当几何体根据法线的设置旋转并朝向视口之后,对其进行光照的计算将导致一种怪异的结果。(光照会随着视口的改变而突变)为了创建各个方向的形象均相同的告示牌,我们需要确信关闭告示牌的光照。综上所述,向场景中添加多个告示牌的基本步骤为:

创建一个告示牌实例并添加到场景;
创建光照关闭的渲染状态;
创建几何体(应用上面的渲染状态)并添加给告示牌节点。
代码:
需要以下的头文件:

#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Billboard>
#include <osg/BlendFunc>
#include <osg/AlphaFunc>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osg/PositionAttitudeTransform>

首先,我们编写一个简便的函数用于生成与告示牌节点相关联的几何体。此函数有两个参数:一个浮点数用于表示放缩特性,以及一个关联给几何体实例的渲染状态指针。这个函数的返回值是一个几何体指针。我们使用简单的四边形来生成几何体。关于如何指定四边形的顶点和纹理坐标,请参照前面的教程。唯一需要注意的是,在创建该几何体的时候,我们需要它相对旋转轴置中。函数的定义如下所示:

osg::Drawable* createShrub(const float & scale, osg::StateSet* bbState)
{
   float width = 1.5f;
   float height = 3.0f;

   width *= scale;
   height *= scale;

   osg::Geometry* shrubQuad = new osg::Geometry;

   osg::Vec3Array* shrubVerts = new osg::Vec3Array(4);
   (*shrubVerts)[0] = osg::Vec3(-width/2.0f, 0, 0);
   (*shrubVerts)[1] = osg::Vec3( width/2.0f, 0, 0);
   (*shrubVerts)[2] = osg::Vec3( width/2.0f, 0, height);
   (*shrubVerts)[3] = osg::Vec3(-width/2.0f, 0, height);

   shrubQuad->setVertexArray(shrubVerts);

   osg::Vec2Array* shrubTexCoords = new osg::Vec2Array(4);
   (*shrubTexCoords)[0].set(0.0f,0.0f);
   (*shrubTexCoords)[1].set(1.0f,0.0f);
   (*shrubTexCoords)[2].set(1.0f,1.0f);
   (*shrubTexCoords)[3].set(0.0f,1.0f);
   shrubQuad->setTexCoordArray(0,shrubTexCoords);

   shrubQuad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));

   // 创建一个颜色数组,并为所有的顶点添加单一的颜色。
   osg::Vec4Array* colorArray = new osg::Vec4Array;
   colorArray->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); // white, fully opaque
   // 创建颜色索引数组。
   osg::TemplateIndexArray
      <unsigned int, osg::Array::UIntArrayType,4,1> *colorIndexArray;
   colorIndexArray =
      new osg::TemplateIndexArray<unsigned int, osg::Array::UIntArrayType,4,1>;
   colorIndexArray->push_back(0);
   // 使用索引数组将其中的第一个值关联给所有的顶点。
   shrubQuad->setColorArray( colorArray);
   shrubQuad->setColorIndices(colorIndexArray);
   shrubQuad->setColorBinding(osg::Geometry::BIND_OVERALL);

   shrubQuad->setStateSet(bbState);

   return shrubQuad;
}

最近VR访客


OSG中国官方网站:http://www.osgChina.org
OSG中国官方讨论区:http://bbs.osgChina.org

OSG专业群-OSG地形研究者 49668412
      OSG地形专业研究 45763709

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

GMT+8, 2021-4-21 08:04 PM

返回顶部