开篇 Toolmaker

来源:互联网 发布:node开发者 编辑:程序博客网 时间:2024/05/08 12:31

Toolmaker描述的是如何创建新类,如何自定义OIV开发包中已有的类。Mentor描述的是如何使用OIV开发包来开发程序。

扩展OIV开发包有几种方法:

一、最快的且不用c++的唯一方法:使用回调函数,如SoCallback, SoEventCallback, SoCallbackAction等支持回调函数来实现用户行为。

二、使用C++的继承类思想。

许多OIV的类和成员函数都标记有SoEXTENDER,表明开发人员可用。标记SoINTERNAL,表明只用在oiv库中不能用于应用程序。这两个标记只用于文档说明的目的,编译器不能检测。

Adding Nodes and Actions to Inventor

添加一个新的节点类需要对那些不能从基类继承的行为实现虚函数。添加一个行为就是从所有支持该行为的节点派生类然后为这些类定义新的方法。每个行为维护了一列静态方法,每个方法对应每个节点类。当对一个场景图的根节点施加一个行为时,OIV使用方法列表(method list),根据节点的类型标识来为场景图中的每个节点查找对应方法。基类SoNode对所有的OIV行为注册了静态方法,每个方法对该行为调用对应的虚函数。如,SoNode为SoGetBoundingBoxAction行为注册了一个静态方法,该方法调用getBoundingBox()虚函数。从SoNode派生的所有类可以重新定义getBoundingBox()方法,如果没有重新定义,该派生类将继承父类的这个方法。SoNode的大部分虚函数什么也没做都需要重新实现。但有些虚函数如search()和write(),实际实现了行为,因此大多数情况下不需要重新实现。注:如果要为OIV添加一个新的行为类,需要为支持该行为的节点建立方法列表。该列表包含了一个指针,指向能支持该行为的每个节点所对应的静态行为方法。

Actions, State, and Elements

当一个行为施加到一个场景图时,Inventor数据库维护了一个遍历状态,它是一个类SoState,用来保存行为执行过程中的状态信息。每个完整的信息保存在一个单独的元素(element)中。如,材质的当前diffuse color就保存在SoDiffuseColorElement对象中。

Enabling Elements

默认,状态中的所有元素都是disabled,节点和行为能够enable元素。元素使能要提前进行,特别是在节点或行为实例被构造前在initClass()方法中进行。使用宏So_ENABLE。如,当拾取时,SoPickStyle节点需要pickstyle元素,它的initClass()方法在拾取行为中使能这个元素:So_ENABLE(SoPickAction, SoPickStyleElement ); 此调用也会使从SoPickAction派生的SoRayPickAction类中的SoPickStyleElement 使能,因为每个行为继承其父类的使能的元素。SoGLRenderAction使能SoViewportRegionElement:enableElement( SoViewportRegionElement::getClassTypeId() );

注:节点使用宏So_ENABLE, 行为使用enableElement方法。

当一个行为施加到一个场景图时,该行为构建了一个SoState实例,并把使能的元素列表传递给状态构造函数。如果行为被构造后列表有变化,该行为自动重新构建状态来包含最新使能的元素。

Setting Elements in the State

当一个节点被遍历时,需要修改状态中的某元素值。如SoDrawStyle节点,改变lineWidth元素的当前值代码如下:

if( ! lineWidth.isIgnored() )

SoLineWidthElement::set( action->state, this, lineWidth.getValue() );

//this: 设置值的节点,lineWidth.getValue() : 元素的新值

每个使能的元素有自己的栈,带唯一的栈索引(statck index)。separator通过对元素栈的压栈和弹出来保存恢复状态。栈的顶部元素含有遍历过程中该元素的当前值。

GettingElements in the State

每个元素都提供一个静态方法get(),获得栈的顶部元素当前值。如

width = SoLineWidthElement::get( state );

State Elements

名字:So+元素+Element.

Caching

当一个节点使用Inventor元素时,会自动保存一些信息,使Inventor判断指定的cache是否仍有效,或者cache中的值或影响cache的值已经改变了要求创建一个新的cache.

情况一:元素值被存为浮点或整数值,Inventor只是将状态中的元素的值与cache中元素值作比较,如果相同,这个cache仍有效。

情况二:元素值由多个数组成,如SoCoordinateElement,场景图中的每个节点实例被自动赋一个node ID,当节点中的任何字段有变化,该node ID会被更新。当一个节点设置一个元素值时,node ID和该值一起被保存在状态中。当构建了一个cache,该node ID也与该值一起被保存在cache中。当Inventor判断指定的cache是否仍有效时,它比较状态与cache中的node ID,如果匹配,该cache仍有效。对于累加状态值的元素,如transformation, 已经修改了元素的所有node ID与元素值一起被保存在状态和cache中。如果两列node ID匹配,该cache仍有效。

如果创建一个使用Inventor元素的新节点类,caching会自动运行。但如果创建的新节点依赖的不是元素,就需要保证新节点从未cached。使用SoCacheElement::invalidate()方法指定该新节点不能被cached。

Runtime Types

使用SoType类。

getClassTypeId() :静态函数,返回指定类的类型标识

getTypeId():虚函数,返回未知类对象的类型标识

isOfType():如果该对象是指定类型或其派生类,则返回真。

对扩展类,必须在数据库初始化后类对象被构建前调用initClass()方法。初始化的顺序是元素、行为、节点。对任何支持运行时类型的新类,方法initClass()必须在头文件中声明,在源文件中实现。

Extender Macros

为抽象和非抽象类提供了宏。宏的包含文件通常是基类的名字,前缀为Sub,如SoSubNode.h,包含了定义新节点类的宏,SoSubAction.h包含了定义新行为类的宏.

原创粉丝点击