カーブに沿わせたオブジェクト配置について考える(2.9-3.0)

道に沿って並ぶ電柱や線路の枕木のようなものを作りたい場合
カーブに沿わせてオブジェクトを配置するといった操作をすることが多いです

ジオメトリノードの搭載でそういった「配置」の選択肢が増えたので
試しながら考察してみたいと思います

## 2.8でも使える配置
まず　これまでのバージョンでも使える方法をおさらいします
子にしたオブジェクトを頂点や面の位置に配置する**インスタンス化**という機能があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/c8c1bddf-bb4f-25ee-8f7d-723cf95f0bf8.png)
経路になるカーブと　面を配置する間隔に合わせた平面を用意して
平面に**配列(Array)**のモディファイアを設定して
「適合する種類」の設定を**カーブに合わせる**に変更して　カーブ項目に経路になるカーブを指定することで
平面がカーブの長さに合わせて複製された状態になり
**カーブ**のモディファイアを設定することでカーブに沿って平面が作成されることになります。

板が意図せず傾いた状態になる場合にはカーブのオブジェクトデータプロパティの「ツイスト方式」を**Z-UP**にするといいでしょう

平面のオブジェクトの**子**に適当なオブジェクトを親子付けして
平面オブジェクトの「インスタンス化」の項目を**頂点**や**面**に変更すると、
頂点や面の位置に　子にしたオブジェクトが現れます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/eacf138b-e4f1-c2de-aa47-0d251abad1c3.png)
**面**にした場合　面の向きに合わせてオブジェクトも回転します
下の「インスタンサーを表示」の ビューポート　とレンダーのそれそれのチェックを外すと
元になった面がビューポート上やレンダリング時には表示されなくなります。


さて、これはこれで便利な機能ですが、少し煩雑なのと、
１つのオブジェクトしか並べられないのでバリエーションのあるものを並べるといったことはできません。
また　うまく配置するには それぞれのオブジェクトの原点が同じ位置にないといけません

## Blender2.9のジオメトリノード
まずはBlender2.93のジオメトリノードの機能を試してみます

ジオメトリノードでは　Collectionの中身からランダムにオブジェクトを選択して配置する機能がつきました
2.9のジオメトリノードではカーブのデータを扱うことができないので
先の方式のようにカーブを利用して面を配置した後に　ジオメトリノードでオブジェクトを配置しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/99d403e0-5d3c-a5a4-1fc0-e5a0fc06493b.png)
頂点位置に配置することになるので　配列のモディファイアのマージをオンにして重なる位置にある頂点は結合しています

面の位置に配置する機能はないようですが1列に配置するのはどうすればいいでしょうか？
線状のポリゴンを用意してもいいですが、頂点ウエイトを設定して　グループでフィルタリングしてみました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/fcf50c8b-05d6-fd69-5e8f-97b2b76d5bff.png)
選択している頂点にGroupの頂点グループが設定してあります。
**ポイント分離**のマスクにGroupと入力することでグループを設定してある頂点とそれ以外にフィルタできています

「インスタンス化」ではカーブの向きに沿って回転していましたが、こちらでは元のオブジェクトと同じ方向を向いてしまっています
とりあえず面の法線の方向に向けてオブジェクトを回転させてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/123b9718-ed05-b049-7fda-3ce0271c8f7a.png)
**回転をベクトルに整列**は「XYZ」の軸をどれだけ回転すると入力されたベクトルの値方向と重なるか計算するノードです
ここでは面法線のnormalを計算の元にしています
（ジオメトリの入出力をつないで入力部分をクリックすると候補に表示されます）

軸に沿わせた回転をさせたい場合には　面を配列複製する時に　線と垂直になるように設定して
整列するベクトルも変更すればいいようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/13a29f0e-4bb0-248a-5455-a2913204c7a7.png)


## Blender 3.0のジオメトリノード
Blender3.0では　ジオメトリノードではカーブを扱えるようになった上に
属性周りの設定が大きく変化しました
カーブに沿わせてランダム選択したもの配置というのはこうなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/31cfc4c4-8b7a-4f29-d4e2-aa6f6daa2f7f.png)

左上にある**オブジェクト情報**でカーブを指定して、**カーブからポイント**で配置するためのポイント情報を取得しています。


指定したコレクションの中のオブジェクトを個別選択できるようにするには
「コレクション情報」の**子を分離**と 「ポイントにインスタンス作成」の**インスタンスのみ**のチェックをオンにする必要があるようです。

コレクション内のオブジェクトは　標準ではグローバル座標でのオブジェクト位置に影響を受ける状態になっていますが
コレクション情報の**子をリセット**をオンにすると　それぞれのオブジェクトの原点位置を基準に配置計算されるようです。
ワールド原点に置いたり　配置の基準になるオブジェクトの原点と揃える必要がなくなるのは便利ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/c1448f97-6c46-4cfd-845e-3daa4ed7be0c.png)
**子をリセット**をオフの状態で「オリジナル」が選択状態だと　グローバル原点からの位置で平行移動した状態になります

2.9でポイントインスタンスに相当する**ポイントにインスタンス作成**は
インスタンスインデックスで　複数入力されたものの中のどれを使用するか等の指定ができるようになったり機能が増えています
インスタンスインデックスに入力されている**ランダム**はインデックス数の範囲内の値をランダム生成して、どのオブジェクトを使うかの指定をしています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/dbbfea35-27ef-d2f8-1852-76578c9457fe.png)

因みに回転に接続している　オイラー回転のノードは
回転でZ軸がカーブの線の方向に向くような値なので　配置するオブジェクトの向きと合わせるように調整するものです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/9655cb94-a84c-b600-855d-37896d24a581.png)
ジオメトリノードでの配置は単に規則的な値だけでなく　どんどんノードを足して思い通りに調整したり　つなぎなおして元に戻したり
試行錯誤が非常に楽なのでどんどん試していきたいですね。