osg::ComputeBoundsVisitor用法(二)

前一章讲了《osg::ComputeBoundsVisitor用法(一)》,现在继续讲osg::ComputeBoundsVisitor用法。

osg::ComputeBoundsVisitor可以用于在场景中较精确估计模型移动的距离,便于和外部传入的逻辑移动的距离进行交互。例如:现有一个这样的场景:

osg::ComputeBoundsVisitor用法(二)_第1张图片 振动台

 如上图是一个振动台,台子由两个osg模型文件构成,下面的一个osg如下:

osg::ComputeBoundsVisitor用法(二)_第2张图片

上面的osg模型(为便于后文表述,称之为 盖子)缓缓移动插入到下面的底座中, 盖子下移或上升的逻辑距离即外部传入距离为【0, 160】区间内,即下图所示:

osg::ComputeBoundsVisitor用法(二)_第3张图片

先说明物理距离和逻辑距离的概念:

  •  物理距离:是指模型文件中的实际距离。
  •  逻辑距离:是指外部调用方传入的需要模型移动的距离,其往往和模型文件中距离不同。(这两个距离参见后文样例)

问题的提出:

  • 当外部传入要让上面的盖子模型下降或上升Height逻辑距离,如 120 时,对上面的盖子在osg类似osg::Matrix::translate函数中的第三个参数即Z轴上设置的具体数值是多少?

解决方法如下:

利用如下代码算出整个盖子从160下降到0的距离,也即银白色支柱完全被盖子遮住时,盖子下降的高度,可以随便摆个按钮,把下面代码放在按钮单击事件函数中,不停单击按钮,直到银白色支柱部分被上面的盖子下降完全盖住为止,算出后再删除该按钮,按钮仅仅由于探测用:

// 没有被其它函数调用,用于在实际测试中探测盖子上升或下降能移动的最大距离
void  CLaunchWnd::getHolderTranslateHeight()
{
	static int n = 0;
	osg::Matrix curMatrix;

	// 先记录盖子当前位置z轴的最小值
	osg::ComputeBoundsVisitor boundVisitor;
 
        //  
	m_spMatrixTransformHolder1->accept(boundVisitor);
	float fZMin = boundVisitor.getBoundingBox().zMin();
	QString qsZMin = QString::number(fZMin);
	CLogToolKits::getInstance()->writeLog(qsZMin.toStdWString());
	curMatrix = m_spMatrixTransformHolder1->getMatrix();

        // 再相应地移动盖子,看盖子能上升到的最大距离
	curMatrix *= osg::Matrix::translate(0, 0, ++n);
	m_spMatrixTransformHolder1->setMatrix(curMatrix);

        // 只要模型的位置发生了变化,就要重新调用accept一次。
	m_spMatrixTransformHolder1->accept(boundVisitor);
	fZMin = boundVisitor.getBoundingBox().zMin();
	qsZMin = QString::number(fZMin);
         
         // 再次记录盖子当前位置z轴的最小值
	CLogToolKits::getInstance()->writeLog(qsZMin.toStdWString());
}

 说明:上面代码中m_spMatrixTransformHolder1定义为:osg::ref_ptrm_spMatrixTransformHolder1,其是盖子模型的父节点。

            通过记录未移动之前和移动之后两次的zMin到日志,可以算出银白色支柱完全被盖子罩住即银白色支柱的高度。日志记录如下:

osg::ComputeBoundsVisitor用法(二)_第4张图片osg::ComputeBoundsVisitor用法(二)_第5张图片

当盖子位于最大位置时,如果再执行上面代码,盖子和银白色支柱就要分离了,如下:

osg::ComputeBoundsVisitor用法(二)_第6张图片

所以盖子下落或上升的最大物理位移为:4669.22 - 43444.22,因为盖子是匀速下落或上升,可以通过等比例关系算出盖子的移动逻辑距离,如下:

double dfHolderPhysicsMaxHeight = 4699.22;  
double dfHolderPhysicsMinHeight = 4344.22;  

// 盖子能够上升或下降的最大物理位移
double dfMaxPhysicsHolderWeiYi = dfHolderPhysicsMaxHeight - dfHolderPhysicsMinHeight ; 

// dfCurHeight是外部传入的盖子需要移动的逻辑位移,dfOldHeight是盖子上一次移动的逻辑位移
double dfHolderLogicWeiYi = dfCurHeight - dfOldHeight; // 盖子移动的逻辑位移

// 通过逻辑位移,算出盖子移动的物理位移,等比例关系换算而成
dfHolderLogicWeiYi dfHolderPhysicsWeiYi = dfMaxPhysicsHolderWeiYi * dfHolderLogicWeiYi / 160;
	
osg::Matrix curMatrix = spMatrixTransformHolder->getMatrix();
curMatrix *= osg::Matrix::translate(0, 0, nHolderPhysicsWeiYi);
spMatrixTransformHolder->setMatrix(curMatrix);

可以看到本场景通过osg::ComputeBoundsVisitor很好解决了,需要说明的是:上述的等比例关系是在盖子匀速情况下才成立,且只要模型的位置发生了变化即调用translate或缩放即调用了scale之类的函数,就要重新调用osg::ComputeBoundsVisitor类的accept函数一次,以获取最新的位置信息。

你可能感兴趣的:(#,osg基础技术点,osg,ComputeBounds)