目录

1.前言

2.osg简介

3.OSG开发环境配置

3.1下载安装VS2022

3.2获取osg库

4.编写、编译并运行第一个osg程序

4.1编写第一个C++ CMake程序

4.2编写第一个osg程序

4.3一个xue微有点追求的osg程序


1.前言

本文介绍开源图形库osg的开发环境配置和编写第一个osg程序的完整过程。这是一个教程,也是一个与各位图形从业者的交流平台。

开发环境:Windows10 专业版、Visual Studio 2022、osg3.6.5;

项目构建:CMake。

Visual Studio从版本2017开始支持CMake项目,本文编写时VS的最新版本是VS2022,我们就使用最新版本。CMake 是一个跨平台、开源的元构建系统,广泛应用于C/C++项目的源码构建,它可以为make、ninja等构建系统生成构建脚本。CMake根据用户在CMakeLists.txt编写的各种命令构建工程,本文对涉及到的CMake命令会进行介绍。

2.osg简介

OpenSceneGraph简称osg,是基于标准C++语言和OpenGL编写的图形引擎,详细介绍见osg主页。

3.OSG开发环境配置

3.1下载安装VS2022

VS官网下载VS2022。VS2022分为社区版,个人版和企业版,其中社区版可免费使用,个人版和企业版可免费使用30天。如使用个人版和企业版,请用你懂得的方式进行,如想减轻使用盗版软件带来的负罪感,社区版也是够用的。

VS安装时需注意,勾选项"用于Windows的C++ CMake 工具"和"MSVC V142 - VS 2019 C++ x64/x86 生成工具"。如下图所示

在此解释一下勾选这两项的原因:

  1. 勾选"用于Windows的C++ CMake 工具"是为了使VS支持CMake工程;
  2. 勾选"MSVC V142 - VS 2019 C++ x64/x86 生成工具"是因为本文使用的osg库是使用VS2019编译的,需要支持2019编译的库。

3.2获取osg库

获取osg库至少有三种方式:

  1. 使用osg的源码编译。在osg的github主页下载osg3.6.5源码并自行编译,网上有很多这类教程,不在此详细描述。如果您想调试osg的源码,请选此方法。本篇教程不需要调试osg源码,因此选用最快的方法,即方法3。
  2. 使用vcpkg编译安装。网上也有很多这类教程,不在此详细描述。由于vcpkg下载速度是个严重的问题,要想快速搭建开发环境也不推荐此方法。
  3. 下载编译好的osg库。要想最快搭建osg的开发环境,推荐此方法。本文使用Objexx编译并提供给osg开源社区的osg库。 下载页面地址:https://objexx.com/OpenSceneGraph.html。

本文例子使用Visual C++ 2019编译的64位osg3.6.5

下载Release和Debug版,并解压到本地硬盘。假设Release版和Debug版的保存路径分别为:"E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Release/ "和 "E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug/"。库的目录组织如下图:

bin目录存放可执行的二进制文件,即exe文件和dll文件,包括实用工具"模型/场景查看器" osg_viewer.exe、"格式转换工具"osg_conv.exe等;include目录存放头文件;lib目录存放.lib库文件。

为了简化本篇教程,本例子只用Debug库,涉及Debug和Release的切换问题,将在后续教程介绍。

至此,所需的软件都已准备就绪。下面我们将创建第一个osg程序。

4.编写、编译并运行第一个osg程序

本着由简入繁、一步一个脚印的原则,我们将首先使用VS2022创建一个CMake工程,并使用标准C++编写一个最简单的程序(Hello World: "没错,就是我!"),程序正常编译和运行后再引入osg库并创建第一个osg窗口,而后创建一个简单的场景,这一切都正常编译运行后,我们的第一个osg程序任务就可以完美结束了。

4.1编写第一个C++ CMake程序

首先我们先用VS2022创建一个CMake工程。

这时候有的同学要问了,为什么要用CMake呢,VS的工程(.sln)不可以吗?

