一、背景
最近一直尝试编译OsgEarth,但各种问题,还未解决。今天想直接尝试下用别人的OsgEarth库,在网上找到了一个,链接为:Osg3.4.0 OsgEarth2.8.0预编译库(VS2015 64bit)
刚好我的电脑上装的就是VS2015,OSG3.4.0和OsgEarth2.8还算比较新。下载完了之后,得到了两个文件夹Osg3.4.0_SDK和OsgEarth2.8_SDK,然后我进行了下环境变量的设置:
1、新建变量OSG_FILE_PATH,并在变量值里面添加Osg3.4.0_SDK中的data文件夹的路径,以及OsgEarth2.8_SDK中data文件夹和tests文件夹的路径;
2、在变量path下,添加Osg3.4.0_SDK中bin文件夹的路径和OsgEarth2.8_SDK中bin文件夹的路径。注意:所有路径,根据电脑中的实际位置。
然后进行了验证,方法为:在DOS中直接输入命令osgViewer gdal_tiff.earth,正常情况下可以显示一个三维地球,并且可以旋转。成功。
二、错误的出现
在验证这个已经编译好了的库是可以使用的之后,想继续用一个简单的VS项目进行验证。然后错误就出现了。我使用的验证方法来自于osgEarth加载谷歌卫星地图的源码案例,这个链接博客里面图片无法显示,可以对照百度文库osgEarth加载谷歌卫星地图的源码案例看其中的图片。一共1120个错误,这里选取了部分截图如下:
对于这些错误,我原以为是因为mymap.earth文件添加不正确,但是发现,错误里面提到的并不是这个。后来我怀疑是不是本身库就是错的。然后我想,即便OsgEarth2.8_SDK有错误,但Osg3.4.0_SDK总不该出错吧。于是我找了个测试Osg的例子,创建了一个控制台项目,并选择了空项目,然后添加了如下代码:
#include <osgViewer/Viewer> #include <osg/Node> #include <osg/Geode> #include <osg/Group> #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgUtil/Optimizer> int main() { //创建Viewer对象,场景浏览器 osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer(); //创建场景组节点 osg::ref_ptr<osg::Group> root = new osg::Group(); //创建一个节点,读取牛的模型 osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg"); //添加到场景 root->addChild(node.get()); //优化场景数据 osgUtil::Optimizer optimizer; optimizer.optimize(root.get()); //设置场景数据 viewer->setSceneData(root.get()); //初始化并创建窗口 viewer->realize(); //开始渲染 viewer->run(); return 0; }
并进行了基本的包含目录、库目录和依赖项的添加,运行,结果……
第一张图里点击了“否”之后,出现的错误是何等的相似,何等的一脸雾水。
三、解决办法
然后我有意无意看到第一张图里反复提到了..\include\um\gl\gl.h这个文件,然后想着是不是这里出了问题,然后百度了一下,有结果。链接为:OSG测试gl.h编译出错,果然有效,在代码前面加一句 #include<Windows.h>就可以了。
然,这里的博主只告诉了要这么做,但并未言明为什么要这么做。另外一个博客OSG gl.h出错解决倒是说了可能的原因,但是还是不太明白,我不认为我代码中#include的一些文件中间有冲突,以下标绿色的文字来源于OSG gl.h出错解决。
解决方法是:
在头文件最开始添加 #include <Windows.h>即可!
对,就是这么尴尬。
具体的原因是:
大概是这样:
1. (此情况经常出现在大型工程项目中)如果存在两个类的头文件a.h和b.h,在a.h中有这样的语句:#include "b.h",在b.h文件中有这样的语句:#include "a.h" 且在一个类中有另一个类的对象时 那么就会出现这样的错误。
2. 没有包含要定义的类的头文件。
3.项目中少加了宏定义,导致头文件重复定义或相应宏无法识别。
4.当有多个头文件时,顺序写反也可能导致相关的错误,其根本是头文件中的预编译语句被隐去了。
e.g
#include <stdio.h>
#include <Windows.h>
#include <WinCrypt.h>
#include <string.h>
如果把第二个和第三个写反,一个宏定义就被#if给注了,就会出现类似错误