基本几何图元

来源:互联网 发布:密钥算法 加密算法 编辑:程序博客网 时间:2024/04/27 23:47

1. 基础绘制方法

在 OSG 当中所有的加入到场景的数据都会加入到一个 Group 当中,而几何图元做为一种需要绘制的对象而非模型也有一个类专门组织, 这个类就是osg::Geode, 该类的作用就是组织一些绘制的对象, 然后传给Group。如图 4.1 所示。
这里写图片描述

从图上可以看出所有基本的绘制功能完成后都会把结点汇集在一个 osg::Geode 当中,然后该 osg::Geode 再自己加入到 root 中完成所有子结点的绘制

1.1 绘制正方形

现在首先来看一些 OSG 中的最基本的绘制路数。下面我们要绘制一个正方形,绘制有色彩,未贴图。首先我们必须要申请一个 osg::Geometry,把这个 Geometry 加入到 Geode 就可以了。 在这个 Geometry 中要设置一些元素,最基本的是顶点 Vertex,颜色 color,以及顶点的关联方式和法线 normal.就可以了。如图 4.2 所示。
这里写图片描述

#ifdef _DEBUG#pragma comment(lib,"osgd.lib")#pragma comment(lib,"osgDBd.lib")#pragma comment(lib,"osgViewerd.lib")#pragma comment(lib,"OpenThreadsd.lib")#pragma comment(lib,"osgGAd.lib")#else#pragma comment(lib,"osg.lib")#pragma comment(lib,"osgDB.lib")#pragma comment(lib,"osgViewer.lib")#pragma comment(lib,"OpenThreads.lib")#pragma comment(lib,"osgGA.lib")#endif#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>//函数声明,绘制该正方体的代码都在这一个函数当中,返回的是 osg::Node 类型。osg::ref_ptr<osg::Node> createQuad() ;void main(){    osgViewer::Viewer viewer;    osg::Group * root = new osg::Group() ;    root ->addChild(createQuad().get()) ;    viewer.setSceneData(root);    viewer.realize();    viewer.run();}osg::ref_ptr<osg::Node> createQuad(){    //申请了一个几何体结点    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;    //首先定义四个点    osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;    geom->setVertexArray( v.get() );    v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );    v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );    v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );    v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );    //定义颜色数组    osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;    geom->setColorArray( c.get() );    geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );    //定义法线    osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;    geom->setNormalArray( n.get() );    geom->setNormalBinding( osg::Geometry::BIND_OVERALL );    n->push_back( osg::Vec3( 0.f, -1.f, 0.f ) );    //设置顶点关联方式    geom->addPrimitiveSet(    new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );    //几何组结点    osg::ref_ptr<osg::Geode> geode = new osg::Geode;    geode->addDrawable( geom.get() );    return geode.get();}

2. 所有可绘制图元

下面例举所有可绘制的几何图元:POINTS[点],LINES[线],LINE_STRIP[线带],LINE_LOOP[闭合线段],TRIANGLES[三角形],TRIANGLE_STRIP[三角带],TRIANGLE_FAN[三角扇],QUADS[四方块],QUAD_STRIP[四方块带],POLYGON[多边形],在这里我们要以封闭的直线为例来说明如何设置线宽属性。

2.1 绘制线宽

在 OSG 中设置直线线宽的专门有一个函数来管理,叫做 LineWidth,它本身属于状态与属性类别中的类。事实上也是从那里派生而来。所有设置状态的操作都与此类似。

