
Genesis å ¥é (7) - Beyond Rigid Bodies
ãGenesisãã®ãBeyond Rigid Bodiesãã«ã€ããŠãŸãšããŸããã
åå
1. Beyond Rigid Bodies
ãGenesisãã¯è€æ°ã®ãç©çãœã«ããŒããçµ±åãããBeyond Rigid Bodiesãã·ãã¥ã¬ãŒã·ã§ã³ããµããŒãããŸããsolver ã¯åºæ¬çã«ãç¹å®ã®ææã»ãããåŠçããããã®ç©çã·ãã¥ã¬ãŒã·ã§ã³ã¢ã«ãŽãªãºã ã®ã»ããã§ããä»åã¯ã3ã€ã®äžè¬çãªãœã«ããŒãåãäžãããããã䜿çšããŠããŸããŸãªç©ççç¹æ§ãæã€ãšã³ãã£ãã£ãã·ãã¥ã¬ãŒãããŸãã
ã»Smooth Particle Hydrodynamics (SPH) Solver
ã»Material Point Method (MPM) Solver
ã»Position Based Dynamics (PBD) Solver
2. SPHãœã«ã㌠ã䜿çšããæ¶²äœã·ãã¥ã¬ãŒã·ã§ã³
æ°Žã®ç«æ¹äœãã·ãã¥ã¬ãŒãããæ¹æ³ãèŠãŠã¿ãŸãã空ã®ã·ãŒã³ãäœæããéåžžã©ããå¹³é¢ã远å ããŸãã
import genesis as gs
# åæå
gs.init()
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt = 4e-3,
substeps = 10,
),
sph_options=gs.options.SPHOptions(
lower_bound = (-0.5, -0.5, 0.0),
upper_bound = (0.5, 0.5, 1),
particle_size = 0.01,
),
vis_options=gs.options.VisOptions(
visualize_sph_boundary = True,
),
show_viewer = True,
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
plane = scene.add_entity(
morph=gs.morphs.Plane(),
)ã»sim_options ãèšå®ãããšãã«ãsubsteps=10 ã®æ¯èŒçå°ã㪠dt ã䜿çšããŠããŸããããã¯ãã·ãã¥ã¬ãŒã¿å ã§ãåã¹ãããã§ããããã substep_dt = 4e-3 / 10 ã®10åã® substeps ãã·ãã¥ã¬ãŒãããããšãæå³ããŸãã以åã«åäœãæ±ã£ãŠãããšãã¯ããããèšå®ããå¿ èŠã¯ãªããåã¹ãããã§1ã€ã®ãµãã¹ãããã®ã¿ãå®è¡ããããã©ã«ãèšå® (substeps=1) ã䜿çšããŸãããæ¬¡ã«ãæ°Žã远å ããŸãããã
ã»åã«èª¬æããããã«ãoptions ã䜿çšããŠåãœã«ããŒãèšå®ããŸããSPHSolver ã䜿çšããŠãããããsph_options ãä»ããŠãã®ããããã£ãèšå®ããå¿ èŠããããŸãããã®äŸã§ã¯ããœã«ããŒã®å¢çãèšå®ããç²åãµã€ãºã 0.01m ã«æå®ããŸãããSPHSolver ã¯ã©ã°ã©ã³ãžã¥ãœã«ããŒã§ãããç²åã䜿çšããŠãªããžã§ã¯ãã衚ããŸãã
ã»vis_options ã§ã¯ãã¬ã³ããªã³ã°ããããã¥ãŒã§ SPH ãœã«ããŒã®å¢çã衚瀺ããããã«æå®ããŸããã
次ã«ãæ°Žãããã¯ãšã³ãã£ãã£ã远å ããŠã·ãã¥ã¬ãŒã·ã§ã³ãéå§ããŸãããããã¯ã远å ããããããããªãžãããããã¯ãããŠã©ãŒã¿ãŒãããã¯ã«å€æŽããããã«å¿ èŠãªå¯äžã®å€æŽã¯ãmaterial ã®èšå®ã§ããå®éã以åãªãžããããã£ã®ã¿ãæ±ã£ãŠãããšãã¯ãããã¯ããã©ã«ãã§ gs.materials.Rigid() ã«å éšçã«èšå®ãããŠããŸãããçŸåšã¯æ¶²äœã·ãã¥ã¬ãŒã·ã§ã³ã« SPH ãœã«ããŒã䜿çšããŠãããããSPH ã«ããŽãªã§ Liquid ãããªã¢ã«ãéžæããŸãã
liquid = scene.add_entity(
material=gs.materials.SPH.Liquid(
sampler='pbs',
),
morph=gs.morphs.Box(
pos = (0.0, 0.0, 0.65),
size = (0.4, 0.4, 0.4),
),
surface=gs.surfaces.Default(
color = (0.4, 0.8, 1.0),
vis_mode = 'particle',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
horizon = 1000
for i in range(horizon):
scene.step()Liquid ãããªã¢ã«ãäœæãããšãã«ãsampler='pbs' ãèšå®ããŸããããã¯ãBox morphãäžããããå Žåã«ããŒãã£ã¯ã«ããµã³ããªã³ã°ããæ¹æ³ãèšå®ããŸããpbs ã¯ãç©çããŒã¹ã®ãµã³ããªã³ã°ãã®ç¥ã§ãããŒãã£ã¯ã«ãç©ççã«èªç¶ãªæ¹æ³ã§é 眮ãããŠããããšã確èªããããã«ã远å ã®ã·ãã¥ã¬ãŒã·ã§ã³æé ãå®è¡ããŸãããŸãã'regular' ãµã³ãã©ãŒã䜿çšããŠãåã«ã°ãªããã©ãã£ã¹ãã¿ãŒã³ã䜿çšããŠããŒãã£ã¯ã«ããµã³ããªã³ã°ããããšãã§ããŸããMPM ãªã©ã®ä»ã®ãœã«ããŒã䜿çšããŠããå Žåã¯ã'random' ãµã³ãã©ãŒã䜿çšããããšãã§ããŸãã
ãŸãã远å ã®å±æ§ã§ãã surface ãæž¡ããããšã«ã泚æããŠãã ããããã®å±æ§ã¯ããšã³ãã£ãã£ã®ãã¹ãŠã®èŠèŠçããããã£ãå®çŸ©ããããã«äœ¿çšãããŸããããã§ã¯ãæ°Žã®è²ãéã¿ããã£ãè²ã«èšå®ããvis_mod='particle' ãèšå®ããŠããŒãã£ã¯ã«ãšããŠèŠèŠåããããšãéžæããŸããã
ãããæ£åžžã«å®è¡ãããšã氎滎ãå¹³é¢äžã«åºãããŸããããœã«ããŒå¢çå ã«å¶éãããŸãã

ãªã¢ã«ã¿ã€ã ã®ç²åäœçœ®ãååŸããã«ã¯ãæ¬¡ã®æäœãè¡ããŸãã
particles = liquid.get_particles()æ¶²äœã®ç©ççç¹æ§ã倿Žããããšãã§ããŸããããšãã°ãç²åºŠ (mu) ãšè¡šé¢åŒµå (gamma) ãå¢ããããšãã§ããŸãã
material=gs.materials.SPH.Liquid(mu=0.02, gamma=0.02),å®å šãªã³ãŒãã¯ã次ã®ãšããã§ãã
import genesis as gs
# åæå
gs.init()
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt = 4e-3,
substeps = 10,
),
sph_options=gs.options.SPHOptions(
lower_bound = (-0.5, -0.5, 0.0),
upper_bound = (0.5, 0.5, 1),
particle_size = 0.01,
),
vis_options=gs.options.VisOptions(
visualize_sph_boundary = True,
),
show_viewer = True,
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
plane = scene.add_entity(
morph=gs.morphs.Plane(),
)
liquid = scene.add_entity(
# ç²æ§ã®ããæ¶²äœ
# material=gs.materials.SPH.Liquid(mu=0.02, gamma=0.02),
material=gs.materials.SPH.Liquid(),
morph=gs.morphs.Box(
pos = (0.0, 0.0, 0.65),
size = (0.4, 0.4, 0.4),
),
surface=gs.surfaces.Default(
color = (0.4, 0.8, 1.0),
vis_mode = 'particle',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
horizon = 1000
for i in range(horizon):
scene.step()
# get particle positions
particles = liquid.get_particles()3. MPMãœã«ã㌠ã䜿çšããå€åœ¢å¯èœãªããžã§ã¯ãã®ã·ãã¥ã¬ãŒã·ã§ã³
MPM ãœã«ããŒã¯ãå¹ åºããããªã¢ã«ããµããŒãããéåžžã«åŒ·åãªç©çãœã«ããŒã§ããMPM 㯠Material Point Method ã®ç¥ã§ãã©ã°ã©ã³ãžã¥ãªã€ã©ãŒã®ãã€ããªãã衚çŸãã€ãŸãããŒãã£ã¯ã«ãšã°ãªããã®äž¡æ¹ã䜿çšããŠãªããžã§ã¯ãã衚çŸããŸãã
ãã®äŸã§ã¯ã3ã€ã®ãªããžã§ã¯ããäœæããŸãã
ã»åŒŸæ§ç«æ¹äœã¯ 'particles' ãšããŠèŠèŠåãããŸã
ã»æ¶²äœç«æ¹äœã¯ 'particles' ãšããŠèŠèŠåãããŸã
ã»åŒŸå¡æ§çäœã¯å ã®çã¡ãã·ã¥ãšããŠèŠèŠåãããŸãããå éšç²åç¶æ (vis_mode='visual') ã«åºã¥ããŠå€åœ¢ãããŸããå éšç²åç¶æ ãå€åœ¢ãããèŠèŠã¡ãã·ã¥ã«ãããã³ã°ãããã®ãããªããã»ã¹ã¯ãã³ã³ãã¥ãŒã¿ã°ã©ãã£ãã¯ã¹ã§ã¯ã¹ããã³ã°ãšåŒã°ããŸãã
å®å šãªã³ãŒãã¯ã次ã®ãšããã§ãã
import genesis as gs
# åæå
gs.init()
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt = 4e-3,
substeps = 10,
),
mpm_options=gs.options.MPMOptions(
lower_bound = (-0.5, -1.0, 0.0),
upper_bound = (0.5, 1.0, 1),
),
vis_options=gs.options.VisOptions(
visualize_mpm_boundary = True,
),
viewer_options=gs.options.ViewerOptions(
camera_fov=30,
),
show_viewer = True,
)
# ã·ãŒã³ã«ãšã³ãã£ãã£ã远å
plane = scene.add_entity(
morph=gs.morphs.Plane(),
)
obj_elastic = scene.add_entity(
material=gs.materials.MPM.Elastic(),
morph=gs.morphs.Box(
pos = (0.0, -0.5, 0.25),
size = (0.2, 0.2, 0.2),
),
surface=gs.surfaces.Default(
color = (1.0, 0.4, 0.4),
vis_mode = 'visual',
),
)
obj_sand = scene.add_entity(
material=gs.materials.MPM.Liquid(),
morph=gs.morphs.Box(
pos = (0.0, 0.0, 0.25),
size = (0.3, 0.3, 0.3),
),
surface=gs.surfaces.Default(
color = (0.3, 0.3, 1.0),
vis_mode = 'particle',
),
)
obj_plastic = scene.add_entity(
material=gs.materials.MPM.ElastoPlastic(),
morph=gs.morphs.Sphere(
pos = (0.0, 0.5, 0.35),
radius = 0.1,
),
surface=gs.surfaces.Default(
color = (0.4, 1.0, 0.4),
vis_mode = 'particle',
),
)
# ã·ãŒã³ã®ãã«ã
scene.build()
horizon = 1000
for i in range(horizon):
scene.step()åºç€ãšãªãç©çãããªã¢ã«ã倿Žããã«ã¯ããããªã¢ã«å±æ§ã倿Žããã ãã§ããããšã«æ³šæããŠãã ãããä»ã®ãããªã¢ã« ã¿ã€ã (MPM.Sand() ã MPM.Snow() ãªã©) ããåãããªã¢ã« ã¿ã€ãã®ããããã£å€ãèªç±ã«è©ŠããŠã¿ãŠãã ããã

4. PBDãœã«ã㌠ã䜿çšããåžã®ã·ãã¥ã¬ãŒã·ã§ã³
PBD ã¯ãPosition Based Dynamics ã®ç¥ã§ãããããã©ã°ã©ã³ãžã¥ãœã«ããŒã§ãããŒãã£ã¯ã«ãšãšããžã䜿çšããŠãšã³ãã£ãã£ã衚çŸããäžé£ã®äœçœ®ããŒã¹ã®å¶çŽã解決ããããšã§ãšã³ãã£ãã£ã®ç¶æ ãã·ãã¥ã¬ãŒãããŸããããããžãŒãç¶æãã 1D/2D/3D ãšã³ãã£ãã£ãã·ãã¥ã¬ãŒãããããã«äœ¿çšã§ããŸãããã®äŸã§ã¯ãPBD ãœã«ããŒã䜿çšããŠåžãã·ãã¥ã¬ãŒãããæ¹æ³ã説æããŸãã
ãã®äŸã§ã¯ã2ã€ã®æ£æ¹åœ¢ã®åžãšã³ãã£ãã£ã远å ããŸãã1ã€ã¯4ã€ã®è§ãåºå®ããããã1ã€ã¯1ã€ã®è§ã®ã¿ãåºå®ãããŠæåã®åžã®äžã«èœã¡ãŸããããã«ãç°ãªã vis_modes ã䜿çšããŠã¬ã³ããªã³ã°ããŸãã
ã·ãŒã³ãäœæããŠãã«ãããŸãã
import genesis as gs
# åæå
gs.init()
# ã·ãŒã³ã®äœæ
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt = 4e-3,
substeps = 10,
),
viewer_options=gs.options.ViewerOptions(
camera_fov = 30,
res = (1280, 720),
max_FPS = 60,
),
show_viewer = True,
)
# ã·ãŒã³ããšã³ãã£ãã£ã«è¿œå
plane = scene.add_entity(
morph=gs.morphs.Plane(),
)
cloth_1 = scene.add_entity(
material=gs.materials.PBD.Cloth(),
morph=gs.morphs.Mesh(
file='meshes/cloth.obj',
scale=2.0,
pos=(0, 0, 0.5),
euler=(0.0, 0, 0.0),
),
surface=gs.surfaces.Default(
color=(0.2, 0.4, 0.8, 1.0),
vis_mode='visual',
)
)
cloth_2 = scene.add_entity(
material=gs.materials.PBD.Cloth(),
morph=gs.morphs.Mesh(
file='meshes/cloth.obj',
scale=2.0,
pos=(0, 0, 1.0),
euler=(0.0, 0, 0.0),
),
surface=gs.surfaces.Default(
color=(0.8, 0.4, 0.2, 1.0),
vis_mode='particle',
)
)
# ã·ãŒã³ã®ãã«ã
scene.build()次ã«ãå¿ èŠãªã³ãŒã㌠(ç²å) ãåºå®ããŸãããããè¡ãããã«ãçŽäº€ç©ºéå ã®äœçœ®ã䜿çšããŠç²åãèŠã€ãã䟿å©ãªããŒã«ãæäŸããŸãã
cloth_1.fix_particle(cloth_1.find_closest_particle((-1, -1, 1.0)))
cloth_1.fix_particle(cloth_1.find_closest_particle((1, 1, 1.0)))
cloth_1.fix_particle(cloth_1.find_closest_particle((-1, 1, 1.0)))
cloth_1.fix_particle(cloth_1.find_closest_particle((1, -1, 1.0)))
cloth_2.fix_particle(cloth_2.find_closest_particle((-1, -1, 1.0)))
horizon = 1000
for i in range(horizon):
scene.step()