ポイントクラウド(point cloud)とは・・・
点群 = 点だけで表示すること
3Dモデルの表示方法の1つです。
ここではThree.jsでモデル読込し、
それを ポイントクラウド表示する方法 をまとめました。
このページの目次
ポイントクラウド表示で大事な2つのポイント
まずポイントクラウド表示で大事なことから。
次の2つが重要ポイントです。
1.点表示には THREE.Points を使うこと
複数の点をまとめて表示したい場合・・・
Three.jsには THREE.Points が用意されています。
▼ 公式でのTHREE.Pointsの解説
Constructor
Points( geometry : Geometry, material : Material )
geometry ? (optional) an instance of Geometry or BufferGeometry. Default is a new BufferGeometry.
material ? (optional) a Material. Default is a new PointsMaterial.
コンストラクタにGeometry(面情報、頂点情報、色、etc...)のインスタンスと、PointsMaterial を渡すことで作成できます。また PointsMaterial から点の大きさ、色、見え方なども超可能です。
2.負荷軽減のためにMeshを結合(merge)すること
次に大事なポイントはこれ。
Meshの結合(merge)すること
これは負荷軽減のために絶対すべきですね。
たとえば簡単なMesh結合の例、こんな感じです、
▼ 2つのMeshを結合するコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/// 1つめのMesh var mesh1 = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2)); /// 2つめのMesh var mesh2 = new THREE.Mesh(new THREE.SphereGeometry(0.5, 8, 8)); /// 結合用のGeometry作成 ar mergedGeometry = new THREE.Geometry(); /// 1つめのMeshを追加 mesh1.updateMatrix(); mergedGeometry.merge(mesh1.geometry, mesh1.matrix); /// 2つめのMeshを追加 mesh1.updateMatrix(); mergedGeometry.merge(mesh2.geometry, mesh2.matrix); |
このように Geometry.merge に対して結合したい geometry と material を渡していけばOK。ただし結合させる前に mesh1.updateMatrix() のような呼び出しが必要です。
実際に読込モデルをポイントクラウド表示してみた
では具体的なポイントクラウド表示について。
ここでは次の場合を想定します。
- 適当な3Dモデルを読み込みする
- モデルの全Meshを結合したGeometry作成
- そこからポイントクラウド生成&表示
読込モデルの形式は何でも構いません。
ここではGLTF形式を読込したことにします。
実際に書いてみたコードがこちら。
▼ 読込モデルをポイントクラウド表示するコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
var loader = new THREE.GLTFLoader(); var path = './duck.glb'; loader.load(path, function(gltf){ var modelObj = gltf.scene; /// モデルをSceneに追加 scene.add(modelObj); /// モデルの表示を微調整... /// ここでは縮尺(scale)を調整 var box = new THREE.Box3().setFromObject(modelObj); var scale = 1 / (box.max.x - box.min.x) * 10; modelObj.scale.set(scale, scale, scale); /** ポイントクラウドを読込モデルから生成 **/ var pointCloudGeo = new THREE.Geometry(); var pointCloudObj3dTypes = [ 'Mesh', 'SkinnedMesh' ]; /// Scene内の全MeshをGeometryに結合する scene.traverse(function(obj3d){ if(pointCloudObj3dTypes.includes(obj3d.type)){ var geo = new THREE.Geometry() .fromBufferGeometry(obj3d.geometry); var mesh = new THREE.Mesh(geo, obj3d.material); mesh.applyMatrix4(obj3d.matrix); mesh.updateMatrix(); pointCloudGeo.merge(mesh.geometry, mesh.matrix); } }.bind(this)); /// 結合が終わったらポイントクラウド生成 var pointCloud = new THREE.Points( pointCloudGeo, new THREE.PointsMaterial({ /// 点のサイズ size: 1, /// 点の色 color: 0xFFFFFF, /// サイズ減退の有無 sizeAttenuation: false }) ); /// サイズ調整とかしてSceneに追加 var box = new THREE.Box3().setFromObject(pointCloud); var scale = 1 / (box.max.x - box.min.x) * 10; pointCloud.scale.set(scale, scale, scale); scene.add(pointCloud); /// ひとまずモデル自体は非表示に modelObj.visible = false; }); |
何をしているかはコメントを参照。
全体の大きな流れとして・・・
- 適当なモデルを読み込み
この例ではGLTFLoaderを使ってGLTFモデルを読み込みしている。ただし読込モデルのフォーマットは STL、PLY、OBJ、etc...なんでもOK。
- 全Meshを1つのGeometryに結合
コードの15~25行目までの部分。パフォーマンス向上のために Mesh または SkinnedMesh を1つのGeometryに結合している。
- ポイントクラウドを生成
コードの26~36行目までの部分。THREE.PointsMaterialから点の大きさ・色・減衰の有無などの設定が可能、あとはSceneに追加するだけ
こういう流れですね。
ポイントクラウド表示の結果はこうなりました。
▼ ポイントクラウド表示する前
▼ ポイントクラウド表示した後
ポイントクラウドの表示切替も簡単です。
ただし、このコードは完全ではありません。
特定モデルだと点表示がおかしくなるですよね・・・
未対応のモデル例 : 2CylinderEngine.glb
もし原因が分かる方がいれば、教えてください (;一_一)
Three.js(WebGL)関連でのその他記事
Three.js関連では、こういう記事も書いてます。
よければご覧ください。
以上、three.jsでのモデルのポイントクラウド表示でした。