|
import bpy |
|
import numpy as np |
|
import random |
|
|
|
# 簡単にアクセスするための変数代入。 |
|
obj = bpy.context.object |
|
par_system = obj.particle_systems[0] |
|
particles = par_system.particles |
|
par_setting = particles.data.settings |
|
|
|
par_len = par_setting.count |
|
par_frame_start = par_setting.frame_start |
|
par_frame_end = par_setting.frame_end |
|
|
|
# パーティクルシステムのプリセット設定。 |
|
def preset(): |
|
par_setting.lifetime = 500 |
|
par_setting.normal_factor = 0 |
|
par_setting.effector_weights.gravity = 0 |
|
|
|
par_setting.physics_type = 'FLUID' |
|
# physics_typeの変更を反映するために、フレーム番号を変える。 |
|
bpy.context.scene.frame_set(1) |
|
|
|
par_setting.fluid.stiffness = 0.03 |
|
par_setting.fluid.fluid_radius = 2 |
|
par_setting.fluid.spring_force = 0.25 |
|
|
|
# 分裂を再現するために、誕生した粒子を既存の粒子のインデックスに対応させる。 |
|
def cellDivision(reloc_index,par_birth,birth_start,frame_step,initial_particles,growth_rate,division_sequential): |
|
|
|
# 最初に誕生した粒子のフレームと位置インデックス配列。 |
|
prev_index = initial_particles |
|
par_birth[:prev_index] = birth_start |
|
reloc_index = np.append(reloc_index, np.arange(0,initial_particles,1)) |
|
|
|
count = 1 |
|
while prev_index < par_len: |
|
next_index = prev_index*growth_rate |
|
# 誕生フレームにランダム性追加。 |
|
newborn = len(par_birth[prev_index:next_index]) |
|
rand = np.random.randint(0,frame_step, size=newborn) |
|
par_birth[prev_index:next_index] = (frame_step*count) - (rand*division_sequential) |
|
# 新しく生まれた粒子を、既存の粒子のインデックスに対応させる。 |
|
reloc_index = np.append(reloc_index, np.arange(0, prev_index, 1)) |
|
|
|
prev_index = next_index |
|
count +=1 |
|
|
|
reloc_index = reloc_index.astype(int) |
|
return (reloc_index, par_birth) |
|
|
|
# フレームごとに粒子の位置をセット。 |
|
def setFrameLocation(reloc_index,par_birth,par_loc, |
|
growth_mode,loc_range,initial_particles,x_axis,y_axis,z_axis): |
|
|
|
frame_start = par_frame_start |
|
if growth_mode == 'cell': |
|
frame_end = bpy.context.scene.frame_end |
|
else: |
|
frame_end = par_frame_end |
|
|
|
# 最初のbirth_timeは以下で自動的にリセットされる。 |
|
for f in range(int(frame_start), int(frame_end)): |
|
bpy.context.scene.frame_set(f) |
|
par_index = np.where(par_birth == f) |
|
if len(par_index[0]) > 0: |
|
for i in par_index[0]: |
|
# birth_timeをセット。 |
|
particles[i].birth_time = par_birth[i] |
|
# 新しい位置をセット。 |
|
par_i = 0 |
|
if growth_mode == 'cell': |
|
par_i = reloc_index[i] |
|
elif growth_mode == 'proceed': |
|
par_i = random.randint(0,initial_particles) |
|
else: |
|
par_i = random.randint(0,i) |
|
new_loc = particles[par_i].location |
|
|
|
# 誕生位置にランダム性追加。 |
|
rand_fac = 1 |
|
rand_floor = 0.001 |
|
rand_axis = np.random.random(3) * [x_axis, y_axis, z_axis] |
|
rand_loc = np.random.uniform(-1,1,3) * (loc_range + rand_floor) |
|
new_loc[0] += rand_loc[0] * rand_axis[0] * rand_fac |
|
new_loc[1] += rand_loc[1] * rand_axis[1] * rand_fac |
|
new_loc[2] += rand_loc[2] * rand_axis[2] * rand_fac |
|
|
|
particles[i].location = new_loc |
|
par_loc[i*3:(i*3)+3] = new_loc |
|
return par_loc |
|
|
|
def execute(growth_mode,birth_delay, birth_start,loc_range,x_axis,y_axis,z_axis, |
|
initial_particles,frame_step,growth_rate,division_sequential): |
|
|
|
# いったんパーティクルシミュレーションを再生すると、粒子位置が記憶されてしまうので、リセットするためにシードを変えてから戻す。 |
|
par_system.seed += 1 |
|
par_system.seed -= 1 |
|
|
|
# 最初のbirth_time配列。 |
|
par_birth = np.array([0.0]*par_len, dtype='float') |
|
particles.foreach_get('birth_time', par_birth) |
|
# 最初の位置配列。 |
|
par_loc = np.array([0,0,0]*par_len, dtype='float') |
|
particles.foreach_get('location', par_loc) |
|
# このインデックスの粒子近くに、新しく誕生した粒子を配置する。 |
|
reloc_index = np.array([]) |
|
|
|
if growth_mode == 'cell': |
|
reloc_index, par_birth = cellDivision(reloc_index,par_birth, |
|
birth_start,frame_step,initial_particles,growth_rate,division_sequential) |
|
|
|
par_birth = par_birth.astype(int) |
|
par_loc = setFrameLocation(reloc_index,par_birth,par_loc, |
|
growth_mode,loc_range,initial_particles,x_axis,y_axis,z_axis) |
|
|
|
# 誕生の遅延。 |
|
par_birth += birth_delay |
|
# 再び位置と誕生時間をセット。 |
|
if growth_mode == 'cell': |
|
particles.foreach_set('location', par_loc) |
|
particles.foreach_set('birth_time', par_birth) |
|
|
|
bpy.context.scene.frame_current = 1 |
|
|
|
# 一般的なパラメータ。 |
|
growth_mode = 'cell' # 増殖モード。cell=周期的増殖、proceed=方向性をもって進む。random=ランダムな増殖。 |
|
birth_delay = 5 |
|
birth_start = 1 |
|
loc_range = 0.1 |
|
x_axis = 0.1 |
|
y_axis = 0.1 |
|
z_axis = 0 |
|
# cellとproceedモードのパラメータ。 |
|
initial_particles = 3 |
|
# cellモードのパラメータ。 |
|
frame_step = 20 |
|
growth_rate = 2 |
|
division_sequential = 0 |
|
|
|
# 実行。 |
|
preset() |
|
execute(growth_mode,birth_delay,birth_start,loc_range,x_axis,y_axis,z_axis, |
|
initial_particles,frame_step,growth_rate,division_sequential) |