🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 通过AnimationNode对LowPoly风格的树进行随机化处理 ***** ## **零、需求分析** H子走进教室,见到黑板写着几个大字 “今日自习——AOI” **H子**:还想问问老师做树的随机处理呢。按照AOI老师的习惯,首先就是需求分析吧。树的模型也已经做好了。 1. 已经有基础对象 2. 高度有变化 3. 树干生长方向有变化 4. 树叶有一定程度的变化 这么看起来不就是很像蘑菇的做法吗?这样的话只要顺着蘑菇的思路做下去,再进行一些改变就好了 ## **壹、H子的自习笔记【树木随机化处理的实现】** **1)** 首先准备好基础模型 ![](https://box.kancloud.cn/3a2ba2983b100af8656e082a16489309_249x411.png) **2)** 创建一条跟树木高度一致的曲线,并命名为TreeDir ![](https://box.kancloud.cn/20f0620110ead9f6d24afc22c6a43edd_302x364.png) **3)** 为树木添加一个曲线形变修改器并拾取TreeDir曲线 ![](https://box.kancloud.cn/cd25d6de3894f9779185cd586b8f4573_503x190.png) **4)** 在曲线树顶位置的端点添加一个钩子,用于控制曲线的变化 ![](https://box.kancloud.cn/2f4be7274e09eabcd87fbdfb9fb332c7_270x361.png) **5)** 给模型添加顶点组,用于控制置换形变区间。指定顶点组名称为Noise ![](https://box.kancloud.cn/e10beedc027cb33f2dbf9b425480b977_1031x459.png) **6)** 给模型添加置换修改器,并设置Noise纹理 同时添加空对象用于控制Noise纹理随机偏移,空对象命名为TreeNoise ![](https://box.kancloud.cn/3da10cfcf2de22f72eb37d4e96c36e64_259x367.png) ![](https://box.kancloud.cn/c42f72a8f50d9d362cd415741db2c348_501x243.png) **7)** 节点树的实现,在蘑菇的基础上进行设计,因为树木主要都是向上生长,所以无需设置顶部曲线控制的空对象旋转,只需要控制一定范围内的移动即可。树干的弯曲弧度只需要利用曲线本身的贝塞尔曲线处理即可。 ![](https://box.kancloud.cn/9cd509997946b88aef150c8ced0e7fdb_1068x877.png) 从上到下的节点组分别为 1. TreeNoise控制 2. TreeDir控制 3. 树木缩放控制 **8)** 脚本的实现。通过脚本控制树木的复制生成,这一步跟蘑菇的处理基本完全一致。以下记录操作代码。 ~~~ if(Time % DoFrame == 0 and Time > 0): #if(len(bpy.context.selected_objects) >= 1): # bpy.ops.object.move_to_layer(layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) bpy.ops.object.select_all(action='DESELECT') bpy.data.objects[BaseObjectNam].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="置换") bpy.ops.object.modifier_apply(apply_as='DATA', modifier="曲线") bpy.ops.object.apply_all_modifiers() 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) ~~~ **9)** 代码调用部分节点图 ![](https://box.kancloud.cn/bcee26d8f39dba4c1d57c0820133673c_1162x595.png) 最后,每10帧就会复制并应用一个模型,并随机移动到XY平面0-20范围内任意一点上,以便后续处理 **10)** 最后完整版本的节点图 ![](https://box.kancloud.cn/35757b14e9eb79e13397fac402d33793_1040x940.png) **11)** 预览效果 ![](https://box.kancloud.cn/16bc62b35df2f11c21c9a9fa3052a21b_889x460.png)