MAX SDK之基本概念(二)

来源:互联网 发布:产品运营数据分析报告 编辑:程序博客网 时间:2024/06/05 09:26

二 SDK的基本概念

2.1 三个抽象基类 
      3DS MAX插件主要用来建模,动画和渲染.这些插件主要继承于下面几个抽象基类之一。
      Anomatable->ReferenceMaker->ReferenceTarget
      这些基本的类提供广泛的函数来实现诸如轨迹视图中显示的功能,或插件之间进行交互的功能。
     (1) Animatable
          类层次中最基本的层次是关于动画的抽象类,为Animatable类。这个类主要的方法是轨迹视图中显示的功能和内存管理。从Animatable类继承的两个类用以在3DS MAX中的各不同部分进行交互。
     (2) ReferenceMaker
          当3DS MAX中的一个引用被创建,创建引用的物体就会对创建引用的目标物体存在依赖性。引用创建者是一个依赖的物体,引用目标是独立的物体。当一个引用目标的状 态发生改变时,引用目标需要通知引用创建者它的改变。属于引用创建者的任何类都必须从抽象类ReferenceMaker类继承。
     (3) ReferenceTarget
         任何属于引用目标的类必须从抽象类ReferenceTarget类继承。见上面ReferenceMaker的解释。
      >>不从这些类继承的插件
     这些插件不从三个抽象基类继承,一般来说,这些类不直接与动画相关。比如,导入导出插件仅仅从3DS MAX中导入和导出数据,因此,它们不会出现在轨迹视图中,且它们的函数独立于其它插件。

2.2 插件体系概述

      SDK中的大部分类都是从抽象基类继承过来的。
      三个抽象基类的根类是Animatable类,它定义了动画和轨迹视图相关的大部分方法。
      从Animatable类继承的类是ReferenceMaker,这个类允许对其它物体创建引用。
      从ReferenceTarget类继承的类是ReferenceTarget,一个引用是场景中两个物体的双向连接,它创 建"ReferenceMaker"和"ReferenceTarget"之间正式的依赖性记录。它的主要功能是使一个引用目标在自身状态发生改变时。通知依赖于它的引用者。
     不从Animatable继承的类主要是那些与动画不相关的类。比如,Interface类提供了一系列方法来调用3DS MAX自身的函数,而Interface类并不继承于Animatable类。
     下图显示了SDK中主要公共类的继承图,最基本的类(即没有父类的类)显示在最上面,继承层次向下和向右。
     图略(参看SDK)


2.3 3DS MAX中的插件 
     这一部分讨论3ds max调用插件方法的途径和插件调用3DS MAX提供的方法的途径。
     (1)用户实现的方法
      每个插件都从3DS MAX的一个基类继承下来的,比如,创建一个几何物体的插件可以从SimpleObject2类继承。
      class MyGeomObject:public SimpleObject2
      {

           //...
      };
      3DS MAX中定义SimpleObject2类的头文件是simpobj.h。插件开发者必须实现SimpleObject2类中的某些方法,换句话说,插件覆盖父类的一些方法。3DS MAX能够调用插件中的这些方法。
      比如,SimpleObject2的BuildMesh()方法,3DS MAX调用该方法得到几何物体的三角网格,插件要实现SimpleObject2::BuildMesh()以产生3ds max所需要的网格。
      (2)基类方法
      有些方法是由基类提供的,即基类自身实现了某些方法。这些方法可以被插件调用。从基类继承的插件可以继承这些方法。比如,一个基本几何物体可能从GeomObject继承,这个基本集合体可以调用NotifyDependents(),这是 ReferenceTarget的一个方法,这个方法继承于基类 (GeomObject->Object->BaseObject->ReferenceTarget)。
     (3)接口方法
      插件也可以调用3DS MAX的方法,通过Interface类提供的接口指针。接口类仅仅是一个没有成员变量并只包含纯虚函数的类。类似于这样的类本质上都不过是一个函数指针表。
      接口类在3ds max中经常使用,最经常使用的接口类是Interface,指向该类的指针可以调用很多方法,插件用这个指针实现3DS MAX提供的一些普通操作。比如,当一个修改器插件想在命令面板上显示用户接口时可以调用Interface的AddRollupPage()方法,或者插件想得到3DS MAX帧滑块指定的当前时间可以调用Interface的GetTime()方法。

