OSG中的DataVariance

前言

要设置一个Object 对象的数据变量,可以调用setDataVariance()并设置输入
参数为Object::DataVariance 枚举量。初始状态下,变度的值是UNSPECIFIED。
用户程序可以将数据变度更改为STATIC 或者DYNAMIC。OSG 将确保绘制遍历
在所有的DYNAMIC 节点和数据处理完成后才会返回。同样,由于绘制遍历在
函数返回后仍然可以继续渲染场景图形,OSG 将确保此时只有STATIC 数据可以
继续进行图形渲染。如果用户的场景图形包含了很少的DYNAMIC 数据,那么
绘制遍历可以很快返回,保证用户程序可以继续执行其它的任务。
场景数据动态更新的核心就是设置数据变度属性DataVariance,它决定了OSG在多线程渲染的过程中的执行策略:只有所有DYNAMIC属性的对象被渲染完毕之后,OSG才会开始执行下一帧的用户更新操作;这样有效地可以避免数据的过快更新造成当前的渲染动作出错,以致系统崩溃。

程序崩溃的原因:
当用户开发了动态更改场景图形的代码时,可能会在修改场景
图形时遇到程序崩溃或者段错误的情况。诸如此类的问题往往都是
由于用户在拣选和绘制遍历过程中修改了场景图形的数据,而造成
系统崩溃。

要设置一个Object 对象的数据变量,可以调用setDataVariance()并设置输入
参数为Object::DataVariance 枚举量。初始状态下,变度的值是UNSPECIFIED。
用户程序可以将数据变度更改为STATIC 或者DYNAMIC。OSG 将确保绘制遍历
在所有的DYNAMIC 节点和数据处理完成后才会返回。同样,由于绘制遍历在
函数返回后仍然可以继续渲染场景图形,OSG 将确保此时只有STATIC 数据可以
继续进行图形渲染。如果用户的场景图形包含了很少的DYNAMIC 数据,那么
绘制遍历可以很快返回,保证用户程序可以继续执行其它的任务。

所有派生自osg::Object的对象都可以设置数据变度的属性,通常设置的时机在新建对象之时,例如:

osg::ref_ptr<osg::Node> createSceneGraph()
{
    
    
	// Load the cow model.
	//osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("E:/osgExercise/CallbackOsg/cow.osg");
	osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
	//osg::ref_ptr<osg::Node> cow = new osg::Node;
	//cow = osgDB::readNodeFile("cow.osg");
	if (!cow.valid())
	{
    
    
		osg::notify(osg::FATAL) << "Unable to load data file. Exiting." << std::endl;
		return nullptr;
	}

	// Data variance is STATIC because we won't modify it.
	cow->setDataVariance(osg::Object::STATIC);

	// Create a MatrixTransform to display the cow on the left.
	osg::ref_ptr<osg::MatrixTransform> mtLeft = new osg::MatrixTransform;
	mtLeft->setName("Left cow \n Dynamic");

	// Set data variance to DYNAMIC to let OSG know that we
	//   will modify this node during the update traversal.
	/*动态更新的核心就是设置数据变度属性DataVariance,它决定了OSG在多线程渲染的过程中的执行策略:只有所有DYNAMIC属性的对象被渲染 完毕之后,
		OSG才会开始执行下一帧的用户更新操作;这样有效地可以避免数据的过快更新造成当前的渲染动作出错,以致系统崩溃。
		这就意味着这个组节点可能在渲染过程中发生变动,可能变动的内容包括:成员属性的改变,新增/替换/删除子节点,或者使用事件/更新/裁减回调实现的自定义变动。*/
	mtLeft->setDataVariance(osg::Object::DYNAMIC);

	// Set the update callback.
	mtLeft->setUpdateCallback(new RotateCB);
	osg::Matrix m;
	m.makeTranslate(-6.f, 0.f, 0.f);
	mtLeft->setMatrix(m);
	mtLeft->addChild(cow.get());

	// Create a MatrixTransform to display the cow on the right.
	osg::ref_ptr<osg::MatrixTransform> mtRight = new osg::MatrixTransform;
	mtRight->setName("Right cow\n Static");
	// Data variance is STATIC because we won't modify it.
	mtRight->setDataVariance(osg::Object::STATIC);
	m.makeTranslate(osg::Vec3(6.f, 0.f, 0.f));
	mtRight->setMatrix(m);
	mtRight->addChild(cow.get());

	// Create the Group root node.
	osg::ref_ptr<osg::Group> root = new osg::Group;
	root->setName("Root node");
	// Data variance is STATIC because we won't modify it.
	root->setDataVariance(osg::Object::STATIC);
	root->addChild(mtLeft.get());
	root->addChild(mtRight.get());

	return root.release();

}
osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
	//osg::ref_ptr<osg::Node> cow = new osg::Node;
	//cow = osgDB::readNodeFile("cow.osg");
	if (!cow.valid())
	{
    
    
		osg::notify(osg::FATAL) << "Unable to load data file. Exiting." << std::endl;
		return nullptr;
	}

	// Data variance is STATIC because we won't modify it.

	mtLeft->setDataVariance(osg::Object::DYNAMIC);

这就意味着这个组节点可能在渲染过程中发生变动,可能变动的内容包括:成员属性的改变,新增/替换/删除子节点,或者使用事件/更新/裁减回调实现的自定义变动。

数据变度的设置对于渲染状态和纹理的动态更新同样有重要的意义。而对于osg::Drawable对象,设置为动态更新意味着它可能在渲染过程中发生顶点属性或者图元的变化;这其中尤为要提及osgText::Text,文字属性的变化必须预先设置动态的数据变度属性,否则可能造成系统运行过程中崩溃:

osg::Vec4 white(osg::Vec4(1.f, 1.f, 1.f, 1.f));
	{
    
    
		//Text.osg文件中有个默认参数:autoRotateToScreen,始终保持字体面向屏幕
		osg::ref_ptr<osgText::Text> text = new osgText::Text;
		text->setFont(font.get());
		text->setColor(osg::Vec4(0.f, 1.f, 1.f, 1.f));  //青色
		text->setCharacterSize(.15f);
		text->setPosition(osg::Vec3(1.f, 0.f, 1.f));
		/*如果要创建一个一直朝向视口的广告牌形式的文
			字,可以使用Text::SCREEN。*/
		text->setAxisAlignment(osgText::Text::XY_PLANE);//因为没有设置SCREEN,所以在Text.osg文件中没有autoRotateToScreen TRUE 属性
		text->setAlignment(osgText::Text::LEFT_TOP);  //左上基准点开始的字体
		text->setText("right_right");
		geode->addDrawable(text.get());

		text->setDataVariance(osg::Object::DYNAMIC);
	}

// 渲染过程中可以动态改变文字的位置和内容等属性

数据变度不能被自动继承。它事实上只有STATIC和DYNAMIC两个可选值,而UNSPECIFIED意味着系统将自动根据初始化时的情况给对象设置数据变度的属性。默认情况下,任何新建对象都是UNSPECIFIED的,如果系统在第一次执行渲染前发现它附带有更新/事件/裁减回调对象的话,则会自动给它设置setDataVariance(osg::Object::DYNAMIC);因此,我们可以说过多的更新回调会造成系统的渲染效率在一定程度上降低,不过即使在非常极端的情况下,也不会低于单线程模式的效率。

在这里插入图片描述
在这里插入图片描述

程序运行结果

在这里插入图片描述

工程下载地址

源码下载

参考

sunflower_cs

Guess you like

Origin blog.csdn.net/aoxuestudy/article/details/121519569