osg中HUD抬头显示重复投射的问题分析

osg中HUD抬头显示重复投射的问题分析_第1张图片

在OSG场景中,采用HUD抬头显示来显示模型的运动参数,但是运行的时候发现HUD出现重复投射的现象,如图中红线框中所示。

抬头显示的CreateHUDText函数如下:

// 创建HUD抬头显示文字
osg::Projection* cOSG::CreateHUDText(void)
{

	// 获取屏幕尺寸
	RECT rect;
	int rect_width,rect_height;
	// Get the current window size
	::GetWindowRect(m_hWnd, &rect);
	rect_width = rect.right - rect.left;
	rect_height = rect.bottom - rect.top;

	// 投影节点用于定义HUD的视景体(view frustrum)
	osg::Projection* HUDProjectionMatrix = new osg::Projection;
	// 投影矩阵的水平和垂直范围与屏幕尺寸相同,
	// 因此该节点子树中的位置坐标将等同于像素坐标
	HUDProjectionMatrix->setMatrix(osg::Matrix::ortho2D(0,rect_width,0,rect_height));
	// HUD模型观察矩阵应使用单位矩阵
	osg::MatrixTransform* HUDModelViewMatrix = new osg::MatrixTransform;
	HUDModelViewMatrix->setMatrix(osg::Matrix::identity());
	// 确保模型观察矩阵不会被场景图形的位置变换影响
	HUDModelViewMatrix->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
	// 添加HUD模型观察矩阵到HUD投影矩阵
	HUDProjectionMatrix->addChild(HUDModelViewMatrix);
	// 添加文字套Geode叶节点中
	HUDModelViewMatrix->addChild(HUDGeode);

	osg::StateSet* HUDStateset = new osg::StateSet();
	HUDGeode->setStateSet(HUDStateset);
	HUDStateset->setMode(GL_BLEND,osg::StateAttribute::ON);
	//关闭光照
	HUDStateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
	// 关闭深度测试
	HUDStateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
	// 透明渲染
	//HUDStateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
	//osgUtil::RenderBin* HUDBin = 
	//new osgUtil::RenderBin(osgUtil::RenderBin::SORT_BACK_TO_FRONT);
	// 确认背景板几何体在最后进行绘制。渲染元(RenderBin)按照数字顺序进行渲染
	// 因此我们设置一个比较大的数字值
	HUDStateset->setRenderBinDetails(11,"DepthSortedBin");

	//////////////////////////////////////////////////////////////////////////
	// 为创建抬头显示信息(HUD)文字显示做准备
	white = osg::Vec4(1.0f,0.0f,0.0f,1.0f);
	// 用来显示汉字
	font_China = osgText::readFontFile("fonts/simhei.ttf");
	text_China = new osgText::Text;
	text_China->setFont(font_China.get());
	text_China->setColor(white);
	text_China->setCharacterSize(20.0);

	text_China->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
	text_China->setPosition(osg::Vec3(0.857*rect_width,0.955*rect_height,0.0f));
	text_China->setDrawMode(osgText::Text::TEXT /*| osgText::Text::BOUNDINGBOX*/);

	font = osgText::readFontFile("Fonts/arial.ttf");
	text_heading = new osgText::Text;

	text_heading->setFont(font.get());
	text_heading->setColor(white);
	text_heading->setCharacterSize(20.f);

	// 制定字符在屏幕上显示的大小,Text可以根据视角,适当缩放文字几何体
	// 以保持它在屏幕上的恒定尺寸
	text_heading->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
	text_heading->setPosition(osg::Vec3(0.892*rect_width,0.955*rect_height,0.0f));
	text_heading->setDrawMode(osgText::Text::TEXT /*| osgText::Text::BOUNDINGBOX*/);

	HUDGeode->addDrawable(text_heading.get());
	HUDGeode->addDrawable(text_China.get());

	return HUDProjectionMatrix;
}
//将HUD作为group节点的子节点
group_SpecialEffects->addChild(CreateHUDText());
//将group节点作为root根节点的子节点
root->addChild(group_SpecialEffects.get());
//创建视口
view1 = CreateView(&m_compositeViewer,root,gc,NULL,0,0,traits->width,traits->height);

上述代码即为HUD显示的结构。出现重复投射的问题后,一开始以为是场景中添加阴影效果、天空盒之后和HUD不兼容或者有冲突的问题,随即把阴影效果模块、天空盒模块都删掉,还是不行。

最后把HUD显示都删掉,发现依然有异常的投射。

osg中HUD抬头显示重复投射的问题分析_第2张图片

这个时候,就有点头绪了,那应该不是其他模块的影响,有可能是重复的加载了HUD显示模块中的文字信息。果然,在 PreFrameUpdate函数中,有这么一行代码:

view1->getCamera()->addChild(HUDGeode.get());

HUDGeode正是CreateHUDText函数中的叶节点对象,是绘制这些的文字的父节点,即相当于把HUD显示的信息重新加载了一遍。把这行代码删除,重复投射的问题就解决了。

通过上述问题,有以下两点的体会:

1、写代码的时候一定要仔细、严谨,否则会付出更多的经历和时间去找BUG;

2、找BUG的时候,需要一步步的排查,逐步缩小范围,排除所有的可疑点后,问题一般就会水落石出了。

你可能感兴趣的:(OSG)