Posted at

unityでポイントクラウド用に点を描画してみた。

今点群マップにハマっています。というのも格安LiDARを買ったので。

そこで描画するときにいくつかハマったのでハマりポイントと

unityで点が描画できることがわかったのでやり方を。


試したこと

1.律儀にプリミティブでスフィアを作った

2.スクリプトからポリゴン書いた

3.頂点が65535を超えて描画されなかったので32bit化した

4.純粋にポリゴンじゃなくて点を描画した

※今回使用したサンプルデータは自前で記録したLiDARのデータです。


1.律儀にプリミティブでスフィアを作った


generatePrimitive.cs

GameObject PointDot = GameObject.CreatePrimitive(PrimitiveType.Sphere);


これでプレハブから複製することなく基本3Dオブジェクトが生成できます。

タイプはsphere,cube,quadなど。

ただし、当たり前ですが、ポイントクラウドで点ごとにこれを行うと

ゲームオブジェクトが馬鹿みたいに増えてめちゃめちゃ重くなります。

ちょっと手っ取り早く見たいときでも避けましょう。


2.スクリプトからポリゴン書いた

数年前、DK2の頃にポジトラ用カメラからポジトラ範囲を描画するために

自前でポリゴンを書いたことがあったので、そんな感じで各点群から三角錐なメッシュを張ってみました。


generateMesh.cs


Vector3 center = new Vector3(x, y, z);//点群点
//頂点
vertices[i * Vertex_size] = center + (Vector3.up);
vertices[i * Vertex_size + 1 ] = center + (Vector3.right + Vector3.down + Vector3.back);
vertices[i * Vertex_size + 2 ] = center + (Vector3.left + Vector3.down + Vector3.back);
vertices[i * Vertex_size + 3 ] = center + (Vector3.forward + Vector3.down );
//三角形

//手前
triangles[i * Surface_size ] = i * Vertex_size ;
triangles[i * Surface_size + 1 ] = i * Vertex_size + 1 ;
triangles[i * Surface_size + 2 ] = i * Vertex_size + 2 ;
//左奥
triangles[i * Surface_size + 3 ] = i * Vertex_size ;
triangles[i * Surface_size + 4 ] = i * Vertex_size + 2 ;
triangles[i * Surface_size + 5 ] = i * Vertex_size + 3 ;
//右奥
triangles[i * Surface_size + 6 ] = i * Vertex_size ;
triangles[i * Surface_size + 7 ] = i * Vertex_size + 3 ;
triangles[i * Surface_size + 8 ] = i * Vertex_size + 1 ;
//底面
triangles[i * Surface_size + 9 ] = i * Vertex_size + 1 ;
triangles[i * Surface_size + 10 ] = i * Vertex_size + 2 ;
triangles[i * Surface_size + 11 ] = i * Vertex_size + 3 ;


こんなかんじで頂点行列作って、面をどの頂点で作るかで行列作って点ごとに追加してmeshfilterに渡してました。

この当時はunityで点の描画が出来ると知らず、三角錐っていう発想。


3.頂点が65535を超えて描画されなかったので32bit化した

このメッシュ化で負荷は減ったので運用していたのですが、なぜか360度ではなく60度ぐらいしか描画されませんでした。

よくよく見てみると60度あたりで頂点数が65535を越えていました。そういえば3Dモデルも65535越えたら分割されてましたっけ。

ってことで65535を越えるために32bit化しました。unity2017からの機能?


32IndexFormat.cs

Mesh mesh = new Mesh();

mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;

これでインデックスバッファーが32bit対応になり頂点が65535越えても描画されます。

Unity - Scripting API: Mesh.indexFormat


4.純粋にポリゴンじゃなくて点を描画した

65535頂点あたりを調べてて、点を描画できることがわかったので切り替え。


SetIndices.cs

    int[] indices = new int[vertices.Length];

for (int i = 0; i < vertices.Length; i++)
{
indices[i] = i;
}
filter.mesh.SetIndices(indices, MeshTopology.Points, 0);

MeshTopologyをPointsに切り替える(っぽい)。

indicesが点群行列。頂点行列ぶっこんでもうまく行かなくて作った。

よく見る点だけの描画はこうやってたんだねぇ、知らなかったw