やさいのつくりかた.

目次/第01章

01CONFIG

「作る」と「読み込む」はどう違うのか

procedural generation — 手続き的生成

この章の3行まとめ
  • ふつうの3Dは、誰かが作ったモデルファイルを読み込んで表示します。
  • このプロジェクトは逆で、実行した瞬間に座標を計算で作ります。これを手続き的生成といいます。
  • だから1個ずつ形が違い、あとから自由に変えられ、しかもデータが軽い。

ゲームや映画の3Dは、ふつう誰かが専用ソフトで作ったモデルファイルを読み込んで表示します。 ファイルの中には「頂点1番は(3.2, 1.1, 0.4)」といった座標が何万個も保存されていて、 プログラムはそれを並べて画面に出すだけです。

このプロジェクトは逆のことをしています。ファイルを読まず、 プログラムを実行した瞬間に座標を計算で作る。これを手続き的生成(プロシージャル生成)と呼びます。 野菜のような自然物と相性がよく、いいことが3つあります。

  • 1個も同じにならない — 数値を少し揺らすだけで、形の違う個体がいくらでも出てきます。実物のきゅうりが1本ずつ違うのと同じです。
  • あとから変えられる — 「もう少し太く」がスライダー1本で通ります。モデルファイルなら作り直しです。
  • 軽い — 23本ぜんぶ合わせても、写真1枚より小さいテキストです。

その代わり、形を言葉ではなく数式で説明できないと作れません。 「トマトってどんな形?」に「肩がへこんでいて、縦に浅い筋が6本あって、上から見ると少しつぶれた丸」と 答えられるかどうかが勝負になります。だからこのプロジェクトのコードは、コメントの半分が 野菜の観察記録です。

ほとんどのファイルが、同じ9層でできている

トマトもシイタケも玉ねぎも、ファイルの構造はまったく同じです。上から順に読めば、 どの野菜でも同じ場所に同じ役割のコードがあります。このサイトの第I部(01〜11章)は、この層に対応させてあります。

// 構成:
//    0. CONFIG      … 品種プリセット(桃太郎 / フルーツトマト / ミニ)
//    1. Rng         … シード付き擬似乱数
//    2. Noise       … 3D値ノイズ / 2D周期ノイズ
//    3. Mesh utils  … 巻き順の自動判定・法線の溶接・掃引
//    4. Profile     … 果実の断面(r, y の2列テーブル)・房の稜・肩のくぼみ
//    5. TextureLab  … 果皮のアルベド・ORM・法線、竹の網代
//    6. Tomato      … 果実 + がく(萼片を1枚ずつ立体で)+ 果梗
//    7. Basket      … ざる
//    8. Scene / 物理(Havok で1個ずつ落とす)
//    9. GUI
トマト.js の冒頭。23本のうち20本が、この並びで書かれている
ただし、例外が3本あります

ブロッコリー.js / カリフラワー.js / ロマネスコ.js は、この9層に収まりません。 形を「横顔」で言い表せないので 4. Profile が無く、 枝分かれした形にはUVが張れないので 5. TextureLab も無い。 代わりに Corymb(房の再帰)や Fractal(黄金角の再帰配置)という層が入っています。 この3本の作り方は第II部(12〜16章)にまとめました。

読む順番のおすすめ。 最初の1本はニンジン.jsがいちばん素直です(円錐に溝を彫るだけ)。 次にキュウリ.js、慣れたらトマト.js。 シイタケ.jsとトウモロコシ.jsは構造が複雑なので後回しでかまいません。
やってみよう
  1. ニンジン.js の先頭のコメント(構成 0〜9)を読んで、他のファイルにも同じ並びがあるか確かめる。
  2. 手続き的生成のいいところ3つを、自分の言葉で1行ずつ書いてみる。
  3. ブロッコリー.js の先頭を開いて、4番と5番が別のものに入れ替わっていることを確かめる。
  4. 身のまわりで「数式で説明できそうな形」を3つ探す(例:ソフトクリーム、ネジ、松ぼっくり)。