3.3 使用OSG中预定义的几何体
在OSG中,为了简化场景的绘制,同时也为了方便开发者能够快速地构造一个场景,它本身预定义了一些常用的几何体。
3.3.1 osg::Shape类
osg::Shape类直接继承自osg::Object基类。osg::Shape类是各种内嵌几何体的基类,它不但可用于剔除和碰撞检测,还可用于生成预定义的几何体对象。
常用的内嵌几何体包括如下几种
osg::Box | 正方形 |
---|---|
osg::Capsule | 太空舱 |
osg::Cone | 椎体 |
osg::Cylinder | 柱体 |
osg::HeightField | 高度图 |
osg::InfinitePlane | 无限平面 |
osg::Sphere | 球体 |
osg::TriangleMesh | 三角片 |
3.3.2 osg::ShapeDrawable类
osg::ShapeDrawable类派生自osg::Drawable类,在osg::ShapeDrawable类的构造函数中提供了关联osg::Shape的方法:
- ShapeDrawable(Shape* shape,TessellationHints *hints = 0);// 第一个参数为shape,第二个参数默认下不细化
3.3.3 网格化类
网格化类(osg::TessellationHints)直接继承自osg::Object基类,osg::Tessellation类的主要作用是设置预定义几何体对象的精细程度、精细程度越高,表示其细分越详细,但对于不同的预定义几何体对象它的作用是不一样的。
- Box(四棱柱):网格化类对于四棱柱没有意义
- Capsule(太空舱):太空舱分3个部分,上下半球部分和圆柱侧面部分,默认圆柱侧面被细分
- Cone(圆锥):直接细分
- Cylinder(柱体):直接细分
- Sphere(球):直接细分
目前,osg::TessellationHints类并不完整,部分类成员函数还没有实现,具体可以查看源码。在内嵌几何体对象中,默认的情况下,网格化类的精细度为0,表示预定义的几何体此时按照原顶点默认绘制,不做任何细化处理。
3.3.4 预定义几何体示例
#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osg/ShapeDrawable>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
//------------------------------------------------------------------------------------
// 绘制多个预定义的几何体
osg::ref_ptr<osg::Geode> createShape()
{
// 创建一个叶节点
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// 设置半径和高度
float radius = 0.8f;
float height = 1.0f;
// 创建精细度对象,精细度越高,细分就越多
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
// 设置精细度为0.5f
hints->setDetailRatio(0.5f);
// 添加一个球体,第一个参数是预定义几何体对象,第二个是精细度,默认为0
geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius),hints));
// 添加一个正方体
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.0f,0.0f,0.0f),2 * radius),hints));
// 添加一个圆锥
geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height),hints));
// 添加一个圆柱体
geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height),hints));
// 添加一个太空舱
geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(8.0f,0.0f,0.0f),radius,height),hints));
return geode.get();
}
//--------------------------------------------------------------------------------
int main()
{
// 创建Viewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group>root = new osg::Group();
// 添加到场景
root->addChild(createShape());
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}