OSG学习笔记-基本几何体的绘制(3-2)

3.2 基本几何体的绘制

​ 本节的例子主要是基本图形的绘制,如线段、三角形、圆及四边形等。

​ 我们知道任何复杂的东西都是由一些简单的部分组合构成的,对于OSG创建的场景和对象也同样如此,它们是有简单的图元(我们把构成3D对象的构件成为图元)按照一定的方式排列和组合而成的,OSG中的所有图元都是一维或二维对象,包括单个的点、直线和复杂的多边形。

3.2.1 几何体类

​ osg::Geometry继承自osg::Drawable。它的主要作用是对指定绘制几何体的顶点数及对数据的解析,主要提供了如下3大类方法:

​ (1)指定向量数据。如顶点数据、纹理坐标及颜色等一系列向量数据,可以通过下面的几个函数来实现。

  • 函数说明
    void setVertexArray(Array* array)设置顶点数组
    void setVertexData(const ArrayData& arrayData)设置顶点数组数据
    void setVertexIndices(IndexArray* array)设置顶点索引数组
    void setNormalArray(Array* array)设置法线数组
    void setNormalData(const ArrayData& arrayData)设置法线数组数据
    void setNormalIndices(IndexArray* array)设置法线索引数组
    void setColorArray(Array* array)设置颜色数组数据
    void setColorData(const ArrayData& arrayData)设置颜色数组数据
    void setColorIndices(IndexArray* array)设置颜色索引数组
    void setTexCoordArray(unsigned int unit,Array*)设置纹理坐标数据
    void setTexCoordData(unsigned int index,const ArrayData& arrayData)设置纹理坐标数据
    void setTexCoordIndices(unsigned int unit,IndexArray*)设置纹理坐标数据

​ (2)设置绑定方式。数据绑定主要有两项,即法线和颜色,可以通过下面的两个函数来实现。

  • 函数说明
    void setNormalBinding(AttributeBinding ab)设置法线绑定方式
    void setColorBinding(AttributeBinding ab)设置颜色绑定方式

​ 绑定方式主要有下面几种:

  • 宏名称说明
    BIND_OFF不启用绑定
    BIND_OVERALL绑定全部的顶线
    BIND_PER_PRIMITIVE_SET单个绘图基元绑定
    BIND_PER_PERMITIVE单个独立的绘图基元绑定
    BIND_PER_VERTEX单个顶点绑定

​ (3)数据解析。当指定了各种向量数据和绑定方式之后,采用何种方式来渲染几何体就是最为关键的。不同的方式下,渲染出来的图形是不一样的,即使效果一样,可能面数或内部机制等也是有区别的。数据解析主要通过如下函数来指定:

​ bool addPrimitiveSet(PrimitiveSet* primitiveSet);

​ // osg::PrimitiveSet是无法初始化的虚基类,因此这里主要是调用它的子类来指定数据渲染,最常用的就是前面介绍的osg::DrawArrays,用法比较简单,初始化一个对象实例,参数说明见前面osg::DrawArray类

​ 通过前面的讲述可知,绘制并渲染几何体主要有如下3大步骤:

(1)创建各种向量数据,如顶点、纹理坐标、颜色和法线等。需要注意的是,添加顶点数据时主要按照逆时针顺序添加,以确保背面剔除(backface culling)的正确。

(2)实例化一个几何体对象(osg::Geometry),设置顶点坐标数组、纹理坐标数组、颜色数组、法线数组、绑定方式及数据解析。

(3)加入叶节点绘制并渲染

3.2.2 基本几何体绘制示例

基本几何体绘制(osg::Geometry)示例演示了创建一个几何体的过程,示例中创建了最简单的四边形。通过该示例学会如何创建简单的几何体。

