2015-01-26 49 views
0

我正在尝试使用gdx-bullet进行一些一般的模拟。 更具体地说,我试图设置一个球体从倾斜平面上滚动时的滚动摩擦。libgdx Bullet 3D和Rolling Friction导致NaN

我将球体的滚动摩擦力设置为非零。我把它放在斜面上方。球落下直到它碰到飞机,在这一点上它应该滚下飞机。然而,作为替代方案,矩阵替换所有的NaN(除了最后一行):

Step 36 
[1.0|0.0|0.0|0.0] 
[0.0|1.0|0.0|0.0] 
[0.0|0.0|1.0|2.0862775] 
[0.0|0.0|0.0|1.0] 

Step 37 
[NaN|NaN|NaN|NaN] 
[NaN|NaN|NaN|NaN] 
[NaN|NaN|NaN|NaN] 
[0.0|0.0|0.0|1.0] 

可执行的代码示例:

import com.badlogic.gdx.math.Matrix4; 
import com.badlogic.gdx.math.Quaternion; 
import com.badlogic.gdx.math.Vector3; 
import com.badlogic.gdx.physics.bullet.Bullet; 
import com.badlogic.gdx.physics.bullet.collision.btBoxShape; 
import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher; 
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape; 
import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase; 
import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration; 
import com.badlogic.gdx.physics.bullet.collision.btSphereShape; 
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld; 
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody; 
import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver; 
import com.badlogic.gdx.physics.bullet.linearmath.btMotionState; 


public class TestRollingFriction { 

    private static class BasicMotion extends btMotionState 
    { 
     Matrix4 m4 = new Matrix4(); 

     @Override 
     public void setWorldTransform(Matrix4 transform) { 
      m4.set(transform); 
     } 

     @Override 
     public void getWorldTransform(Matrix4 transform) { 
      transform.set(m4); 
     } 

     public String toString() { 
      return m4.toString(); 
     } 
    } 

    public static void main(String[] args) 
    { 
     Bullet.init(); 

     btDefaultCollisionConfiguration collisionConfiguration = new btDefaultCollisionConfiguration(); 
     btCollisionDispatcher dispatcher = new btCollisionDispatcher(collisionConfiguration); 
     btDbvtBroadphase broadphase = new btDbvtBroadphase(); 
     btSequentialImpulseConstraintSolver solver = new btSequentialImpulseConstraintSolver(); 
     btDiscreteDynamicsWorld collisionWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); 
     collisionWorld.setGravity(new Vector3(0, 0, -9.8f)); 

     // Create a box at the origin, of size 1,1,1 
     btCollisionShape boxShape = new btBoxShape(new Vector3(1, 1, 1)); 
     // Rotate it by 20 degrees about the y axis so that the sphere will roll off it 
     btMotionState boxMotion = new BasicMotion(); 
     Quaternion q = new Quaternion(new Vector3(0,1,0),20); 
     boxMotion.setWorldTransform(new Matrix4(q)); 

     // Print out the box's matrix 
     System.out.println(boxMotion); 

     btRigidBody boxBody = new btRigidBody(0, boxMotion, boxShape); 
     boxBody.setFriction(2); 
     boxBody.setRollingFriction(0.2f); 
     collisionWorld.addRigidBody(boxBody); 

     btCollisionShape sphereShape = new btSphereShape(1); 
     btMotionState sphereMotion = new BasicMotion(); 

     // Set the sphere's position, rotation, and scale 
     Matrix4 tempM2 = new Matrix4(new Vector3(0, 0, 4), new Quaternion(), new Vector3(1,1,1)); 
     sphereMotion.setWorldTransform(tempM2); 
     btRigidBody sphereBody = new btRigidBody(3, sphereMotion, sphereShape); 

     // Does not matter what I put in here; 
       // If it's non-zero, then the matrix ends up with NaN in it. 
     sphereBody.setRollingFriction(0.2f); 
     sphereBody.setFriction(2); 

     collisionWorld.addRigidBody(sphereBody); 

     int count = 0;  
     while(count < 100) 
     { 
      collisionWorld.stepSimulation(0.05f); 

      System.out.println(count); 
      System.out.println(sphereMotion); 
      count++; 
     } 
    } 
} 

我得到相同的结果在Android和Linux桌面都运行。

任何想法我做错了什么? 谢谢!

回答

0

我终于明白出了什么问题。 从本质上讲,我:

  • 启用球的滚动摩擦
  • 设置球的localInteria零

要解决这个问题,我需要调用

Vector3 localInertia = new Vector3(); 
float mass=1; 
// Calculate the inertia of the sphere, with mass=1, 
// and store it into 'localInertia' 
sphereShape.calculateLocalInertia(mass, localInerertia); 

btRigidBody sphereBody = new btRigidBody(mass, sphereMotion, sphereShape, localInertia); 

一旦我添加了调用以获得局部惯性,然后将其添加到刚体,它开始正常工作。