merryboy 发表于 2008-11-28 13:57:54

Windows下从头开始创建一个最简单的OpenSceneGraph-2.6.0 程序及调试环境Debug)

Windows下编译 OpenSceneGraph-2.6.0 的方法,主要实现从源代码逐步编译出一个可调试的运行环境.
我主要使用VMWare Server 1.0.7+XP+.NET 2003来测试OSG软件,我也是用这种方法来测试新的软件,原因在于装错了,可以删除后拷贝备份的文件继续试试软件,不用重新装操作系统,很方便啊.
需要下载的软件包:
OpenSceneGraph-2.6.0.zip 下载地址
http://www.openscenegraph.org/downloads/stable_releases/OpenSceneGraph-2.6/OpenSceneGraph-2.6.0.zip

3rdParty_Win32binaries_2005_05_10.zip 下载地址
http://www.openscenegraph.org/downloads/dependencies/3rdParty_Win32binaries_2005_05_10.zip

cmake-2.4.7-win32-x86.exe 下载地址
http://www.tntdown.cn/download.asp?id=19650&dp=1

msvcr71d.dll 下载地址
http://www.zhaodll.net/dll/download.asp?softid=463&downid=2&id=461

msvcp71d.dll 下载地址
http://www.zhaodll.net/dll/download.asp?softid=458&downid=2&id=456

.NET版本是Microsoft Visual Studio .NET 2003(VC7,Microsoft开发环境 2003版本,Version 7.1.3091)

具体步骤如下:
1、解压缩 OpenSceneGraph-2.6.0.zip ,3rdParty_Win32binaries_2005_05_10.zip两个文件(方法是解压到当前文件夹(X)).
2、把3rdParty_Win32binaries_2005_05_10.zip 解压缩出来的文件夹 3rdParty拷贝到 OpenSceneGraph-2.6.0.zip解压缩出来的文件夹OpenSceneGraph(需要改个名字,不用2.6.0后缀)下面.
3、在C:盘下创建一个OSG文件夹,然后把OpenSceneGraph拷贝到这个文件夹下面.
4、安装 cmake-2.4.7-win32-x86.exe ,一切都是缺省.
5、通过 开始-->程序-->CMake2.4-->CMake 运行CMake程序.
6、将C:\OSG\OpenSceneGraph\CMakeLists.txt拖到CMake窗口中.
7、这时在Where is the source code:中会显示C:\OSG\OpenSceneGraph,在Where to build the binaries:中会显示C:\OSG\OpenSceneGraph,修改binaries这一项,变成C:\OSG\OpenSceneGraph\build,点击Configure,会弹出一个编译器的选项,自动就行,不用改变,然后按ok,弹出Create Directory窗口,按 确定.
8、修改 ACTUAL_3DPARTY_DIR这项,由C:/OSG/3rdparty指向C:\OSG\OpenSceneGraph\3rdParty
   修改 BUILD_OSG_ARAPPERS这项,由OFF 改成 ON
   其他不动

   如果你想这时编译例子程序,可以修改BUILD_OSG_EXAMPLES这项,由OFF 改成 ON

参数解释:
ACTUAL_3DPARTY_DIR:即整合的第三方开发库所在目录,如果下载了OSG提供的整合好的第三方开发库,那么可以在这里设置解压缩之后它的位置,CMake将在下次配置时自动搜索所需的Lib文件和头文件路径.
BUILD_OSG_EXAMPLES:是否编译OSG所有例子程序的选项.
BUILD_OSG_ARAPPERS: 这一项要选,不然后面编译自己的测试程序的时候,会报无法打开文件"osgIntrospectiond.lib"错误.
CMAKE_CONFIGURATION_TYPES:定义了工程文件中工程配置的种类,缺省值包括Debug,Release,MinSizeRel和RelWithDebInfo四种类型.注意不同的配置类型在工程中对应不同的编译选项,可以在CMAKE_CXX_FLAGS和CMAKE_EXE_LINKER_FLAGS中进行修改.
CMAKE_INSTALL_PREFIX:用于以后保存编译生成的EXE,DLL和LIB文件的路径,在这个路径下会自动建立bin和lib目录,以便区分存放结果.

