开发的预备知识
OpenSceneGraph开发时,需要调用各种各样的类方法,因此这里需要提前了解一些C++中的类的一些基本概念,可以参考这篇文章:一篇搞懂C++面向对象
向量
既有大小又有方向的量被称为向量
模长为1的向量被称为单位向量,n维向量的模长公式:
在OSG中坐标轴方向如图(V是在空间内的任意一个向量):
OSG中的向量类型
Byte类型就是char类型(字符类型),由上图可知,单精度浮点数Float类型的向量有两种定义方式。
向量(vector)对应的方法(以Vec3f类为例):
Vec3f() //默认构造函数,建立一个零向量
Vec3f(float x,float y,float z) //构造函数,直接设置向量的三个分量
Vec3f(const Vec2f& v2,float w) //构造函数,通过已知的二维向量和一个第三分量的值来构建
float operator*(const Vec3f& )const //执行两向量的点乘,并返回浮点数值
const Vec3f operator^(const Vec3f& )const //执行两向量的叉乘,并返回新的向量
float& operator[](unsigned int i) //获取向量中某一分量的值
float length()const //计算向量的模长
float length2()const //计算向量的模长的平方值
float normalize() //对向量进行归一化处理,即向量模长变为1,返回值为改变前的向量模长
四元数
图中i,j,k为虚数,也可以理解为x,y,z三条坐标轴,前面三个表示向量轴的坐标,后面一个w表示要旋转的角度。
四元数可以表达物体绕任意向量轴的旋转!!!!!!!
V是一个三维空间里任意的向量。
OSG中使用Quat类来表示四元数。下面是该类的一些方法:
Quat() //默认构造函数,构造一个没有旋转的四元数
Quat(double x,double y,double z,double w) //构造函数,直接设置四元数的四个分量
Quat(float angle,const Vec3f& axis) //构造函数,使四元数沿某个向量轴旋转一定角度
const Quat operator*(const Quat& )const //两个四元数相乘,相当于将两个旋转动作叠加
void makeRotate(
double angle, //使四元数沿某个向量轴旋转一定角度
double x,double y,double z)
void makeRotate(
double angle, //使四元数沿某个向量轴旋转一定角度
const Vec3f& vec)
void makeRotate(
float angle1,const Vec3f& axis1,
float angle2,const Vec3f& axis2,
float angle3,const Vec3f& axis3)
//使四元数沿3个坐标轴各自旋转一定角度
void makeRotate(
const Vec3f& vec1, //使四元数从向量轴vec1旋转到向量轴vec2
const Vec3f& vec2)
矩阵
OSG中表达矩阵的类是Matrix类(矩阵4x4),osg::Matrixf或osg::Matrix表示矩阵中的元素为float浮点数,osg::Matrixd表示矩阵中的数为double浮点数。
下面是该类的一些方法:
Matrix() //默认构造函数,这将构建一个单位矩阵
Matrix(
double,double,double,double, //构造函数,构建4x4的矩阵
double,double,double,double,
double,double,double,double,
double,double,double,double)
double operator()(int row,int col) //获取指定行列的矩阵元素
bool invert(const Matrixd& ) //生成指定矩阵的逆矩阵并传递给当前矩阵
Vec3d preMult(const Vec3d& ) //矩阵右乘一个行向量。常用于向量的空间变换
Vec3d preMultTranslate(const Vec3d& ) //矩阵右乘一个平移向量
Vec3d preMultRotate(const Vec3d& ) //矩阵右乘一个旋转向量
Vec3d preMultScale(const Vec3d& ) //矩阵右乘一个缩放向量
Martrixd operator*(const Matrixd& )const //矩阵相乘,叠加两个矩阵的效果
static Martrixd translate(const Vec3d& ) //定义一个平移矩阵
static Martrixd rotate(const Quat& ) //定义一个旋转矩阵
static Martrixd scale(const Vec3d& ) //定义一个缩放矩阵
static Matrixd frustum( //设置透视投影矩阵
double left,double right,
double bottom,double top,
double zNear,double zFar)
static Matrixd lookAt( //设置一个观察矩阵
const Vec3d& eye,
const Vec3d& center,
const Vec3d& up)
上面代码先执行了Z轴方向的放大,再执行了X方向的旋转,最后执行了Y轴的平移。
下面这段代码与上面的代码效果一样。
包围体
包围体主要用于记录一些必要的属性信息(如中心,包围半径等),分为包围球和包围盒。
包围球采用BoundingSphereImpl类来定义,下面是该类的一些方法:
BoundingSphereImpl( //构造函数,传入包围球中心和半径
const vec_type& center,
value_type radius)
void expandRadiusBy(const vec_type& ) //拓展包围球,使其能容纳指定的顶点,
//且在拓展时不会变动当前包围球的中心
void expandBy(const vec_type& ) //拓展包围球,使其能容纳指定的顶点,
//且在拓展时会变动当前包围球的中心
void expandRadiusBy(const BoundingSphereImpl& ) //拓展包围球,使其能容纳指定的包围球,
//且在拓展时不会变动当前包围球的中心
void expandBy(const BoundingSphereImpl& ) //拓展包围球,使其能容纳指定的包围球,
//且在拓展时会变动当前包围球的中心
void expandRadiusBy(const BoundingBoxImpl& ) //拓展包围球,使其能容纳指定的包围盒,
//且在拓展时不会变动当前包围球的中心
void expandBy(const BoundingBoxImpl& ) //拓展包围球,使其能容纳指定的包围盒,
//且在拓展时会变动当前包围球的中心
bool contains(const vec_type& )const //判断包围球是否含有某个顶点
bool intersects(const BoundingSphereImpl& )const
//判断包围球是否与另一个包围球相交
包围盒采用BoundingBoxImpl类来定义,该类的方法与包围球类似,这里就不一一赘述了。
下图最后一个方法是包围盒独有的:
数组对象
OSG中数组类的基类是Array。
下面是该类的一些方法:
Array(
Type arrayType,
GLint dataSize, //构造函数,三个参数为 数组类型,
//各元素分量数(即各个数据的大小),数据类型
GLenum datatype)
const GLvoid* getDataPointer() const //虚函数,获取数组第一个元素的地址指针
unsigned int getTotalDataSize() const //虚函数,获取数组元素的总大小,
//即元素个数*各元素分量数
unsigned int getNumElements() const //虚函数,获取数组元素的总个数
例程代码:
OSG内存管理机制
总结下来就是每个对象都类似于C++11里面的智能指针的共享指针一样,关于C++共享指针,可以参考这篇文章:C++11智能指针详解。
OSG中的智能指针
OSG中的智能指针类似于C++中的共享指针,OSG中智能指针形式:osg::ref_ptr<>
例程代码:
方法:
.get() //通过智能指针获得所指对象地址,智能指针仍然指向对象地址
.release() //真正获得了对象地址,且原智能指针已置空