RhinoInside Unity で Rhino へメッシュを送るやり方
05 March, 2020 - 2 min read - Tags: Unity,RhinoInside,CSharp,Rhinoceros,構造とデジタル
Rhino.Inside.Unity で Unity から Rhino にメッシュを送る部分を作成したので、送り方を説明します。
なお作った結果として、メッシュはデータ量が多いからか動作が非常に重くなるので、リアルタイムでメッシュのやり取りをしない限りは FBX などを介して送ったほうがよさそうです。
モチベーション
mcneel の GitHub に Rhino から Unity にメッシュを送る部分があるのですが、Unity から Rhino に送る部分がなかったためその部分を作成しました。
今回作成したのは、Unity でゲームオブジェクトにアタッチされているメッシュそのもの(MeshFilter の中の Mesh)を送っているだけです。 transform で設定する position、rotation、scale は送っていません。 このこともあって冒頭で FBX などのものをすすめています。
メッシュの変換を作成
作成したベースは Rhino.Inside.Unity の sample2 を使っています。
Rhino に送るためには Unity のメッシュ(UnityEngine.Mesh)を Rhino のメッシュ(Rhino.Geometry.Mesh)に変換する必要があるので、そこを作成します。
上記サンプルの中では Convert.cs の中でその変換をやっているので、そこに追記します。いわゆる拡張メソッドです。
追記した内容は以下です。
static public Rhino.Geometry.Mesh ToRhino(this UnityEngine.Mesh _mesh)
{
Vector3[] verteces = _mesh.vertices;
int[] triangles = _mesh.triangles;
var result = new Rhino.Geometry.Mesh();
List<Brep> brep = new List<Brep>();
for (int i = 0; i < triangles.Length / 3 - 1; i++)
{
var pt1 = verteces[triangles[3 * i]].ToRhino();
var pt2 = verteces[triangles[3 * i + 1]].ToRhino();
var pt3 = verteces[triangles[3 * i + 2]].ToRhino();
brep.Add(Brep.CreateFromCornerPoints(pt1, pt2, pt3, 0.00001));
}
for (int i = 0; i < brep.Count; i++)
{
result.Append(Rhino.Geometry.Mesh.CreateFromBrep(brep[i]));
}
return result;
}
Unity の Mesh(_mesh)を受け取って、そこから Brep を作り、その Brep から Rhino の Mesh を作っています。
Brep のつくり方は、まず Unity のメッシュの vertices と triangles を使って構成する 3 点を取得します。 この点は Unity の Vector3 なので、ToRhino で Rhino の Point3d に変換し、CreateFromCornerPoints で Brep を作ります。
最後の引数は、tolerance なので、想定する精度をもとに決めればよいですが、Unity の 1 は 1m 相当なので、ここで tolerance を 1mm と思って 1 にすると細かいモデルはうまく送れないのでここでは 0.0001 にしています。必要な精度で適宜設定してください。
Mesh は Brep から CreateFromBrep でつくり Append することでひとまとまりのメッシュにしています。
Rhino へ送るための CallBack を作成
送るメッシュは別途 RhinoInsideController.cs を作ってそれを適当なゲームオブジェクトにアタッチして、そこに _sendObject として受け取るようにしてます。
public GameObject _sendObject;
void Update()
{
var mesh = _sendObject.GetComponent<MeshFilter>().mesh.ToRhino();
using (var args = new Rhino.Runtime.NamedParametersEventArgs())
{
args.Set("mesh", mesh);
Rhino.Runtime.HostUtils.ExecuteNamedCallback("SendObject", args);
}
}
Grasshopper で受け取る CallBack の作成
Grasshopper で受け取る側は以下です。
void Register(IGH_Component component)
{
if(!registered)
{
Rhino.Runtime.HostUtils.RegisterNamedCallback("SendObject", ToGrasshopper);
comp = component;
registered = true;
}
}
void ToGrasshopper(object sender, Rhino.Runtime.NamedParametersEventArgs args)
{
Rhino.Geometry.GeometryBase[] values;
if (args.TryGetGeometry("mesh", out values))
{
mesh = values[0] as Rhino.Geometry.Mesh;
}
comp.ExpireSolution(true);
}
サンプルのデータ
ここで作ったものは Unity のプロジェクトごと ここの Sample3 にあげました。
Unity 2018.4 で作っています。参考にしてください。