9、按下"Configure",进入第二次配置
10、按下"Configure",就会出现 OK可点击的状态
11、先不要急于按下"Configure",点击右上的选框"Show Advanced Values",可以看到列表框中的选项增加了.这其中很多选项是之前未经选择的.这其中需要重新进行配置的主要是各个第三方开发库的头文件路径和Lib文件路径;如果用户平台上还有其他GUI库,例如Qt,Fltk,wxWidgets等,那么也需要在这里重新进行配置.
配置第三方开发库的相关参数时,主要需要配置以下两个参数的值:
……_INCLUDE_DIR:头文件的位置.
……_LIBRARY:需要链接的静态库文件.
12、按下OK键
13、进入C:\OSG\OpenSceneGraph\build文件夹下,选择OpenSceneGraph.sln,在Debug模式下,选择 生成(B)-->生成 ALL_BUILD (U),然后耐心等待,编译好后,在Release模式下,选择 生成(B)-->生成 ALL_BUILD (U),然后耐心等待,最后的效果是,生成了Debug和Release下的lib和dll库.
我用了一个网吧的计算机安装测试,环境是Intel x4 8700+VMware 5.0+XP(1024MB)(VMware上的系统)+XP(主系统)(2048MB),只编译Debug,花费时间1小时25分钟.
14、编译完成后,就开始我们建立环境了.
15、首先在C:\OSG\建一个目录,OSG2.6,在这个目录下分别建debug,release目录,在这些目录下建lib,bin目录,还要在OSG2.6目录下建一个include目录
具体目录结构如下:
C:\OSG\OSG2.6
   debug
   lib
   bin
   release
   lib
   bin
   include
16、开始拷贝相关文件:
具体步骤如下:
a、include下文件:
   到C:\OSG\OpenSceneGraph\3rdParty\include\下,把所有的文件拷贝到C:\OSG\OSG2.6\include下.
   到C:\OSG\OpenSceneGraph\include\下,把所有的文件拷贝到C:\OSG\OSG2.6\include下.
   到C:\OSG\OpenSceneGraph\build\include 下有Config.h文件,把这些文件拷贝到C:\OSG\OSG2.6\include下.

b、debug文件夹下的bin中的文件:
   把下载后的msvcpd71.dll和msvcr71d.dll文件解压后,拷贝到debug\bin下.
   到C:\OSG\OpenSceneGraph\3rdParty\bin\下,把所有D.dll结尾的文件拷贝到debug\bin下.
   到C:\OSG\OpenSceneGraph\build\bin\下,把所有的.dll和.exe结尾的文件结尾的文件拷贝到debug\bin下.
   到C:\OSG\OpenSceneGraph\build\bin\osgPlugins-2.6.0\下,把所有的.dll结尾的文件结尾的文件拷贝到debug\bin下.

c、debug文件夹下的lib中的文件:
   到C:\OSG\OpenSceneGraph\3rdParty\lib\下,把所有D.lib结尾的文件,拷贝到debug\lib下.
   到C:\OSG\OpenSceneGraph\build\lib\debug\下,把所有lib结尾的文件,拷贝到debug\lib下.

17、设置环境变量 系统变量
(我的电脑-->属性-->高级-->环境变量-->系统环境变量-->编辑(I))
   Path在后面添加   ;C:\OSG\OSG2.6\debug\bin;
新建(W)
   OSG_NOTIFY_LEVEL DEBUG_FP
   OSG_ROOT          C:\OSG\OSG2.6\debug\
   OSG_FILE_PATH    C:\OSG\OSG2.6\data\

18、修改屏幕属性(属性-->设置-->颜色(C)-->选择 真彩色(32位)-->确定)
   然后注销用户,重新登录系统就可以了.

19、开始配置VC7项目