2.4 插件之间的通信-引用结构 
      在面向对象的示例中,相互独立的插件物体协同工作以实现系统的全部功能,因此内部物体需要进行通信。3DS MAX中利用引用结构作为控制通信的体系结构。
      (1)个案研究
      考虑下面一个例子以理解为什么需要内部通信。
      3DS MAX动画控制器有一个Look At插件(注视约束插件),这是一个空间变换控制器,它可以控制其在场景中的位置,旋转,缩放。Look At控制器旋转它所属的项目以使其朝向(或注视)另一个物体。比如,创建一个自由相机并且指定一个Look At控制器作为相机的空间变换控制器,然后在场景中选择一个Box作为Look At控制器的目标,这会使自由相机旋转以至其方向正对于Box。无论何时,只要Box移动,控制器就会重新设置以使相机仍然指向Box。当然,如果从场景中删除Box,摄像机将能识别并保持不动。
      现在考虑这些项目(摄像机,Look At控制器,Box)都是插件,每个插件与其它插件都没有关系,那么它们之间是怎么通信的呢?比如,摄像机怎么知道在Box移动的时候需要改变自己的方向?Look At控制器怎么知道场景中的Box被删除?这些物体进行通信的答案就是References(引用)。
      (2)Reference引用
      一个引用是联合两个项目的方法,此时一个项目被认为依赖于另一个项目。在上面的例子中,Look At控制器依赖于Box,摄像机依赖于Look At控制器。也就是说,如果Box发生改变它需要让依赖于它的其它物体知道这些改变。控制器通过引用,得到Box发生改变的通知。控制器通过同样的方式通知依赖于它的项目。当控制器发生改变时,它让依赖于它的项目知道,于是,摄像机得到通知。
      一个物体通过创建引用建立依赖关系,当一个物体创建一个引用,就被称为引用创建者,那些被依赖的物体被称之为引用目标。在上面的例子里,摄像机是引用创建者,它引用Look At控制器,那么Look At控制器就是摄像机的引用目标;同时Look At也是引用创建者,它引用Box,Box是控制器的引用目标。实际上,Box有它自己的引用,比如,它的空间变换控制器。
      3DS MAX存在很多内部创建的引用,在一个简单的场景中,可能存在数十个引用(很多为3DS MAX内部使用),而在一个复杂的场景中,可能存在数百个引用。

2.5 场景中结点与物体的关系 
      场景中每一个物体都关联一个结点,场景中结点和物体存在着一一对应的关系。球、网格、摄像机、灯光和辅助物体都是场景中的物体,所有这些物体能可以被变换、旋转等等。
      在场景中,结点管理它关联的物体:空间变换控制器,使用的材质,关于父子层次的信息,组信息等等。
     (1)结点的空间变换控制器控制物体在场景中的位置,旋转,缩放。
     (2)渲染器使用结点的材质来设置物体的表面特征,比如颜色,纹理,凹凸。
     (3)层次信息用来控制物体的连接/未连接状态和反向动力学(IK)。
     通常可以得到一个结点然后提取指定的场景物体,用结点封装场景物体是有效的。