答案是:可以。VS工程经过界面化的配置就可以开发运行osg程序,但是我依然推荐大家使用CMake工程,因为在程序员生涯中,您一定会接触开源、跨平台的C++项目,您甚至会自己开发一套开源软件,而在这个过程中一定绕不开CMake,所以CMake命令虽然入门有难度,但是学习它是很有必要的。因此在此文中,我将创建CMake工程,并与大家一起探索和使用这个优秀的工具。

言归正传,我们开始创建第一个CMake工程。

1.新建文件夹"learn_osg_01",在文件夹内创建文件"CMakeLists.txt"和文件"main.cpp",此时两个文件都是空的。

2.打开VS2022,选择"打开本地文件夹",并选择"learn_osg_01"目录。

3.此时VS经过一番自动操作,完成了CMake工程的生成工作。可以发现此时在"learn_osg_01"目录下多了两个文件夹".vs"和"out",其中".vs"目录下会生成VS的项目配置、缓存等文件,由VS自动维护,我们可以不用关心,甚至可以在关闭工程时删除(再次打开VS还会重新生成);"out"目录下将存放将来编译、链接生成的各种文件。

4.在"main.cpp"中编写"Hello World"程序。

#include <iostream>int main(int argc, char** argv)
{std::cout << "Hello, osg!" << std::endl;return 0;
}

5.这是一个可正常编译运行的C++源程序,正确使用CMake可生成可执行程序。CMake如何知道怎么构建呢?答案是通过"CMakeLists.txt"文件的指令。我们在"CMakeLists.txt"中输入以下代码并保存:

project("learn_osg_01")
add_executable(${PROJECT_NAME} main.cpp)

6.点击VS菜单的"生成-全部生成",VS会自动调用相关工具生成"learn_osg_01.exe",F5可运行调试,此时在控制台上已经可以输出"Hello, osg!"。

至此,第一个CMake C++程序已经完成了。在进行下一步之前请容我简要介绍一下用到的两条CMake指令。

project("learn_osg_01")

project()指令的作用是设置项目名称,并存放在变量PROJECT_NAME中,如果在顶层的CMakeLists.txt中调用此指令,会同时把项目名称存放在变量CMAKE_PROJECT_NAME中,同时还会自动设置以下变量:

PROJECT_SOURCE_DIR:  项目源码的绝对路径,在此例中是"E:/一坨路径.../learn_osg_01"

PROJECT_BINARY_DIR: 项目二进制目录的绝对路径,在此例中是"E:/一坨路径.../learn_osg_01/out/build/x64-Debug"

另外project()指令还可指定版本,语言等。

add_executable(${PROJECT_NAME} main.cpp)

add_executable()指令的作用是使用指定的源文件生成目标可执行文件,指令的第一个参数是要生成可执行文件(Windows系统中是exe文件)的名称,本例中会生成"learn_osg_01.exe",名字后边的参数是源文件列表,此例中目前只有一个源文件,即"main.cpp",如有多个源文件,要依次列在后边,用空格或换行隔开。

我们已经搞明白了这几行代码,接下来我们要开始编写基于osg的程序了。

4.2编写第一个osg程序

写过Visual C++项目的同学一定了解,在VC++项目中,通过图形界面就可配置库,非常方便。对于CMake工程,我们要用自己勤劳的双手输入指令代码去完成配置。

我们要引入osg库,首先要告诉编译器库头文件的位置。在CMake中使用include_directories()指令实现。

include_directories("E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug/include")

include_directories()指令告诉编译器搜索头文件的路径,把目录加入到属性INCLUDE_DIRECTORIES中。

我们还要告诉编译器库文件的位置。在CMake中使用link_directories()指令实现。

link_directories("E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug/lib")

link_directories()指令告诉链接器器搜索库文件的路径,把目录加入到属性LINK_DIRECTORIES中。

接下来我们还要告诉编译器,具体链接哪个库文件。在CMake中使用target_link_libraries()指令实现。

target_link_libraries(${PROJECT_NAME} osgdosgViewerd
)

