注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

豆芽兵的生存探索

因,记录。留下历史,看到未来...

 
 
 

日志

 
 

第七节:泡沫案例(1)  

2012-06-07 16:53:10|  分类: RealFlow探索 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
 
7.1案例概述

创建泡沫(foam)和水花(spray)RealFlow最常讨论的话题之一。已经有一些不错的方法来创建泡沫粒子,可以满足不同的需求。

尽管这样,我还是想用创建泡沫做为开始。因为这是一个非常好的例子,来应用你前面所学的所有知识。接下来的,我会一步步讲解写出脚本,你会从这一个个小步骤里慢慢学会应用所学的知识点。(译者注:按我学习经验,确实在做出本案例后才突然发现,啊,我尽然会用Realflow Python脚本了。希望更多人在学习本节后有我一样的体验。)

7.2自然界的泡沫(foam)和水花(spray)

泡沫其实是表面互相分隔的小气泡。为了能形成分隔,需要用表面活性剂(tenside)来降低流体的表面张力。泡沫分散在空气或别的气体介质中。自然界中会有一些泡沫自然生成,例如发酵时。(译者注:原文是alges or fermentation ,但alges怎么也查不到)

水花的性质与之很相似,但不一定需要用tenside(表面活话剂)。海面上,当空气和水混合时,水花很常见。碎浪就是这样。此外分散在空气中的小水珠也能产生spray(译者注:因为这个词有水花,浪花,水雾的意思,为避免误解,后面都用英文。也是为了写脚本命名做好准备)。泡沫和spray不是固定的形态,他们能些微的相互转化。

泡沫和spray白色的外观是光的光谱色散造成的。这个效应就是著名的瑞利散射(Rayleigh scattering)现像:半径比光的波长小很多的微粒对入射光的散射。

这一切与用RealFlow创建spray有什么关系呢? 泡沫的颜色,主要是材质和渲染的事情。此外,物理或化学现像很难实现。但也有一些属性,我们可以运用到模拟泡沫中来

1.创建过程可以基于压力(pressure),年龄(age)或速度(velocity)(碎浪,暴风)

2.Spray可以由小粒子分散在空气中形成。

3. 不同大小的泡沫气泡通常会累积至更大

4.空气分散在水里会导致不同轻重的泡沫,不同于同样密度(dense)的水。

5.泡沫和Spray可以变成水,反之亦然。

6.泡沫和喷雾可以组成大的粒子组

上面已经为我们案例提供很多信息了。 现在我们必须找到一种方法,在 RealFlow 的脚本中实现这些功能。RealFlowPython脚本涉及到的大部分物理属性,已经在上面列出来了。第三点肯定是最大的问题, 因为它不容易计算粒子之间的内部力量。我们需要用发射器脚本达到这个目标,当然还要有适当的

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
  15.拍碎浪产生的浪花

译者八卦:上面这一大段看起来一点用没有,翻译时很费力差点想放弃这部分。但原作者这么详细的讲泡沫的自然本质有什么用呢。一直到好几个月后我才慢慢理解原作者。这些追求自然本质的精神很值得学习。自然本质才是CG特效的立足点,对我本身影响很大。很感谢原作者。希望也能给正在看的你一些帮助。

 

7.3创建泡沫

正如你看到的,泡沫的创建需要由各种参数来控制: Pressure, velocity, density and age. 次要因素是质量(mass),相邻粒子的数量还有分离的时间。单个的粒子永远不会像泡沫或spray的。

 首先我们需要一个粒子发射源。从泡沫粒子中分离出水粒子,建议用第个二发射器来存储产生的粒子。现在第一个挑战就很明确了:声明浪花从水粒子分离泡沫的阈值。最明显的参数肯定是速度(velocity).

 

Velocity是一个矢量,由x,y,z三个分量组成。但用这三个值来对粒子速度进行检测是不明智的。因为矢量是有一个描述强度的量,就是模长(Magnitude)(如果不了解矢量请看前面章节)

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索提示:正常计算矢量的模长

