概述
目录
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 生成工具"。如下图所示
在此解释一下勾选这两项的原因:
- 勾选"用于Windows的C++ CMake 工具"是为了使VS支持CMake工程;
- 勾选"MSVC V142 - VS 2019 C++ x64/x86 生成工具"是因为本文使用的osg库是使用VS2019编译的,需要支持2019编译的库。
3.2获取osg库
获取osg库至少有三种方式:
- 使用osg的源码编译。在osg的github主页下载osg3.6.5源码并自行编译,网上有很多这类教程,不在此详细描述。如果您想调试osg的源码,请选此方法。本篇教程不需要调试osg源码,因此选用最快的方法,即方法3。
- 使用vcpkg编译安装。网上也有很多这类教程,不在此详细描述。由于vcpkg下载速度是个严重的问题,要想快速搭建开发环境也不推荐此方法。
- 下载编译好的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}
osgd
osgViewerd
)
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}
osgd
osgViewerd
)
注意到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,想让程序跑起来了。遗憾的是,目标还不能正常运行,因为找不到动态链接库。
解决这个问题至少有两个办法:
- 将动态链接库路径配置到系统环境变量;
- 将动态链接库拷贝到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}
osgd
osgViewerd
)
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}
osgd
osgViewerd
osgDBd
)
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.前言2.osg简介3.OSG开发环境配置4.编写、编译并运行第一个osg程序的全部内容,希望文章能够帮你解决osg开发配置与第一个osg程序1.前言2.osg简介3.OSG开发环境配置4.编写、编译并运行第一个osg程序所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复