lissajous figure matlab代码,绘制动态利萨如图形(Lissajous Figures)
图1.在二维空间不同的 Lissajous figure示例。
相位,ρ,不太容易解释。根据定义,它是振荡状态随时间变化与起始值的距离。简明的说来,就是Lissajous figure 整体外观的偏移。
依据时间的批处理脚本(Batch Scripts)
使用模拟事件(simulation),我们不会碰到任何关于时间(time)
的问题,因为每个模拟步长或帧,可看作时间的流逝。在批处理脚本中不会这么自动,因为这个脚本类型不是基于任何模拟或事件。因此,时间可被考虑成一个无限
的序列,在每一步添加一定值。在计算机模拟中,甚至可以用负的时间值。但关键是,使用负时间真的能产生一些新的结果或图形吗?
实际上可以创建一个循环,让计数器在每一步加1。粒子数也需要循环来定义,你最后就可以控制图片的“分辨率”了(一张图形,有运行时间越长,粒子数越就可能会越清晰。这是一种比拟)。
正如您所了解到,从ρ定义你需要一些初始值。这是必要的,因为新的时间步是基于之前那个的。这个思路来自于分形(fractals)(详细了解分形请参考文章:分形艺术
)。你需要让时间初始值要大于或等于0,因为没有“负”的时间。
time = 0
step = 0.025
for i in
range(0,2000,1):
time = time +
step
#用这三个公式计算单个值
#创建位移矢量
#添加粒子发射器
核心部分是:
for i in
range(0,2000,1)
这个行命令意思是:“变量i要从1运行到2000,步长是1。”结果是一个整数序列:1,2,3,4,…2000。在这个循环每一个“i”常量值是0.025(=step(步长
)),会添加到当前时间。最初时间是0,现在增加每一个步长 在这个循环中:0.025, 0.050, 0.075, ..., 50.
这基本上是Axyz,ω123,ρ123起始值。
在循环之前,要先引入这些变量。现在我们准备好了所有需要的批处理脚本。最初的参数代表最终图片外形。当成一种游戏来玩吧,你会惊讶的发现即使只是轻微的改变,就创建出完全不同的图形。
importmath
scene.reset()
Ax=2.0
Ay=2.0
Az=2.0
omega1=1.67
omega2=1.22
omega3=0.89
phi1=1.54
phi2=2.98
phi3=1.68
time=0
step=0.025
stop=2000
nullVel=Vector.new(0,0,0)
emitter=scene.get_PB_Emitter("Container01")
emitter.setParameter("Type","Dumb")
foriinrange(0,stop,1):
time=time+step
x=Ax*math.sin(omega1*time+phi1)
y=Ay*math.sin(omega2*time+phi2)
z=Az*math.sin(omega3*time+phi3)
particlePos=Vector.new(x,y,z)
emitter.addParticle(particlePos,nullVel)
使用这个脚本步骤:
1.
建立一个Container粒子发射器(默认名称Container01)
2.
在Layout 菜单下,打开Batch Script窗口。
3.
粘贴入上面提供的脚本
4.
在这个窗口下的Script下点击Run
5.
会看RealFlow开始自动绘制曲线。成功!!!
注意这时你只能看到粒子,它是没有变成Bin文件导出的,你拨一下时间栏它就可能消失。可以点击一下Simulation,就会保存下来了
你可以导出这个粒子渲染出去,加一些后期修饰什么的。
本文章开始说,为了避免产生N多个粒子文件,所以在Batch Script下写这个脚本。
像如果想要动态序列粒子怎么办??自己小小思考下。再往下看吧。到时你可以比较一下,他的方法好还是你的方法好。
在开始使用这个脚本前插播一个关于Container小介绍
Tips :Container(容器)
这也是一种发射器类型,类似于binary和NBinary发射器类型。实际上它不是真的发射粒子,因为它本身只作为一种接受其实粒子源的容器,只接受,不产生。通常这种类型与Filter Daemon(这是一种过虑辅助器)结合使用。你可以指定特写条件下的粒子转移到这个Container发射器中。这就很容易制作泡沫(foam)或水花(spry)了,会单独输出来。尽管这个发射器不发射粒子,它具有所有其它发射器具有的功能。它的粒子可以与刚体(rigid body)或RealWave进行交互,你也可以控制所有相关的物理参数。
这个Container粒子容器自身的面板,不提供任何设置,因为它只能从其实粒子发射器接受粒子。
当然,循环终止值可以小于或大于2000。另一个重要的事是要使用dumb 粒子。为避免麻烦,脚本执行这必须做的事。另外粒子velocity是0.如果你想保存这图形,只要保存场景或创建初始状态。用高一点Resolution(译者注:经本人试验,这个值与最终粒子数无关,最终粒子数等于stop值),用稠密的粒子拖尾,图形也可以mesh.最好用不同 ω 和 ρ值进行试验创建Lissajous figures,这两值对最终影响很大。

