SolidML で簡単にモデル生成

SolidML で簡単にモデル生成:



2018-12-15_22h06_08.png

SolidML Demonstration


はじめに

WebGL Advent Calendar 2018 の16日目の記事です。

keimと申します。一年くらい前までは shadertoyGLSLfan など Shader Art 界隈で遊んでおり、去年のアドベントカレンダーでは「レイマーチングでガラスレンダリング」の記事を書いたり、今年は縁あって GLSL Tech Night 2018スピーカーとして登壇させていただいたりしました。

ここ数か月は主に three.js で遊んでおり、ちょうど最近作っていたものが出来上がりつつあったので、この場を借りて公開させていただこうと思います。


Structure Synth

2007年ころ登場したStructure Synthというアプリをご存知でしょうか?

複雑な幾何学立体を非常に簡潔なスクリプトで生成することができるソフトです。Frickrグループには Structure Synth で生成した立体のレンダリング結果が大量に置かれており、どんな事ができるか何となく解ると思います。

開発者は、フラクタル界隈ではかなり有名なSyntopia blogというブログを運営されているMikael H Christensen氏で、2010年まで開発され、現在は更新を停止しています。

2011年からは Fragment Shader によるレイトレースを利用したFragmentariumの開発に移行しており、こちらはポリゴンの制約を受けない本格的なフラクタル立体を描く事ができます。

GPUの性能が向上し Shader レイトレースのノウハウもだいぶ蓄積されてきた現在、フラクタル形状を生成するのにポリゴンベースのStructure Synth はあまり良い選択肢とは言えません。しかし、ポリゴンは汎用的な技術のため一般的な3D描写との相性が良く、オブジェクト数が制限されたフラクタルの独特の形状は他に類のない魅力があり、いまだにコアなファンの支持を受けています。


SolidML

この Structure Synth のスクリプトである Eisen Script を使って three.js の BufferGeometry を生成してみたいと思い、今年10月くらいから実装を開始しました。

11月下旬には一通りの実装を終えたのですが、得意なMMLと似ていると感じ、自分が書きやすいようにシンタックスシュガーを適当に入れていくうちに別言語の様相を呈してきました。

そこで、それまで StructureSynth.js という名前だったものを SolidML と改名してリリースすることにしました。

ここでは SolidML の簡単な利用方法を紹介します。まだ作り途中のため、ドキュメント整備まで手が回っていませんが、徐々に準備していきたいと考えています。


環境

ブラウザで https://keim.github.io/SolidML/demo/index.html にアクセスして左のテキストエリアにスクリプトを打って Build ボタンを押せば生成することができます。ビルドに成功すると url query にスクリプトの平文が含まれるので、このようにリンクでスクリプトをシェアすることができます。


API

https://keim.github.io/SolidML/jsdoc/index.html に一通り書いてありますが、

- Github レポジトリsrc/SolidML.jssrc/SolidMLBufferGeometry.js を呼び込む。

- SolidML.BufferGeometry のコンストラクタに Eisen Script 文字列を渡して、インスタンスを作成する。

これで他のTHREE.BufferGeometryと同じ感覚で利用することができます。

solidml.js
const geometry = new SolidML.BufferGeometry( "20{rx18y2s0.90}R#R@37{tube:6{x1rz10}R}" ); 
const material = new THREE.MeshPhysicalMaterial( { color : new THREE.Color( 0xff0000 )} ); 
const mesh = new Mesh( geometry, material ); 


構文

基本的には Eisen Script にシンタックスシュガーや追加コマンドを加えたものなので、Eisen Script そのままでも動きます。Eisen Scriptの解説は本家に任せるとして、ここでは SolidML の記法をベースに開設したいと思います。

(本家との比較は、README.mdを参照ください。)


1.プリミティブを生成する



solidml.jpg


box.es
box 
boxshperelinegridcylinderconetorustetraoctadodecaicosatrianglemeshtubecmeshctube の予約語を書くとそれぞれに対応した大きさ1の形状を置くことができます。
linecylinderconetorus など軸が存在する形状はx軸が基準となります。

また、shperelinecylinderconeなどは、shpere:20とコロンの後に数字を打つと形状のポリゴン分割数を指定することができます。


solidml (1).jpg


script



2.変換&複製する

translate.es
10{x2}sphere 
予約語やルール名の前に {...}で変換方法を指定し、その前に変換回数を指定することで、指定回数分変換を繰り返しつつ、形状を置きます。上記スクリプトでは「10回 xを+2移動させつつ 球を配置する」ので、以下のような形状を生成します。



solidml (1).jpg


script


