BlenderのThree.js exporterで書きだしたデータから、CANNON.jsのConvexPolyhedronに読み込ませるためのデータを生成する方法のメモ。
CANNON.jsの情報が少ないのでだいぶ大変。
結論から言うと、Blenderで書きだしたJSONファイルは、なんか変なフォーマットになっていたのでまずはそこを修正。
具体的には、facesプロパティの数がやたらと多い。meta dataを見ると150くらいなのに、配列数は700とかあった。
多分、Three.js側でなにかしら利用しているんだと思うけど、CANNON.jsでは使わないので編集。
さらによく見てみると、セパレータとして使われているように見える数字が。
faces配列の最初の数字はおそらくセパレータとして機能しているみたいなので、その数字を配列からすべて消す。その上で、meta dataに書かれている数だけ先頭から取り出し新しい配列にする。
サンプルは以下。
{
//...略
"vertices" : [1,-1,-1,1,-1,1,-1,-1,1,-1,-1,-1,1,1,-1,0.999999,1,1,-1,1,1,-1,1,-1],
"faces" : [35,0,1,2,3,0,0,1,2,3,35,4,7,6,5,0,4,5,6,7,35,0,4,5,1,0,0,4,7,1,35,1,5,6,2,0,1,7,6,2,35,2,6,7,3,0,2,6,5,3,35,4,0,3,7,0,4,0,3,5],
//...略
}
facesの中に、35
という明らかにindexとしておかしい数値が含まれている。
なので、まずはこの35
をすべて消し、さらにmeta dataに"faces": 6
と書かれてるので、配列の数を6にする。
修正後は以下。
"faces" : [0,1,2,3,0,0],
データを修正したら、CANNON.jsのモデルデータを使ったサンプルを元に、以下のようにしたら無事動いた。
var compound = new CANNON.Compound();
for(var i=0; i<someModel.length; i++){
var rawVerts = someModel[i].verts;
var rawFaces = someModel[i].faces;
var rawNormals = someModel[i].normals;
var rawOffset = someModel[i].offset;
var verts=[], faces=[], normals=[], offset;
// Get vertices
for(var j=0; j<rawVerts.length; j+=3){
verts.push(new CANNON.Vec3( rawVerts[j] ,
rawVerts[j+1],
rawVerts[j+2]));
}
for(var j=0; j<rawNormals.length; j+=3){
normals.push(new CANNON.Vec3(rawNormals[j+0],
rawNormals[j+1],
rawNormals[j+2]));
}
// Get faces
for(var j=0; j<rawFaces.length; j+=3){
faces.push([rawFaces[j],rawFaces[j+1],rawFaces[j+2]]);
}
// Get offset
offset = new CANNON.Vec3(rawOffset[0],rawOffset[1],rawOffset[2]);
// Construct polyhedron
var someModelPart = new CANNON.ConvexPolyhedron(verts,faces, normals);
// Add to compound
compound.addChild(someModelPart,offset);
}
compound
は複合体を表しているぽい。
ので、これをRigidBodyのコンストラクタに形状データとして渡してやれば、あとはCANNON.jsがちゃんと物理演算してくれる。
var body = new CANNON.RigidBody(1, compound);
基本的に凸多面体がベースなので、複雑なモデルデータの場合はそれぞれ凸多面体の複合体となるように分割しなければいけないから、Blenderから書き出すのは大変かも。