启动Microsoft Visual Studio .NET 2003(VC7,Microsoft开发环境 2003版本,Version 7.1.3091),建立一个Win32控制台项目,在应用程序设置选项卡里,选择空项目,点击完成.为了在工程选项里出现C/C++的选项,先给工程添加一个空的C++源文件.
具体步骤:文件(F)-->新建(N)-->项目(P)-->Visual C++项目-->Win32项目-->名称(N):Test-->确定-->应用程序设置-->选中 控制台应用程序(O)-->选中 空项目(E) -->完成-->在右边 解决方案"Test"下 选择 源文件 右击-->添加(D)-->添加新项(W)-->C++文件(.cpp)-->名称(N): Test-->打开(O)

OpenSceneGraph运行需要多线程DLL的运行时库和RTTI,所以,在建立每个OpenSceneGraph工程后,第一件事就是更改工程设置.

(由于我们现在使用的是Debug版本,所以只用填写Debug信息)
具体步骤:项目(Test) 属性-->配置(C)-->Debug

打开项目属性,在C/C++选项卡里,点击代码生成页,更改运行时库,对于Debug版,用多线程调试 DLL (/Mdd),对于Release版,用多线程 DLL (/MD).
具体步骤:C/C++-->代码生成-->运行时库-->Debug版多线程调试 DLL (/Mdd)
//Release版,用多线程 DLL(/MD)这里只提出来,不用设置

设置C/C++选项卡里的语言页的启用运行时类型信息为:是(/GR).(Debug版下设置)
具体步骤:C/C++-->语言-->启用运行时类型信息-->是(/GR)-->确定


会出现这个无法解析的外部符号 _winmain@16 错误信息
具体步骤:链接器-->System-->子系统-->选择 控制台(/SUBSYSTEM:CONSOLE)

OpenSceneGraph程序需要链接对应的库文件,打开链接器选项卡里的输入页,设置附加依赖项,对于Debug版,是OpenThreadsd.lib,osgd.lib,osgDBd.lib,osgFXd.lib,osgGAd.lib,osgIntrospectiond.lib,osgManipulatord.lib,osgParticled.lib,osgShadowd.lib,osgSimd.lib,osgTerraind.lib,osgTextd.lib,osgUtild.lib,osgViewerd.lib,对于Release版,设置这些lib文件不带"d"的版本.
(由于我们现在使用的是Debug版本,所以只用填写Debug信息)
具体步骤:链接器-->输入-->附加依赖项 中填写
OpenThreadsd.lib
osgd.lib
osgDBd.lib
osgFXd.lib
osgGAd.lib
osgIntrospectiond.lib
osgManipulatord.lib
osgParticled.lib
osgShadowd.lib
osgSimd.lib
osgTerraind.lib
osgTextd.lib
osgUtild.lib
osgViewerd.lib
-->确定-->确定

设置编译时头文件路径
工具-->选项-->项目-->VC++ 目录-->显示以下内容的目录(S)-->包含文件-->在最后面创建一个新的目录-->最后行的地方双击,添上 C:\OSG\OSG2.6\include 一项

设置编译时库文件路径
工具-->选项-->项目-->VC++ 目录-->显示以下内容的目录(S)-->库文件-->在最后面创建一个新的目录-->最后行的地方双击,添上 C:\OSG\OSG2.6\debug\lib


这样,工程属性就设置好了.

merryboy 发表于 2008-11-28 13:58:38

7、编辑程序
首先 在左尖三角 选择成Debug
然后在刚才建立的空文件里输入如下内容:
/* OpenSceneGraph example, osgpick.
*
*Permission is hereby granted, free of charge, to any person obtaining a copy
*of this software and associated documentation files (the "Software"), to deal
*in the Software without restriction, including without limitation the rights
*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions:
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*THE SOFTWARE.
*/
/* osgpick sample
* demonstrate use of osgUtil/PickVisitor for picking in a HUD or
* in a 3d scene,
*/
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgGA/TerrainManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/io_utils>
#include <osgText/Text>
#include <sstream>
// class to handle events with a pick
class PickHandler : public osgGA::GUIEventHandler {
public:
    PickHandler(osgText::Text* updateText):
      _updateText(updateText) {}
      
