Blender で作ったモデルを Houdini で四面体に分割する

タイトルの通りです。Houdini は昨日インストールしたばっかりなので使い方に怪しい所があるかもしれません。

メッシュの四面体分割は有限要素法による解析などでよく用いられており(メッシュを切るなどと言います)、いくつも専用のソフトが存在します。

いくつか試してみたのですが、一番使いやすく、目的に合った分割をしてくれた Houdini の四面体分割機能を使って Blender で作ったモデルを処理する方法を解説します。

モデルを作る

Blender でモデルを作ります。注意点として、

  • \mathbb R^3 上に埋め込める 2 次元多様体になっていること

言い換えると、

  • モデルに穴が開いていないこと[1]
  • ポリゴンが自己交差していないこと
  • 辺が 3 つ以上のポリゴンで共有されていないこと
  • 頂点が離れた面で共有されていないこと

等を満たす必要があります。

こんなモデルを作りました。

出力する前に、モディファイアを適用し、ポリゴンがきちんと外向きになるように修正(編集モードに入って A, Shift+N)しておきます。

準備が済んだら *.stl 形式でモデルをエクスポートします。他の形式でも大丈夫かもしれません。

Houdini で四面体に分割する

Houdini を起動し(Apprentice で大丈夫です)、右下の Objects とあるところで右クリックして File IO → File を選択してノードを作成します。

こんなのが出てくるので、ダブルクリックして中に入り、

上の方のパネルから出力した STL ファイルを設定して読み込みます。

変な方向を向いてるかもしれませんが、四面体分割をする上では支障にならないので放置しても大丈夫です[2]。気になる場合はオブジェクトの回転を適当に設定しておきましょう(一旦ノードを出る必要があります)。

右クリックから Tet Embed を選び、ノードを接続します。

画像のピンク色の部分をクリックすると、早速四面体分割されたメッシュが表示されます。

後は上のパネルから Tet Embed ノードのパラメータをいじくり倒して望みの分割になるまで調整しましょう。

Add Surface Triangles にチェックを入れておいてください。

調整が終わったら、再び File ノードを作成して Tet Embed の出力を入力に繋げます。

出力ファイルの拡張子は *.json にしておきましょう。

すると少々終わっている形式の JSON ファイルが出力されますので、頑張って CTF して読んでいきましょう。

なんと今回は便利なローダーを用意しました。

function loadGeometry(geom) {
    function find(obj, path) {
        for (const name of path) {
            obj = obj[obj.indexOf(name) + 1];
        }
        return obj;
    }
    const idxs = find(geom, ["topology", "pointref", "indices"]);
    const pattrs = find(geom, ["attributes", "pointattributes"]);
    let verts = null;
    for (const pattr of pattrs) {
        if (find(pattr[0], ["name"]) != "P") continue;
        verts = find(pattr[1], ["values", "tuples"]);
        break;
    }
    const prims = find(geom, ["primitives"]);
    let tets = null;
    let tris = null;
    for (const prim of prims) {
        const from = find(prim[1], ["startvertex"]);
        const num = find(prim[1], ["nprimitives"]);
        const type = find(prim[0], ["type"]);
        if (type == "Polygon_run") {
            tris = Array.from({ length: num }, (v, i) => idxs.slice(from + i * 3, from + (i + 1) * 3));
        }
        if (type == "Tetrahedron_run") {
            tets = Array.from({ length: num }, (v, i) => idxs.slice(from + i * 4, from + (i + 1) * 4));
        }
    }
    return {
        verts: verts,
        tris: tris,
        tets: tets,
    };
}

出力された JSON ファイルはそのまま JavaScript のオブジェクトとして読み込めるので、ブラウザのコンソールにでも張り付けてオブジェクト化し、それを上記の関数に入れると、出力から

  • verts: 頂点座標の 2 次元配列
  • tris: メッシュ表面の三角形の添え字の 2 次元配列
  • tets: 四面体の添え字の 2 次元配列

が得られます。後は好きなように加工して保存すれば使うことができます。

もし Houdini の仕様が変わってローダーが機能しなくなっていたら、うまいことエスパーして改造してから使ってください。

おわり

よい物理演算ライフを!


  1. ここでの穴とは「面が途切れてモデルの内側が見える」ような穴を指します。トーラスのような穴は大丈夫です。 ↩︎
  2. 後から気付いたんですが、Blender 側でエクスポート時に軸の向きをきちんと設定してやれば回転しなくて済むようです。 ↩︎

このエントリーをはてなブックマークに追加