#ifdef _DEBUG#pragma comment(lib,"osgd.lib")#pragma comment(lib,"osgDBd.lib")#pragma comment(lib,"osgViewerd.lib")#pragma comment(lib,"OpenThreadsd.lib")#pragma comment(lib,"osgGAd.lib")#else#pragma comment(lib,"osg.lib")#pragma comment(lib,"osgDB.lib")#pragma comment(lib,"osgViewer.lib")#pragma comment(lib,"OpenThreads.lib")#pragma comment(lib,"osgGA.lib")#endif#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>#include <osg/LineWidth>//函数声明,绘制该正方体的代码都在这一个函数当中,返回的是 osg::Node 类型。osg::ref_ptr<osg::Node> createQuad() ;void main(){    osgViewer::Viewer viewer;    osg::Group * root = new osg::Group() ;    root ->addChild(createQuad().get()) ;    viewer.setSceneData(root);    viewer.realize();    viewer.run();}osg::ref_ptr<osg::Node> createQuad(){    //申请了一个几何体结点    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;    osg::ref_ptr <osg::LineWidth> LineSize = new osg::LineWidth;    LineSize ->setWidth (10.0) ;    geom->getOrCreateStateSet()->setAttributeAndModes(LineSize.get (),osg::StateAttribute::ON);    //首先定义四个点    osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;    geom->setVertexArray( v.get() );    v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );    v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );    v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );    v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );    //定义颜色数组    osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array;    geom->setColorArray( c.get() );    geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX );    c->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );    c->push_back( osg::Vec4( 0.f, 1.f, 0.f, 1.f ) );    c->push_back( osg::Vec4( 0.f, 0.f, 1.f, 1.f ) );    c->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );    //定义法线    osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;    geom->setNormalArray( n.get() );    geom->setNormalBinding( osg::Geometry::BIND_OVERALL );    n->push_back( osg::Vec3( 0.f, -1.f, 0.f ) );    //设置顶点关联方式    geom->addPrimitiveSet(        new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 0, 4 ) );    //几何组结点    osg::ref_ptr<osg::Geode> geode = new osg::Geode;    geode->addDrawable( geom.get() );    return geode.get();}

3. 内置几何类型

如同 OpenGL 一样,OSG 同样有一套内置几何类型,这些几何类型都在类 osg::Shape 中,这些 shape 本身都可以本当成一个 Draw 结点加入到 geode 中,然后再人 geode 中添加到 root 里进行渲染。
形状共有九种,分别为:osg::Box[盒子],osg::Capsule[胶囊形],osg::CompositeShape[组合型],osg::Cone[圆锥形],osg::Cylinder[圆柱形],osg::HeightField[高程形],osg::InfinitePlane[有限面],osg::Sphere[球形],osg::TriangleMesh[三角蒙皮]。
下面来看一下这些内置几何类型的渲染过程,如图 4.5 所示。

这里写图片描述

#ifdef _DEBUG#pragma comment(lib,"osgd.lib")#pragma comment(lib,"osgDBd.lib")#pragma comment(lib,"osgViewerd.lib")#pragma comment(lib,"OpenThreadsd.lib")#pragma comment(lib,"osgGAd.lib")#else#pragma comment(lib,"osg.lib")#pragma comment(lib,"osgDB.lib")#pragma comment(lib,"osgViewer.lib")#pragma comment(lib,"OpenThreads.lib")#pragma comment(lib,"osgGA.lib")#endif#include <osgDB/ReadFile>#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>#include <osg/ShapeDrawable>#include <osg/Shape>osg::ref_ptr<osg::Node> createShape() ;void main(){    osgViewer::Viewer viewer;    osg::Group * root = new osg::Group() ;    root ->addChild(createShape().get()) ;    viewer.setSceneData(root);    viewer.realize();    viewer.run();}osg::ref_ptr<osg::Node> createShape(){    //几何组结点    osg::ref_ptr<osg::Geode> geode = new osg::Geode;    float radius = 0.08f;    float height = 0.1f;    osg::TessellationHints* hints = new osg::TessellationHints;    hints->setDetailRatio(0.5f);    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(0.2f,0.0f,0.0f),2*radius),hints));    geode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3(0.4f,0.0f,0.0f),radius,height),hints));    geode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3(0.60f,0.0f,0.0f),radius,height),hints));    geode->addDrawable(new osg::ShapeDrawable(new osg::Capsule(osg::Vec3(0.80f,0.0f,0.0f),radius,height),hints));    return geode.get();}

参考书:FreeSouth的《QpenSceneGraph程序设计》