基于Jbullet的3D-java冲突检测

基于Jbullet的3D-java冲突检测,java,3d,game-engine,bulletphysics,jbullet,Java,3d,Game Engine,Bulletphysics,Jbullet,所以,我花了很长时间,试图从头开始为自己的游戏引擎开发一个碰撞检测系统,但由于时间不够,结果一无所获。最后,我决定尝试使用Jbullet使事情变得更快。现在文档基本上是无用的,我在尝试将bullet代码转换为java时遇到了一些困难(或者我转换的代码不起作用)。我一直在努力搜索库代码,但我所希望的节省时间几乎毫无用处。所以,我要解释我在做什么,也许你们能帮我。我只是在寻找简单的碰撞检测,比如你击中了什么东西,然后现在就打印一行。剩下的我可以自己解决 所以我创造了我的世界: BroadphaseI

所以,我花了很长时间,试图从头开始为自己的游戏引擎开发一个碰撞检测系统,但由于时间不够,结果一无所获。最后,我决定尝试使用Jbullet使事情变得更快。现在文档基本上是无用的,我在尝试将bullet代码转换为java时遇到了一些困难(或者我转换的代码不起作用)。我一直在努力搜索库代码,但我所希望的节省时间几乎毫无用处。所以,我要解释我在做什么,也许你们能帮我。我只是在寻找简单的碰撞检测,比如你击中了什么东西,然后现在就打印一行。剩下的我可以自己解决

所以我创造了我的世界:

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);