目录
〇、 提要:
《OSG快速入门指导》 下载地址
一 、Geometry 概述
osg::ref_ptr<osg::Node> createSceneGraph()
{
// 创建一个用于保存几何信息的对象
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 ) );
// 向 Geode 类添加几何体(Drawable)并返回 Geode
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable( geom.get() );
return geode.get();
}
1. 操作方法
- 创建顶点、颜色、法线的数组
- 创建osg::Geometry ,a.顶点、颜色、法线放入Geometry b.osg::DrawArrays指定绘制方式
- osg::Geode 场景实例化,几何信息放入 节点 中
2.向量与数组类
类 | 说明 | 用途 |
---|---|---|
osg::Vec2 | 二维浮点数组 | 2D纹理 |
osg::Vec3 | 三维浮点数组 | 顶点、法线数据 |
以下是std::vector<>版本 | — | — |
osg::Vec2Array | vec2的数组 | 纹理坐标数组 |
osg::Vec3Array | vec3的数组 | 顶点数组 |
osg::Vec4Array | vec4的数组 | 颜色数组 |
提示:vector的用法 resize() operator[] 可以减少重新分配内存
3.Drawable类 - Geometry
- 用于保存渲染数据
- Drawable是一个无法直接实例化的虚基类
Drawable 子类
- Geometry
Geometry函数 | OpenGL对应函数 | 说明 |
---|---|---|
设置VBO数据(相当于) | — | — |
setVertexArray | glVertextPointer() | 存入顶点,说白了就是核心的VAO+VBO |
setColorArray | glColorPointer() | 存入颜色 |
setNormalArray | glNormalPointer() | 存入向量 |
分行 | 指定其他变量和顶点是否在一行 | — |
setColorBinding | setColorBinding(osg::Geometry::BIND_PER_VERTEX) | 相当于Core模式下,在一行中 |
setNormalBinding | setColorBinding(osg::Geometry::OVERALL) | 相当于Core模式下,在每一行都有 |
画 | — | — |
addPrimitiveSet() | addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) ); | 设置渲染方式 |
- addPrimitiveSet(osg::PrimitiveSet*) 和 osg::DrawArrays
geom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
解释:
addPrimitiveSet(↓)
a. osg::DrawArrays(QUADS)–按照顺序画方形
b. osg::DrawElementsUByte(QUADS)–按照指定顺序画方形
c. osg::DrawElementsUByte(POINTS)–按照指定顺序画点
这个就是最重要的那句–画
4.PrimitiveSet 类图
类型 | ||
---|---|---|
DrawArrays | 按照顺序绘制 | DrawArrays(mode) |
DrawElementsUInt | 按照指定点绘制 |
DrawArrays mode类型
OSG | GL |
---|---|
osg::PrimitiveSet::POINTS | GL_POINT |
osg::PrimitiveSet::LINES | GL_LINES |
二、叶节点(Geode)
- 叶节点(Geode)不再有子节点了
- 保存几何(Geometry)以便渲染
- Geode::addDrawable(Drawable–Geometry)
三、组节点(osg::Group)
提要:Group 定义了针对子节点的接口,所有派生自Group的节点都支持子节点 (Geode是例外,他没有Group属性)
1 子接口 – 来自osg::Group
内部数据: std::vector< ref_ptr > child
class Group:public Node
{
//内部数据
std::vector< ref_ptr<Node> > child;
//增 删 改 查
bool addChild(Node*);
bool removeChild(Node*);
bool replaceChild(Node*);
bool containChild(Node*);
//个数
unsigned int getNumChildren();
}
2 父接口–来自osg::Node
内部列表:std::vector<Group*> ParentList;
因为只是引用,不用管理析构,所有就是普通指针
class Node: public Object
{
//定义类型
typedef std::vector<Group*> ParentList;
//查询
ParentList& getParents();
Group* getParent(unsigned int I);
}
对比
类型 | 父接口-来自Node | 子接口-来自Group |
---|---|---|
存储 | std::vector<Group*> ParentList ParentList parents | std::vector< ref_ptr<Node> > child |
增 删 改 | 无 | bool addChild(Node*); bool removeChild(Node*); bool replaceChild(Node*); |
查 | bool containChild(Node*) | ParentList& getParents(); Group* getParent(unsigned int I); |
typedef std::vector<Group*> ParentList;
a. 子节点不需要管理父节点内存,直接保存普通指针,因为只有父节点可以释放子节点
b. 子节点保存了多个父节点
c. 这个指针是自动清除管理的
d. 通常:一个节点有一个父节点 (getNumParents( )==0),获取 getParent(0)
3.变换节点(Transform)
Transform | Matrix | |
---|---|---|
类名 | osg::Transform osg:: MatrixTransform osg::PositionAttitudeTransform | osg::Matrix |
功能 | 节点:记录所有变换 | 矩阵-计算工具 |
3.1 Matrix 计算工具
osg::Matrix = 4×4 矩阵
Matrix 本身就是一个4×4 矩阵(16个float),是用来纯计算的
- 矩阵赋值
osg::Matrix m;
m(0,1) = 0.f; //第0行 第1列
m(1,2)= 0.f; //第1行 第2列
- 向量×矩阵 矩阵×矩阵
osg::Matrix T;
T.makeTranslate(x,y,z);
osg:Matrix R;
R.makeRotate(angle,axis);
Vec3 vPrime= v*R*T;
OSG和OpenGL的矩阵乘法对比
OSG | OpenGL |
---|---|
左乘 | 右乘 |
v2= v1×R×T; | v2 = T×R×v1 |
OSG右乘 | 按照数学乘法 |
- 矩阵右乘,导致节点连接方式变化
图示 | 说明 |
---|---|
![]() | 首先,创建一个移动的MT的MatrixTransform,产生了移动节点 之后,创建一个旋转的MR的MatrixTransform,产生了旋转节点,把这个节点挂在移动节点下 最后,将Geode挂到旋转节点下 |
3.2 矩阵变换节点(MatrixTransform)
类名 | 类型 | 说明 | |
---|---|---|---|
MatrixTransform | 节点 | Reference - 自然支持 ref_ptr<> | 就是为了接住matrix |
Matrix | 计算工具 | 普通类,不支持智能指针 | 就是为了计算 |
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
osg::Matrix m;
m.setTtranslate(x,y,z);
mt->setMatrix(m);
Matrix::set函数 ,按照列传入;
osg::Matrix m;
m.set( 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
10.f, 0.f, 0.f, 1.f );
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
mt.setMatrix(m);
3.3 位置属性变换节点(PositionAttitudeTransform)
猜测:
MatrixTransform | PositionAttitudeTransform |
---|---|
是AutoCAD中的Matrix矩阵 | 是Bentley中的 yaw pitch roll 的方式 |
-
四元数 osg::Quat
转多少度,绕着哪个轴 -
绕着一个轴转
osg::Quat q0(弧度,轴);
Float angle(M_PI*0.5f);
osg::Vec3 axis(0.7f,0.7f,0.f);//倾斜的轴
osg::Quat q0(angle,axis);
- 绕着 yaw pitch roll 转
osg::Quat q0(弧度yaw,弧度pitch,弧度roll,轴yaw,轴pitch,轴roll);
osg::Vec3 yawAxis(0.f,0.f,1.f);
osg::Vec3 pitchAxis(1.f,0.f,0.f);
osg::Vec3 rollAxis(0.f,1.f,0.f);
osg::Quat q1(yawRad,yawAxis,pitchRad,pitchAxis,rollRad,rollAxis);
四 LOD 细节层次节点
- LOD可以加子节点
-
LOD可以控制子节点的显示
解释:
上图:LOD有三个子节点,当观察点的距离符合第一个子节点的有效范围时,才显示 -
代码
osg::ref_ptr<osg::Geode> geode1;
osg::ref_ptr<osg::Geode> geode2;
osg::ref_ptr<osg::LOD> lod = new osg::LOD;
lod->addChild(geode1.get(),0.f,1000.f);
lod->addChild(geode2.get(),950.f,1200.f);
解释:
a.当视点与这个子节点距离小于1000个单位时显示
b.LOD 是针对每一个子节点可以指定范围
五 开关节点(osg::Switch)
osg::ref_ptr<osg::Switch> sw= new osg::Switch;
sw->addChild(group0.get(),true);
sw->addChild(group1.get(),false);
sw->addChild(geode.get(),false);