bulletのjavaラッパでHelloWorld成功

まず、bullet本体のbtRigidBody::btRigidBodyConstructionInfoと、btTypedConstraint::btConstriantInfo1およびbtTypedConstraint::btConstraintInfo2を内部クラスから外に出す。で、bulletを再ビルド。この、作業自体は簡単。


bullet.i

%module bullet
%{
#include <btBulletDynamicsCommon.h>
%}
%javaconst(1);
%include "LinearMath/btScalar.h"
%include "LinearMath/btVector3.h"
%include "LinearMath/btQuaternion.h"
%include "LinearMath/btTransform.h"
%include "LinearMath/btMotionState.h"
%include "LinearMath/btDefaultMotionState.h"
%include "btBulletCollisionCommon.h"
%include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
%include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
%include "BulletCollision/BroadphaseCollision/btDispatcher.h"
%include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
%include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
%include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
%include "BulletCollision/CollisionShapes/btCollisionShape.h"
%include "BulletCollision/CollisionShapes/btConvexShape.h"
%include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
%include "BulletCollision/CollisionShapes/btSphereShape.h"
%include "BulletCollision/CollisionShapes/btConcaveShape.h"
%include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
%include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
%include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h"
%include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h"
%include "BulletDynamics/Dynamics/btRigidBodyConstructionInfo.h"
%include "BulletDynamics/Dynamics/btRigidBody.h"
%include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
%include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
%include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
%include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
%include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
%include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
%include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
%include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
%include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
%include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
%include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"

superクラスのヘッダが、subクラスのヘッダより上に来るように並べる必要がある。
Mingwgcc-4.5.2でビルドした。
vcではswig実行時にifdefで__MINGW32__が無いほうに分岐したときに死ぬのでできなかった。
cl.exeへの最適化指示?(attribute(xxx))とか__forceinline)がswig的にシンタックスエラーになるっぽい。


Makefile

PACKAGE=org.swig.bullet
DST=src/main/java/org/swig/bullet

bullet.dll: bullet_wrap.o
	g++ -shared -o $@ $^ -L../../bullet-2.78-build/lib -lBulletDynamics -lBulletCollision -lLinearMath -Wl,--add-stdcall-alias

bullet_wrap.o: bullet_wrap.cxx
	g++ -c -o $@ -IC:/Java32/jdk1.6.0_26/include -IC:/Java32/jdk1.6.0_26/include/win32 -I../src $^

bullet_wrap.cxx: bullet.i
	mkdir -p $(DST)
	swig -c++ -java -I../src -outdir $(DST) -package $(PACKAGE) -D_WIN32 -D__MINGW32__ bullet.i

clean:
	rm -rf src *.cxx bullet.dll

dll作成時に-Wl,--add-stdcall-aliasをつけるのが必要で、これでしばらくはまった。


動作を確認したbulletのHello worldのテストコード。
先頭のSystem.loadLibraryでdllを指定している。
あとは、c++のコードをコピペしてスタックに変数を確保しているところをnewで置き換えたくらいである。
終了処理は全て省いているが、GC任せでいいことにしておこう。


Sample.java

import org.swig.bullet.*;

class Sample {

    public static void main(String[] args){
        System.loadLibrary("bullet");

        btBroadphaseInterface broadphase = new btDbvtBroadphase();

        btDefaultCollisionConfiguration collisionConfiguration = new btDefaultCollisionConfiguration();
        btCollisionDispatcher dispatcher = new btCollisionDispatcher(collisionConfiguration);

        btSequentialImpulseConstraintSolver solver = new btSequentialImpulseConstraintSolver();

        btDiscreteDynamicsWorld dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);

        dynamicsWorld.setGravity(new btVector3(0,-10,0));


        btCollisionShape groundShape = new btStaticPlaneShape(new btVector3(0,1,0),1);

        btCollisionShape fallShape = new btSphereShape(1);


        btDefaultMotionState groundMotionState = new btDefaultMotionState(new btTransform(new btQuaternion(0,0,0,1),new btVector3(0,-1,0)));
        btRigidBodyConstructionInfo groundRigidBodyCI=new btRigidBodyConstructionInfo(0,groundMotionState,groundShape,new btVector3(0,0,0));
        btRigidBody groundRigidBody = new btRigidBody(groundRigidBodyCI);
        dynamicsWorld.addRigidBody(groundRigidBody);


        btDefaultMotionState fallMotionState =
            new btDefaultMotionState(new btTransform(new btQuaternion(0,0,0,1),new btVector3(0,50,0)));
        float mass = 1;
        btVector3 fallInertia=new btVector3(0,0,0);
        fallShape.calculateLocalInertia(mass,fallInertia);
        btRigidBodyConstructionInfo fallRigidBodyCI=new btRigidBodyConstructionInfo(mass,fallMotionState,fallShape,fallInertia);
        btRigidBody fallRigidBody = new btRigidBody(fallRigidBodyCI);
        dynamicsWorld.addRigidBody(fallRigidBody);


        for (int i=0 ; i<300 ; i++) {
            dynamicsWorld.stepSimulation(1/60.f,10);

            btTransform trans=new btTransform();
            fallRigidBody.getMotionState().getWorldTransform(trans);

            System.out.println("sphere height: "+trans.getOrigin().getY());
        }

        dynamicsWorld.removeRigidBody(fallRigidBody);
        dynamicsWorld.removeRigidBody(groundRigidBody);
    }
}

swig素晴らしい。
めずらしく予定通りの作業量でこなせたのであった。


ということで、本題のMMDモーション再生への組み込みに進む。