一、环境搭建
1. 安装OSG
Windows
-
下载预编译包:从OSG官方网站下载
-
设置环境变量:
-
添加
OSG_ROOT
指向安装目录 -
将
%OSG_ROOT%\bin
添加到PATH
-
Linux (Ubuntu)
sudo apt-get install openscenegraph libopenscenegraph-dev openscenegraph-examples
macOS (使用Homebrew)
brew install open-scene-graph
2. 验证安装
osgversion # 查看版本
osgviewer cow.osgt # 测试示例模型
二、第一个OSG程序
1. 基本程序结构
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
int main() {
// 创建Viewer
osgViewer::Viewer viewer;
// 加载模型
osg::Node* node = osgDB::readNodeFile("cow.osgt");
// 设置场景数据
viewer.setSceneData(node);
// 运行查看器
return viewer.run();
}
2. 编译命令
Linux/macOS
g++ hello_osg.cpp -losgViewer -losgDB -o hello_osg
Windows (Visual Studio)
-
新建C++项目
-
配置包含目录:
$(OSG_ROOT)\include
-
配置库目录:
$(OSG_ROOT)\lib
-
添加依赖库:
osgViewer.lib;osgDB.lib;OpenThreads.lib
三、核心概念
1. 场景图结构
场景根(Group)
├─ 变换节点(MatrixTransform)
│ └─ 几何节点(Geode)
│ └─ 几何体(Geometry)
└─ 细节层次节点(LOD)
├─ 高细节模型
└─ 低细节模型
2. 基本组件
组件 | 说明 |
---|---|
osg::Node | 场景图中所有节点的基类 |
osg::Group | 可包含子节点的组节点 |
osg::Geode | 几何体节点(叶子节点) |
osg::Geometry | 存储几何数据(顶点、法线等) |
osgViewer::Viewer | 3D场景查看器 |
四、创建自定义场景
1. 创建简单几何体
osg::Geode* createQuad() {
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// 设置顶点
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(-1,0,-1));
vertices->push_back(osg::Vec3(1,0,-1));
vertices->push_back(osg::Vec3(1,0,1));
vertices->push_back(osg::Vec3(-1,0,1));
geom->setVertexArray(vertices);
// 设置颜色
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1,0,0,1)); // 红
colors->push_back(osg::Vec4(0,1,0,1)); // 绿
colors->push_back(osg::Vec4(0,0,1,1)); // 蓝
colors->push_back(osg::Vec4(1,1,0,1)); // 黄
geom->setColorArray(colors);
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
// 添加图元
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
geode->addDrawable(geom);
return geode.release();
}
2. 构建场景图
osg::Group* createScene() {
osg::ref_ptr<osg::Group> root = new osg::Group;
// 添加多个几何体
root->addChild(createQuad());
// 添加变换节点
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
transform->setMatrix(osg::Matrix::translate(2,0,0));
transform->addChild(createCube());
root->addChild(transform);
return root.release();
}
五、交互与动画
1. 键盘事件处理
class KeyboardHandler : public osgGA::GUIEventHandler {
public:
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) {
switch (ea.getKey()) {
case 'a':
// 处理A键按下
return true;
case osgGA::GUIEventAdapter::KEY_Left:
// 处理左箭头
return true;
}
}
return false;
}
};
// 添加到查看器
viewer.addEventHandler(new KeyboardHandler());
2. 简单动画
class AnimationCallback : public osg::NodeCallback {
public:
void operator()(osg::Node* node, osg::NodeVisitor* nv) {
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
if (mt) {
double time = osg::Timer::instance()->time_s();
mt->setMatrix(osg::Matrix::translate(0, 0, sin(time)*2));
}
traverse(node, nv);
}
};
// 应用到变换节点
transform->setUpdateCallback(new AnimationCallback());
六、进阶主题
1. 着色器编程
osg::StateSet* addShader(osg::Node* node) {
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(osgDB::readShaderFile(osg::Shader::VERTEX, "shader.vert"));
program->addShader(osgDB::readShaderFile(osg::Shader::FRAGMENT, "shader.frag"));
osg::StateSet* stateset = node->getOrCreateStateSet();
stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
return stateset;
}
2. 粒子系统
osg::Node* createFireEffect() {
osgParticle::ParticleSystem* ps = new osgParticle::ParticleSystem;
// 配置粒子系统...
osgParticle::ModularEmitter* emitter = new osgParticle::ModularEmitter;
emitter->setParticleSystem(ps);
// 配置发射器...
osg::Group* root = new osg::Group;
root->addChild(emitter);
root->addChild(new osgParticle::ParticleSystemUpdater(ps));
return root;
}
七、调试与优化
1. 性能分析工具
-
osgstats
:查看场景统计信息 -
osgviewer --stats
:运行时显示性能数据
2. 优化技巧
-
使用
osgUtil::Optimizer
优化场景 -
合理使用LOD(细节层次)节点
-
合并几何体减少绘制调用
八、学习资源
-
示例代码:
$OSG_ROOT/share/OpenSceneGraph/bin
中的示例程序