    ~PickHandler() {}
   
    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);
    virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea);
    void setLabel(const std::string& name)
    {
      if (_updateText.get()) _updateText->setText(name);
    }
   
protected:
    osg::ref_ptr<osgText::Text>_updateText;
};
bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
    switch(ea.getEventType())
    {
      case(osgGA::GUIEventAdapter::PUSH):
      {
            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
            if (view) pick(view,ea);
            return false;
      }   
      case(osgGA::GUIEventAdapter::KEYDOWN):
      {
            if (ea.getKey()=='c')
            {      
                osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
                osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter(ea);
                event->setX((ea.getXmin()+ea.getXmax())*0.5);
                event->setY((ea.getYmin()+ea.getYmax())*0.5);
                if (view) pick(view,*event);
            }
            return false;
      }   
      default:
            return false;
    }
}
void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
{
    osgUtil::LineSegmentIntersector::Intersections intersections;
    std::string gdlist="";
    float x = ea.getX();
    float y = ea.getY();
    if (view->computeIntersections(x,y,intersections))
    {
      for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
            hitr != intersections.end();
            ++hitr)
      {
            std::ostringstream os;
            if (!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty()))
            {
                // the geodes are identified by name.
                os<<"Object \""<<hitr->nodePath.back()->getName()<<"\""<<std::endl;
            }
            else if (hitr->drawable.valid())
            {
                os<<"Object \""<<hitr->drawable->className()<<"\""<<std::endl;
            }
            os<<"      local coords vertex("<< hitr->getLocalIntersectPoint()<<")"<<"normal("<<hitr->getLocalIntersectNormal()<<")"<<std::endl;
            os<<"      world coords vertex("<< hitr->getWorldIntersectPoint()<<")"<<"normal("<<hitr->getWorldIntersectNormal()<<")"<<std::endl;
            const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
            for(unsigned int i=0;i<vil.size();++i)
            {
                os<<"      vertex indices ["<<i<<"] = "<<vil<<std::endl;
            }
            
            gdlist += os.str();
      }
    }
    setLabel(gdlist);
}
osg::Node* createHUD(osgText::Text* updateText)
{
    // create the hud. derived from osgHud.cpp
    // adds a set of quads, each in a separate Geode - which can be picked individually
    // eg to be used as a menuing/help system!
    // Can pick texts too!
    osg::Camera* hudCamera = new osg::Camera;
    hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
    hudCamera->setViewMatrix(osg::Matrix::identity());
    hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
    hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
   
    std::string timesFont("fonts/times.ttf");
   
    // turn lighting off for the text and disable depth test to ensure its always ontop.
    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-60.0f,0.0f);
   
    {
      osg::Geode* geode = new osg::Geode();
      osg::StateSet* stateset = geode->getOrCreateStateSet();
      stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
      stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
      geode->setName("simple");
      hudCamera->addChild(geode);
      
      osgText::Text* text = newosgText::Text;
      geode->addDrawable( text );
      
      text->setFont(timesFont);
      text->setText("Picking in Head Up Displays is simple!");
      text->setPosition(position);
      
      position += delta;
    }   
   
   
    for (int i=0; i<5; i++) {
      osg::Vec3 dy(0.0f,-30.0f,0.0f);
      osg::Vec3 dx(120.0f,0.0f,0.0f);
      osg::Geode* geode = new osg::Geode();
      osg::StateSet* stateset = geode->getOrCreateStateSet();
      const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"};
      osg::Geometry *quad=new osg::Geometry;
      stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
      stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
      std::string name="subOption";
      name += " ";
      name += std::string(opts);
      geode->setName(name);
      osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad
      osg::Vec4Array* colors = new osg::Vec4Array;
      colors = new osg::Vec4Array;
      colors->push_back(osg::Vec4(0.8-0.1*i,0.1*i,0.2*i, 1.0));
      quad->setColorArray(colors);
      quad->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
      (*vertices)=position;
      (*vertices)=position+dx;
      (*vertices)=position+dx+dy;
      (*vertices)=position+dy;
      quad->setVertexArray(vertices);
      quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
      geode->addDrawable(quad);
      hudCamera->addChild(geode);
      
      position += delta;
    }   
   
   
   
    { // this displays what has been selected
      osg::Geode* geode = new osg::Geode();
      osg::StateSet* stateset = geode->getOrCreateStateSet();
      stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
      stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
      geode->setName("The text label");
      geode->addDrawable( updateText );
      hudCamera->addChild(geode);
      
      updateText->setCharacterSize(20.0f);
      updateText->setFont(timesFont);
      updateText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
      updateText->setText("");
      updateText->setPosition(position);
      updateText->setDataVariance(osg::Object::DYNAMIC);
      
      position += delta;
    }   
   
    return hudCamera;
}

