RhinoInside Unity の公式サンプルで遊ぶ
29 February, 2020 - 2 min read - Tags: Unity,Grasshopper,RhinoInside,CSharp,Rhinoceros,構造とデジタル
公式の RhinoInside Unity をちょっといじって遊んでみます。
Unity 側のゲームオブジェクトの座標を取得して Grasshopper に送り、その情報をもとに Rhino 側でジオメトリを計算しメッシュを返し、Unity でゲームオブジェクトとして表示することをやっています。
なおこの記事は、Unity、Rhino、C# を基本的な操作を理解していることを前提にしています。
RhinoInside は 2020/02/29 現在開発中の機能なので、RhinoWIP(Rhino7)を使えるかたにしか使えない機能です。 RhinoInside でなにができるか気になる方は こちらの記事 をどうぞ。
セットアップ
RhinoInside Unity を使うためにはmcneel の GitHubを参照してください。概要を説明します。
-
リポジトリをクローンしてください。コマンドプロンプトからやる場合は以下のコマンドを入れてください。
git clone --recursive https://github.com/mcneel/rhino.inside.git rhino.inside
- RhinoCommon を取得するため rhino.inside\Unity\Sample1\Assets\Standard Assets\RhinoInside のフォルダに行き RhinoCommon.Update.bat をダブルクリックしてください。
これで使えるようになります。
Sample2 で遊ぶ
遊んでいくベースとするのは rhino.inside\Unity\Sample2 のフォルダのデータなので UnityHub などを使っているならば、上記フォルダを追加して開きましょう。
Unity を開くと上の画像のように Grasshopper があるので Show を押すと Unity の裏で Rhino と Grasshopper が起動し、ゲームオブジェクトの "Grasshopper Geometry" が作られます。
Grasshopper では "callunity2.gh" ファイルを開くと、Unity の MainCamera の座標を gh に送りその点に対して gh 上でジオメトリの操作をして作られたメッシュを Unity に返す中身になっています。Unity とやり取りする部分だけ C#スクリプトのコンポーネントで作成されています。
gh の中身の概要としては Box で領域を作ってその中に Populate3D で点をランダムにうち、その点と Unity の MainCamera の座標の Distance をとってその関係から Remap してその点に sphere を作る挙動になっています。
動作はこんな感じです。
これだけだと sample そのままで面白くないので、gh の中で点をうつ基準になっている Box のサイズも Unity 側から操作できるようにしてみます。
Sample2 を改造してみる
Unity 側
まず Unity に Box のサイズをコントロールするものを作ります。 gh 内で Box を作成するためには Box の xyz 座標があればいいので、unity のゲームオブジェクトの transform を送ればいいとして、Unity で CreateEmpty でゲームオブジェクトを作って”ControlPoint”と名前を付けます。
この "ControlPoint" を gh 側へ送るために GrasshopperInUnity.cs をいじります。 このファイルでは最初の方は MenuItem での操作の部分が書いてあり一番下の Update の部分に追記していきます。
Update の初めの部分を読むと
var pt = Camera.main.gameObject.transform.position.ToRhino()
となっていて、MainCamera のポジションを ToRhino しています。
ToRhino でやっていることは、transform.position で取得できるのは Vector3 なので、ToRhino で Rhino.Geometry.Point3d に変換しています。その後 args に”point”という名前で pt をセットし、
Rhino.Runtime.HostUtils.ExecuteNamedCallback("ToGrasshopper", args)
で送ってます。
なので、"ControlPoint" の transform.position を ToRhino すれば良さそうなので同じように書いて以下のように追記します。
var gameObj = GameObject.Find("ControlPoint");
var pt2 = gameObj.transform.position.ToRhino();
using (var args = new Rhino.Runtime.NamedParametersEventArgs())
{
args.Set("controlpoint", new Rhino.Geometry.Point(pt2));
Rhino.Runtime.HostUtils.ExecuteNamedCallback("ToGrasshopper1", args);
}
これで Unity 側での作業は終わりです。
Grasshopper 側
Unity から受け取るのは MainCamera のものと同じなので既にある receive のコンポーネントをコピーします。中身を以下のように書き換えます。
Point pt = null;
bool registered = false;
IGH_Component comp = null;
void Register(IGH_Component component)
{
if(!registered)
{
Rhino.Runtime.HostUtils.RegisterNamedCallback("ToGrasshopper1", ToGrasshopper);
comp = component;
registered = true;
}
}
void ToGrasshopper(object sender, Rhino.Runtime.NamedParametersEventArgs args)
{
Rhino.Geometry.GeometryBase[] values;
if (args.TryGetGeometry("controlpoint", out values))
pt = values[0] as Rhino.Geometry.Point;
comp.ExpireSolution(true);
}
書き換えた点は、9 行目で、Unity から届く登録された名前は”ToGrasshopper1”なのでその点を修正しています。 同様に 20 行目も TryGetGeometry するものの名前を”controlpoint”に変えています。
これで C#コンポーネントが完成したのでその出力であるポイントの情報を Deconstruct して Box の入力に入れます。
以上で作業は終わりです。
これでうまくいっていれば Unity 側から操作できるようになっていると思います。 よくわかりませんが書きたての時はうまく動かなかったり Unity が落ちたりするので、ダメなときは Unity 再起動するとうまくいく場合があるかもしれません。
あなたもこれで RhinoInside Unity で遊んでみてください。