FAQ

下面所列的是一些用户常见的问题。
更多的问题与解答可以登录3drealtimesimulation.

问题

  1. Q 1:我并不了解什么是OpenSceneGraph,可以简单地介绍一下吗?
  2. Q 2:我在哪里能获取OpenSceneGraph的相关信息?
  3. Q 3:OpenSceneGraph和来自www.opensg.org 的OpenSG有什么区别吗?
  4. Q 4:我听说最近即将有OSG相关的书籍出版,请问有没有具体的信息?
  5. Q 5:我不是微软Visual Studio的用户。请问OpenSceneGraph是否支持其他的编译环境,例如mingw32?
  6. Q 6:我从哪里可以获得.osg文件格式的参考手册?我在OSG的文档目录下没有找到相关信息。
  7. Q 7:我可以使用CVS来获取最新的源代码吗?
  8. Q 8:我为什么不能在VisualStudio中读取OSG的工程文件了?
  9. Q 9: OpenSceneGraph的摄像机类是什么?
  10. Q 10:我试图保存节点到文件的时候,OSG却崩溃了。我使用Windows系统。是不是VisualStudio的STL库造成了这种影响?
  11. Q 11:如何在OSG中渲染地形?
  12. Q 12:我的GLUT使用得不理想,又或者GLUT不支持某些特性怎么办?
  13. Q 13:有没有可能在场景中绘制2D图像?
  14. Q 14:我怎样能够移动场景中的模型?
  15. Q 15: 15:为什么在我的osghangglide例程中,山体是全白色且没有阴影的?
  16. Q 16:我已经编译生成了所有的文件,但是链接时会出现错误,运行时还会出现崩溃?
  17. Q 17: 17:我在编译的时候看到了很多“warning C4541: ‘dynamic_cast’ used on polymorphic type ‘class osg::Object’ with /GR-”字样的警告信息,这是怎么回事?
  18. Q 18: 我不熟悉矩阵数学的运算,怎么办?
  19. Q 19: 我可以实现骨骼动画吗?
  20. Q 20. OSG似乎忽略了我设置的近/远剪切平面(near/far clipping plane),为什么?
  21. Q 21. 如果我交由OpenSceneGraph负责远/近剪切平面的计算,那我如何得到计算的值呢?
  22. Q 22:有没有可以参考的教程?
  23. Q 23:我在编译OSG 0.9.4-2时,出现了“Producer/*.: No such file or directory”的错误,为什么?
  24. Q 24: OpenSceneGraph都支持什么数据格式?
  25. Q 25:为什么OSG的头文件命名不是.h或者.hpp后缀?
  26. Q 26: 我的编辑器不能将OSG头文件识别为C++文件,怎么办?
  27. Q 27: 我尝试在Mac OSX下运行OpenSceneGraph的示例程序,但是没有显示窗口,这是怎么回事?
  28. Q 28: 为了调试方便,我希望程序运行时出现更多的提示信息,有可能吗?
  29. Q 29: OSG的发行版中包括了Qt等GUI开发框架的嵌入方法示例,那么对于Gnome/GTK+是否也有类似的例子?
  30. Q 30: 我的OSG粒子系统是可用的,但是把它放置于场景中时会出现奇怪的现象,怎么回事?
  31. Q 31: 我在使用PrimitiveSet对象表示单个点的时候,或者说,我创建的几何体在距离视点很远的时候好像突然消失了,为什么?
  32. Q 32: 当我执行MatrixTransform节点的放缩变换时,我的模型颜色变暗或者变淡了,这是怎么回事?
  33. Q 33: 如何向.osg文件中插入说明信息,换句话说,如何对.osg文件中的段落进行注释?
  34. Q 34: 可以在一个已有的渲染系统中使用OSG吗?
  35. Q 35: 我从osg::Drawable派生了新的类,但是我的drawImplementation函数只被系统调用了一次?
  36. Q 36: 我可以在OSG中直接使用OpenGL命令吗?
  37. Q 37: 如果我不使用Producer,我可以使用已有的MFC或者wxWidgets窗口来运行OSG吗 ?
  38. Q 38: 我能够为OpenSceneGraph的发展做出什么贡献?
  39. Q 39: 如何得到一个加载后的节点或者3D模型的包围盒(BoundingBox)?
  40. Q 40: 当我使用了多个视口或者多个渲染窗口时,我用到的纹理显示不正确?
  41. Q 41: 我设置两个或多个视口共享同一个场景图形,但是我希望限制各个视口中只显示场景图形的某一部分,我应该怎么做?
  42. Q 42: 对于上一个问题,好像我的设置没有效果?
  43. Q 43: 如何捕捉屏幕图像?
  44. Q 44: 如何在运行时改变Producer的图标?
  45. Q 45: 如何添加一个新的维基(Wiki)页面?
  46. Q 46: 当我渲染点精灵(point sprite)到FBO/pbuffer时,我的帧速下降很快,怎么办?
  47. Q 47:我已经设置透明色或者透明材质了,但是我的几何体还是以实体形式渲染,为什么?


Q 1:我并不了解什么是OpenSceneGraph,可以简单地介绍一下吗?

OpenSceneGraph是一个基于C++的3D图形开发库。SceneGraph库允许用户使用图形数据结构来表达场景中的物体,其中图形数据结构指的是,将一些具有公共属性的对象成组,以便在必要的时候修改全组对象的共同属性。OpenSceneGraph可以自动管理场景绘制的必要资源,如细节层次(LOD)等;但是一些不必要的细节,例如那些会降低图形硬件场景绘制速度的代码,则不在此列。

Q 2: 我在哪里能获取OpenSceneGraph的相关信息?

A: 可以登录下面的地址:

官方网站 http://openscenegraph.org/ 新闻邮件组 http://openscenegraph.org/mailman/listinfo/osg-news 用户邮件组 http://openscenegraph.org/mailman/listinfo/osg-users

Q 3:OpenSceneGraph和来自www.opensg.org 的OpenSG有什么区别吗?

A: 请参阅下面的说明:

http://donburns.net/osgarchiver/archives/June2004/0615.html http://donburns.net/osgarchiver/archives/August2003/0410.html

Q 4: 我听说最近即将有OSG相关的书籍出版,请问有没有具体的信息?

A: 现在您可以登录 http://www.osgbooks.com 随时关注OSG书籍的出版和修订信息。欢迎您购买这些书籍来支持我们的工作。更多的OSG相关书籍将不断推出。

Q 5: 我不是微软Visual Studio的用户。请问OpenSceneGraph是否支持其他的编译环境,例如mingw32?

A:OSG的发行版包括使用Cygwin和Mingw编译的版本,您也可以在用户邮件组中获取相关的支持。

Q 6:我从哪里可以获得.osg文件格式的参考手册?我在OSG的文档目录下没有找到相关信息。

A: UseTheSourceLuke! 请阅读源代码!目前还没有针对OSG场景描述语言的参考文档。

Q 7: 我可以使用CVS来获取最新的源代码吗?

A: 可以。请参阅文档中 SVN的设置方法,以获取最新的OpenSceneGraph版本。

Q 8: 我为什么不能在VisualStudio中读取OSG的工程文件了?

A: 请注意,OSG早期版本的.makefile文件并不是用Developer Studio生成的,因此有些.dsp文件可能使用Unix结束符格式进行保存。你可以采取多种方法来解决这一问题。比如:使用写字板打开并重新保存.dsp文件;使用cygwin工具unix2dos;或者使用WinZip来打开tar压缩包(注意选中WinZip的“TAR File Smart CR/LF conversion”选项,它位于Options->Configuration->Miscellaneous)。

Q 9: OpenSceneGraph的摄像机类是什么?

A:有以下三种选择:
1、建议使用osgViewer。osgviewer以及其他几乎所有的示例程序都演示了构造场景的方法,主要使用了一个osgViewer对象以及一个响应用户输入来控制摄像机的漫游器对象(manipulator)。
2、使用osgUtil::SceneView和osg::Matrix。
3、创建自己的摄像机类。

Q 10: 我试图保存节点到文件的时候,OSG却崩溃了。我使用Windows系统。是不是VisualStudio的STL库造成了这种影响?

A: 微软的编译环境对于STL的实现有一些已知的问题。一个解决方法是使用STLport(http://www.stlport.org/),并安装最新的VS集成补丁(service pack)。如果这一问题仍然存在,请确信原先的OpenSceneGraph版本已经清理完毕并重新进行了编译。VC++的较新版本(VC7及以上)已经修正了对STL的支持,因此不必再使用STLport。

Q 11: 如何在OSG中渲染地形?

A: OpenSceneGraph包括了osgTerrain NodeKit库的支持,用于实现大型分页地理信息数据库的生成。
如果你希望实现对地形添加连续变化的细节层次,请参阅Demeter(http://www.terrainengine.com/)和http://www.vterrain.org/

 

Q 12: 我的GLUT使用得不理想,又或者GLUT不支持某些特性怎么办?

A: 你也可以使用wxWidgets(http://www.wxwidgets.org/),或者SDL(Simple Direct Media Layer,http://www.libsdl.org/)。它们都是开源软件且支持OpenGL ,因此可以与OSG相整合。

Q 13: 有没有可能在场景中绘制2D图像?

A: 可以参考examples/osghud.cpp的源代码。你可以在场景中创建一个子图形来浏览3D场景,再创建另一个子图形,使用osg::Projection或者osg::MatrixTransform设置其正交投影变换,实现绘制2D图形的功能。

Q 14: 我怎样能够移动场景中的模型?

A: 可以考虑将模型节点添加给Transform节点。这样就可以通过改变Transform节点的变换值来移动模型。可以参考osgreflect的源代码,其中使用Transform创建模型的镜像体,以实现所需的功能。

Q 15:为什么在我的osghangglide例程中,山体是全白色且没有阴影的?

A: 可能的原因是:程序没有查找到osgdb_rgb,也许是因为rgb文件插件没有进行编译。
1、检查程序是否能获取所需的纹理数据文件。
2、检查是否已经下载了演示用的数据文件包。确认INSTALL文件中所述的环境变量的设置是否正确,包括OSGHOME,OSGDATA和OSGFILEPATH。在Windows环境中,设置环境变量的位置为:控制面板->系统->高级->环境变量。

Q 16: 我已经编译生成了所有的文件,但是链接时会出现错误,运行时还会出现崩溃?

A: 可以尝试make clean,然后make。这类问题有时是因为版本不同,以致API函数或者工程链接库的设置改变而造成的。尝试清除并重新编译所有的文件即可解决这一问题。
链接错误还可能是由于Visual Studio没有添加某些库而导致的。在工程的设置菜单下,点击“链接”选项卡,对于每一个可能用到的.dll链接库,都需要与一个同名的.lib文件对应。例如,如果程序需要使用调试版的核心库osgd.dll,那么便需要在设置中添加对应的osgd.lib。其搜索路径可以在“工具”->“选项”中设置。
在Linux下,如果要设置.lib库的路径,需要在/etc/ld.so.conf.d/进行添加,并执行ldconfig。

Q 17: 我在编译的时候看到了很多“warning C4541: ‘dynamic_cast’ used on polymorphic type ‘class osg::Object’ with /GR-”字样的警告信息,这是怎么回事?

A: 需要打开允许运行时类型(run-time type)的标识。在VisualStudio中,可以直接在工程选项里添加/GR参数,也可以在工程设置菜单中,选择“C++”选项卡的“Language”项,并选中“Enable RTTI”项。

Q 18: 我不熟悉矩阵数学的运算,怎么办?

A: 您不妨参考这个网址: http://www.j3d.org/matrix_faq/

Q 19: 我可以实现骨骼动画吗?

A: 开源工程osgCal集成了OSG与Cal3D,请参考: - http://osgcal.sourceforge.net/

Q 20. OSG似乎忽略了我设置的近/远剪切平面(near/far clipping plane),为什么?

A:使用osgUtil::SceneView时,远/近剪切平面在运行时根据视点与场景的值自动进行计算。这种设计可以优化深度缓存的远/近深度范围,否则可能由于远/近平面的设置不当而产生斑驳(z-fighting)的现象。
用户也可以重新设置这一特性,使用:
sceneview->setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR)
如果视口为osgProducer::Viewer,则可以使用:
viewer.getCullSettings().setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);

Q 21. 如果我交由OpenSceneGraph负责远/近剪切平面的计算,那我如何得到计算的值呢?

A: 可以使用拣选访问器(cull visitor)特性,即:
sceneView->getCullVisitor()->getCalculatedNearPlane();
sceneView->getCullVisitor()->getCalculatedFarPlane();

Q 22: 有没有可以参考的教程?

A: 在这个链接中可以找到更多教程-> here.

Q 23:我在编译OSG 0.9.4-2时,出现了“Producer/*.: No such file or directory”的错误,为什么?

A:请首先安装 OpenProducer

Q 24: OpenSceneGraph都支持什么数据格式?

您可以搜索src/osgPlugins文件夹,其中包括所有OSG支持的数据格式。下表所列的文件格式截止到2007年6月:

\3dc
ac3d
bmp
dds
directx
dw
dx
flt
fly
freetype
geo
gif
iv
ive
jpeg
lib3ds
logo
logos
lwo
md2
obj
osg
osgParticle
osgText
osgtgz
out
pfb
pic
png
pnm
quicktime
rgb
tga
tgz
tiff
txp
zip

您可以参考各个插件目录下的详细解释和源代码,以获取更多信息。
Demeter(http://www.terrainengine.com/)和Virtual Terrain Project(http://www.vterrain.org/)还提供了更多的文件格式支持。

 

Q 25: 为什么OSG的头文件命名不是.h或者.hpp后缀?

A: Robert Osfield针对这个问题在邮件组发表过一篇文章,请参见:

http://sourceforge.net/mailarchive/message.php?msg_id=5544675 http://osgcvs.no-ip.com/osgarchiver/archives/July2003/0575.html

Q 26: 我的编辑器不能将OSG头文件识别为C++文件,怎么办?

A: 可以根据编辑器和系统平台的特性进行修改:
? VisualStudio:OSG源代码的VisualStudio目录下中有一个名为LANGEXT.DAT的文件,可以按照其中的说明进行修改。
? Vim:OSG头文件包含一个模式字符串“-*-c++-*-”,位于每个头文件的开始处。启动Vim,输入“:set runtimepath”指定Vim查找脚本的位置。然后即可在指定的目录下创建配置文件。进入或者创建刚指定的目录,再在该目录下创建文件scripts.vim。文件的内容如下:
? if getline(1) =~ '-*-c++-*-'
? set filetype=cpp
? endif
? Emacs:记忆模式字符串即可。
? Nedit:可以指定某些目录下的文件均为C++文件。
? Dev-C++:在Tools->Editor Options->General菜单下,“Use Syntax Highlighting”编辑框内添加“;;”,编辑框的内容应当类似“c;cpp;h;hpp;;”这样就可以不检查扩展名就执行文件的语法检查。

Q 27: 我尝试在Mac OSX下运行OpenSceneGraph的示例程序,但是没有显示窗口,这是怎么回事?

A: 在运行程序之前,需要设置以下的环境变量:
? tcsh:
? setenv DYLD_BIND_AT_LAUNCH 1
? bash:
? export DYLD_BIND_AT_LAUNCH=1
如果在运行OSG程序时出现“can’t open library”的错误信息,则需要设置环境变量DYLD_LIBRARY_PATH,指定OSG库文件和插件文件的路径。

Q 28: 为了调试方便,我希望程序运行时出现更多的提示信息,有可能吗?

A: 设置OSG_NOTIFY_LEVEL环境变量,将提示信息设置为更高级别,OSG的调试信息级别从低到高为:(参考include/osg/Notify)
ALWAYS
FATAL
WARN
NOTICE
INFO
DEBUG_INFO
DEBUG_FP

Q 29: OSG的发行版中包括了Qt等GUI开发框架的嵌入方法示例,那么对于Gnome/GTK+是否也有类似的例子?

A: 可以参考OSGEdit的源代码(http://www.sf.net/projects/osgedit),它包括了一个GTK的事件适配器。(在OSGEdit程序源代码中实现了一个C++类,用于将GTK+收到的事件适配到osgGA的事件框架中)

Q 30: 我的OSG粒子系统是可用的,但是把它放置于场景中时会出现奇怪的现象,怎么回事?

A:有可能是粒子系统对象(particle system)和粒子发射器(emitter)对象同时被旋转了。粒子系统对象的位置变换必须与绝对世界坐标系,或者粒子的参考坐标系(例如发射粒子的飞机或汽车)相一致。如果要改变参考坐标系中粒子的位置,则应当仅仅改变发射器的位置,而非改变继承自Drawable的ParticleSystem对象。当用户为“fountain.osg”的根节点添加一个Transform变换时,事实上已经为发射器和粒子系统同时添加了位移/旋转变换;因此,为了获得正确的结果,用户应当遍历场景图形并避免为包含ParticleSystem对象的Geode叶节点错误地添加Transform。(感谢Marco Jez的回答)
下面的链接中讨论了这一问题并给出了相应的源代码:
http://www.nps.navy.mil/cs/sullivan/osgTutorials/osgParticleHelper.htm

 

Q 31: 我在使用PrimitiveSet对象表示单个点的时候,或者说,我创建的几何体在距离视点很远的时候好像突然消失了,为什么?

A: 缺省情况下,OSG使用一种“小特性拣选”(small feature culling)的方法来选出大于单位预定义屏幕尺寸的物体。有一些物体的细节较多,与视点相距一定距离的时候,忽略这些细节也不会影响到观察的质量,此时上述特性是十分有用的。不过用户也可以重置osgUtil::SceneView对象的cullingMode属性来禁止这一特性:
osg::CullStack::CullingMode cullingMode = sceneview->getCullingMode();
cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING);
sceneview->setCullingMode( cullingMode );
也可以调整“小特性拣选”所参照的单位屏幕像素大小,使用:
sceneview->setSmallFeatureCullingPixelSize( minimumSize );

Q 32: 当我执行MatrixTransform节点的放缩变换时,我的模型颜色变暗或者变淡了,这是怎么回事?

A:可能是法线由于几何顶点的放缩也随之变化了。为了保证法线始终是归一化的,需要设置StateSet对象的属性:
stateSet->setMode( GL_RESCALE_NORMAL, osg::StateAttribute::ON );

Q 33: 如何向.osg文件中插入说明信息,换句话说,如何对.osg文件中的段落进行注释?

A:根据.osg文件解析的特性,可以采取如下的方法向.osg文件插入注释:
Comment {
This file is proprietary and you shoudn't be reading it.
Please close your editor now!
-Microsoft
}
如果想要屏蔽文件中的一个段落,则使用:
Comment {
TexGen {
UniqueID TexGen_4
DataVariance? STATIC
mode SPHERE_MAP=]
}
}

Q 34: 可以在一个已有的渲染系统中使用OSG吗?

A: 这有一定的难度,不过在一个已有的渲染系统中使用OSG是完全可能的。
首先,OSG的核心部件是osgUtil::SceneView。这个类负责管理OSG特有的渲染任务。如果你希望用到OSG的动画特性,那么还需要构建自己的FrameStamp对象。
这两个对象的设置如下所示:
unsigned int frameNumber = 0;
osg::Timer timer;
osg::Timer_t start_tick = timer.tick();
osg::ref_ptr<osgUtil::SceneView> sceneViewer = new osgUtil::SceneView();
osg::ref_ptr<osg::FrameStamp> frameStamp = new osg::FrameStamp();

sceneViewer->setDefaults();
sceneViewer->setComputeNearFarMode( osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR );
sceneViewer->setSceneData( rootNode );
注意,这里需要把rootNode替换为实际的OSG模型节点。
注意,上面的代码调用了setComputeNearFarMode函数,这一点非常重要。否则的话,OSG可能会在渲染对象时使用不同的远/近平面,因而对象在深度缓存中的数值也可能与其它场景不同,因而产生一些古怪的错误。
如果你希望使用与渲染器其它部分不同的光照,在这里可以调用:
sceneViewer->setLightingMode( osgUtil::SceneView::SKY_LIGHT );
或者
sceneViewer->setLightingMode( osgUtil::SceneView::HEADLIGHT );
基本的设置过程就是这样。
现在我们需要调用SceneView以进行渲染,这还需要下面所述的一些工作。
第一,建议用户在OpenGL代码执行之前,对所有的模型观察矩阵(modelview),投影矩阵(projection)和纹理矩阵(texture)都调用glPushAttribs( GL_ALL_ATTRIB_BITS )和glPushMatrix,并在用户代码执行完毕之后调用相应的glPopAttribs和glPopMatrix函数,对OSG代码也作同样处理。这样可以避免OSG与其它OpenGL代码产生冲突,示例如下:
glPushAttrib( GL_ALL_ATTRIB_BITS );
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

用户或者OSG的执行代码...

glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
此外,在使用SceneView时,用户需要将已有的视口、投影和模型观察矩阵传递给该对象。示例代码如下:
GLint viewParams[4];
glGetIntegerv( GL_VIEWPORT, viewParams );
sceneViewer->setViewport(viewParams[0], viewParams[1], viewParams[2], viewParams[3]);

GLfloat glMat[16];
osg::Matrix osgMat;

glGetFloatv( GL_PROJECTION_MATRIX, glMat );
osgMat.set( glMat );
sceneViewer->getProjectionMatrix().set( osgMat );

glGetFloatv( GL_MODELVIEW_MATRIX, glMat );
osgMat.set( glMat );
sceneViewer->getViewMatrix().set( osgMat );
下一步是更新FrameStamp对象(如果你使用自己编写的类):
double time_since_start = timer.delta_s( start_tick, timer.tick() );
frameStamp->setReferenceTime( time_since_start );
frameStamp->setFrameNumber( frameNumber++ );
sceneViewer->setFrameStamp( frameStamp.get() );
最后,你可以调用SceneView对象的方法了:
sceneViewer->update ();
sceneViewer->cull ();
sceneViewer->draw ();
如果上述的过程都正确,应当可以成功地在另外的渲染系统中使用OSG了,这样可以利用OSG的诸多优势,而不必担心出现系统之间的冲突

Q 35: :我从osg::Drawable派生了新的类,但是我的drawImplementation函数只被系统调用了一次?

A: 可以尝试关闭这个类的显示列表支持:
drawable->setUseDisplayList( false );
否则的话,系统会生成一个显示列表,它会在下一次渲染时替代drawImplementation函数来绘制图形。

Q 36: 我可以在OSG中直接使用OpenGL命令吗?

A: 可以的,请参看osgteapot例程。

Q 37: 如果我不使用Producer,我可以使用已有的MFC或者wxWidgets窗口来运行OSG吗?

A: 不使用Producer(仅限于OSG 1.2版本),甚至没有创建任何窗口都是可以使用OSG的,可以参看OSG 1.2版本的osgsimple例程,它演示了如何在一个普通的窗口环境下运行OSG。OSG本身不判断是否存在窗口,因此用户程序可以使用普通窗口和OpenGL图形上下文(graphics context)来运行OSG。osgsimple中使用了Producer,但是其框架也可以在用户自己的窗口系统中实现。
用户可以选择Producer或者自己的窗口环境来运行OSG,设置摄像机Camera的RenderSurface属性(仅限于OSG 1.2版本),如下:
osgProducer::Viewer viewer;
viewer.getCamera(0)->getRenderSurface()->setWindow( myWindow );
其中变量myWindow对应一个X11的窗口,或者Win32的窗口句柄。
更多信息请参考http://osgcvs.no-ip.org/osgarchiver/archives/November2004/1019.html

Q 38: 我能够为OpenSceneGraph的发展做出什么贡献?

A: 对某些功能做出改动后,做出适当的说明,并将整个文件发送到OSG邮件组列表。不要在邮件中仅仅发送改动的地方,或者文件的一部分,那样可能因为难以检查和合并而无法被接收。
您也可以在网站的社区(Community)版块发布代码改动和文章。欢迎您为OSG开发全新的功能模块,例如新的NodeKits和插件。然后您只需要在osg-users和osg-submissions邮件组发布新的消息即可。

Q 39: 如何得到一个加载后的节点或者3D模型的包围盒(BoundingBox)?

A: 为了保证性能,OSG的所有内部节点,以及所有的Drawable派生类都保存有osg::BoundingSphere对象。
如果你打算使用节点的包围盒(BoundingBox),那么在这之前需要将其包围球(BoundingSphere)转化为包围盒的形式,即:
BoundingBox bb;bb.expandBy(node->getBound());

Q 40: 当我使用了多个视口或者多个渲染窗口时,我用到的纹理显示不正确?

A:每个渲染窗口都有其独立的OpenGL上下文(OpenGL context)。OSG本身并不知道用户是如何设置窗口显示的,因此我们需要保证每个osg::State对象都与其独一无二的OpenGL上下文相关联,因此我们需要:
1. 对于每个窗口,获取关联的osgUtil::SceneView对象。
2. 对于每个SceneView对象,获取关联的osgUtil::State对象。
3. 调用State对象的State::setContextID()方法,将一个不重复的数字作为OpenGL上下文的唯一标识。
以上的步骤可以表述为:
// 这个方法将会自动创建osg::State对象
sceneview0->setDefaults();
// 设置ID为0(缺省情况下自动设置为0)sceneview0->getState()->setContextID(0);

sceneview1->setDefaults();
sceneview1->getState()->setContextID(1);
注意,上下文ID是作为向量索引使用的,它会自动增加,因此请尽量避免设置很大的数。从0开始计数,然后逐次递增即可。

Q 41: 我设置两个或多个视口共享同一个场景图形,但是我希望限制各个视口中只显示场景图形的某一部分,我应该怎么做?

A:视口中绘制的图像取决于拣选遍历(Cull Traversal)的结果。每个视口都有唯一的osgUtil::SceneView对象,且每个osgUtil::SceneView都有唯一的CullVisitor对象。用户可以设置每个CullVisitor对象(或者SceneView类的CullSettings对象)的遍历掩码(traversal mask),在CullVisitor遍历各个节点时,它会执行其apply方法并执行“按位与”操作。而对于每个节点,可以设置其拣选掩码的值,不同的视口会显示与其掩码相对应的场景子图形。
如下所示:
leftSceneView->getCullVisitor()->setTraversalMask( 0x1);
rightSceneView->getCullVisitor()->setTraversalMask( 0x2 );

leftNode->setNodeMask(0x1);
rightNode->setNodeMask(0x2);

 

Q 42: 对于上一个问题,好像我的设置没有效果?

A:当用户使用osgProducer::Viewer类时,可以使用更简单的方法来设置视口所有Camera对象和SceneHandler对象(包括SceneView)的全局属性。这其中也包括遍历掩码,缺省情况下设置为0xFFFFFFFF。在设置某个CullVisitor的遍历掩码之前,用户需要保证它不会与全局的掩码设置发生冲突,参考代码如下:(CullSettings在遍历过程中会传递给CullVisitor对象)
osgProducer::Viewer::SceneHandlerList shl = viewer.getSceneHandlerList();
osgProducer::Viewer::SceneHandlerList::iterator p;
unsigned int n = 0;
for( p = shl.begin(); p != shl.end(); p++ )
{
int inheritanceMask = (*p)->getSceneView()->getInheritanceMask();
inheritanceMask &= ~(osg::CullSettings::CULL_MASK);
(*p)->getSceneView()->setInheritanceMask( inheritanceMask );
(*p)->getSceneView()->setCullMask( 1<<(n));
n++;
}

Q 43: 如何捕捉屏幕图像?

A: Producer的例子,请参看ViewerEventHandler.cpp,ViewerEventHandler::SnapImageDrawCallback方法:
int x,y;
unsigned int width,height;
camera.getProjectionRectangle(x,y,width,height);
osg::ref_ptr<osg::Image> image = new osg::Image;
image->readPixels(x,y,width,height, GL_RGB,GL_UNSIGNED_BYTE);
osgDB::writeImageFile(*image,_filename);
GLUT的例子请参看SST工程:
osg::ref_ptr<osg::Image>image = new osg::Image;
unsigned int w = glutGet(GLUT_WINDOW_WIDTH);
unsigned int h = glutGet(GLUT_WINDOW_HEIGHT);
image->allocateImage(w, h, 1, GL_RGB, GL_UNSIGNED_BYTE);
image->readPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE);

Q 44 : 如何在运行时改变Producer的图标?

A:对于Microsoft Windows和Visual Studio 7.x的用户:
首先在解决方案中添加一个图标(工程->添加资源->图标)。
当viewer->realize()执行之后,执行下面的代码:
Producer::Window wnd = viewer->getCamera(0)->getRenderSurface()->getWindow();
HICON h1 = LoadIcon(GetModuleHandle(0), "YOUR_ICON");
DWORD dw = SetClassLongPtr(wnd, GCL_HICON, (LONG_PTR)h1);
其中的字符串“YOUR_ICON”需要使用资源文件(.rc)中的图标名称替代。

Q 45: 如何添加一个新的维基(Wiki)页面?

A: 请参看 SandBox!

Q 46: 当我渲染点精灵(point sprite)到FBO/pbuffer时,我的帧速下降很快,怎么办?

A: 简单来说:你可以改变PointSprite对象的坐标零点模式,将其设置为LOWER_LEFT:
osg::PointSprite *ps = new osg::PointSprite;
ps->setCoordOriginMode(osg::PointSprite::LOWER_LEFT);
从原理上讲,可以先阅读nVidia OpenGL 2.0的技术支持文档,有关点精灵的章节。其中有这样的说明文字:
渲染到像素缓存(也就是pbuffer)或者帧缓存(也就是FBO)对象时,可以改变渲染状态GL_POINT_SPRITE_COORD_ORIGIN为GL_LOWER_LEFT,以加快硬件渲染速度。指定该属性为GL_UPPER_LEFT时,pbuffer和FBO的渲染将会强制在CPU上执行点的位置变换。

Q 47: 我已经设置透明色或者透明材质了,但是我的几何体还是以实体形式渲染,为什么?

A:你需要将StateSet关联到几何体或者它的父物体上,以便激活OpenGL图像混合模式(GL_BLEND):
file geom.osg

Geometry {
[...]
StateSet {
GL_BLEND ON
}
PrimitiveSets 1
{
[..]