プログラミング

Unityでメッシュをさわるノウハウ

投稿日:2018年5月2日 更新日:

ヒマなので覚書。ウラを取っていない経験則なので話半分で読んでください。
あと、3Dの基本概念とUnity固有の話の区別が付いていないのでごめんなさい。

もくじ

Meshクラスの基本

Unityでポリゴンをガッツリいじろうと思うとMeshクラスを読む必要がある。
可動モデルの場合、SkinnedMeshRendererクラスのBakeMeshを使ってベイクしてやるとボーン変形後の情報を持ったメッシュが取れる。
可動させないならSkinnedMeshRenderer.sharedMeshで良いと思う。

だいたい以下のメンバーを読むことになる。

  • Mesh.vertices(頂点一覧)
  • Mesh.triangles(三角形を形成する頂点のインデクス)
  • Mesh.uv(UVマップ上の頂点の座標)

ポリゴンの読み方

Mesh.trianglesはヘンな構成で、配列の要素3個で三角形をつくる。例えば{0,1,2,1,2,3}という配列の場合、最初の3つ「0,1,2」が1つ目の三角形、次の3つ「1,2,3」が2つ目の三角形になる。数字は、Mesh.verticesの添字に使う。

なので簡単には、以下のようなコードで三角形の座標を取得できる。

for (int i = 0; i < mesh.triangles.Length; i += 3)
{
Vector3 A = mesh.vertices[mesh.triangles[i]];
Vector3 B = mesh.vertices[mesh.triangles[i + 1]];
Vector3 C = mesh.vertices[mesh.triangles[i + 2]];
/* 三角形ABCへの処理*/
}

しかしこのコードには実用上いくつか問題がある。

マテリアルを気にするならMesh.trianglesを使ってはいけない

Mesh.trianglesは、マテリアルの区別なく全ての三角形を返す。
したがって、これで取り出した情報はマテリアルと紐付けられない。
Meshクラスは、サブメッシュという区分けでマテリアルを区別している。
サブメッシュ単位の三角形を取得するmesh.GetTriangles関数を使って、マテリアルごとに三角形を処理すると良い。引数としてサブメッシュ番号を指定する。
サブメッシュの個数は、mesh.subMeshCountから取得できる。
マテリアル自身はRenderer.materials配列から取得できる。配列の添字はサブメッシュ番号と一致する。

Meshクラスの配列を直接読んではいけない

理由は知らないけど、verticesなどの配列は、書き込みはもちろん読み込みすら馬鹿みたいに重い。
for文の中で毎回参照なんてやっているととてもマトモな速度では動いてくれなくなる。
したがって一度ローカルにおいてしまって、そこから読み出すと良い。

以上をもとに、マテリアルごと、かつ常識的な速度で動作するように改造したコードは以下のとおり。

Vector3[] meshVertices = mesh.vertices;

for (int subMesh = 0; subMesh < mesh.subMeshCount; subMesh++) {
int[] submeshTriangles = mesh.GetTriangles(subMesh);
for (int i = 0; i < submeshTriangles.Length; i += 3)
{
Vector3 A = meshVertices[submeshTriangles[i]];
Vector3 B = meshVertices[submeshTriangles[i + 1]];
Vector3 C = meshVertices[submeshTriangles[i + 2]];
/* 三角形ABCへの処理*/
}
}

とにかくMeshクラスのメンバへのアクセスは異様に重たいので、配列を個々にアクセスするような真似は避けて作業しないといけない。
ほんだらまた。

-プログラミング

執筆者:

関連記事

no image

SwitchBotの温湿度計、防水かどうかでBluetoothのデータの取り方違うぞ

SwitchBotは機器のAPIを公開していて、ユーザーの自作プログラムからBluetooth(BLE)越しにデータが取れたりします。 特に温湿度計のデータを取りたいというニーズは強くて、安価で安定し …

どうして私はC言語で仕事をしているのか

みなさんプログラミング言語は学んでますか?今から始めますか? 最初に学ぶべきプログラミング言語ってなんだと思いますか?そうです。C言語です。 C#でもC++でもObjective-Cでもなく、Pure …

no image

プログラミングとアルゴリズムのはなし

みんなー!小学校でプログラミングの授業がはじまるよー!! プログラミングってなんだろう? プログラミングって、コンピューターに「○○をしなさい」って命令して、なにかの問題を解いたり、ゲームをつくったり …

国土地理院の地図データをUnityで読みたい(願望)

なんかgoogleのAdSense通ったんで有益な情報載せないとなって。 国土地理院のオープンデータ 国土地理院が公開している(正確には国土地理院のデータを利用して国土交通省国土政策局国土情報課が公開 …

no image

UnityのCompute Shaderに線分と三角形の衝突判定をさせる

はじめてCompute Shader使ってみた。でもあまり性能は出ないのでただの失敗の記録です。 まず元のアルゴリズムはコレ。 線分と三角形の当たり判定 – 富士見研究所 で、これをまず三角形の表裏問 …