OSG立体模式下动态修改相机远近裁剪面的实现

1. 非立体模式下动态修改相机远近裁剪面

class GLB_DLLCLASS_EXPORT CGlbGlobeClipHandler : public osg::NodeCallback
    {

  struct CustomProjClamper : public osg::CullSettings::ClampProjectionMatrixCallback
   {

    template<class matrix_type, class value_type>
            bool _clampProjectionMatrix(matrix_type& projection, double& znear, double& zfar, value_type nearFarRatio) const

    {....}

  ...........

  }

}

mpr_cliphandler = new CGlbGlobeClipHandler(p_globe);
mpr_p_root->setUpdateCallback((osg::NodeCallback*)mpr_cliphandler);

在根节点回调中mpr_cliphandler计算CustomProjClamper的成员变量double _nearFarRatio的值,然后在_clampProjectionMatrix中使用它来计算最远最近裁剪面.

osg::ref_ptr<osg::CullSettings::ClampProjectionMatrixCallback> clamper = new CGlbGlobeClipHandler::CustomProjClamper();

mpr_cliphandler->mpr_p_clampers[mpr_osgviewer->getCamera()] = clamper;
mpr_osgviewer->getCamera()->setClampProjectionMatrixCallback(clamper.get());

2. 立体模式下动态修改相机远近裁剪面

在osg3.2.1版本上测试发现,红绿立体模式、Quad_Buffer立体模式下以上代码不起作用,不能动态修改远近裁剪面 。

追踪源代码发现在 osgUtil的SceneView类 void SceneView::cull()中以下代码

_cullVisitorLeft->setDatabaseRequestHandler(_cullVisitor->getDatabaseRequestHandler());
 _cullVisitorLeft->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback());
 _cullVisitorLeft->setTraversalMask(_cullMaskLeft);
 computeLeftEyeViewport(getViewport());
 bool computeNearFar = cullStage(computeLeftEyeProjection(getProjectionMatrix()),computeLeftEyeView(getViewMatrix()),_cullVisitorLeft.get(),_stateGraphLeft.get(),_renderStageLeft.get(),_viewportLeft.get());

// set up the right eye.
 _cullVisitorRight->setDatabaseRequestHandler(_cullVisitor->getDatabaseRequestHandler());
 _cullVisitorRight->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback());
 _cullVisitorRight->setTraversalMask(_cullMaskRight);
 computeRightEyeViewport(getViewport());
 computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),_cullVisitorRight.get(),_stateGraphRight.get(),_renderStageRight.get(),_viewportRight.get());

if (computeNearFar)
 {
       CullVisitor::value_type zNear = osg::minimum(_cullVisitorLeft->getCalculatedNearPlane(),_cullVisitorRight->getCalculatedNearPlane());
       CullVisitor::value_type zFar =  osg::maximum(_cullVisitorLeft->getCalculatedFarPlane(),_cullVisitorRight->getCalculatedFarPlane());
       _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
 }

跟踪发现_cullVisitor中的_clampProjectionMatrixCallback对象为空,说明对主camera设置ClampProjectionMatrixCallback不能影响到_cullVisitor的_clampProjectionMatrixCallback。

这样解决办法就出来了,将主camera用到的ClampProjectionMatrixCallback对象设置一份给_cullVisitor就可以了!!!!!!!!!!

经测试通过,方法可行............................OK

时间: 2024-11-05 00:42:15

OSG立体模式下动态修改相机远近裁剪面的实现的相关文章

awstats CGI模式下动态生成页面缓慢的改进

本文可以看做是 http://kaifly.blog.51cto.com/3209616/1719248 这篇文章的下篇,在使用过程中发现awstats在cgi模式下动态生成分析报告慢的问题 (尤其是有些站点每天两个多G的日志,查看起来简直是在考验人的耐性),本文分享一种改造这个缺点的思路. 首先再来总结下awstats的处理过程以及查看分析结果的两种方式,来看官方版说明: Process logs: Building/updating statistics database,建立/更新统计数据

【案例分享】使用ActiveReports报表工具,在.NET MVC模式下动态创建报表