target_link_libraries()指令指定哪些库需要链接到目标上。本例的目标是最终要生成的exe文件,由上文中add_executable()指令指定,需要链接的库是osgd.lib和osgViewerd.lib。

至此本例的CMake库配置已经基本完成,目前为止CMakeLists.txt文件的全部内容如下:

project("learn_osg_01")set(OSG_DIR "E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug")
include_directories(${OSG_DIR}/include)
link_directories(${OSG_DIR}/lib)add_executable(${PROJECT_NAME} main.cpp)target_link_libraries(${PROJECT_NAME} osgdosgViewerd
)

注意到include_directories()指令和link_directories()指令都用到了osg库的根目录,本着方便快捷、便于维护的目的,我们使用set()指令把osg库根目录赋值给变量OSG_DIR,本文件后续再使用可以直接引用此变量。

接下来我们就可以在代码中调用osg库了。

我们创建一个osgViewer::Viewer对象,并运行该Viewer的主循环。main.cpp文件中的代码改造如下

#include <osgViewer/Viewer>
#include <iostream>int main(int argc, char** argv)
{std::cout << "Hello, osg!" << std::endl;osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;return viewer->run();
}

F7启动目标生成,可以看到目标已经成功生成。

此时,您一定迫不及待的要按下F5,想让程序跑起来了。遗憾的是,目标还不能正常运行,因为找不到动态链接库。

解决这个问题至少有两个办法:

  1. 将动态链接库路径配置到系统环境变量;
  2. 将动态链接库拷贝到exe目录。

第一个办法最简单也最节省硬盘空间,但是如果您在同时开发多个项目,而每个项目使用的osg版本是不同的,那这个办法会引起意想不到的错误;

接下来我们介绍一下第二种办法。

有同学可能会想到手动去拷贝dll文件,这是一个解决方案但显然有点low,那有什么看起来比较有调性的方法呢?用CMake!

file(GLOB OSG_DLLS ${OSG_DIR}/bin/*.dll)
file(COPY ${OSG_DLLS} DESTINATION ${CMAKE_BINARY_DIR})

使用file()指令可自动拷贝源路径下的所有.dll文件到目标路径。file()指令可对文件系统进行操作,它的功能远不止本例中用到的这些,感兴趣的同学可以继续研究一下。

在CMakeLists.txt文件中增加上两行指令并保存,CMake会自动完成文件拷贝,这时F5启动程序,您将看到一个全屏显示的osg窗口,第一个osg程序终于运行起来了!

有的同学要问了:“我不想全屏启动应用程序怎么办?”

在main.cpp中添加一行代码,指定窗口的位置和大小

viewer->setUpViewInWindow(50, 50, 800, 600);

运行结果如下图所示

至此,一个空场景的osg窗口已经运行起来了。

CMakeLists.txt的完整代码是:

project("learn_osg_01")set(OSG_DIR "E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug")
include_directories(${OSG_DIR}/include)
link_directories(${OSG_DIR}/lib)add_executable(${PROJECT_NAME} main.cpp)target_link_libraries(${PROJECT_NAME} osgdosgViewerd
)file(GLOB OSG_DLLS ${OSG_DIR}/bin/*.dll)
file(COPY ${OSG_DLLS} DESTINATION ${CMAKE_BINARY_DIR})

main.cpp的完整代码是:

#include <osgViewer/Viewer>
#include <iostream>int main(int argc, char** argv)
{std::cout << "Hello, osg!" << std::endl;osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;viewer->setUpViewInWindow(50, 50, 800, 600);return viewer->run();
}

此教程到此可以告一段落了,但是作为一个有追求的程序员,空场景显然不符合我们的调性,因此我们继续折腾一下,让场景里显示一个三维物体。

4.3一个xue微有点追求的osg程序

我们在场景中创建一个地球模型。

首先在坐标(0,0,0)处创建一个半径为1.0的球,main.cpp函数中添加代码:

#include <osg/Geode>
#include <osg/ShapeDrawable>...int main(int argc, char** argv)
{...osg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 1.0f)));viewer->setSceneData(geode);...
}

编译运行结果如下:

这是一个没有灵魂的球,我们将为这个球注入地球的灵魂,通过——贴纹理。

本例子使用的纹理下载链接

下载后放于"E:/test/"目录下。

在main.cpp中添加代码

#include <osg/Texture2D>
#include <osgDB/ReadFile>...int main(int argc, char** argv)
{...osg::ref_ptr<osg::Texture> texture = new osg::Texture2D(osgDB::readRefImageFile("E:/test/world.png"));auto stateSet = geode->getOrCreateStateSet();stateSet->setTextureAttributeAndModes(0, texture);...}

在CMakeLists.txt中添加代码:

target_link_libraries(${PROJECT_NAME} osgDBd
)file(GLOB OSG_PLUGIN_DLLS ${OSG_DIR}/bin/osgPlugins-*/osgdb_png*.dll)
file(COPY ${OSG_PLUGIN_DLLS} DESTINATION ${CMAKE_BINARY_DIR})

