4
3

More than 5 years have passed since last update.

CANNON.jsのConvexPolyhedronにBlenderから書きだしたデータを読み込ませる

Posted at

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から書き出すのは大変かも。

4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3