OSG基础知识

您所在的位置:网站首页 osg什么意思 OSG基础知识

OSG基础知识

2023-09-10 06:18| 来源: 网络整理| 查看: 265

本文主要讲解OSG中一些枯燥的空间数学方面知识,及其一个重要的数据结构-数组,和其内存管理机制-智能指针

一、基本数学组件

1.1二维与多维向量

构建一个单精度浮点类型的三维向量vector是:osg::Vec3f  vector

构建一个双精度浮点类型的四维向量vector是:osg::Vec4d  vector

以osg::Vec3f 为例来实现各种类型的向量运算

osg::Vec3 v1;

v1.set(1.0, 1.0, 1.0)  //设置向量的值

v1.normalize()          //对向量进行归一化处理

float x=v1[0]              //获取分量的值,即获得第一个元素的值

osg::Vec3 v2(2.0, 5.0, 8.0)     //通过构造函数赋值,直接设置三个分量的值

v2 *= 0.5                                 //向量的数乘运算

v2 =osg::Vec3(1.0, 0.0, -2.0) -v2 //向量的四则运算中的减法

float  distance = (v1 -v2 ).length()   //求取两向量的距离

float  dotproduct  = v1 * v2         //向量点乘

osg::Vec3   crossProduct = v1 ^ v2  //向量叉乘

1.2四元数

四元数的优势在于:它可以表达物体绕任意向量轴的旋转,并且和欧拉角度旋转与旋转矩阵的方法相比,其效率效高,操作也更加灵活

四元数由三个复数和一个实数组成

设置沿x轴逆时针旋转90度的代码

osg::Quat quat(psg::PI_2,  osg::Vec3(1.0,  0.0,  0.0);

其中osg::PI_2是OSG中的预定义宏,数学上表示为pi/2

osg::Quat  quat(osg::DegreesToRadians(90.0),  osg::Vec3(1.0,  0.0,  0.0);

和上一行代码表示的含义相同,其第一个参数直接使用角度值而非弧度值来表达旋转角度,应用到一个函数osg::DegreesToRadians()

osg::Quat  quat3 = quat1 * quat2 

它表示这两次旋转结果的叠加之和

osg::Vec3  vec;

double angle;

quat.getRotate(angle,vec );   //通过getRotate()函数获取四元数包含的旋转动作内容,即它所依据的旋转轴和旋转角度

double  degree = osg::RadiansToDegrees(angle);  //将弧度值转换为角度值

1.3矩阵

osg::Matrix   mat1;   //定义一个单位矩阵

mat1.makeRotate(osg::Quat(osg::PI_2, osg::Vec3(1.0, 0.0, 0.0));     //旋转,沿x轴逆时针旋转90度

mat1.preMultTranslate(osg::Vec3d(0.0,  1.0, 0.0 ));                     //沿y方向平移

double   a11 =mat1 (1,1);  // 获取第二行和第二列的元素

osg::Matrix   mat2; 

mat2.makeScale(osg::Vec3d(1.0, 1.0, 2.0));  // 设置为缩放矩阵

osg::Matrix   mat3; 

mat3 = mat2 * mat1 ;    //    级联两个矩阵

osg::Vec3d  vec(0.0, 0.0, 1.0);

vec = vec * mat3;    //将矩阵用于向量的空间变换

其最终的效果为几个动作叠加:先执行Z方向的放大,在执行X方向的旋转,最后执行Y方向的平移。

osg::Matrix   mat3; 

mat3 = osg::Matrixd::scale(osg::Vec3d(1.0, 1.0, 2.0)) *  osg::Matrixd::rotate(osg::Quat(osg::PI_2,osg::Vec3(1.0, 0.0, 0.0))  *   osg::Matrixd::translate(osg::Vec3d(0.0, 1.0, 0.0));

 

osg::Vec3d  vec(0.0, 0.0, 1.0);

vec = vec * mat3; 

这段代码和上面的代码作用是相同的,不同的是其书写方式,以及用到了新的类的函数,新类为osg::Matrixd

1.4包围体

OSG中支持两种类型的包围体,即包围球和轴对称包围盒,它们主要用于场景图形结点层次的实现。包围球和包围盒都是不和绘制的对象,它们值负责记录一些必要的属性信息(如中心,包围半径等),同时用于一些必要的数学运算,并且,包围体中心表达的往往不是世界坐标系下的物体中心,而是取决于它处于场景树中的哪一级局部坐标系。

创建一个单精度的包围球:

osg::BoundingSphere   bs(osg::Vec3(0.0, 0.0, 0.0), 1.0f)   //第一个获得中心点,第二个获得半径长度

创建一个包围盒

osg::BoundingBox  bb(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(1.0, 2.0, 3.0))  //第一个参数为最小端点,第二个参数为最大端点

二、数组对象

2.1数据数组(基类为Array)

这类数组数据类型为单精度或双精度的浮点数据,包括数值、多维向量等,主要用于OpenGL定点坐标,颜色,纹理坐标等属性数组的设置

为了使Array真正具备保存多种类型的数据的能力,需要定义一个模板类并接受不同的模板参数,同时还需要使用std:::vector向量组来记录数组中的多个元素信息。

下面快速构建一个Vec3类型的数据数组,并使用标准模板库向量组的操作方法对其进行各种操作

//定义三维向量数组

osg::Vec3Array*  array  = new  osg::Vec3Array;

//向数组中传入数据

array->push_back(osg;:Vec3(1.0,0.0,0.0));

array->push_back(osg;:Vec3(1.0,-1.0,2.0));

//这两种方法都可以获取数组的某个元素

osg::Vec3&  element1 = (* array)[0];

osg::Vec3   element2=array->at(1);

//使用迭代器遍历数组

for(osg::Vec3Array::iterator  itr=array->begin(); itr!=array->end(); ++itr)

{

       osg::Vec3&  vec  =*itr:

      ...

}

2.2数据索引数组

此类数组的元素一般是整数类型,索引数组在绘制OpenGL集合图元时尤为常见

索引数组类派生自Array类,名为IndexArray,它除了继承Array类的所有成员函数之外还定义了自己的成员。

其基本操作方法与数据数组的操作并无本质区别。

三、内存管理机制

OSG中使用场景树结构来管理整个三维世界,如果需要绘制一个规模宏大的场景,则是必要创建和维护众多的结点对象。二这一场景不在继续渲染时,对于传统的开发流程来说,就需要手动卸载其中所有的节点,释放所有已分配的内存空间,在进行下一步的工作。。如果未能释放所有场景对象,则会产生内存泄漏,OSG提供一种“垃圾收集”机制,通过“内存引用计数”的形式来管理场景中的节点和绘制体,每个场景中的对象都维护着一个引用计数值,当它被其他对象使用时,引用计数值加1,反之减一。当一个对象的引用计数为0时,它将自动从内存中释放。

3.1智能指针

osg::ref_ptr类

使用如下方法来定义一个使用智能指针来管理的参照对象

osg::Geode*  geode=new  osg::Geode;

osg::ref_ptr  geodePtr=geode;//创建一个新的ref_ptr对象,并将一个新建的Geode指针分配给它。

osg::Geode*  obj1 = *geodePtr;    //获取Geode指针

groupNode->addChild(geodePtr);//   获取指针并传递给其他函数

//在这个过程中,如果超出了geodePtr的生命周期范围,南无这个智能指针变量在析构的过程中会自动将Geode对象的引用计数值减1,一共引用了一次,运行结束后减1,则该结点变量会被自动卸载。

3.2参考对象

参考对象是引用计数和对象自动卸载的实际执行者。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3