引入osgDB库,同时将插件库中的png文件读写插件dll拷贝到可执行文件同目录下。

编译运行,出现三维地球的场景终于出现了,如下图

osg默认为我们增加了相机操控器,可以通过鼠标操作浏览场景。

按下鼠标坐标左键并拖动:旋转场景;

按下鼠标中键并拖动:平移场景;

按下鼠标右键并拖动:缩放场景;

鼠标滚轮:缩放场景;

键盘空格键:恢复初始相机视角;

键盘ESC键:退出。

本教程的代码已经全部编写完成。代码不多,但篇幅略长,每句代码都有说明,有些更是踩过坑后总结的经验,旨在为新手同学提供详细、友好的入门教程,同时希望对老手也有所启发。感谢各位能阅读到此,希望与大家在学习探索osg的旅程上结伴同行。

最后附上完整代码。

CMakeLists.txt

project("learn_osg_01")set(OSG_DIR "E:/osg/OpenSceneGraph-3.6.5-VC2019-64-Debug")
include_directories(${OSG_DIR}/include)
link_directories(${OSG_DIR}/lib)add_executable(${PROJECT_NAME} main.cpp)target_link_libraries(${PROJECT_NAME} osgdosgViewerdosgDBd
)file(GLOB OSG_DLLS ${OSG_DIR}/bin/*.dll)
file(COPY ${OSG_DLLS} DESTINATION ${CMAKE_BINARY_DIR})
file(GLOB OSG_PLUGIN_DLLS ${OSG_DIR}/bin/osgPlugins-*/osgdb_png*.dll)
file(COPY ${OSG_PLUGIN_DLLS} DESTINATION ${CMAKE_BINARY_DIR})

main.cpp

#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>#include <iostream>int main(int argc, char** argv)
{std::cout << "Hello, osg!" << std::endl;osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;viewer->setUpViewInWindow(50, 50, 800, 600);osg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 1.0f)));osg::ref_ptr<osg::Texture> texture = new osg::Texture2D(osgDB::readRefImageFile("E:/test/world.png"));auto stateSet = geode->getOrCreateStateSet();stateSet->setTextureAttributeAndModes(0, texture);viewer->setSceneData(geode);return viewer->run();
}

