这里介绍的是MAYA内生长表面的制作方法,飞行器由飞机投下后变形展开,然后机身外壳在 滑翔一段时间后收缩消失,由于会有近距离特写镜头,要求收缩消失飞行器的外壳必须有厚度,导角。所以不 能用透明贴图的办法,在这里采用了编辑NURBS LOFT历史的方法来解决。 1 首先创建一个NURBS球体,在Z方向旋转90度,使球体的极点指向要制作的飞行器前方。 2 通过选择HULL缩放移动编辑CV点,将球体作成飞行器展开前的形状,必要时在需要 增加细节的地方插入参数线,(INSERT ISOPARMS) 3 然后选择ISOPARAM 用DETATCH命令将飞行器外壳在接缝处断开,把飞行器分解成 各个独立的NURBS面 4 选择U或V方向的ISOPARAMS参数线,用DUPLICATE SURFACE CURVES 将NUBERS 表面参数线复制出后删除原始表面,按先后次序选种各个由参数线复制出的曲线 5 然后在MAYA 的MODELING模块下的SURFACE菜单的LOFT命令的OPTION BOX 中确认CLOSE 取消,选中PARTIAL制作保留历史的LOFT表面,在这个LOFT节点的INPUT将会出现几个SUBCURVE节点 调节其中的MIN和MAX值就可以制作出表面长出或收缩消失的效果 6 建立一个LOCATOR物体用ADD ATTRIBUTE给它加入一个FLOAT属性,设置其最小值最大值和缺省值,运用 CONNECTION EDITOR 再将这个属性作为SUBCURVE的MIN或MAX输入连接,控制所有SUBCARVE参与LOFT的 部分,也可以用MAYA的DRIVEN KEY来控制。 7 为了使分离开的飞行器的外壳在长出或消失时能有厚度和倒角,选中LOFT产生的NURBS LOFT表面执行 OFFSET SURFACE命令,产生一个原始表面的OFFSET表面,由于保留了构造,当原始表面改变时,新 产生的OFFSET表面也会随着改变, 8 分别选中原始LOFT表面及OFFSET表面对应边缘的参数线,确认LOFT命 令中的OPTION BOX中选中COMPLETE选项,制作四个LOFT面封闭这两个表面的四个过缘,保留构造历史,这 样就做成了一个可以长出或收缩消失的有厚度的表面。 9 如果有很近的镜头的话,你也许需要为你的飞行器外壳制作出导角,在这里我们使用ROUND TOOL工具, 分别选择要做导角处理的相邻边缘,在CHANNNEL BOX中设置好导角的半径,按ENTER键。就制作成保持结构历史的导角,需要注意的是导角面带着历史生长收缩时比较消耗系统资源,而且导角半径不能太大否则导角结构将会失败。 10 需要注意的是当我们需要移动飞行器时只能移动由SUBCURVES LOFT产生的那个表面,其他的表面由于带有历史将会一起移动 以上步骤非常麻烦特别是当飞行器的面和参数线非常多时,制作工作变成了枯燥无味道重复劳动,所以我编写了一个简单的MEL脚本,这个脚本对需要有大量物体生长的动画项目很有用,当我们把成型的球体用DETACH断开后就可以选中所有需要增加厚度和进行生长变形动画的面,到MAYA的SCRIPT EDITOR里打开MEL脚本,按下键盘ENTER键执行.MAYA就会出现一个窗口让你选择曲面生长变行的方向,生成面的厚度,按确定键后场景中所有的选中表面就会被自动处理,场景中同时还增加一个LOCATOR。在属性编辑器中展开其Transform 节点的Extra属性栏,你会发现在里面为每个生长变形曲面新增加了一个控制属性,动画这些属性我们就可以做成飞行器生长变形的效果, if (`window -q -ex ocw`) {deleteUI ocw; } window -title "offsetControlWindow" ocw; columnLayout -adjustableColumn true; separator -height 10 -style "none"; global string $myMethod; $myMethod="u"; radioButtonGrp -numberOfRadioButtons 2 -label "uv choeser" -labelArray2 "u" "v" -on1 "$myMethod=\"u\"" -on2 "$myMethod=\"v\"" uvchoeser; floatSliderGrp -label "offset depth" -field true -minValue 0 -maxValue 1 -value 0.05 depthSliderGrp; button -label "confirm" -c "building"; separator -height 30 -style "out"; showWindow ocw; //-------------------------------------------------------------------- proc building () { DeleteHistory; string $sel[]=`ls -sl`; string $currentSurface; for ($currentSurface in $sel) {print $currentSurface; string $shapeName[]=`ls -dag -s $currentSurface`; int $nurbsUV[]; int $nurbsU; int $nurbsV; string $myComm; global string $myMethod; if (`nodeType $shapeName[0]`=="nurbsSurface") { rebuildSurface -ch 1 -rpo 1 -rt 0 -end 1 -kr 2 -kcp 1 -kc 0 -su 16 -du 3 -sv 18 -dv 3 -tol 0.01 -dir 2 $currentSurface; $nurbsUV=`getAttr ($currentSurface+".spansUV")`; $nurbsU=$nurbsUV[0]; $nurbsV=$nurbsUV[1]; if ($myMethod=="u") { for($i=0;$i<=$nurbsU;$i++) { select -r ($currentSurface+".u["+$i+"]"); duplicateCurve -ch 0 -n ($currentSurface+"uFrame"+$i) ( $currentSurface+".u["+$i+"]" ); } } else { for($i=0;$i<=$nurbsV;$i++) { select -r ($currentSurface+".v["+$i+"]"); duplicateCurve -ch 0 -n ($currentSurface+"vFrame"+$i) ( $currentSurface+".v["+$i+"]" ); } } select -cl; delete ($currentSurface); float $offsetDistance=`floatSliderGrp -q -value depthSliderGrp`; string $originalSurface[]; string $offsetSurface[]; if (!`objExists shellControl`) { spaceLocator -p 0 0 0 -n shellControl ; } $myComm="attributeExists "+$currentSurface+"control shellControl"; if (!eval($myComm)) { $myComm="addAttr -ln "+$currentSurface+"control -at double -min 0 -max 1 -dv 0 |shellControl"; eval $myComm; } if ($myMethod=="u") { for ($i=0;$i<=$nurbsU;$i++) { select -add ($currentSurface+"uFrame"+$i); } } else { for ($i=0;$i<=$nurbsV;$i++) { select -add ($currentSurface+"vFrame"+$i); } } $originalSurface=`loft -ch 1 -u 1 -c 0 -ar 1 -d 3 -ss 1 -rn 1 -po 0 -rsn true -n $currentSurface`; string $subCurve[]; $subCurve=eval("listHistory -pdo true -lf false "+$originalSurface[1]); string $tempObj; for ($tempObj in $subCurve) { if (`nodeType $tempObj`=="subCurve") { $myComm="connectAttr -f shellControl."+$currentSurface+"control "+$tempObj+".minValue"; eval $myComm; } } $nurbsUV=`getAttr ($originalSurface[0]+".spansUV")`; $nurbsU=$nurbsUV[0]; $nurbsV=$nurbsUV[1]; $offsetSurface=`offsetSurface -ch on -m 0 -d ($offsetDistance)`; select -cl; select -add ($originalSurface[0]+".u[0]"); select -add ($offsetSurface[0]+".u[0]"); loft -ch 1 -u 1 -c 0 -ar 1 -d 3 -ss 1 -rn 0 -po 0 -rsn true; select -cl; select -add ($originalSurface[0]+".u["+$nurbsU+"]"); select -add ($offsetSurface[0]+".u["+$nurbsU+"]"); loft -ch 1 -u 1 -c 0 -ar 1 -d 3 -ss 1 -rn 0 -po 0 -rsn true; select -cl; select -add ($originalSurface[0]+".v[0]"); select -add ($offsetSurface[0]+".v[0]"); loft -ch 1 -u 1 -c 0 -ar 1 -d 3 -ss 1 -rn 0 -po 0 -rsn true; select -cl; select -add ($originalSurface[0]+".v["+$nurbsV+"]"); select -add ($offsetSurface[0]+".v["+$nurbsV+"]"); loft -ch 1 -u 1 -c 0 -ar 1 -d 3 -ss 1 -rn 0 -po 0 -rsn true; } } } 11 至于飞行器外壳的展开动画则用MAYA 的Driven Key来实现,我们在LOCATOR中用ADD ATTRIBUTE增加一些属性后就可以用这些属性作为飞行器外壳的表面的位置和旋转的驱动者(DRIVER)来方便道控制飞行器外壳开的动画。 12 渲染时使用的是MAYA标准的渲染器,为了控制渲染速度场景中只打了3盏灯,烟尘等效果由HOUDINI中的IMAGE3D完成