#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Group>
#include<osg/Geode>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
// 创建一个四边形节点
osg::ref_ptr<osg::Node>createQuad()
{
	// 创建一个叶节点对象
	osg::ref_ptr<osg::Geode> geode = new osg::Geode();

    // 创建一个几何体对象
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();

    // 创建顶点数组,注意顶点数组的添加顺序是逆时针
    osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
    
    // 添加数据
    v->push_back(osg::Vec3(0.0f,0.0f,0.0f));
    v->push_back(osg::Vec3(1.0f,0.0f,0.0f));
    v->push_back(osg::Vec3(1.0f,0.0f,1.0f));
    v->push_back(osg::Vec3(0.0f,0.0f,1.0f));

    // 设置顶点数据
    geom->setVertexArray(v.get());

    // 创建纹理坐标
    osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();
    vt->push_back(osg::Vec2(0.0f,0.0f));
    vt->push_back(osg::Vec2(1.0f,0.0f));
    vt->push_back(osg::Vec2(1.0f,1.0f));
    vt->push_back(osg::Vec2(0.0f,1.0f));

    // 设置纹理坐标
    geom->setTexCoordArray(vt);
    
    // 创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array();
    vc->push_back(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
    vc->push_back(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
    vc->push_back(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
    vc->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));

    // 设置颜色数组
    geom->setColorArray(vc.get());

    // 设置颜色的绑定方式为单个顶点
    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

    // 创建法线数组
    osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
    nc->push_back(osg::Vec3(0.0f,-1.0f,0.0f));

    // 设置法线数组
    geom->setNormalArray(nc.get());
   
    // 设置法线的绑定方式为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

    // 添加图元,绘制基元为四边形
    geom->addPrimitiveSet(new osg::DrawArray(osg::PrimitiveSet::QUADS,0,4));

    // 添加到叶节点
    geode->addDrawable(geom.get());

    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(CreateQuad());

    // 优化场景数据
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());

    viewer->setSceneData(root.get());

    viewer->realize();

    viewer->run();

    return 0;
}

3.2.3 索引绑定几何体绘制示例

#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
// 创建一个四边形节点
osg::ref_ptr<osg::Node> createQuad()
{
	// 创建一个叶节点对象
    osg::ref_ptr<osg::Geode> geode = new osg::Geode();
    
    // 创建一个几何体对象
    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
    
    // 创建顶点数组
    osg::ref_ptr<osg::Vec3Array> v = new osg:: vec3Array();
    
    // 添加数据
    v->push_back(osg::Vex3(0.0f,0.0f,0.0f));
    v->push_back(osg::Vex3(1.0f,0.0f,0.0f));
    v->push_back(osg::Vex3(1.0f,0.0f,1.0f));
    v->push_back(osg::Vex3(0.0f,0.0f,1.0f));
    v->push_back(osg::Vex3(0.0f,-1.0f,0.0f));
    
    // 设置顶点数据
    geom->setVertexArray(v.get());
    
    // 创建四边形顶点索引数组,指定绘图基元为四边形,注意添加顺序
    osg::ref_ptr<osg::DrawElementsUInt>quad = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);
    
    // 添加数据
    quad->push_back(0);
    quad->push_back(1);
    quad->push_back(2);
    quad->push_back(3);
    
    // 添加到几何体
    geom->addPrimitiveSet(quad.get());
    
    // 创建三角形顶点索引数组,指定绘图基元为三角形,注意添加顺序
    osg::ref_ptr<osg::DrawElementUInt> triangle = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES,0);
    triangle->push_back(4);
    triangle->push_back(0);
    triangle->push_back(3);
    
    // 添加到几何体
    geom->addPrimitiveSet(triangle.get());
    
    // 创建颜色数组
    osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array();
    vc->push_back(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
    vc->push_back(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
    vc->push_back(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
    vc->push_back(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
    
    // 创建颜色索引数组
    osg::TemplateIndexArray<unsigned int ,osg::Array::UIntArrayType,4,4>* colorIndex = new osg::TemplateIndexArray<unsigned int ,osg::Array::UIntArrayType,4,4>();
    // 添加数据,注意添加数组顺序与顶点一一对应
    colorIndex->push_back(0);
    colorIndex->push_back(1);
    colorIndex->push_back(2);
    colorIndex->push_back(3);
    colorIndex->push_back(2);
    
    // 设置颜色数组
    geom->setColorArray(vc.get());
   
    // 设置颜色索引数组
    geom->setColorIndices(colorIndex);
    
    // 设置颜色的绑定方式为单个顶点
    geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
    
    // 创建法线数组
    osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();
    nc->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
    
    // 设置法线数组
    geom->setNormalArray(nc.get());
    
    // 设置返现的绑定方式为全部顶点
    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
    
    // 添加到叶子节点
    geode->addDrawable(geom.get());
    
    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(createQuad());
    
    osgUtil::Optimizer optimizer;
    optimizer.optimize(root.get());
    
    viewer->setSceneData(root.get());
    viewer->realize();
    viewer->run();
    
    return 0;
}
    

版权声明:本文为liangfei868原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。