CMeshを変更しよう(4)
頂点に構造体を使うかどうかはともかく、CMeshからstd::vectorを排除することには成功しました。
コンバーターを作るにはちょっと気合が必要なので、今回は一時オブジェクトCLoaderTmpMesuを作り、そこからCMeshを構築するようにしました。新しいCMeshはこんな具合です。
CMesh { // マテリアルの異なる面などを"サブセット"というグループで分けている struct SSubsetInfo { int startIdx; // このサブセットの頂点開始インデックス int num; // このサブセットの頂点数 }; SMaterial **m_materials; // マテリアル int m_numMaterials; SVertex *m_verts; // 頂点 int m_numVerts; SSubsetInfo *m_subsets; // サブセット int m_numSubsets; }
m_facesは廃止し、頂点は全て順番に並ぶようにしました。例えは、サブセットが3つあり(sub[i], 0<=i<3)、それぞれがa,b,c個の頂点を持つ場合、CMeshのm_vertsでは頂点が
- m_verts=
- { sub[0].v[0], sub[0].v[1], ..., sub[0].v[a-1], sub[1].v[0], sub[1].v[1], ..., sub[1].v[b-1], sub[2].v[0], sub[2].v[1], ..., sub[c-1] }
という順番で並んでいます(当然頂点の総数は、a+b+c個)。これをCMesh::SSubsetInfoの情報で表すと、sub[0]の場合はstartIdx=0, num=aで、sub[1]の場合はstartIdx=a, num=b、sub[2]はstartIdx=a+b, num=c といった具合になります。
sub | startIdx | num |
---|---|---|
sub[0] | 0 | a |
sub[1] | a | b |
sub[2] | a+b | c |
この変更により、glDrawArrays()が使えるようになりました。今まで(glDrawElements()を使っていた)と比べると、若干早くなったような気がします*1。
今回は変更ついでと言うことでこの形にしたわけですが、この形だと頂点の数が面の数x3から逃れられません。最適化などを行い、1つにまとめられる重複頂点などをまとめることができなくなりました。まあ、手間の割りにメリットが少なそうなので、そんな最適化を行う予定は当分ないわけですが……頂点データが連続して入っているのと、総頂点数が少ないのとではどちらが優れているのでしょう?
*1:詳しくはテストしていないですが、1万頂点のメッシュで0.3msほど速くなったので