2.6 过程对象 
      过程对象是视口中用户能够创建和控制的对象。比如包括摄像机、灯光、几何物体(长方体、球或者更复杂的物体)。
      过程对象由自定义属性定义和创建,比如半径(对于球),或者长度(矩形)。正因为如此,参数对象也是被认为是过程独享的同义词。
      几何物体必须最终转换为三角网格,以便可以渲染。3DS MAX渲染器和光线跟踪渲染(mental ray renderer)都是工作在MESH物体级别下。所以基本物体、布尔物体、阁楼、粒子系统、面片栅格、NURBS曲面都必须转换为三角网格。只有一个例外:光线跟踪支持一个指定的基本体头发,并且比三角网格更为有效。
      比如说,一个基本体球,由它的半径,分段数,半球设置等参数来定义,而不是由它的顶点和面片来定义此网格曲面。但需要代表此球的三角网格用以渲染,所以在运行中,通过球的参数来计算网格的顶点和面片。
      对于一个过程对象,3DS MAX提供修改器来扩展对象。可以对对象应用修改器进行适当的修改,变形、处理和编辑。用户也能够利用空间弯曲插件来改变几何体的世界空间位置。对于插件开发者而言,所有这些功能的实现都必须要理解从参数物体到可修改的三角面片模型的转换过程。
      3DS MAX的几何管道系统用来控制这些处理和转换。几何管道系统是用来使参数物体可以被修改器修改,最后产生一个适合的三角网格模型用来渲染和在视口中显示。

2.7 时刻和事件间隔 
      插件开发者处理动画需要指定时间点和时间间隔.
      (1) 时间点
      3DS MAX中基本的时间单位是Timue。SDK中在任何需要指定时间点的时候使用Timue。1Timue等于1/4800秒。
      Timue同样是一个3ds max数据类型。
       比如,如果插件需要知道当前的系统时间(在3DS MAX中以帧滑块表示),可以调用Interface::GetTime()。这个方法返回当前的时间(以Timue为单位,即1/4800s)。
      (2)时间间隔
      在3ds max中,时间间隔(Interval类)通常被用来定义一个时间段,在这个时间段内物体不发生改变。为了尽可能快,3DS MAX避免在任何时候重新评估计算物体。如果一个动画插件可以指定多长时间内它不发生改变,3DS MAX就可以知道它不用在这段时间内重新评估计算物体。
      比如,3DS MAX需要知道在多长时间内修改器的修改是有效的。以弯曲修改器在100帧的动画中为例,用户改变弯曲的角度,并标志在第0帧到第50帧内不弯曲,在50-100帧时弯曲45度。则在前50帧内,3DS MAX不需要重新评估计算修改器(毕竟,在前50帧不弯曲)。3DS MAX用有效时间间隔来标识什么时间段是变形的有效时间。有效时间间隔是一个时间段,比如在23帧处返回的有效时间间隔可能是FOREVER,在56帧返回的有效时间间隔可能是瞬时的。

2.8 动画控制器 
      3DS MAX中所有的动画都由一个称之为Animtable controller(动画控制器)的插件管理,或者简称为控制器。
      一些控制器基于关键帧,这说明用户在关键时间点上设置控制器的值,然后控制器通过在两个关键帧之间插值,计算并设置其它时间的值。
      其它控制器是基于程序的,在特定的时间点编程状态下设置其值(比如噪波控制器用不规则的碎片形功能计算其值)。
      有六种基本的控制器种类,每个控制器控制一个特定的数据类型:
      (1)浮点值(float)
      (2)三个浮点值(Point3)
      (3)位置(Matrix3)
      (4)旋转(Quat)
      (5)缩放(Scalue)
      (6)变换(Matrix3)
      插件开发者能够创建一个新的控制器类型,或者使用一个已存在的控制器类型。
      许多控制器用的参数变量,比如一个程序球的半径参数变量。3DS MAX提供给开发者工具,使用参数变量以更容易地管理它们。.最重要的是参数块,参数块提供一个为插件参数和控制器(控制插值或者生成值的控制器)存储值的系统。

2.9 参数块 
       参数块非常重要,它用来存储和显示插件的变量值。
       对于插件和用户交互所需要的数据,3DS MAX提供存储,获取和显示这些数据的类。大多数插件以对话框的形式显示信息,并且用户可以控制这些显示信息(比如定义一个程序物体的参数)。
      参数块存储插件使用的变量(通常称之为参数),同时管理撤销/重做功能,并自动提供这些参数给MAXScript,同时管理引用系统中的消息通知。
      参数块在相关类的协同下自动地将数据显示到3DS MAX的用户接口,这将开发者从繁琐的底层任务中解脱出来。

