本文介绍如何创建一个装饰圣诞树的动画,让圣诞树随着16世纪德国歌曲O Tannenbaum(即英文版O Christmas Tree)同步起舞。一根圣诞树枝将充当指挥,蜡烛作为指挥棒。为了让动画更加生动有趣,我们在歌曲的下半部分增加了雪花飘落的场景和圣诞树大幅度充满喜感的摇动。下面的视频展示了该设计的最终效果:
我将通过以下步骤来创建动画:
1) 绘制一个具有曲线分支的松树,树枝可以平滑地上下左右移动。 2) 在枝条上添加不同颜色的装饰物 (彩球,五角星) 和蜡烛。允许装饰物相对于枝尖移动。 3) 根据声音频率,将4种乐音转换成2维运动。模拟与音乐同步的指挥运动。 4) 用强制球形悬垂物模拟装饰物的运动。利用瑞利耗散函数计算装饰物的摩擦。 5) 添加降雪来装饰一个白色的圣诞节。 6)根据音乐建立枝条的动画。
特别感谢我的同事 Andrew Steinacher 为动画选曲,并分析音乐以获取树枝运动的数据(下文"从音乐到运动"一节)。感谢 Amy Young 将动画帧和音乐转换为一个视频剪辑。
制作松树
松树的参数
树的尺寸,树的整体形状和树枝的数量。适当的变量名称使其含义一目了然。
树干和树枝的颜色。
生成可移动的树枝
每个树枝都有一个矩形横截面,其尺寸是变化的(作为离树干距离的函数)。树枝的梢端略微向上,以具有圣诞树的标志性形状。在其最宽的尺寸上,使树枝与锥体(树干)平滑地拟合。变量 τ 和 σ 分别确定树梢的上下运动和左右位置。树枝是根据四个B样条曲面(上,下,左,右)建立,以使其表面具有平滑的外观,只有少量的点定义表面。
高度 h 处的半径是最大树干半径和顶端半径 0 的线性插值。
树枝的侧面只是顶面和底面之间的连接部分。
为了方便后面的使用,让我们为枝梢位置定义一个函数。
一个交互式演示,令树枝和树梢作为 {σ,τ} 的一个函数。
给树干添加树枝 树干是一个圆锥,其顶端是树顶。
树枝的尺寸随高度降低;在几何尺寸上逐渐变小。所有树枝水平的总和等于树高减去底部的台阶部分。
树枝贴合在树干上,无间隙。
使树枝交错以获得更逼真的树形状。这是我将在以下使用的树。可以直接更改树参数,变成另一棵树。
可以很容易地生成更多的树枝,使松树更繁茂。
装饰圣诞树
现在我们来制作一些装饰物,来把圣诞树装饰得更漂亮。我加了一些闪闪发光的球,五角星和蜡烛。顺便建议你圣诞树上使用图林根劳沙小饰物(https://www.krebslauscha.de/christmas-ornaments/about_us/history/)。
装饰物,蜡烛,树顶
彩球
闪闪发亮的彩球必不可少。
这是一个带有小球的树枝。{σ,τ} 变量允许改变球相对于树梢的位置。
这里有一棵树,彩球直上直下地排列,球的颜色随机。
树上球的排列方向随机。如果后来树枝移动了,将计算球的自然运动(即对应的运动方程的解)。
五角星
现在来做五角星。由于这种装饰不是旋转对称的,所以我允许到它相对于悬挂的线有一个方位角。
用五星装饰的树。
蜡烛
蜡烛脚位于树枝的尖梢,蜡烛主体,发黑的灯芯和火焰。为了使动画更容易, 并避免火灾的危险, 我使用电动蜡烛, 使火焰不会随着树枝运动而改变形状。
一根白色和一根红色蜡烛。
后面,我会用带着蜡烛的长树枝作为指挥,所以这里让蜡烛远离树干。
这棵树的每个树枝上均有一根蜡烛。
树顶
为了好玩,我在树顶加了一个可旋转的 Mathematica 图标。
装饰圣诞树
我们将单独把一个树枝作为指挥。其余的树枝, 将随机分为四组,用两种颜色的小球、五角星和蜡烛进行装饰。 现在, 让我们在每个树枝上加一个装饰物或蜡烛。我将使用上面的树和27个树枝。根据它们在树干上的高度和方位角按顺序开始装饰。
按索引对树枝进行着色, 从底部红色开始,到顶部的紫色。
根据声音把所有树枝分为4小组和一个指挥树枝。
这里是根据它们所代表的声音来着色的树枝图形。
最后得到的用枝梢位置作为参数的树。也允许在枝梢的饰物倾斜和着色。
所有树枝和指挥枝的静止位置拉长,蜡烛倾斜。
三棵树,随机选择所有参数。
下面的互动演示允许移动树枝, 允许装饰物绕枝梢移动,并允许根据个人喜好给装饰物着色。
从音乐到运动
到此为止,我们已经做好了一棵枝条可以摆动、挂满装饰物的参数化圣诞树,接下来需要把音乐与枝条(以及装饰)的运动关联起来。
获取四种乐音
使用乐曲的 MIDI 文件。
提取四种乐音。
乐音转换为频率
第一种乐音的时间-频率图。
平滑曲线以表示运动中的频率。
四种乐音的频率。
四种乐音的平滑缩放频率。
这是(平滑后的)前三种乐音的三维图线。
获得摇摆模式
锚定特定歌词,以生成所有的节拍。
在歌词之间插入节拍:
节拍略有变化, 如果不考虑上述锚固方法, 可能会导致运动和声音之间的不同步:
这里有个微妙之处:B 样条插值能给出很好的平滑曲线。与插值不同,实际给定的点不在生成的曲线上。这看起来不错,很平滑, 达到了我们希望的动画视觉效果。但插值是对于点对进行的。这意味着对于 B 样条函数的给定参数 (介于0和1之间),没有得到相对于第一个参数的线性插值。相反, 必须反转插值以得到时间作为插值参数变量的函数。考虑到这个效果对于正确调整音乐与树枝运动是很重要的。
此图显示了插值和重新缩放的 B 样条函数参数之间的差异。
用工具提示和彩色矩形可视化歌词以及它们与摇摆运动的关系:
指挥运动
作为指挥的树枝进行的是简单的周期性运动,与音乐同步。
这次,我使用了插值。
这是得到的指挥棒的形状。
枝条根据乐音的运动
将声音"翻译"成树枝的运动有各种各样的方式。我们给出两种可能性, 一种与声音的频率有关, 另一种基于音符的开始。
可能性1
首先将声音转换成二维运动:垂直运动:声音水平运动的平滑频率: 声音的当前平滑频率与先前频率的不同
可能性2
首先将声音转换成二维运动: 垂直运动: 音符改变水平运动: 摇摆
树梢的最终运动与 σ-τ 平方 [-1, 1]*[-1, 1]。
模拟装饰物的摆动
现在物理知识(终于)派上用场了。我将把装饰物 (球、五星) 模拟成一个具有摩擦的受迫球形摆。受迫是通过枝梢位置来实现的, 这反过来又来自于 voiceστ[j][time]。
受迫球形摆
球坐标系下的受迫球形摆的拉格朗日形式
添加一个瑞利耗散函数 ℱ 来提供摩擦力。
示例显示, 在适当的 [ScriptF]ϕ, [ScriptF]θ 参数值情况下,摆动迅速减弱。
计算装饰物的运动
得到枝梢位置的 δ 和 τ 方向, 将其作为时间函数进行插值。
计算被模拟为球形摆的装饰物的运动。为了使运动有些变化,我使用垂直方向的小随机偏差作为装饰物的初始条件(模拟随机热空气运动)。
对于在下半场的时间范围, 我使用不同的振幅 (对应于更响亮的音乐) 作为受迫振幅。
这里是一个随机选择的装饰物的球面坐标角。我们看到当音乐变强时,振幅增大。
摇摆的圣诞树
给五星添加颜色。
摆运动的快速垂直开始和缓慢收场。
指挥动作的开始。
采用较低视点, 因为树通常比人高。
来点雪花!
人人都盼望一个白色的经典圣诞节,雪花当然必不可少。所以,让我们来造一些丛空而降的3维的花。无需求解偏微分方程(http://psoup.math.wisc.edu/papers/h3l.pdf), 我们将使用元胞自动机在六边形网格上生成具有六边形对称性的雪花形状。
雪花形状(二维)
让我们借用 Ed Pegg 的雪花模式代码(http://demonstrations.wolfram.com/SnowflakeLikePatterns/). 只需导入笔记本, 以编程方式提取定义变量十六进制和雪花的相关单元。
由于有些雪花是断开的,我选择了一些我认为有趣的、即足够复杂的雪花。
这里有五片雪花供下一步使用。
三维雪花形状
我把2维雪花变成3维雪花。
模拟降落板
Tanabe 和 Kaneko在1994年给出了一个简单的2维降落板模型。因此, 为了得到可能落体形状的直观感受,我们将模型做成了一个交互式的演示。
我对降落过程的模拟采用的是现象学和启发式,而不是通过微分方程求解。根据雪花和空气的密度值, 连同它们大多直接下降的厚度/面积比,以及一些小的横向运动和内部旋转。
飘落的雪花
模拟绕质心的内部转动和一些小侧向运动。
整段动画采用了数百个雪花。
制作动画帧
现在, 通过伸展指挥树枝来启动动画, 同时在音乐播放时使顶部旋转。然后, 我们将聆听和观看一段乐曲。然后, 我们将在树上移动, 并产生一些降雪。然后是乐曲高潮部分, 装饰物随着圣诞树猛烈摇摆,然后渐渐平静下来, 并收回指挥树枝。我为每秒钟的声音生成24帧。
导出动画帧需要几个小时,在这之前将进行最后一个测试:
现在使用您最喜爱的电影编辑软件 (如 Adobe After Effects), 把摇摆的树、声音和降雪放在一起吧!
点击“阅读原文”上Wolfram社区查看源代码。祝大家圣诞快乐!