oFで樹木のモデリング (1)

ここ最近、openFrameworksを使って樹木のモデリングをしようと試行錯誤しています。
oFで悪戦苦闘しながらも、なんとか樹木っぽいモデリングができたので方法を紹介したいと思います。obj

樹木といえばProcessingでも有名なサンプルがありますね。
http://www.processing.org/examples/tree.html

sample

このサンプルは2次元ですが、ここでは3次元の樹木をモデリングしたいのです。
さらに、モデリングデータをobjに書き出してCINEMA 4Dでレンダリングしたいと思います。

とはいえ、基本はProcessingと同様に二分木の作成からスタートです。

まずは枝の基本となるbranchクラスを作ります。
このクラスは自分自身へのポインタを二つ持つ自己参照クラスです。
rightには幹を、leftには枝を発生させます。
branchはrightとleftに次々に新しいインスタンスを生成し、再帰関数で数珠つなぎのデータ構造を作ります。
この時、leftは必ずしも生成される訳ではなく、低確率で生成されます。
ここに確率を加えた事で枝の歪みを表現しようと思います。
branchのイメージは図のような感じです。

tree2

 

branchはgrowという再帰関数で枝を次々に生成します。

branchを連続的に生成する方法は下図のような感じです。
branchは子世代を生成するに従って、だんだんと枝が細くなります。
もしも枝が十分な太さを持っていたら、rightに子世代を生成できます。(Step 1)
rightは親世代から少しだけ回転させます。この回転角が大きいと柳のような丸みの強い幹になり、回転角が小さいと白樺のように真っすぐな幹になります。
次に一定確率でleftに子世代を生成します。leftでも親世代から回転を加えますが、この回転角が大きいと枝がよく広がった木になり、回転角が小さいと真上に枝を伸ばす木になります。(Step 2)

 

tree1

 

 

この仕組みをoFで実装する為にコードを書いてみます。

まずはHeaderです。

次にcppファイルの方を書きます。

branchの設定はmake関数を、消去はdeleteTree関数を使います。

make関数は枝を生成するgrow関数内で何回も呼ばれます。

現状で必要ない変数も定義されていますが、後にアニメーション付けで便利なために書き加えています。

 

次に再帰関数のgrowとdrawです。

 

 

どちらの関数も処理が終わった後にもう一度同じ関数を呼び出す記述があります。

終了条件を間違えたら無限ループに陥るシビアな設計です。

最後に、子世代の位置を決定する関数です。

まず親世代の位置であるparentPosから自分の位置であるposへのベクトルVを求めます。

ベクトルVと 適当なベクトル(1,1,1)との外積を求めて、Vに垂直なベクトルNを求めます。

正規化したベクトルVに枝の長さLをかけると、posを原点としたときの枝の外周の1点を求める事ができます(座標P)。

このPを、ベクトルNを軸に回転させたあとベクトルVを軸に0~360°の乱数で回転させると原点基準の子世代座標Rが求まります。

最後に自分の位置posを足せば子世代の座標が求まります。

 

このbranchクラスをoFのtestApp内で呼び出せば、樹木の骨格を計算できます。

 

スクリーンショット 2014-04-03 19.34.03