Vala プログラミング

WebGPU プログラミング

おなが@京都先端科学大

Julia MeshCat SPH 流体シミュレーション (Mesh)

Julia MeshCat ライブラリを用いた、水柱崩壊のシミュレーションです。
流体のシミュレーションには、SPH (Smoothed Particle Hydrodynamics) 法を
使用しています。
前回は、PointCloudを用いて、粒子による描画を行いました。
今回は、Marching cubes法を用いて、meshによる描画を行います。

水柱崩壊のシミュレーション(meshによる描画)
f:id:onagat12:20200609115034g:plain

水柱崩壊のシミュレーション(povrayによる描画)
f:id:onagat12:20200609115108g:plain

1. meshの描画
 粒子による描画をmeshによる描画にするには、粒子の集まりの表面(のようなもの)に
 meshを張ります。具体的には、粒子の密度がゼロとなる境界にmeshを張っていきます。
 (「修士論文 水の実時間アニメーション 天田崇」
 https://library.naist.jp/mylimedio/dllimedio/showpdf2.cgi/DLPDFR003344_P1-56
 の方法を参考にしました。)

・meshの生成
 ①distance field 値を計算する。
  陰関数には、粒子の密度を用いる。
 ②distance field 値から、Marching cubes法を用いて、meshのvertexとfaceを
  生成する。
 GeometryTypesとMeshingライブラリを使用します。

using Meshing
using GeometryTypes

function create_mesh(nloop)
    println("nloop ", nloop)

    DT = 0.004
    positions = Simulation(DT)
    resolution  = 0.75
    sdf = SignedDistanceField(HyperRectangle(Vec(-2.,-2,-2),Vec(14.,30,20)), resolution) do v
        sum = 0.0
        map(positions) do position
            distance = norm(v - position) * simscale
            sum += w_rho(distance, h)
        end
        # density
        density = sum * mass * w_rho_coef
        density - rest_density
    end
    
    m = SimpleMesh(sdf, MarchingCubes())
end

# 描画
N = 200

for i = 1:N
    m = create_mesh(i)
    m.vertices .*= 0.1
    setobject!(vis, m, material)
    # transform 関連
end


2. povrayによる描画
 下のpovファイルを使って描画しています。これは、「粒子法入門 越塚他著」にある
 povファイルを参考にしています。

povファイル

#include "colors.inc"
#include "glass.inc"

global_settings{max_trace_level 20}
camera{ location <-2.5, 1.0, -2.8> look_at <0.5, 0.5, -1.5>}
light_source{ <0.5, 1, 0.25> color rgb<1, 1, 1>}
sky_sphere{
   pigment{
      gradient y
      color_map{
         [0.0 color rgb<1.0,1.0,1.0>*0.5]
         [0.2 color rgb<1.0,1.0,1.0>*0.2]
      }
   }
}

plane { y, 0.0
   texture {
      pigment{checker color White color Gray70 scale 0.2}
   }
   finish { ambient 0.5}
}

mesh2{
   vertex_vectors { 6296,
      <0.1,0.1,-0.058611978>
      <0.1,0.07704518,-0.05>
      <0.07704518,0.1,-0.05>
          ・・・(途中省略)
      <0.8040384,0.925,1.675>
      <0.775,0.92816883,1.675>
      <0.775,0.925,1.6781456>
   }
   face_indices { 3143,
      <3,2,1>
      <6,5,4>
      <6,4,7>
        ・・・(途中省略)
      <6287,6286,6285>
      <6290,6289,6288>
     <6293,6292,6291>
   }

   rotate x*(-90)
   texture { T_Glass3 } interior{ I_Glass ior 1.33 }
}


meshデータの生成
meshデータ(vertex_vectorsとface_indices)は以下のようにして生成しています。

function writeData(i, mesh)
    filename = string("out", lpad(i,4,"0"), ".dat")
    out = open(filename, "w")
    # vertices
    println(out, "vertex_vectors { ", length(mesh.vertices), ",")
    map(mesh.vertices) do vertex
        println(out, "<", Float32(vertex[1]), ",", Float32(vertex[2]), ",", Float32(vertex[3]), ">")
    end
    println(out, "}")
    # face indices
    println(out, "face_indices { ", length(mesh.faces), ",")
    map(mesh.faces) do face
        println(out, "<", face[1], ",", face[2], ",", face[3], ">")
    end
    println(out, "}")
    close(out)
end