问题是,要在哪里使用到这个脚本呢?实际上它是个噱头,实际工作中流体或粒子模拟这些图片不会发挥非常重要的作用。这个示例告诉你怎样转变公式用到Python代码中,你还得到一个有趣的结果。并学习到关于物理和数学上的一些东西,物理和数学对我们CG工作者是非常重要的。
这个特殊的批处理脚本方法更多的优点是:你能轻松在三维软件中可视化物理过程和结构。你可以专注于研究脚本并不用太意于投射(projection),透视(perspective),材质(shading),粒子系统(particle system)等。
(这是一种很重要的认识,可以把工作试验当成一种很有趣的事来做,并不需要能得到什么了不起的结果,享受这种把物理或数学变成图形的过程吧。况且最终的它真的对工作没有帮助吗?这个答案由来你回答了。)
动态化利萨如图形(
Lissajous
Figures)
上面介绍的是批处理脚本的一部分,粒子位置可以绘制出来了。你肯定注意到生成图形时的动画也是很有趣的。这代码与之前脚本几乎完全一样的,但需要一个函数创建每一帧的变化。可以使用参数是“omega”和“phi”.
最好办法是组合一个基于帧的值。函数输出当前帧是:
frame =
scene.getCurrentFrame()
再让“omega”和“phi”参数乘以当前帧。但仅这样处理图形会没有平滑过渡,因为越来越多帧,“omega”,“phi”的值将会越来越高。
为了获得更好的效果,首次测试值除以200。
omega1-3 = initialValue *
frame / 200
phi1-3 =
initialValue * frame / 200
当然你也可以换成其它值,例如 100或300。再给“omega”和“phi”设置不同的值。用更小的值最终过渡会更光滑。
这代码放在“StepsPost”事件部分。目前场景模拟不会有任何合理图形,因为每一帧新的粒子会添加到之前的粒子上,所有看起来很糟糕。现在需要什么方法更新这个场景给每一个新帧。RealFlow提供了“reset()”函数,但不能用在这儿,因为这只会跳回初始帧。
方法是放在"FramesPre"里写上第二个脚本。现在在"StepsPost"里的核心脚本生成新粒子之前
的粒子会被删除。这个程序只有几行,但非常有效:
emitter=scene.getEmitter("Container01")
particleList=emitter.getParticles()
forparticleinparticleList:
emitter.removeParticle(particle.getId())
这已经是整个脚本来刷新屏幕。利用RealFlow的拍屏功能你可以轻松看到模拟的动画效果。
这一部分是放在StepsPre下的脚本(Part1):
emitter =
scene.getEmitter("Container01")
particleList =
emitter.getParticles()
for particle in
particleList:
emitter.removeParticle(particle.getId())
第二部分是放在StepsPost下面
importmath
frame=scene.currentFrame
#scene.reset()
Ax=2.0
Ay=2.0
Az=2.0
omega1=1.67*frame/200
omega2=1.22*frame/200
omega3=0.89*frame/200
phi1=1.54*frame/200
phi2=2.98*frame/200
phi3=1.68*frame/200
time=0
step=0.025
stop=2000
nullVel=Vector.new(0,0,0)
emitter=scene.get_PB_Emitter("Container01")
emitter.setParameter("Type","Dumb")
foriinrange(0,stop,1):
time=time+step
x=Ax*math.sin(omega1*time+phi1)
y=Ay*math.sin(omega2*time+phi2)
z=Az*math.sin(omega3*time+phi3)
particlePos=Vector.new(x,y,z)
emitter.addParticle(particlePos,nullVel)
看到我在上面把scene.reset屏蔽了,如果让它起作用的话,那么只会一直重置场景,无法正常模拟。
还看到我加了frame = scene.currentFrame因为RealFlow中frame不是直接可调用的函数,需要使用currentFrame来获取当前帧的值。关于这些内置函数,都可以在RealFlow帮助文档看到。(小提示:RealFlow看帮助文档最好新开一个场景,因为不小心搜索一下,就会让RF崩溃)
更多推荐

所有评论(0)