merryboy 发表于 2008-11-28 13:58:53

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);
    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
   
    // if not loaded assume no arguments passed in, try use default mode instead.
    if (!scene) scene = osgDB::readNodeFile("fountain.osg");
    osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
    if (!group)
    {
      group = new osg::Group;
      group->addChild(scene.get());
    }
    osg::ref_ptr<osgText::Text> updateText = new osgText::Text;
    // add the HUD subgraph.   
    group->addChild(createHUD(updateText.get()));
    if (arguments.read("--CompositeViewer"))
    {
      osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
      // add the handler for doing the picking
      view->addEventHandler(new PickHandler(updateText.get()));
      // set the scene to render
      view->setSceneData(group.get());
      view->setUpViewAcrossAllScreens();
      osgViewer::CompositeViewer viewer;
      viewer.addView(view.get());
      return viewer.run();
    }
    else
    {
      osgViewer::Viewer viewer;

      // add all the camera manipulators
      {
            osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
            keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
            keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
            keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
            unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
            keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
            std::string pathfile;
            char keyForAnimationPath = '5';
            while (arguments.read("-p",pathfile))
            {
                osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
                if (apm || !apm->valid())
                {
                  num = keyswitchManipulator->getNumMatrixManipulators();
                  keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
                  ++keyForAnimationPath;
                }
            }
            keyswitchManipulator->selectMatrixManipulator(num);
            viewer.setCameraManipulator( keyswitchManipulator.get() );
      }
      // add the handler for doing the picking
      viewer.addEventHandler(new PickHandler(updateText.get()));
      // set the scene to render
      viewer.setSceneData(group.get());
      return viewer.run();
    }
}

保存文件(Ctrl+S)-->按F5-->是(Y) ,显示结果.

错误信息:osg fatal error C1060: 编译器的堆空间不足
解决方法:重新安装.NET 2003版本或更高版本的编译环境.
Microsoft Visual Studio .NET 2002(VC7,Microsoft开发环境 2002版本,Version 7.0.9486)会出现的问题
错误信息:test fatal error LNK1104: 无法打开文件"osgIntrospectiond.lib"
解决方法:修改 BUILD_OSG_ARAPPERS这项,由OFF 改成 ON,在CMake中设置哈.
错误信息:atomic下缺少config
解决办法:在build\include 下有Config.h文件,把这些文件拷贝到C:\OSG\OSG2.6\include下.

错误信息:无法解析的外部符号 _winmain@16
解决办法:项目 属性-->链接器-->System-->子系统-->选择 控制台(/SUBSYSTEM:CONSOLE)
为什么OSG2.0里面的代码在OSG 2.6会报错,还没有解决哈.
我这里有编译好的可以调试的资源(没有压缩146MB)(压缩后21.3MB),要的可以说一声.最好能QQ传.
来源于网络,回归于网络.
我的Email:happy.every.day@126.com QQ:48399956
快乐!
2008年11月25日
页: [1]
查看完整版本: Windows下从头开始创建一个最简单的OpenSceneGraph-2.6.0 程序及调试环境Debug)