Vel= (3.2, 2.8, 1.5)

| vel | = sqr(velx2 + vely2 +velz2)

| vel | = sqr(10.24 + 7.84 + 2.25)

| vel | = 4.51

 RealFlow提供了一个简单的方法获得模长,不用进行另外的计算:

 vel.module( )

 这个函数能自动返回给定的矢量的模长。你可以在下面看到脚本是具体怎么使用它的。

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索 Events Script: Foam_001.rfs

def onSimulationStep():

 

  threshold = 2.6

  water     = scene.getEmitter("Water")

  foam      = scene.getEmitter("Foam")

 

 particle  = water.getFirstParticle()

 while (particle):

 

   vel     = particle.getVelocity()

   vel_mag = vel.module()

   pos     = particle.getPosition()

   id      = particle.getId()

  if (vel_mag > threshold):

    foam.addParticle(pos,vel)

    water.removeParticle(id)

 

  particle = particle.getNextParticle()

每个粒子有一个特定的ID。当遍历到这个粒子时,ID可以用来区分,这到底是泡沫粒子(Foam)还是水粒子(Water)。

 还要考虑一些事,在设置RealFlow场景时。发射器必须把Resolution值设置为同一大小 Foam发射器不是用来产生粒子的,而是为了存储浪花粒子的一个容器。所以,Speed值要设置成0.0water粒子颜色设置成蓝色的,foam粒子设置成白色的,为了更容易区分。

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
  16 Foam_001设置的场景

 

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
  17Foam_001.rfs基于Velocity创建的泡沫

 Foam_001.rfs 的脚本语法你已经很熟悉了。这里与前面讨论的是用的同一个思路。

 if (vel_mag > threshold):

 foam.addParticle(pos,vel)

 water.removeParticle(id)

 第一句,脚本添加了一个foam发射器,基于当前water 粒子的位移pos和速度vel。第二步,在water发射器中相同的粒子都要被删除。 水和泡沫的分离已经完成。这 些动作只有在速度矢量的模长vel_mag大于threshold值(阈值)才会发生。

 看一下上图.扩散的白色泡沫粒子十分均匀。可能有另外参数可以增加随机效果。下一个想法肯定是用Pressure.所以下个脚本,我们比较Pressure的值给一个阈值,代替Velocity.因为PressureFloat类型,不要再计算模长了。但我们仍需要,速度矢量给addparticle()函数。

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索Events Script: Foam_002.rfs

 


def onSimulationStep():

 threshold = 10000

 water     = scene.getEmitter("Water")

 foam      = scene.getEmitter("Foam")

 particle  = water.getFirstParticle()

 while (particle):

   pres = particle.getPressure() 

  vel  = particle.getVelocity()

  pos  = particle.getPosition()

  id   = particle.getId()

  if (pres > threshold):

 

   foam.addParticle(pos,vel)

   water.removeParticle(id)

  particle = particle.getNextParticle()

 思路是非常相似的,但结果与图17,明显不一样。我们给了一点随机,让它更自然一点。

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
 
  18.Foam_002.rfs基于Pressure创建的泡沫

脚本 Foam_003 Foam_004用了密度(Density)和质量(Mass),给存在的泡沫。我没有把路径列表放在这里,可以在相关文件夹下找到:

 The_Foam_Project > Scripts

 替换为

