【OSG学习笔记】Day 2: Hello Cow

0 阅读2分钟

去除图片水印 (1).png

第二天,我们来实现下渲染3D奶牛模型。

实现「Hello Cow」3D 模型渲染

OpenSceneGraph(OSG)是轻量级高性能的 3D 图形引擎,本文以「Hello Cow」为例,从环境配置、代码编写、CMake 构建到运行验证,手把手完成第一个 OSG 3D 模型渲染程序,解决新手常见的环境变量、库依赖、编译链接等问题。

前置准备

昨天忘记配置环境变量,导致今天使用时候找不到对应的库。 这里配置一下。

1 配置永久环境变量

让系统和 CMake 识别 OSG 路径,编辑全局配置文件:

sudo vim /etc/profile

在文件末尾添加以下内容:

# OSG 环境变量配置
export OSG_ROOT=/usr/local/osg
export PATH=$OSG_ROOT/bin:$PATH
export LD_LIBRARY_PATH=$OSG_ROOT/lib:$LD_LIBRARY_PATH
export CMAKE_PREFIX_PATH=$OSG_ROOT:$CMAKE_PREFIX_PATH
export PKG_CONFIG_PATH=$OSG_ROOT/lib/pkgconfig:$PKG_CONFIG_PATH

保存后让配置立即生效:

source /etc/profile

# 验证配置(输出 /usr/local/osg 则生效)
echo $OSG_ROOT

2 配置系统动态链接库(解决运行时库依赖)

将 OSG 库路径写入系统配置,避免运行时「找不到共享库」:

# 创建 OSG 库配置文件
echo "/usr/local/osg/lib" | sudo tee /etc/ld.so.conf.d/osg.conf

# 更新动态链接库缓存
sudo ldconfig

# 验证(能查到 osgViewer 库则成功)
ldconfig -p | grep libosgViewer

核心代码

实现的代码已经上传gittee: hello_cow

1 代码功能说明

实现最基础的 3D 模型加载与渲染:

  • 创建 OSG 视窗对象;
  • 加载 cow.osg 模型文件;
  • 优化场景数据并启动渲染循环;
  • 包含错误提示,便于新手排错。

2 完整代码(hello_cow.cpp)

// 引入OSG核心头文件:分别对应视窗渲染、节点、几何体节点、组节点、文件读写、场景优化
#include <osgViewer/Viewer> // OSG的视窗渲染器,用于创建窗口和渲染场景
#include <osg/Node> // OSG所有场景节点的基类,是场景图的基本组成单元
#include <osg/Geode> // 几何体节点,用于承载可渲染的几何体(如点、线、面)
#include <osg/Group> // 组节点,可包含多个子节点,是场景图的分支节点
#include <osgDB/ReadFile> // OSG的文件读取工具,用于加载模型文件(.osg/.ive等格式)
#include <osgDB/WriteFile> // OSG的文件写入工具(本示例未使用,保留头文件供扩展)
#include <osgUtil/Optimizer> // OSG的场景优化器,用于优化场景图结构提升渲染效率

 
// 主函数:OSG程序的入口
int main() {
// 1. 创建视窗渲染器对象,负责创建窗口、处理事件、渲染场景
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

// 2. 创建根节点(组节点),作为整个场景图的根,所有其他节点都挂载在其下
osg::ref_ptr<osg::Group> root = new osg::Group();

// 3. 加载模型文件:加载OSG自带的示例模型cow.osg(需确保模型文件路径正确)
// readNodeFile返回osg::Node指针,失败时返回nullptr
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");

// 4. 将加载的模型节点添加到根节点下,成为根节点的子节点
root->addChild(node.get());

// 5. 创建场景优化器,对场景图进行优化(如合并重复节点、优化渲染状态等)
osgUtil::Optimizer optimizer;

// 执行优化:传入根节点,优化整个场景图的结构和渲染性能
optimizer.optimize(root.get());

// 6. 将优化后的场景图设置给视窗渲染器
viewer->setSceneData(root.get());

// 7. 初始化视窗渲染器:创建窗口、初始化渲染上下文等
viewer->realize();

// 8. 启动渲染循环:处理窗口事件、持续渲染场景,直到窗口关闭
return viewer->run();
}

