libgdx子弹3D和滚动摩擦导致NaN

时间:2015-01-26 21:45:02

标签: java 3d libgdx bullet

我正在尝试使用gdx-bullet进行一些常规模拟。 更具体地说,我试图在球体从倾斜平面滚落时设定球体的滚动摩擦力。

我将球体的滚动摩擦设置为非零。我把它放在斜面上方。球体落下直到它撞击飞机,此时它应该沿着飞机滚下。但是,相反,矩阵将替换为所有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桌面上运行相同的结果。

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

1 个答案:

答案 0 :(得分:1)

我终于弄清楚出了什么问题。 基本上,我:

  • 启用球的滚动摩擦
  • 将球的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);

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