OSG 开源教程
整理:荣明、王伟
北 京
2008 年 4 月
1
序
第一次接触 OSG 是在 2001 年,当时开源社区刚刚兴起,还没有现在这
么火。下载了 OSG 源码,但是在看了几个 Demo 之后,感觉没有什么特别之
处。时隔七年之后,我再次将目光投向 OSG,发现 OSG 确实有其独到之处,
很多 3D 效果已经不弱于甚至超过商业软件,有感于开源力量的巨大。但是,
与当前主流 3D 商业软件如 Vega、VegaPrime、VTree、Performer 等相比,
开源软件的缺点也很明显,其中文档缺乏可谓其致命弱点之一。开发者只
能从浩瀚的源码中,进行编程的学习,效率不高。
OSG 组织也意识到这一点,不断推出一些官方教程,网络上有很多 OSG
爱好者发布的心得和教程。我收集、整理了许多学习资料,其中美国海军
研究生院发布的 OSG 教程非常好,可 作为 OSG 的官方教程的一个很好补充。
它共有十一个专题,结合例子程序,一步步教你如何进行 OSG 的开发。我
将其编辑成一个较为完善的教材,供大家学习。在教材整理过程中,王伟
调试了源程序,对该书编辑和修订做了大量的工作;实验室的学生杨宇蒙、
冯锐、章仕锋、李永川和李益强阅读了本书,并提出了宝贵的修改意见,
在此一并表示感谢。
希望这本小册子能对大家学习 OSG 编程起到一定的帮助作用。
谢谢大家阅读本书!
荣 明
二 OO 八年四月于崔春园
(本书的资料全部来自互联网,仅供个人学习交流使用。感谢竹林小舍、array 翻译了 Navy 的教程。)
2
目录
1.使用Open Scene Graph几何 ..................................................................................................................... 1
1.1 背景 ................................................................................................................................................. 1
1.2 代码 ................................................................................................................................................. 1
2.使用StateSet产生有纹理的几何体 ......................................................................................................... 4
2.1 本章目标 ......................................................................................................................................... 4
2.2 背景 ................................................................................................................................................. 4
2.3 加载纹理,生成状态集合并将他们附加到节点上 ...................................................................... 6
3.使用Shape,改变state ............................................................................................................................. 8
3.1 本章目标 ......................................................................................................................................... 8
3.2 使用Shape类 ................................................................................................................................... 8
3.3 设置状态 ......................................................................................................................................... 9
4.更多的StateSet ...................................................................................................................................... 10
4.1StateSet如何工作 ......................................................................................................................... 10
4.2 例子及代码 ................................................................................................................................... 10
5.从文件中加载模型并放入到场景中 ....................................................................................................... 12
5.1 本章目标 ....................................................................................................................................... 12
5.2 加载几何模型并加入到场景中 .................................................................................................... 12
6.osg Text、HUD、RenderBins ................................................................................................................. 15
6.1 本章目标 ....................................................................................................................................... 15
6.2 摘要 ............................................................................................................................................... 15
6.3 代码 ............................................................................................................................................... 15
7.搜索并控制开关和DOF(自由度)节点(Finding and Manipulating a Switch and DOF Node) . 20
7.1 搜索场景图形中的一个有名节点 ................................................................................................. 20
7.2 按照“访问器”模式搜索有名节点 ................................................................................................. 22
8.使用更新回调来更改模型 ....................................................................................................................... 26
8.1 本章目标 ........................................................................................................................................ 26
8.2 回调概览 ........................................................................................................................................ 26
8.3 创建一个更新回调 ......................................................................................................................... 26
9.处理键盘输入 ........................................................................................................................................... 29
9.1 本章目标 ........................................................................................................................................ 29
9.2 GUI(图形用户接口)事件处理器: .......................................................................................... 29
9.3 简单的键盘接口类 ........................................................................................................................ 30
9.4 使用键盘接口类 ............................................................................................................................ 31
9.5 处理键盘输入实现更新回调 ........................................................................................................ 32
9.5.1 本节目标 ............................................................................................................................. 32
9.5.2 问题的提出 ......................................................................................................................... 32
9.5.3 解决方案 ............................................................................................................................. 33
10.使用自定义矩阵来放置相机(Positioning a Camera with a User-Defined Matrix) .......................... 36
10.1 本章目标 ...................................................................................................................................... 36
10.2 设置矩阵的方向和位置 .............................................................................................................. 36
10.3 声明一个用于设置相机的矩阵 ................................................................................................... 37
10.4 使用矩阵设置视口摄相机 ........................................................................................................... 38
3
11. 实现跟随节点的相机 ............................................................................................................................ 38
11.1 本章目标 ...................................................................................................................................... 38
11.2 概述 .............................................................................................................................................. 38
11.3 实现 .............................................................................................................................................. 39
11.4 环绕(始终指向)场景中节点的相机 ....................................................................................... 42
11.4.1 本节目标 ........................................................................................................................... 42
11.4.2 实现 ................................................................................................................................... 42
1
1.使用 Open Scene Graph 几何
本节涵盖了生成基本几何形状的一些方法。生成几何物体的方法有这么几种:在最底层对
OpenGL 基本几何进行松散的包装,中级是使用 Open Scene Graph 的基本形状,以及更高级一些的
从文件读取。这篇教程涵盖的是最低层的。这种方法弹性最大但最费力。通常在 Scene Graph 级别,
几何形状是从文件加载的。文件加载器完成了跟踪顶点的大部分工作。
1.1 背景
对一下几个类的简单解释:
Geode 类:
geode 类继承自 node 类。在一个 Scene Graph 中,node(当然包含 geode)可以作为叶子节点。
Geode 实例可以有多个相关的 drawable。
Drawable 类层次:
基类 drawable 是一个有六个具体子类的抽象类。
geometry 类可以直接有 vertex 和 vertex 数据,或者任意个 primitiveSet 实例。
vertex 和 vertex 属性数据(颜色、法线、纹理坐标)存放在数组中。既然多个顶点可以共享相
同的颜色、法线或纹理坐标,那么数组索引就可以用来将顶点数组映射到颜色、法线、或纹理坐标
数组。
PrimitiveSet 类:
这个类松散的包装了 OpenGL 的基本图形-POINTS,LINES,LINE_STRIP,LINE_LOOP,...,POLYGON.
1.2 代码
以下这节代码安装了一个 viewer 来观察我们创建的场景,一个‘group’实例作为 scene graph
的根节点,一个几何节点 ( geode)来收集 drawable,和一个 geometry 实例来关联顶点和顶点数据。
(这个例子中渲染的形状是一个四面体)
...
int main()
{
...
osgProducer::Viewer viewer;
osg::Group* root = new osg::Group();
osg::Geode* pyramidGeode = new osg::Geode();
osg::Geometry* pyramidGeometry = new osg::Geometry();
下一步,需要将锥体 geometry 和锥体 geode 关联起来,并将 pyramid geode 加到 scene graph
的根节点上。
pyramidGeode->addDrawable(pyramidGeometry);
root->addChild(pyramidGeode);