CMakeLists.txt

1 CMake 配置说明

  • 手动指定 OSG 路径,避免 CMake 自动查找的坑;
  • 区分「头文件目录」和「库文件目录」,规避「链接目录」警告;
  • 自动复制模型/贴图文件到编译目录,简化运行步骤。

2 完整 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(osg_cow_demo)

# 基础配置
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# ========== 核心:手动指定OSG路径(彻底避开find_package的坑) ==========
# 你的OSG安装根目录(固定写死,避免CMake猜路径)
set(OSG_INSTALL_DIR "/usr/local/osg")


# 1. 头文件目录(仅编译用,不参与链接)

include_directories(
${OSG_INSTALL_DIR}/include # OSG头文件
${CMAKE_CURRENT_SOURCE_DIR}
)

# 2. 库文件目录(仅告诉CMake去哪里找库,不直接链接)
link_directories(${OSG_INSTALL_DIR}/lib)
# 3. 生成可执行文件
add_executable(osg_cow osg_cow.cpp)

# 4. 链接OSG库文件(只写库名,不写目录!这是关键)
target_link_libraries(osg_cow
# 直接写OSG的库名(CMake会去link_directories里找)
osgViewer
osg
osgDB
osgUtil
OpenThreads
osgGA
)

# ========== 复制模型文件(可选) ==========
foreach(FILE cow.osg cow.png)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE})
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${FILE}
${CMAKE_CURRENT_BINARY_DIR}/${FILE}
COPYONLY
)
endif()
endforeach()


# 调试信息(确认路径)
message(STATUS "OSG头文件路径: ${OSG_INSTALL_DIR}/include")
message(STATUS "OSG库文件路径: ${OSG_INSTALL_DIR}/lib")

编译与运行「Hello Cow」

1 编译步骤(清除缓存,避免旧配置干扰)

# 进入项目目录(假设代码在 ~/osg_hello_cow 下)
cd ~/osg_hello_cow

# 彻底删除旧 build 目录(关键:清除缓存)
rm -rf build

# 新建 build 目录并编译
mkdir build && cd build
cmake ..  # 无警告,仅输出调试信息
make -j$(nproc)  # 编译生成 osg_cow 可执行文件

2 运行程序

# 在 build 目录下运行
./osg_cow

3 运行效果

  • 弹出独立的 3D 视窗,显示带纹理的奶牛模型;
  • 支持交互操作:
    • 鼠标左键拖拽:旋转模型;
    • 鼠标滚轮:缩放模型;
    • 键盘 WSAD:平移视角;
    • 关闭窗口:退出程序。

image.png

常见问题排查

1 CMake 提示「找不到 OSG 库」

  • 确认 OSG_INSTALL_DIR 路径正确(对应 /usr/local/osg);
  • 重新执行 source /etc/profile 加载环境变量。

2 编译报错「找不到 osgViewer/Viewer」

  • 检查 OSG 头文件路径:ls /usr/local/osg/include/osgViewer/Viewer
  • 重新编译 OSG 并开启 BUILD_ALL_MODULES=ON

3 运行时「找不到 libosgGA.so」

  • 确认 /etc/ld.so.conf.d/osg.conf 已配置;
  • 重新执行 sudo ldconfig 更新动态链接库。

总结

  1. 环境配置核心:通过 OSG_ROOT 配置路径,ldconfig 解决运行时库依赖;
  2. CMake 避坑:区分「头文件目录」和「库文件目录」,仅链接库名不链接目录;
  3. 新手关键:模型与贴图文件需同目录,文件名小写,编译前清除缓存;
  4. 交互基础:OSG 内置鼠标/键盘交互,无需额外代码即可操作模型。

去除图片水印.png