提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表.今天我们来一起了解一下什么是报表,报表的结构.构成元素,以及为什么需要报表. 什么是报表 简单的说:报表就是通过表格.图表等形式来动态显示数据,并为使用者提供浏览.打印.导出和分析的功能,可以用公式表示为: 报表 = 多样的布局 + 动态的数据 + 丰富的输出 报表通常包含以下组成部分: 报表首页:在报表的开始处,用来显示报表的标题.图形或说明性文字,每份报表只有一个报表首页. 页眉:用来显示报表中的字段名或对记录的

05---MVC模式下动态调整Cell高度三部曲

动态调整Cell高度三部曲 我们在做项目开发的过程中经常会遇到每一个cell的高度及cell的子控件的显示个数不同,以我最近开发的微格为例,讲解一下MVC模式动态的调整Cell宽高的三部曲 1>.自定义Cell,重写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier方法 在此方法中添加所有的可能显示的子控件 子控件的frame通过构建的cellFrame模型进行设置

ubunut在系统恢复模式下无法修改root密码的分析和解决

前些日子本猫的ubuntu 14.10貌似出了点问题,想修改下root密码,但是无奈原系统有错正常情况下无法修改啊,这是逼我重装的节奏吗? 在ubuntu开机后立即按住left_shift不放,调出grub菜单.因为我没装双系统,所以默认grub菜单是隐藏的.依次选择"高级选项"->xxx(recovery mode)->root.咦,还是要root密码才可以进入恢复模式的控制台呢!遂ctl+d,再次重启系统,同样进入xxx(recovery mode)主界面后(不要按回车

Unity3D Editor模式下批量修改prefab

最经遇到一个需要批量修改已经做好的prefab的问题,查了一些资料最终实现了但是还是不够完美,通过学习也发现unity的编辑器功能还是非常强大的.废话不多说直接上代码: 1 [ExecuteInEditMode] 2 [MenuItem("Tools/RecordPoint Add Flame")] 3 private static void RecordPointAddFlame() 4 { 5 GameObject twoSphere = AssetDatabase.LoadAss

微信浏览器下动态修改 微信title

var $body = $('body'); document.title = 'title' // hack在微信等webview中无法修改document.title的情况 var $iframe = $('<iframe src="/favicon.ico"></iframe>').on('load', function() { setTimeout(function() { $iframe.off('load').remove() }, 0) }).ap

vi文本模式下批量修改指定字符串

在Vi里面实现字符串的批量替换. a. 文件内全部替换: %s#abc#def#g(用def替换文件中所有的abc) 例如把一个文本文件里面的"linuxidc.com"全部替换成"linuxidc.net": :%s#linuxidc.com#xwen.net#g (如文件内有#,可用/替换,比如:%s/linuxidc.com/xwen.net/g) b. 文件内局部替换: 把10行到50行内的"abc"全部替换成"def"

CentOS单用户模式下修改ROOT密码和grub加密

Linux 系统处于正常状态时,服务器主机开机(或重新启动)后,能够由系统引导器程序自动引导 Linux 系统启动到多用户模式,并提供正常的网络服务.如果系统管理员需要进行系统维护或系统出现启动异常时,就需要进入单用户模式或修复模式对系统进行管理了. 使用单用户模式有一个前提,就是您的系统引导器(grub)能正常工作,否则要进行系统维护就要使用修复模式. 特注:进入单用户模式,没有开启网络服务,不支持远程连接 Linux 系统中不同的运行级别(Run Level)代表了系统的不同运行状态,例如

单用户模式下mount -o remount,rw / 有大用途

我们的Linux系统在无法启动时候,通常需要进入单用户模式下进行修改一些配置文件,或调整一些参数方可.但是在进入单用户模式后,我们的/文件系统是只读模式,无法进行修改,那么这个时候我们就需要用到一条命令:mount –o remount,rw / 这个命令来让我们的/路径文件系统为可读模式,这样就可以实现自由修改了. 例如: 增加了/etc/mtab /dev/sdb1 /install ext3 rw 0 0 /etc/fstab LABEL=/install /install ext3 de