我正在尝试使用 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 桌面上运行时得到相同的结果。
你知道我做错了什么吗?谢谢!
我终于明白出了什么问题了。本质上,我:
- 启用球的滚动摩擦
- 将球的 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);
一旦我添加了获取局部惯性的调用,然后将其添加到刚体,它就开始正常工作。
我是一名优秀的程序员,十分优秀!