最近作っていたthree.jsでの作品で軽量化を図ろうとGeometry
をBufferGeometry
というものに書き換える作業がありました。
その中でも特にジオメトリの頂点をいじる時に迷った点がいくつかあったのでここに残しておきます。
#BufferGeometryについて
BufferGeometry
は通常のgeometry
よりもより効率的な表現ができるみたいです。
いろいろな方の情報を見てみると生のwebGLを触る感覚で制御できるだとか。(知らなかった)
ただ、公式リファレンスにも書いてある通り、通常のジオメトリのほうが弄る分には楽らしいですね。
#わざわざこれを使う必要があるの?
実際、これを使わなくても通常のジオメトリでほぼ同じ処理はできます。
ただ、より多くの頂点がある場合には処理速度に差が出るので、Three.jsのページが重くなった時の改善策の一つとなりそうなので覚えておこうと思いました。
#通常のジオメトリとの違い
大きな違いとしてはバッファジオメトリは頂点などのデータをBufferAttribute
を通して行うようです。
##インスタンス生成
通常のジオメトリ制作に関してはこのような形式になります。
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( -10, 10, 0 ),
new THREE.Vector3( -10, -10, 0 ),
new THREE.Vector3( 10, -10, 0 )
);
geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
geometry.computeBoundingSphere();
そしてBufferGeometry
の場合は下記のとおりです。
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
-10.0, 10.0, 0,
-10.0, -10.0, 0,
10.0, -10.0, 0,
] );
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
どちらも
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
と
var mesh = new THREE.Mesh( geometry, material );
を書き加えてシーンに入れてしまえば下図のような赤い三角形が見えると思います(カメラのZ座標を100
に設定しています。)
PlaneやBoxといったプリミティブの生成に関してはほぼ変化がありません。クラス名にbufferが付くくらいです。
生成に関する引数も変わりません。
//Geometry
var planeGeo = new THREE.PlaneGeometry(width, height,widthSegments,Segments);
//BufferGeometry
var planeGeo_B = new THREE.PlaneBufferGeometry(width, height,widthSegments,Segments);
##頂点の座標を動かす
個別の頂点を指定して動かすためには全く別のメソッドを使います。
ですが引数の考えなどはほぼ同じであるため、その点に気を遣えば特に問題はありません。
//Geometry
geometry.vertices[i].setX(posX);
//BufferGeometry
geometry_B.attributes.position.setX( i , posX);
##頂点座標の変化を更新するとき
これはどちらのジオメトリにも言えますが頂点情報を毎フレーム更新するには更新の許可をする文を記入しなければいけません。
これも通常のジオメトリとbufferジオメトリで記述する文章が異なるので注意です。
//Geometry
geometry.verticesNeedUpdate=true;
//BufferGeometry
geometry.attributes.position.needsUpdate = true;
##法線情報の更新
ジオメトリの頂点情報が変化すると法線も計算しなおした方がいいでしょう。
これに関してはどちらも利用するメソッドは同じです。
geometry.computeVertexNormals ();
geometry_B.computeVertexNormals ();
ただ、通常のジオメトリには
geometry.computeFaceNormals ()
geometry.computeFlatVertexNormals ()
のメソッドも存在しています。
##持っている頂点の数
あとここも地味に躓いた。微妙に名前が違うんですよね。
//Geometry
geometry.vertices.length
//BufferGeometry
geometry_B.attributes.position.count
#さいごに
筆者の僕もThree.jsの初心者です。
ただ、このあたりの情報に関してはほとんど情報がなかったため、同じ道を通る方のために残しておくことにしました。
もし間違っている点、説明の至らない点がありましたら、遠慮なくコメント等で指摘頂けますと幸いです。随時更新いたします。