見出し画像

Genesis 入門 (7) - Beyond Rigid Bodies

「Genesis」の「Beyond Rigid Bodies」についてまとめました。

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()

次回



いいなと思ったら応援しよう!