1 状况承继

当读者设置节点的烘托状况时,这个状况将被赋予当时的节点及其子节点。如果子节点对同一个烘托状况设置了不同的特点参数,那么新的子节点状况参数将会掩盖原有的。也就是说,默许状况下子节点可以改动自身的某个状况参数或者承继父节点的同一个状况。如图5—2所示的光照状况承继图体现了这个概念的实现进程。

OSG之状态继承

状况承继特性在许多状况下都非常有用,但有时烘托可能需求更多特性。假定场景图形中有一个包括了实体多边形几何体的节点,如果要以线框方式来烘托场景图形,读者的程序就需求掩盖这种多边形烘托方式状况,而不管它出现在什么方位。OSG允许用户依据场景图形中恣意方位的烘托特点和方式需求单独改动原有的状况承继特性。可以选择以下几种枚举方式。

  • osg::StateAttribute::OVERRIDE:如果将一个烘托特点和方式设置为OVERRIDE,那么所有的 子节点都将承继这一特点或方式,子节点对它们的更改将会无效。
  • osg::StateAttribute::PROTECTED:这种方式可以视为OVERRIDE的一个例外。凡是设置为 PROTECTED的烘托特点或方式,均不会受到父节点的影响。
  • osg:StateAttribute:INHERIT:这种方式强制子节点承继父节点的烘托状况,其作用是子节点 的烘托状况被解除,而运用父节点的状况代替。

读者可以对这些参数进行位或叠加操作,然后再作为setAttribute()和setMode()建立一个场景图形和setAttributeAndModes()的第二个参数输入。下面的代码段将强制运用线框方式烘托场景图形:

//获取根节点的烘托状况 StateSet

osg:StateSel*state=root->getOrCreateStateSet();

//创立一个PolygonMode 烘托特点

osg:PolygonMode*pm=new osg:PolygonMode();

osg:PolygonMode::FRONT_AND_BACK,osg:PolygonMode::LINE);

//强制运用线框烘托 state->setAttributeAndModes(pm, osg::StateAmributeONjong::StateAtribute:OVERRIDE);

运用PROTECTED参量可以确保父节点的烘托状况不会掩盖子节点的烘托状况。例如,读者可能创立了一个发光的场景,其中包括有运用亮度照明的光源几何体,如果其父节点禁用了光照,那么光源几何体的烘托将会犯错。这时,对光源几何体的GL_LIGHTING 烘托状况运用PROTECTED就可以确保它依然可用。

2 烘托状况示例

烘托状况(ClipeNode)示例的代码如程序清单所示。

#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/ClipNode>
#include <osg/PolygonMode>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include <osg/AnimationPath>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <iostream>
#include "utility.h"
osg::ref_ptr<osg::Node> createClipNode(osg::ref_ptr<osg::Node> subgraph)
{
	osg::ref_ptr<osg::Group> root = new osg::Group();
	osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
	// 多边形制作方式,正面和不和都制作
	osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode();
	polymode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
	// 启动多边形制作方式,并指定状况承继特点为OVERRIDE
	stateset->setAttributeAndModes(polymode, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
	// 多边形制作节点
	osg::ref_ptr<osg::Group> wireframe_subgraph = new osg::Group;
	// 设置烘托状况
	wireframe_subgraph->setStateSet(stateset.get());
	wireframe_subgraph->addChild(subgraph.get());
	//root->addChild(wireframe_subgraph.get());
	osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
	// 更新回调,实现动态裁剪
	osg::ref_ptr<osg::NodeCallback> nc = new osg::AnimationPathCallback(subgraph->getBound().center(), osg::Vec3(0.0f, 0.0f, 1.0f), osg::inDegrees(45.0f));
	transform->setUpdateCallback(nc.get());
	//创立裁剪节点
	osg::ref_ptr<osg::ClipNode> clipnode = new osg::ClipNode();
	osg::BoundingSphere bs = subgraph->getBound();
	bs.radius() *= 0.2f;
	// 设置裁剪节点的围住盒
	osg::BoundingBox bb;
	bb.expandBy(bs);
	// 依据前面指定的围住盒创立6个裁剪平面
	clipnode->createClipBox(bb);
	// 禁用拣选
	clipnode->setCullingActive(false);
	transform->addChild(clipnode.get());
	root->addChild(transform.get());
	root->addChild(wireframe_subgraph.get());
	// 创立未被裁剪的节点
	osg::ref_ptr<osg::Group> clippedNode = new osg::Group;
	clippedNode->setStateSet(clipnode->getStateSet());
	clippedNode->addChild(subgraph.get());
	root->addChild(clippedNode.get());	
	return root.get();
}
int main()
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	osg::ref_ptr<osg::Node> root = new osg::Node();
	// 加载模型
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(GetCurrentPath() + "\\Data\\cow.osg");
	root = createClipNode(node.get());
	// 优化场景数据
	osgUtil::Optimizer optimzer;
	optimzer.optimize(root.get());
	setWindowSize(viewer.get(), 600, 400, "ClipNode");
	viewer->setSceneData(root.get());
	viewer->realize();
	viewer->run();
	return 0;
}

作用图

OSG之状态继承

动态作用图