osg开发配置与第一个osg程序相关推荐

  1. TypeScript笔记(1)——环境配置与第一个ts程序

    TypeScript(1):开发环境配置与第一个ts程序 李俊才 CSDN:jcLee95 作者博客地址:https://blog.csdn.net/qq_28550263?spm=1000.2115 ...

  2. 指南-Luat二次开发教程指南-第一个Luat程序

    第一个Luat程序 目录名称 第一个Luat程序 第一个工程 安装编辑器 更改软件各项默认设置 推荐安装的拓展 新建工程 模块化编程 连接硬件 点亮LED小灯 让LED灯闪烁起来 第一个工程 本文将从 ...

  3. acr单片机c语言开发入门,AutoCAD2013二次开发C语言第一个ObjectArx2013程序HelloWorld.docx...

    AutoCAD2013 二次开发 C++语言的第一个 ObjectArx2013 程序 HelloWorld .八,.■ 刖言 AutoCAD2013 二次开发 C++语言的 ObjectArx SD ...

  4. Day01开发环境和第一个Java程序

    职业发展[了解]  为什么需要了解职业发展 既然我们在这儿学习,要知道我们经过大概半年的学习我们能够达到什么水平,以及三五年以后能够达到什么水平,这就需要了解职业规划.  职业发展 IT领袖:年入数十 ...

  5. IOS开发-我的第一个IOS程序

    学完前面的ObjC基础,那么接下来我可以开始我的IOS开发之旅了- 1.首先打开Xcode创建一个工程 2.选择IOS->Application->SingleView Applicati ...

  6. OpenGL---Windows下配置与第一个OpenGL程序

    下面记录一下Windows下配置OpenGL与我的第一个OpenGL程序. 第一步:选择一个编译环境    现在Windows系统的主流编译环境有Visual Studio,Broland C++ B ...

  7. 安卓开发之-编写第一个java程序HellowWorld

    1.我这边用的visual studio Code编辑器,百度可以下载(安装以后如果是英文版本的可以在百度找一下安装中文的扩展插件). 2.正文开始:安装好编辑器在桌面创建一个java文件夹(文件夹可 ...

  8. 微信小程序开发手记之七:一个小程序上线后的总结(上)

    终于,经过大概一周时间,磕磕绊绊地提交审核了,一个移动猿开发小程序,也算有了些心得,也遇到了些坑,这里和大家一起分享下. 怎么样调布局 先说一个题外话,最后引入正题. 如果翻看过一些资料,大家肯定很容 ...

  9. android开发培训!作为一个Android程序员你还不会JetPack?安卓系列学习进阶视频

    开头 让我们一起来看看,字节跳动的第三面,面试官都问了什么?(第一二面的题目及答案已整理,需要的可以在文末领取) 从七月中旬开始,我前前后后差不多一共投递了八十份简历,到目前为止,我参加面试的面试有十 ...

最新文章

  1. .Net中如何操作IIS(源代码)
  2. hive操作create,alter等
  3. okhttp3 请求html页面,OkHttp3源码详解(二) 整体流程
  4. 遇见低码:在价值中审视
  5. daily scrum 12.2
  6. 详解CSS中:nth-child的用法
  7. 基于TensorFlow的车牌识别系统 (附代码)
  8. html5 自动连线,基于html5二个div 连线
  9. Base64原理及魔改更换码表
  10. 从0到一开发微信小程序(4)—小程序组件
  11. 【第一组】第四次冲刺例会纪要
  12. 知识付费的本质是什么?现在入行知识付费行业晚吗?
  13. 多任务学习——【ICML 2018】GradNorm
  14. PowerBI数据处理-聚合
  15. 2018-04-21-linux-sources-list html-url、隐藏滚动条
  16. 准静态、静态、动态(动力学分析)
  17. 豆瓣8.0分,尺度堪比色戒,一部让人绝望的电影
  18. UnityShader水体渲染
  19. Hadoop是做什么的,hadoop集群搭建作用
  20. 用计算机弹出音乐谱,抖音计算器弹奏歌曲谱子是什么_抖音计算器音乐乐谱大全_管理资源吧...

热门文章

  1. 计算机机房联合接地线用什么线,机房中 机柜设备外壳为什么接地? 机房如何做接地?...
  2. 卷积神经网络模型部署到移动设备
  3. 局域网内使用的多人协同编辑文档的软件哪个好?对比5款主流平台
  4. 作业1-游戏分类与热点探索
  5. 复旦FM1208 CPU卡调试
  6. python爬虫操作 (本次爬虫的百度、风景、酷狗和人物)
  7. 雅虎市值_雅虎! 推出更多社交
  8. python 营销软件_最近超火的赚钱工具Python到底怎么用?
  9. python判断整除_python 如何判断整除?
  10. 植物大战僵尸 1.0 简体中文版