OSG(Open Scene Graphics)是一款用c++编写的基于OpengGL接口的三维引擎,具有跨平台能力,在GIS等多个领域应用广泛。国内不少公司基于它开发出了自己的三维产品,山人所在公司就是其中之一。近日碰到一个要在场景中画三维饼状图的问题,研究了一天多,基本搞定,不敢私藏,写出来与大家共享,也请大家指教。闲言碎语不多讲,先上图,看看目标效果。
要完成这个功能,大致有几个问题要解决:
(1)画扇体
(2)实现半透明效果
(3)文字显示
(3)HUD节点
每一问题都不是太难,具体实现方法,且听山人一一道来。
(1)画扇体
OSG本身提供了绘制球、圆柱、长方体、圆锥等多种常用几何体的方法,遗憾的是唯独没有画扇体的方法,我们只能自己实现。先画扇形面,其原理我们在小学五年级就学过了,记不记得,跟求圆的面积差不多,画大扇形面就是画许多个联在一起的小扇形,当扇形角度极小时,又可以把小扇形近似的看成等腰三角形,而画三角形的方法,我们是相当相熟悉的。这样画一个大扇形的问题就归结为画许多个顶角极小的并且相连接的等腰三角形的问题。
所谓扇体者,而非扇形者,盖其有厚度也。所以我们接下来还要绘制侧面,包括两条矩形侧边和一条弧形侧面,前者直接画就行了,后者就是画许多相联的小矩形,每个矩形长取扇体厚度,宽取上面画小扇形三角形的底边。
这样一个扇体就绘制完成了。以X轴正方向为起点,逆时针旋转,在(0~2π)之间由起始角和终止角可确定多个扇体,这些不同着色的扇体按角度排列一周,就是个圆饼。可问题并没完,多个扇体紧挨在一起,并不美观,我们希望扇体之间能有一定的缝隙,实现方法就是每个扇体沿其对称轴往外平移一定距离。
(2)实现半透明效果
OSG实现半透明跟在OpenGL里差多不多,实现要点有两个,一个是打开透明模式,开启Alpha混合(GL_BLEND);二是关闭深度测试(GL_DEPTH_TEST)。但有时这样透明物体显现不出来,还要调整下渲染顺序,使透明物体靠后绘制(setRenderBinDetails)
osg::StateSet* stateset =new osg::StateSet;
stateset->setMode(GL_BLEND,osg::StateAttribute::ON); //Alpha混合开启
stateset->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); //取消深度测试
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED );
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setRenderBinDetails(11, "RenderBin");
还有一点,这个属性加在几何体(Geometry)上,而不要加在(Geode)上。
画扇体的函数实现如下:
//画扇体
osg::Node* DrawSector(osg::Vec3 vecCenter, float radius, float height, float startAngle, float endAngle, float delta,osg::Vec4 vecColor,std::string strText=std::string(""))
{
osg::ref_ptr<osg::Geode> geode=new osg::Geode;//扇体节点
osg::Quat qu;//扇体外移
qu.makeRotate((startAngle+