ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

osg学习-1《绘制基本单元》

2022-08-21 10:37:25  阅读:203  来源: 互联网

标签:1.0 0.0 osg 数组 顶点 绘制 单元


 1 基于场景的图形绘制

        OpenSceneGraph简称OSG是非常著名的三维可视化,在绘制复杂场景方面比VTK更有优势。在OSG中存在两棵树,即场景树和渲染树。场景树是一棵由Node组成的树,这些Node可能是矩阵变换、状态切换或真正的可绘制对象,它反映了场景的空间结构,也反映了对象的状态。

       OSG程序使用组节点来组织和排列场景中的几何体。场景树通常包括了多种类型的节点,以执行各种各样的用户功能。OSG主要包含3大基本类节点,即Node、 Geode(叶节点)和 Group(组节点)。OSG中其他的大部分节点都继承自Group节点,少部分继承自Node节点及 Geode节点,但Geode和Group均继承自Node节点。

2 场景基本绘图类

在OSG中创建几何体的方法比较简单,通常有3种处理几何体的手段,一是使用松散封装的OpenGL绘图基元;二是使用OSG中的基本几何体:三是从文件中导入场景模型。

(1)向量与数组类

在OSG中定义了大量的类来保存数据,数据通常是以向量的形式来表示的,向量数据主要包括顶点坐标、纹理坐标、颜色和法线等。例如,定义osg:Vec2来保存纹理坐标:定义osg:Vec3来保存顶点坐标和法线坐标;定义osg:Vec4保存颜色的RGBA值。osg:Vec2、osg:Vec3和osg:Vec4是分别用来保存向量的二维数组、三维数组和四维数组,这些类不仅能够保存各种数据,还提供了向量的基本运算机制,如加、减、乘、除四则元算、点积和单位化等相关的操作。

(2)Drawable

Drawable类是一个纯基类,无法实例化。作为可绘制对象基类的osg::Drawable类,它派生了很多类,

(3)PrimitiveSet

osg:PrimitiveSet类继承自osg:Object虚基类,但它不具备一般场景中的特性。osg:PrimitiveSet类的继承关系图 

 

该类主要松散封装了OpenGL的绘图基元,通过指定绘图基元来指定几何体顶点将采用哪一种或几种基元绘制。常用的绘图基元包括如下几种:

POINTS-GL POINTS  //绘制点

LINES GL LINES  //绘制线

LINE STRIP GL LINE STRIP  //绘制多段线

LINE_LOOP-GL LINE LOOP  //绘制封闭线

TRIANGLES-GL_TRIANGLES  //绘制一系列的三角形(不共用顶点)

TRIANGLE_STRIP -GL_TRIANGLE STRIP  //绘制一系列三角形(共用后面的两个顶点)

TRIANGLE FAN =GL TRIANGLE FAN   //绘制一系列三角形,顶点顺序与上一条语句绘制的三角形不同

QUADS GL_QUADS  //绘制四边形

QUAD_STRIP GL QUAD STRIP//绘制一系列四边形

POLYGON-GL POLYGON  //绘制多边形

从osg:PrimitiveSet类的继承关系图可以看出,它的派生类主要有如下3个:

☑osg:DrawArrays类。继承自osg:PrimitiveSet,,它封装了glDrawArrays(顶点数组绘图命令,用于指定顶点和绘图基元。

☑osg:DrawElements类。它又派生出3个子类,分别是osg:DrawElementsUByte、osg:DrawElementsUShort和osg:DrawElementsUInt,封装了glDrawElements(的指令,可以起索引的作用,在后面的示例中会用到。

☑osg:DrawArrayLengths类。它的主要作用是多次绘制,即多次调用glDrawArrays(,且每次均使用不同的长度和索引范围,在绘制过程中用得不是很多。

DrawArrays的基本用法如下:

osg::DrawArrays::DrawArrays(GLenum mode,GLint first,GLsizei count )

/*参数说明:第一个参数是指定的绘图基元,即前面所列举的常见绘图基元:第二个参数是指绘制几何体的第一个顶点数在指定顶点的位置数:第三个参数是使用的顶点的总数*/

还有一点值得注意的是,虽然osg:PrimitiveSet类提供与OpenGL一样的顶点机制,但是在内部渲染上还是有一定区别的。根据渲染环境的不同,渲染的方式也是不一样的,可能会采用顶点、顶点数组、显示列表或者glBeginO/glEndO)来渲染几何体,继承自Drawable类的对象(如Geometry)在默认条件下将使用显示列表。其中,osg:Drawable:setUseDisplayList(alse)用于手动禁止使用显示列表。

还有一种比较特殊的情况,如果设置BIND PER PRIMITIVE绑定方式,那么OSG将采用glBeginO/glEndO函数进行渲染。因为在设置使用绑定方式为BIND_PER PRIMITIVE后,它就为每个独立的几何图元设置一种绑定属性。

 

3 基本几何体绘制

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

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

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

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

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

下面一个例子展示了绘制四边形的过程,关键在于构建四边形几何体的过程,createQuad()函数。

主要步骤包括,

(1)创建叶节点对象,

(2)创建几何对象,

(3)创建定点数组,给几何对象设置顶点数据

(4)创建纹理坐标,给几何对象设置纹理坐标

(5)创建颜色数组,给几何对象设置颜色数组

(6)创建法线数组,给几何对象设置法线数组,并设置绑定方式

(7)给几何对象添加图元,设置绘图方式

(8)添加几何对象到叶节点

// osg_hello.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <iostream>

#ifdef _WIN32
#include <windows.h>
#endif

#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgUtil/Optimizer>

/// <summary>
/// 创建一个四边形节点
/// </summary>
/// <returns></returns>
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(0, vt.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));

    //设置额色数组
    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::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4)); 
    
    //添加到叶节点
    geode->addDrawable(geom.get());

    return geode.get();
}


int main()
{
    // 创建Viewer对象,场景浏览器创建一个节点。viewer->setSceneData(root.get())viewer->realize(viewer - un();
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

    //创建场最组节点
    osg::ref_ptr<osg::Group> root = new osg::Group();

    //读取牛的模型
    //osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("../../test/cow.osg");
    
    //创建可绘制模型
    auto node = createQuad();

    //添加到场景
    root->addChild(node.get());

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

    //设置场景数据
    viewer->setSceneData(root.get());

    //设置渲染的窗口
    //viewer->setUpViewAcrossAllScreens();  //default on all screens
    viewer->setUpViewOnSingleScreen(0);

    //开始渣染
    viewer->run();

    return 0;
}


渲染效果如下

 参考资料,

《openscenegraph三维渲染引擎编程指南》4.1--4.2.2节

标签:1.0,0.0,osg,数组,顶点,绘制,单元
来源: https://www.cnblogs.com/oliver2022/p/16609422.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有