基于Jbullet的3D-java冲突检测
所以,我花了很长时间,试图从头开始为自己的游戏引擎开发一个碰撞检测系统,但由于时间不够,结果一无所获。最后,我决定尝试使用Jbullet使事情变得更快。现在文档基本上是无用的,我在尝试将bullet代码转换为java时遇到了一些困难(或者我转换的代码不起作用)。我一直在努力搜索库代码,但我所希望的节省时间几乎毫无用处。所以,我要解释我在做什么,也许你们能帮我。我只是在寻找简单的碰撞检测,比如你击中了什么东西,然后现在就打印一行。剩下的我可以自己解决 所以我创造了我的世界:基于Jbullet的3D-java冲突检测,java,3d,game-engine,bulletphysics,jbullet,Java,3d,Game Engine,Bulletphysics,Jbullet,所以,我花了很长时间,试图从头开始为自己的游戏引擎开发一个碰撞检测系统,但由于时间不够,结果一无所获。最后,我决定尝试使用Jbullet使事情变得更快。现在文档基本上是无用的,我在尝试将bullet代码转换为java时遇到了一些困难(或者我转换的代码不起作用)。我一直在努力搜索库代码,但我所希望的节省时间几乎毫无用处。所以,我要解释我在做什么,也许你们能帮我。我只是在寻找简单的碰撞检测,比如你击中了什么东西,然后现在就打印一行。剩下的我可以自己解决 所以我创造了我的世界: BroadphaseI
BroadphaseInterface broadphase = new DbvtBroadphase();
CollisionConfiguration collisionConfig = new DefaultCollisionConfiguration();
Dispatcher dispatcher = new CollisionDispatcher(collisionConfig);
ConstraintSolver solver = new SequentialImpulseConstraintSolver();
DynamicsWorld dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfig);
return dynamicsWorld;
所以我有我的实体类,在那里我有另一个类,它存储连接到实体的物理对象的所有信息。这使我可以简单地执行以下操作:entity.getPhysics().getCollisionObject()/.setPosition()等
然后在该类中创建我的CollisionObject:
List<org.lwjgl.util.vector.Vector3f> mesh = model.getModel().getVertices();
ObjectArrayList<javax.vecmath.Vector3f> vertices = new ObjectArrayList<javax.vecmath.Vector3f>();
for(org.lwjgl.util.vector.Vector3f vertex:mesh){
javax.vecmath.Vector3f v = new javax.vecmath.Vector3f(vertex.x, vertex.y, vertex.z);
vertices.add(v);
}
ConvexHullShape shape = new ConvexHullShape(vertices);
ShapeHull hull = new ShapeHull(shape);
hull.buildHull(shape.getMargin());
ConvexHullShape newShape = new ConvexHullShape(hull.getVertexPointer());
CollisionObject result = newShape;
应该可以简化网格(从文档中)。然后我只创建碰撞对象。很简单,我想
我创建了我的刚体(虽然我不确定我需要一个刚体或只是一个碰撞对象,如果有人能让我知道这是真的,那就太好了):
然后我进行游戏循环:
dynamicsWorld.stepSimulation(DisplayManager.getFrameTimeSeconds(), 7);
dynamicsWorld.performDiscreteCollisionDetection();
dynamicsWorld.setInternalTickCallback(new InternalTickCallback(){
@Override
public void internalTick(DynamicsWorld world, float delta) {
Dispatcher dispatcher = world.getDispatcher();
int manifoldCount = dispatcher.getNumManifolds();
for(int i = 0; i < manifoldCount; i ++){
PersistentManifold manifold = dispatcher.getManifoldByIndexInternal(i);
RigidBody object1 = (RigidBody)manifold.getBody0();
RigidBody object2 = (RigidBody)manifold.getBody1();
CollisionObject physicsObject1 = (CollisionObject)object1.getUserPointer();
CollisionObject physicsObject2 = (CollisionObject)object2.getUserPointer();
boolean contact = false;
javax.vecmath.Vector3f normal = null;
for (int j = 0; j < manifold.getNumContacts(); j++) {
ManifoldPoint contactPoint = manifold.getContactPoint(j);
if (contactPoint.getDistance() < 0.0f) {
contact = true;
normal = contactPoint.normalWorldOnB;
break;
}
}
if (contact) {
System.out.println("hit");
}
}
}
}, null);
然后我创建了鬼体:
Transform transform = new Transform(new Matrix4f(new Quat4f(rotation.x, rotation.y, rotation.z, 1), position, scale));
this.transform = transform;
transform.origin.set(position);
GhostObject body = new GhostObject();
body.setCollisionShape(shape);
body.setWorldTransform(transform);
那我就照你说的做,它还是不回“打”
更新职位和资料:
public void increasePosition(float dx,float dy, float dz){
this.position.x += dx;
this.position.y += dy;
this.position.z += dz;
physics.updatePosition(new javax.vecmath.Vector3f(position.x, position.y, position.z));
}
public void increaseRotation(float dx, float dy, float dz){
this.rotX += dx;
this.rotY += dy;
this.rotZ += dz;
physics.updateRotation(new javax.vecmath.Vector3f(rotX, rotY, rotZ));
}
好的,这是我的PhysicsEntity类,我在这里设置它:
public PhysicsEntity(DynamicsWorld world, TexturedModel model, Vector3f position, Vector3f rotation, float scale){
this.model = model;
this.position = position;
this.rotation = rotation;
this.scale = scale;
shape = createShape();
body = createBody();
object = new CollisionObject();
object.setCollisionShape(shape);
world.addCollisionObject(body);
}
private GhostObject createBody(){
Transform transform = new Transform(new Matrix4f(new Quat4f(rotation.x, rotation.y, rotation.z, 1), position, scale));
this.transform = transform;
transform.origin.set(position);
GhostObject body = new GhostObject();
body.setCollisionShape(shape);
body.setWorldTransform(transform);
return body;
}
private CollisionShape createShape(){
CollisionShape result = new BoxShape(new Vector3f(10,10,10));
return result;
}
public void updatePosition(Vector3f position){
transform.origin.set(position);
body.setWorldTransform(transform);
}
public void updateRotation(Vector3f rotation){
transform.basis.set(new Quat4f(rotation.x, rotation.y, rotation.z, 1));
body.setWorldTransform(transform);
}
<>谢谢, < p>我的子弹经验被限制在C++,但也许我能帮助你。你说什么都没发生是什么意思?对象是否正确地受重力影响,但未调用碰撞回调,或者问题是它根本不移动?它显然不会移动,因为它的质量是0,所以它是静态的。如果调用,质量为0的对象也可以是运动学对象
body.setCollisionFlags(body .getCollisionFlags() | CollisionFlags.KINEMATIC_OBJECT);
body.setActivationState(CollisionObject.DISABLE_DEACTIVATION);
静态和动态对象都检测碰撞,但仅检测动态对象(质量大于0)。我建议首先使用一个简单的碰撞形状,例如球体。通过这种方式,您可以验证模拟是否有效。凸面外壳可能很棘手。从一个简单的例子开始。现在谈谈碰撞检测方法。调用dynamicsWorld.stepSimulation
时,将应用所有力,并进行碰撞检测和解决。因此,在这之后,您可以通过PersistentManifolds
进行迭代,就像您在这个模拟步骤中检查哪些对象相互碰撞一样。现在我不确定,但是当您调用dynamicsWorld.performDiscreteCollisionDetection()时代码>很可能没有检测到冲突,因为它们都刚刚解决
在几乎所有的标准情况下,您都希望使用刚体
。例外是像衣服和幽灵物体这样的软体,它们可以用来检测碰撞而不产生任何反应
编辑
在不需要碰撞,只需要碰撞检测的情况下,您不需要刚体
。它可以是静态的,动态的或运动学的,这两者都不是你的情况。相反,您希望使用ghosObject
。它只检测碰撞,但不反应。首先调用它的getNuMoverAppingObjects()
,然后调用getOverlappingObject(int-index)
,可以轻松检查它是否与某个对象重叠
编辑2
看起来您正确地创建了对象。假设转换是正确的,并且对象确实应该重叠,您可能缺少的是dynamicsWorld.addCollisionObject(body)代码>我在第一眼看到时就错过了,但看起来你只是创建了对象,而没有将其添加到世界中,所以子弹头引擎没有意识到它的存在
编辑3
好的,还有一些建议只是为了确保碰撞被检测到。您创建了多少物理对象(重影或刚体)并将其添加到世界中(使用dynamicsWorld.add…
)?如果只有一个,显然无法检测到碰撞。子弹不会将物理对象与场景几何体碰撞,但只能与另一个物理对象碰撞。你能把你的代码贴在你创建和移动这些对象的地方吗
伊迪顿
您已经发布了创建PhysicsEntity的函数,但我仍然不知道您创建了多少实体,以及使用了哪些参数。有必要检查它们的世界坐标,并验证它们是否真的应该碰撞
你对四元数的使用有点令人不安。您可能会将参数x、y、z分别传递为x、y、z轴上的旋转。这不是它的工作原理。我建议使用另一个构造函数,它以旋转轴和角度为参数
因为代码和问题非常复杂,我看不到您发布的代码中的直接原因,我建议使用调试器并逐步检查代码,查看是否所有对象都正确初始化,它们的位置是否如预期的那样,最后进入冲突代码查看,为什么它没有发生。所以当我说什么都没有发生时,我的意思是它没有回击。我不希望实体对被击中做出反应。最终,我将设置它,使玩家实体不能穿过墙壁/对象等。我只是希望对象在接触时返回“命中”。这就是为什么我把质量设为零。我只是尝试创建一个框,但它不起作用,还尝试设置冲突标志和激活状态,仍然没有任何结果。我不希望物体受到重力的影响,所以也没有重力。基本上我会自己设置反应。我已经对我的答案添加了一个编辑,请检查它是否是你需要的。好的,所以我也会编辑我的答案
int overlaps = player.getPhysics().getBody().getNumOverlappingObjects();
for(int i = 0; i < overlaps; i++){
//player.getPhysics().getBody().getOverlappingObject(i).
System.out.println("hit");
}
if(collision){
physics = new PhysicsEntity(dynamicsWorld, model,new javax.vecmath.Vector3f(position.x, position.y, position.z), new javax.vecmath.Vector3f(rotX, rotY, rotZ), scale);
physics.updatePosition(new javax.vecmath.Vector3f(position.x, position.y, position.z));
physics.updateRotation(new javax.vecmath.Vector3f(rotX, rotY, rotZ));
}
public void increasePosition(float dx,float dy, float dz){
this.position.x += dx;
this.position.y += dy;
this.position.z += dz;
physics.updatePosition(new javax.vecmath.Vector3f(position.x, position.y, position.z));
}
public void increaseRotation(float dx, float dy, float dz){
this.rotX += dx;
this.rotY += dy;
this.rotZ += dz;
physics.updateRotation(new javax.vecmath.Vector3f(rotX, rotY, rotZ));
}
public PhysicsEntity(DynamicsWorld world, TexturedModel model, Vector3f position, Vector3f rotation, float scale){
this.model = model;
this.position = position;
this.rotation = rotation;
this.scale = scale;
shape = createShape();
body = createBody();
object = new CollisionObject();
object.setCollisionShape(shape);
world.addCollisionObject(body);
}
private GhostObject createBody(){
Transform transform = new Transform(new Matrix4f(new Quat4f(rotation.x, rotation.y, rotation.z, 1), position, scale));
this.transform = transform;
transform.origin.set(position);
GhostObject body = new GhostObject();
body.setCollisionShape(shape);
body.setWorldTransform(transform);
return body;
}
private CollisionShape createShape(){
CollisionShape result = new BoxShape(new Vector3f(10,10,10));
return result;
}
public void updatePosition(Vector3f position){
transform.origin.set(position);
body.setWorldTransform(transform);
}
public void updateRotation(Vector3f rotation){
transform.basis.set(new Quat4f(rotation.x, rotation.y, rotation.z, 1));
body.setWorldTransform(transform);
}
body.setCollisionFlags(body .getCollisionFlags() | CollisionFlags.KINEMATIC_OBJECT);
body.setActivationState(CollisionObject.DISABLE_DEACTIVATION);