💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# **通过AnimationNode制作小蘑菇** * * * * * ## **零、需求分析** **H子**:**AOI**老师,我现在做完了石头,准备开始做点别的东西了,想要先做其他的比较通用的小道具。 **AOI**:那么你打算做些什么。小草之类的? **H子**:先做小蘑菇。而且模型已经做好了一个。 ![](https://box.kancloud.cn/e5d835a86724180c0116764636edffc0_224x255.png) **H子**:因为查了一下文档,看起来要靠程序化生成还挺费功夫的,所以我设想是干脆做出一个基本的形态,然后让他有所变化,变出别的形态,让它看起来是同一类但是却不是同一个东西。 **AOI**:这算是你对于这种情况的解决方案给出的解答吧。不管是对还是错,总之先去尝试。 确实对于技术不需要纠结于某一种,只要能最快达成目的就是好的。 那么你希望外观有什么地方不一样呢。 **H子**:首先的话,高度,伞部的大小肥瘦,还有一定程度的弯曲。 那么就在现在这个情况下进行一下需求分析吧: 1. 已经有基础对象 2. 高度有变化 3. 伞部的大小和肥瘦有变化 4. 蘑菇要有弯曲 那么就在这个基础上进行对原始模型的改造和添加随机的变化吧。 ## **壹、给蘑菇的形变添加修改器吧【Blender修改器 Hook的运用】** **H子**:首先的话,我的蘑菇是分成两个部分来做的,伞盖和蘑菇柄。 ![](https://box.kancloud.cn/47b76e9f7767fd0c60bbaeb0871240ea_285x231.png) 顶点组也根据这部分的结构分成了两个组。 ![](https://box.kancloud.cn/ea3fa50c8cf8f2f7fc74fe7a0f2f7538_221x84.png) **AOI**:这次要进行的操作的话,本身其实是没太有预先区分的必要的。不过已经拆分好也没问题。 **AOI**:首先,要让蘑菇有大小变化,伞盖形状能独自控制形态变化,你能想到哪个修改器吗? **H子**:骨骼绑定?通过骨骼对上下部分分别控制。 **AOI**:用骨骼并非不行,这也是一种方法,不过其实还有更简单的做法就是了,那就是Hook修改器。 **H子**:这个我知道!做贝塞尔曲线的时候用过,给曲线的控制点加上Hook就可以简单的拖着走了。 **AOI**:确实就是那个东西,但是事实上钩子不仅仅可以用在贝塞尔曲线的控制点上,也可以用在模型对象的顶点上。 操作方法也是一样的。比如这个蘑菇,要对他的伞盖进行操作。 那么,选中伞盖的模型,并按下Ctrl+H,选择【挂钩到一个新物体】 ![](https://box.kancloud.cn/c847f2762ee51a4f6b98881c6bac4da5_212x129.png) 场景上就会出现一个新的空物体,这样就完成了对伞盖部分的挂钩操作,也可以看到修改器面板上增添了一个Hook修改器。 ![](https://box.kancloud.cn/9c7877df5ca98c4832fd45bad7d13bd7_257x200.png) ![](https://box.kancloud.cn/d0aa2a0a727382f1f9941535e9097624_229x206.png) 记得给空物体改名字,方便后面操作,也方便自己辨别对象。 **H子**:做好了。我看到上面有一个叫衰减类型的参数,上面还有半径和强度两个参数,是表示类似于软选择一样的作用吗。 **AOI**:对的,这地方确实是软选择那种功能。这里指的是钩子作用范围的衰减,选中的顶点会百分百的受到影响,而没被选中的定点,就会根据顶点和选中区域的半径以及衰减类型进行影响。 **H子**:也就是说,如果我的菇柄部分想要上半部分受到钩子的影响,但是下半部分不受到影响。中间有一个平滑的过渡。我只要对菇柄的上端的顶点添加钩子,然后设置好衰减参数就可以了? **AOI**:你可以试试看。 **H子**:先选中空对象,再选中模型,切换到编辑模式,挂钩到选中的物体...... ![](https://box.kancloud.cn/12836a28ef58b73584e4b9de1f8202b4_452x353.png) 做好了!确实实现了我要的效果。 ![](https://box.kancloud.cn/a4bdc523eb0a2979e3d3a511e1c15dc3_222x380.png) ![](https://box.kancloud.cn/f4b6a0e9bc341b215bfef35f7cca0653_511x356.png) **AOI**:这样的话,伞盖跟菇柄就关联起来了。操作空物体的移动,旋转跟缩放都产生了相应的影响。 到这里第一步就完成了。 ## **贰、让蘑菇伞盖更自然的起伏吧【Nosie纹理和Displace修改器的运用】** **H子**:接下来老师先别说,让我自己来试试看吧。 **AOI**:好,那么接下来你打算做什么呢。 **H子**:我打算让伞盖有一定的形变,所以决定用Noise纹理和Displace修改器进行随机的形变。 首先,给蘑菇添加一个Displace修改器。 ![](https://box.kancloud.cn/eedf851ee309c2403b3adc42ab42b378_608x432.png) 然后再在场景上添加个空物体,用于控制Displace,命名为NoiseTag。 ![](https://box.kancloud.cn/814a7ff4ccc932752ae987239b0a81ae_310x241.png) 给Displace新增一个控制形变的纹理,并设置好纹理参数 ![](https://box.kancloud.cn/01d5f9ab9df147c94c88dcd44639b3c7_223x134.png) ![](https://box.kancloud.cn/31f06fb8b520f68d261683ba7ee2e2c6_240x586.png) 选中蘑菇的伞盖部分,并将其设置为一个顶点组,用于限制Displance形变的范围。 ![](https://box.kancloud.cn/a1beb8d9e7aa49b14c58611212978816_377x255.png) ![](https://box.kancloud.cn/18994bc97c3f9dfd37b098abeea66cb8_239x225.png) 回到修改器设置界面 把方向设置成【Z】,贴图坐标系设置为【物体】,并选择刚创建用于控制Nosie的空对象用作空物体,并且根据需要调整强度。 ![](https://box.kancloud.cn/a7c07ec4da53facd6d14b01245dafffd_226x253.png) 这个时候,改变空对象的位置就已经可以见到伞盖有适当的变化了。 ## **叁、通过AnimationNode让蘑菇变化起来【AnimationNode节点RandomVector和ObjectTransfromsOutput的运用】** **H子**:做到这里的话,接下来就是要对两个空对象产生随机位置,然后使得蘑菇有所变化吗? **AOI**:对的,做随机石头的时候,已经做过类似的操作了,所以,这次你可以自己试试看吗。 **H子**:好的。 那就先操作Displace修改器的空物体用于产生随机的伞盖变化吧。 先创建一个新的节点树。并且添加**TimeInfo**节点 ![](https://box.kancloud.cn/52d46114d8de6fba1f6a5466e8c9f6c3_118x54.png) 再添加**RandomVector**节点和**ObjectTransfromsOutput**节点 ![](https://box.kancloud.cn/969f1f73c57ffca9ae03c0a890da40f4_116x100.png) ![](https://box.kancloud.cn/cd50c09f94af331094fa217fe39418ed_124x136.png) 在选中NoiseTag对象作为ObjectTransfromsOutput节点的操作对象,勾上Loc的XYZ三个复选框,使得对对象的空间位置生效 然后把节点连起来 ![](https://box.kancloud.cn/4dc548d695c423d54f6ab6dc52693e82_671x160.png) 这样就设置好了控制随机伞盖随机形变的节点组了。 **AOI**:这一步做的很好。效果确实的出来了,根据需要可以调整RandomVector的Scale值控制幅度。 **H子**:那接下来就该做控制伞盖的形状变化了。 首先和控制Displace一样的做法,首先创建用于控制伞盖位置Hook控制器的控制节点。目标对象是BaseTaget。 ![](https://box.kancloud.cn/e0e9c5736628aa9d9d0b08ceecffd70a_828x190.png) 接下来了就该做随机大小了。为了不让伞盖脱离圆形这个状态,所以果然XY轴要公用一个随机数吧。但是Z轴要分开。 **AOI**:这个时候就要考虑自己组合一个Vector值了,会用到一个叫**CombineVector**的节点 ![](https://box.kancloud.cn/6dd3b76fbfdc5778994437353efc0cea_150x131.png) 只要用**Random Number**节点产生目标范围的数据,再合并成Vector就可以了 **H子**:我试试看。 创建好随机数节点,然后合并成一个Vector。XY公用一个数据,Z再用一个数据,设置好数据范围。 考虑到想要以我建模的时候制作的大小作为默认的1单位,那么再设置随机数范围的时候,就使用包含负值的数,使得最后的形变能一定程度的变大或者缩小。 所以把合并之后的Vectro和(1,1,1)值相加,得到最后的随机形变向量。 ![](https://box.kancloud.cn/a926232a34eb847025ddd06155e77880_1200x479.png) 好了!可以随意变化了。 **AOI**:做的不错。那么接下来就是做旋转吧。 **H子**:搜了一下Combine,发现果然有Combine Euler这类节点阿。那么我直接随机一个范围的值用这个节点来合并旋转就好了吧 ![](https://box.kancloud.cn/90a26aef1bdb2b3e445dcfab68a21828_793x309.png) 然后再合并到Object Tranforms Output上面 ![](https://box.kancloud.cn/36eb5604ff76c4e7ace8ff09655895d4_888x509.png) ## **肆、应用模型变换【Sculpt脚本的再次运用】** **AOI**:在做石头的使用,已经尝试使用命令面板获取操作过程的命令,以及使用脚本节点进行脚本的调用,这里也是一样的做法,只不过这次并不是使用Sverchok进行模型的BAKE,而是把基础的蘑菇模型复制一份,并应用所有的修改器。 **H子**:首先选中基础的模型,然后按Shift+D复制一个 然后再按Ctrl+A呼出应用变换菜单,选择Apply All Modifiers ![](https://box.kancloud.cn/a3fcc6237d40e328bf86019fbdaaa62e_229x326.png) 这样就可以得到这一段的命令了,复制下来,再进行后续的操作 ![](https://box.kancloud.cn/2be6d8df902d1d2ff819930e5c476525_1908x86.png) 先创建一个Script节点。 ![](https://box.kancloud.cn/0faf5607886ce3057b1afce229ffed9d_231x308.png) 并且根据需要添加好足够的入口节点。 ~~~ #如果当前时间>0帧并小于最大计算帧 if((TimeInput > 0) and (TimeInput <= MaxFrame)): #如果等于BakeFrame的整数倍帧数的时候 if(TimeInput % BaekFrame == 0): #选中名为ObjecrName的对象 bpy.data.objects[ObjecrName].select = True #复制选中的对象 bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":False, "mode":'TRANSLATION'}, TRANSFORM_OT_translate={"value":(0, 0, 0), "constraint_axis":(False, False, False), "constraint_orientation":'GLOBAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False}) #应用修改器 bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Hook-空物体") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Hook-空物体.002") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Displace") bpy.ops.object.apply_all_modifiers() #把复制出来的对象随机放在PosX和PosY的范围内。 bpy.ops.transform.translate(value=(PosX, PosY, 0), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1) #取消模型的选择 bpy.ops.object.select_all(action='DESELECT') ~~~ **H子**:好的,播放一下,确实的能复制出来了! ## **伍、H子的努力【并没有更多的努力了】** 最终的效果看起来是这样的 ![](https://box.kancloud.cn/0537adcf80068147566377b4eaeb665e_919x317.png) 小蘑菇的生成已经没有什么问题了,H子一时间也没想到有什么可以继续补充和优化的地方,所以这次便先到此为止了。 最终的节点图: ![](https://box.kancloud.cn/fbbccbf121c4a3bc966f6ebd69dd5c47_1444x945.png) 最终代码和正文中并没有什么改变,因此不再赘述。