2.10 图形接口 
      用户同3DS MAX的交互主要通过命令面板的卷展栏和对话框,鼠标(或者写字板)、键盘、和3D视口。SDK提供给开发者控制每个用户交互的区域。
      插件通常用以下几个方式显示它们的用户交互控制:
      (1)卷展栏:体现于材质编辑器,环境,和渲染对话框中。
      (2)模态对话框
      (3)非模态对话框
      >>控制
      对话框或卷展栏中许多按钮,微调控制项,编辑区域等都来自于3DS MAX的Custom Control。这帮助3DS MAX中各个插件的图形接口外观一致。
      >>鼠标
      鼠标与视口交互在SDK中通过Command Modes(命令模式)控制。
      >>键盘
      键盘加速器允许用户通过将功能和按键绑定以执行一个插件功能。
      >>视口
      插件经常需要在3D视口中绘制以显示其内容或其它小物件,可以通过调用交互渲染器(GraphicsWindow类)提供的方法。

2.11 DLL函数 
      这一部分介绍每一个插件DLL都需要的五个函数,更多详情参阅Required  DLL Functions(Detailed)。
      每一个插件开发者需要提供DllMain的代码,和四个Lib函数,下面简单地描述这几个函数:
      一、函数初始化
      DllMain() 这个函数是Windows用来初始化DLL的钩子程序,3DS MAX插件使用该函数来初始化一般的控制库和3DS MAX定制的控制。
      二、3DS MAX管理和给DLL插件归类的函数
      这四个函数描述了DLL提供的插件的数目和属性。
      (1) LibNumberClasses()    该函数返回DLL中插件类的数目。
      (2) LibVersion()    该函数允许系统处理DLL插件的废置版本。
      (3) LibDescription()    这个函数返回给用户一个文本字符串,如果该DLL是不可用的。
      (4) LibClassDesc(i)    这个函数返回一个descriptor类对象的指针,这是一个类描述符,每个DLL插件类都有该描述符对象,一个类描述符有以下功能:
          a)描述每个插件类的属性;
          b)创建插件类;
          c)销毁插件类;
      开发者可以在一个DLL文件中放置多个插件,在这种情况下,LibClassDesc()将会执行一个switch语句,并返回不同的类描述符指针。

2.12 创建插件和运行的类型ID标识 
      Descriptor类继承于ClassDesc2,它有几个重要的用途,但最重要的两个是该插件的分类,和为该插件实例分配内存。
      一个DLL插件包括许多插件类,在运行时,3DS MAX通过LibNumberClasses函数调用DLL,以确定其包含多少个插件类。然后根据插件类的个数,循环调用静态的描述符类(调用LibClassDesc(i))。Max得到类描述符后,通过调用类描述符的Create()方法分配插件的实例。
      每一个插件类都必须有一个类标识(ClassID)。
      每个插件对象关联两个类标识(2 IDS),它们是:
      (1)Class ID唯一标识一个插件类
      (2)Super Class ID指定插件类的超类。
      比如,一个球对象有一个唯一的Class ID,可以简单地通过SDK提供的程序生成这个ID,它唯一标识该插件类。(该程序在/MAXSDK/HELP/GENCID.EXE)
      它的超类ID是GEOMOBJECT_CLASS_ID,因为它属于基本几何体。超类IDS由MAX定义,每个插件都必须属于其中的一个分类。
      比如,所有的纹理贴图插件都有相同的超类ID,为TEXMAP_CLASS_ID。每个单独的纹理贴图插件都有它自己唯一的类标识符ID。因此,超类ID定义该插件属于哪一个分类(这里是纹理贴图插件),而类ID唯一标识一个特定的插件类。
      • 运行时类型ID
      类描述符的方法ClassDesc::SuperClassID()返回超类ID,ClassDesc::ClassID()返回类ID。
      •创建插件
      类描述符的另一个函数是为插件类实例分配内存。比如,当装载一个3DS MAX文件,该文件包含一个程序球,3DS MAX需要创建一个球插件的实例。它通过调用球的类描述符ClassDesc::Create()实现。
原创粉丝点击