JBulletことはじめ

IKまで実装

http://jbullet.advel.cz/
オリジナルのBulletのほぼ忠実な移植のようだ。
OpenGL等によるビジュアルを伴わない最小のサンプル
http://bulletphysics.org/mediawiki-1.5.8/index.php/Hello_World
のJBullet版を書いてみた(scala-2.9向け)。

import com.bulletphysics.util.ObjectArrayList
import com.bulletphysics.collision.broadphase.DbvtBroadphase
import com.bulletphysics.collision.dispatch.CollisionDispatcher
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration
import com.bulletphysics.collision.shapes
import com.bulletphysics.dynamics.DiscreteDynamicsWorld
import com.bulletphysics.dynamics.RigidBody
import com.bulletphysics.dynamics.RigidBodyConstructionInfo
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver
import com.bulletphysics.linearmath.DefaultMotionState
import com.bulletphysics.linearmath.Transform
import javax.vecmath

object Main extends App {

  val broadphase = new DbvtBroadphase();

  val collisionConfiguration = new DefaultCollisionConfiguration();
  val dispatcher = new CollisionDispatcher(collisionConfiguration);

  val solver = new SequentialImpulseConstraintSolver;

  val dynamicsWorld = new DiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);

  dynamicsWorld.setGravity(new vecmath.Vector3f(0,-10,0));


  val groundShape = new shapes.StaticPlaneShape(new vecmath.Vector3f(0,1,0),1);

  val fallShape = new shapes.SphereShape(1);


  val groundMotionState = new DefaultMotionState(new Transform(new vecmath.Matrix4f(
    new vecmath.Quat4f(0,0,0,1),new vecmath.Vector3f(0,-1,0), 1.0f)));
  val groundRigidBodyCI=new RigidBodyConstructionInfo(0,groundMotionState,groundShape,new vecmath.Vector3f(0,0,0));
  val groundRigidBody = new RigidBody(groundRigidBodyCI);
  dynamicsWorld.addRigidBody(groundRigidBody);


  val fallMotionState = new DefaultMotionState(new Transform(new vecmath.Matrix4f(
    new vecmath.Quat4f(0,0,0,1),new vecmath.Vector3f(0,50,0), 1.0f)));

  val mass = 1;
  val fallInertia=new vecmath.Vector3f(0,0,0);
  fallShape.calculateLocalInertia(mass,fallInertia);
  val fallRigidBodyCI=new RigidBodyConstructionInfo(mass,fallMotionState,fallShape,fallInertia);
  val fallRigidBody = new RigidBody(fallRigidBodyCI);
  dynamicsWorld.addRigidBody(fallRigidBody);

  var lastHeight=50.0f;
  for (i <- 0 until 300) {
    dynamicsWorld.stepSimulation(1/60.f,10);

    val trans=new Transform;
    fallRigidBody.getMotionState().getWorldTransform(trans);

    println("sphere height: %f(%f)".format(trans.origin.y, lastHeight-trans.origin.y));
    lastHeight=trans.origin.y;
  }

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

注意点としては、bulletのクラスのプレフィクスであるbtは無い。次に、btQuaternion, btVector3にあたるクラスがjbulletではなくてvecmathから提供される。btTransformの初期化は以下のようなコードになる。

new Transform(new vecmath.Matrix4f(
    new vecmath.Quat4f(0,0,0,1),new vecmath.Vector3f(0,-1,0), 1.0f))

TransformのコンストラクタでQuaternoinとVectorを受け付けるものはなくなっていて、vecmath.Matrix4f経由で作成するようだ。このときMatrix4fは第3の引数でscale値を取る。
そんなわけで最小の必要なjarは、jbullet.jarとvecmath.jarの2つである。なんにせよ、使い手は素のbulletをある程度知っていることを前提にされる。知っていればすんなりと変換していける感じだ。


だが、しかしbtGeneric6DofSpringConstraintが実装されていない(jbulletはbullet2.72ベースで、btGeneric6DofSpringConstraintは2.75で追加された)ことが発覚。jbulletにbtGeneric6DofSpringConstraintを移植するのは手間隙がかかるので、JMEに含まれるnative bulletというものを試してみることにした。