変換コマンドには、軸並行移動(xyz)、軸回転(rxryrz)、拡大縮小(s)、3x3行列指定(m)があります。本家コマンドと全く同じです。連続した変換は中かっこ内に逆順(行列をかける方向)で書きます。例えば「y軸中心に10度回転してx方向に2移動」は {x2ry10} と記述します。

transandrot.es
10{x2ry10}box 


solidml.jpg


script


変換を分けて連続で記述すると全ての組み合わせを実行します。以下の例では「x+2を5回」と「y+2を4回」で全変換をかけるため、全部で20個のcylinderが並びます。

transandrot.es
5{x2}4{y2}cylinder 


solidml (2).jpg


script



3.色操作

変換コマンドと同様に、色変換または色指定を記述することができます。本家と同様にSVG keyword names、cssと同様の16進数カラー表現、HSBによるカラー表、おぼびalpha指定が記述可能です。

colortransform.es
{x0 red}  box 
{x2 navy}  sphere 
{x4 #ff00ff} grid 
{x6 #0f0} cylinder 
{x8 h60sat1b1} cone 
{x10 a0.5} torus 


solidml (9).jpg


script


hsatba の各コマンドはひとつ前のオブジェクト設置時の色からの変化分を記述します。色相は加算、それ以外は乗算されます。初期値は{hue:0, saturation:1, brightness:1}の赤です。
*コマンドは色のブレンディングを計算します。例えば*blue 0.1であれば、一個オブジェクトを設置するたびに0.1だけ青成分を混ぜます(本家blendコマンドのシンタックスシュガーです)。

また、彩度・明度のみのブレンドも可能です。*s0.8 0.1は、彩度0.8に向けて0.1だけ近づけます(本家では彩度明度は乗算しかできないため、目的値に向かって値を近づける方法が提供されていませんでした。)

colortransform.es
{y0} 36{x1 h10} sphere 
{y2} 36{x1 sat0.9} tetra 
{y4} 36{x1 b0.9} box 
{y6} 36{x1 a0.9} octa 
{y8} 36{x1 *blue 0.1} dodeca 
{y10sat0.01} 36{x1 *s0.8 0.1} icosa 


solidml (8).jpg


script


#?コマンドを用いるとあらかじめ color pool として指定した色リストからランダムに色を抽出します(本家color randomset color pool list:のシンタックスシュガーです。)color pool は色リストのほかに @cp:h0(色相のみ乱数)、@cp:g0(グレイスケールの中から乱数)があります。無指定の場合、RGB3値とも乱数で決定します。本家のcolor poolと同等の機能実装で、仕様は開発者ブログに説明があります。

colorpool.es
@cp[black,yellow,yellow] 
10{x2#?} cone 


solidml (10).jpg


script



4.メッシュ、チューブ

meshtubecmeshctubeの各コマンドは、連続で呼び出されると変換の進む方向に向かってメッシュを作ります。meshはスケーリングが線の細さに影響しますが、tubeはスケーリングによらず一定の太さでメッシュを生成します。また、meshはフラットシェーディングによって角が現れるのに対してcmeshはスムースシェーディングのためシリーンダー形状を生成するようになります。

これらのコマンドは、shpereと同様、コロンで区切って数字を指定することで、断面の正多角形を指定することができます。

colorpool.es
100{x1ry10s0.99} mesh 


solidml (11).jpg


script



5.ルール

(これが一番の肝なのですが、とても時間がかかりそうなので後日追記の形とさせてください。ごめんなさい。)

基本的に本家のルール記述のシンタックスシュガーです。以下、雰囲気だけ。


  • rule NAME maxdepth 10 w 1 {...} -> #NAME@10@w1{...}

  • #NAME { A (B | C) D } という記述は #NAME { A B D } #NAME { A C D } に展開されます。
(To Be Added)


6.システムコマンド

@1000 max depth。再帰呼び出しの最大回数
@mo10000 max object。オブジェクトの最大数
@s1234 乱数のシード値の指定。
@bg[#679,#fff,#eef] 背景の空、床、チェッカーボードの各色を指定。
@mat[10,90,30,20] 素材の metalness, roughness, clearcoat, clearcoat roughness を%で指定。

(To Be Added)


まとめ

(すいません。後半間に合わず、中途半端な解説でリリースしてしまいました。後日追記します。)

SolidML は、Struture Synth の Three.js への拡張実装です。URLをもちいて比較的簡単にシェアできますので、面白い形状ができたらSNSで拡散したり、Gist で書き捨てしたりしてくれると嬉しいです。

この技術はうまく使えば、例えばメカパーツをベースに生成することでシューティングゲームのボス生成とか、応用範囲が結構広いのではないかと考えています。もうちょっと色々展開できたらと思っています。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)