Rustのコミュニティの出来事についてまとめている"This Week in Rust"というサイトがあります。その"This Week in Rust"の428号あたりから、464号あたりまで、 Fornjotというプロジェクトの開発状況のアップデートに関するリンクがほぼ毎回掲載されていました。本稿ではそのFornjotについて紹介をします。
Fornjotとは
FornjotはRustで書かれた3D CADアプリ、つまり3次元モデルを設計するためのアプリです。3D CADアプリと聞いて多くの方が思い浮かべるのは、GUIでポインティングデバイスを使って3次元モデルを設計するアプリではないでしょうか。Fornjotによる3次元モデルの設計はGUIでは行いません。Fornjotは
#[fj::model] // `model`関数をモデル関数に設定
pub fn model(#[param(default = 10.0)] side: f64) -> fj::Shape {
#[rustfmt::skip] // 見やすさのため`rustfmt`での整形をスキップ
let square = fj::Sketch::from_points(vec![ // 4つの点を指定して立方体の底面を生成
[0.0, 0.0],
[side, 0.0],
[side, side],
[0.0, side],
]);
let cube = fj::Sweep::from_path(square.into(), [0.0, 0.0, side]); // 生成した底面をZ軸方向にスイープして立方体を生成
cube.into() // `cube`を`fj::Shape`型に変換して戻り値とする
}
上記のコードを実行することによって、図に示す3次元モデルが生成されます。コードの詳細については後述します。
コードから3次元モデルを生成する3D CADアプリはFornjotが登場する前から存在しており、OpenSCADが有名です。なぜ新しい3D CADアプリを開発したのか、なぜコードファーストCADアプリなのかといった疑問については、Fornjotの開発者がFornjotのブログやFAQでたくさん語っているので、そちらをご参照ください。
本稿ではFornjotの簡単な使い方について紹介していきますが、まずご了承いただきたい点について説明します。Fornjotはまだ開発の初期にあるアプリであり、現時点では実用的に使用できる段階には至っていません。また、開発されて間もないアプリであるがゆえに、今後大規模な変更が加えられる可能性があり、本稿の内容が適用できなくなることもあり得ます。これらの状況をご理解いただいたうえで本稿をお読みください。
なお、この記事は次の環境を前提としています。
macOS Ventura 13.0.1
rustup 1.25.1 (bb60b1e89 2022-07-12)
rustc 1.65.0 (897e37553 2022-11-02)
cargo 1.65.0 (4bc8f24d3 2022-10-20)
Fornjot 0.23.0
Fornjotの使い方〜設計用プロジェクトの作成
Fornjotで3次元モデルを生成するためにはfj-app
というプログラムを使います。まず、cargo
を使ってfj-app
クレートをインストールします。
$ cargo install fj-app
Fornjot ではライブラリクレートのプロジェクトを作って、そのプロジェクトの中で3次元のモデルを設計します
$ cargo new --lib fj-playground $ cd fj-playground
設計用プロジェクトでは、Fornjotのエンドユーザ向けAPIを定義しているfj
クレートが必要になりますので、Cargo.
で依存関係を設定します。Cargo.
を以下のように記述します。
なお、Cargo.
では特に触れられていませんが、設計用プロジェクトはクレートタイプcdylib
のライブラリクレートとしてビルドされますfj-host
クレートのソースコード)。その理由については後述します。
クレートタイプをcdylib
に変更すると、ライブラリクレートが動的システムライブラリを出力するようになります。
それでは、src/
に設計用のコードを書いていきます。先に掲載した立方体を生成するコードを再掲します。このコードからは、1辺が10の立方体が生成されます。
src/
ではfj::
アトリビュートの付いた、戻り値の型がfj::
となる関数を定義しますmodel
という名前の関数がモデル関数にあたります。
モデル関数には、3次元モデルの生成時にfj-app
から値を渡すことのできるパラメータを設定できます。モデル関数の引数にparam
アトリビュートを付けることで、引数がパラメータとして扱われます。このコード例では、立方体の1辺の長さとして既定値が10のside
というパラメータを使っています。
モデル関数ではまず、fj::
関数を使って1辺が10の正方形のfj::
を生成して、それがsquare
を束縛しています。次に、fj::
関数を使って、square
をZ軸方向に10だけスイープした形、つまり1辺が10の立方体を生成して、それがcube
を束縛しています。
最後に、into
関数でcube
をfj::
に変換して、これをモデル関数の戻り値としています。
Fornjotの使い方〜3次元モデルの生成
作成した設計用プロジェクトから3次元モデルを生成するには、fj-app
を使います。fj-app
では設計用プロジェクトのディレクトリを-m
オプションで指定します。
$ fj-app -m .
これで、3次元モデルの表示用のGUIが起動して、生成された3次元モデルを見ることができます。
また、-e
オプションを使うことで3MF
形式やSTL
形式のファイルに3次元モデルをエクスポートすることもできます。
$ fj-app -e cube.stl -m .
これで、cube.
というファイルに3次元モデルがエクスポートされます。STL
形式は現状多くの3Dプリンタのスライサがサポートしているファイル形式ですので、エクスポートの機能を使うとFornjotで設計した3次元モデルを3Dプリンタで出力するといった使い方も見えてきます。ちなみに、筆者が3D CADアプリに興味を持ったのは、自作キーボードのケースを設計して3Dプリンタで出力したかったからでした。
前述のモデル関数のパラメータについては-p
オプションを使って変更できます。side
パラメータの既定値は10ですが、次のようにすると1辺が20の立方体が生成されます。
$ fj-app -m . -p side=20
立方体なので3次元モデルの見た目だけでは変化が分からないかもしれませんが、サイドバーに
ここまでFornjotの簡単な使い方を紹介しました。本稿で示した例は、Fornjotの説明をするために単純化したものですので、ご自身で書き換えて、どのような3次元モデルが生成できるのか試してみてください。Fornjotで使用できるAPIについては、fj
クレートのドキュメントで調べることができます。
また、FornjotのGitHubリポジトリにもいくつかのサンプルがあります。例えば、star
モデルは、既定値ではとげの数が5個の星型をベースとした立体を生成します。
$ git clone -b v0.23.0 https://github.com/hannobraun/Fornjot.git $ cd Fornjot $ cargo run -- -m star
star
モデルのモデル関数にはnum_
というパラメータがあります。num_
パラメータを変更することで、star
モデルからとげの数を変更した星型をベースとした立体を生成できます。次のようにすると、とげの数が10個の星型をベースとした立体が生成されます。
$ cargo run -- -m star -p num_points=10
どのようにしてこのようなことを実現しているのか、興味のある方はstar
モデルのモデル関数を見てみてください。
この記事では、2次元モデルを生成して、それをスイープすることで3次元モデルを生成するという3D CADアプリの基本的な操作を紹介しました。さらに複雑な3次元モデルを生成するとなると、複数の3次元モデルを生成して、それらの3次元モデルに対して和、差、積といったブーリアン演算を行うことになるのですが、現時点ではFornjotにはブーリアン演算が実装されていません。もちろん、Fornjotの開発者もブーリアン演算の重要性は理解しており、その実装には高い優先度が設定されていますので、今後に期待したいところです。
コードファーストCADアプリのDSLとしてのRust
現時点で、Fornjotで3次元モデルを設計するために使用できるDSL
ところで、3次元モデルの生成にかかる時間をできる限り短くすることは、開発体験の向上につながります。また、3次元モデルのコードの修正結果は、できる限り早く、できれば即時に生成される3次元モデルに反映されてほしいところです。Rustはプロジェクトのビルドに時間がかかると言われることがありますが、Fornjotでは設計用プロジェクトからどのようにして3次元モデルを生成しているのでしょうか。
設計用プロジェクトはRustのライブラリクレートのプロジェクトと同じ形式をしていて、設計用プロジェクト単体で何かを実行できるものではありません。前述のとおり、設計用プロジェクトから3次元モデルを生成するにはfj-app
を使う必要があります。設計用プロジェクトをバイナリクレートのプロジェクトの形式にして、3D CADエンジン、GUIなどのためのFornjotのクレートを依存関係に設定した上でcargo run
で3次元モデルを生成するというしくみもあり得るのですが、そのようなしくみを現状のFornjotは採用していません。
設計用プロジェクトをたくさんのクレートに依存させてしまうと、設計用プロジェクトのビルドに時間がかかってしまい、前述のfj
クレートのみに依存させて、動的システムライブラリを出力するように設計用プロジェクトをビルドしています。そしてfj-app
fj-app
クレートが依存しているfj-host
クレート)libloading
クレートを使って設計用プロジェクトから出力された動的システムライブラリをロードして、3次元モデルを生成します。これが設計用プロジェクトのライブラリクレートのクレートタイプをcdylib
にしている理由です。このようなしくみを採用することで、Fornjotでは設計用プロジェクトのビルドの時間を短縮しています。
まとめ
本稿では、3D CADアプリのFornjotについて、簡単な使い方を紹介しました。Fornjotには今後、設計用プロジェクトの出力を動的システムライブラリからWebAssemblyへと変更する計画もあるようで、技術的にも面白いプロジェクトです。興味を持った方は、ぜひFornjotのリポジトリを覗いてみてください。