pres = particle.getPressure(

 我们用了这些:

 dens = particle.getDensity()

 mass = particle.getMass()

 这里有这些结果的展示:

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
 

19Foam_002.rfs基于Density创建的泡沫

 密度方法也产生很好的模拟与随机扩散的泡沫粒子。这个简单的方法非常有效,也能达到我们要求。与Pressure方法一样成为一个好的备选方案。

 不太好的方法当然是使用用质量(mass).所有泡沫和水粒子质量不能随着时间而进行改变。这些所有的测试,都会在后面工作中用到。

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
 

20Foam_003.rfs基于mass创建的泡沫

 现在我们知道,怎样从一个发射器转移粒子到另一个发射器。我们可以把泡沫粒子转化为水粒子。为了这个目的,Age属性就显得很重要,(相比于VelocityPressure.)如果观察一个单个的粒子,就会发现VelocityPressure是随着时间衰减的。RealFlow模拟这物理效果很准确,所以可以满足我们的目的。

 用第三个发射器存储新的粒子是一个好主意。另外颜色可以帮助我们辨别更新中的粒子。为了避免太统一,要加上一个随机因素,可以添加到粒子的Age上。事实上有一种使用模块(Module)的方法。模块是一个外部的延伸,以提高Python的能力。是有很多不同模块的,但RealFlow的最常见的当然是随机模块(random),和(math)数学模块。Random效果显而易见,math提供了一些函数,像正弦(sine),余弦(cosine),平方根(square root),双曲正弦(hyperbolic sine)等。

导入模块语法是:

 import module_name

 对于随机完整的语句是:

 import random

 

 (译者注:这部分是Python基本知识。你稍微了解一下Python就知道Modules

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索Events Script: Foam_005.rfs

 

def onSimulationStep():

 import random

 

  threshold_pres = 5000

  water          = scene.getEmitter("Water")

  foam           = scene.getEmitter("Foam")

  rewater        = scene.getEmitter("ReWater")

 

  # Go through water particles

 

 particle_water = water.getFirstParticle()

 while (particle_water): 

  pres_water = particle_water.getPressure()

  vel_water  = particle_water.getVelocity()

  pos_water  = particle_water.getPosition()

  id_water   = particle_water.getId()

 

  if (pres_water > threshold_pres):

    foam.addParticle(pos_water,vel_water)

    water.removeParticle(id_water)

 

  particle_water = particle_water.getNextParticle()

 

  # Go through foam particles, check age and pressure

 

 particle_foam  = foam.getFirstParticle()

 while (particle_foam):

   current_age   = particle_foam.getAge()

   random_age    = random.uniform(-0.1,0.1) 

   threshold_age = random_age + 0.5 

 

  if (current_age >= threshold_age):  

   pres_foam = particle_foam.getPressure()

   vel_foam  = particle_foam.getVelocity()

   pos_foam  = particle_foam.getPosition()

   id_foam   = particle_foam.getId()

 

    if (pres_foam < threshold_pres):

          

      rewater.addParticle(pos_foam,vel_foam)

      foam.removeParticle(id_foam)

 

  particle_foam = particle_foam.getNextParticle()

第七节:泡沫案例(一) - 豆芽兵 - 豆芽兵的生存探索
  21Foam_005.rfs  展示了不同状态的结果

 脚本看着很长,但还是一样的思路。第二个循环仅是把第一个的条件改变一下。我们用泡沫粒子转换成水粒子。为了更真实的动态,我们需要引入Age

current_age   = particle_foam.getAge()

random_age    = random.uniform(-0.1,0.1) 

threshold_age = random_age + 0.5

 唯一新的方法是定义了这个random_age变量。random.uniform(-0.10.1)表达式意思是Python创建一个在-0.10.1之间的随机数.random_age值是加上了0.5。用这个方法,粒子转变就在0.40.6秒之间,但只有在pres_foam值小于5000.

粒子只有达到这两个条件才能转换成水的粒子,他们是半随机的。这个脚本是一个很好的复杂if条件例子。

只要改变几个值,我们就能成功控制大量创建的泡沫。因为脚本已经读出Velocity,我们甚至能增加这些参数,例如,检查不对的Pressure Velocity 预渲染。

(本小节未完,请看下面一小节)

  评论这张
 
阅读(3081)| 评论(6)
推荐

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018