如何在LibGDX 3D中引发碰撞事件?


9

在下面的代码中,我举了一个我想做的事的例子。我有相机,当它碰到其中一个盒子时,我希望它停止移动,该怎么办?

public class Main extends ApplicationAdapter {

    private final ModelBuilder builder = new ModelBuilder();
    private final Environment environment = new Environment();
    private ModelBatch modelBatch;
    private PerspectiveCamera camera;
    private Model model;
    private ArrayList<ModelInstance> instance = new ArrayList<ModelInstance>();
    private FirstPersonCameraController controller;
    private BoundingBox[] boxBounds = new BoundingBox[1000];
    private BoundingBox cameraBox = new BoundingBox();
    private Vector3 cameraSpeed = new Vector3();
    private Vector3 oldCameraPos = new Vector3();
    private Vector3 newCameraPos = new Vector3();

    @Override

    public void create() {
        modelBatch = new ModelBatch();


        //build the camera
        camera = new PerspectiveCamera(67, graphics.getWidth(), graphics.getHeight());
        camera.position.set(0f, 10f, 0f);
        camera.lookAt(0, 10, 0);
        camera.near = 1f;
        camera.far = 1000f;
        camera.update();

        //build all the boxes
        for (int i = 0; i < 1000; i++) {
            model = builder.createBox(
                    (float) Math.random() * 50,
                    (float) Math.random() * 50,
                    (float) Math.random() * 50,

                    new Material(ColorAttribute.createDiffuse(

                            (float) random(),
                            (float) random(),
                            (float) random(), 1)
                    ), Position | Normal);

            instance.add(new ModelInstance(model));
            instance.get(i).transform.setToTranslation(
                    (float) random() * 1000 - 500,
                    (float) random() * 1000,
                    (float) random() * 1000 - 500);

            boxBounds[i] = new BoundingBox();
            boxBounds[i] = model.calculateBoundingBox(boxBounds[i]);
        }

        //build the ground
        model = builder.createBox(700f, 1f, 700f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Position | Normal);
        ModelInstance ground = new ModelInstance(model);
        instance.add(ground);

        //build the center
        model = builder.createBox(5f, 5f, 5f, new Material(ColorAttribute.createDiffuse(Color.RED)), Position | Normal);
        ModelInstance center = new ModelInstance(model);
        instance.add(center);


        //code the lights here
        DirectionalLight light = new DirectionalLight().set(255, 255, 255,
                (float) random(),
                (float) random(),
                (float) random());

        //set up the enviroment
        environment.set(new ColorAttribute(AmbientLight, 255f, 255f, 255f, 1f));
        environment.add(light);

        //set up the camera controller
        controller = new FirstPersonCameraController(camera);
        controller.setDegreesPerPixel(0.25f);
        controller.setVelocity(20);
        input.setInputProcessor(controller);
    }

    @Override
    public void render() {
        //set up OpenGL
        gl.glViewport(0, 0, graphics.getWidth(), graphics.getHeight());
        gl.glEnable(GL_BLEND);
        gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        gl.glClearColor(0, 0, 0, 0);

        //render the modelInstances
        modelBatch.begin(camera);
        modelBatch.render(instance, environment);
        modelBatch.end();
        controller.update();

        if (input.isKeyPressed(Input.Keys.R)) {
            camera.lookAt(0, 0, 0);
        }

        cameraSpeed = newCameraPos.sub(oldCameraPos);

        cameraBox = new BoundingBox(new Vector3(camera.position.x,
                camera.position.y,
                camera.position.z),

                new Vector3(camera.position.x + 10,
                        camera.position.y + 10,
                        camera.position.z + 10));

        for (int i = 0; i < 1000; i++) {
            if (cameraBox.contains(boxBounds[i])) {
                camera.position.x = camera.position.x - cameraSpeed.x;
                camera.position.y = camera.position.y - cameraSpeed.y;
                camera.position.z = camera.position.z - cameraSpeed.z;
            }
        }

        System.out.println(cameraSpeed.x + " " + cameraSpeed.y + " " + cameraSpeed.z);
    }

    @Override
    public void dispose() {
        modelBatch.dispose();
        model.dispose();
    }
}

结果:

结果


您可以检测他是否在盒子上(如果他的y是<box.y && y> box.y + box.height,并且如果需要,可以对x和z进行同样的处理,然后根据他的速度将其Y向上更改)
Articles

Answers:


1

我编写的物理引擎分三步工作

每帧:

  1. 所有物理对象都计算自己的速度矢量
  2. 物理引擎循环遍历对象并根据以下内容更新其新位置

    位置+ =速度* deltaTime;

  3. 物理引擎解决了所有碰撞

首先,我建议不要让FirstPersonCameraController设置摄像机的位置,而是让FirstPersonCameraController控制摄像机的速度而不是位置,然后让物理引擎更新摄像机的位置,从而使摄像机成为物理对象。

编写物理引擎听起来可能很吓人,但这实际上只是一种方法,它可以移动场景中的所有对象,然后确保实体对象不重叠。

最后,根据您的需要,我使用了两种方法来解决冲突。

  1. 基本重叠

物理引擎移动完所有对象之后。然后遍历对象以查看哪些对象重叠。如果有任何重叠,则说明它们已经碰撞。您必须决定如何解决此冲突,但是通常这意味着您将向后移动一个或两个对象,直到它们不再重叠。

这种方法的最大缺点被称为子弹直通纸问题。如果您的相机移动得足够快,可以在一帧中穿过整个立方体,那么当您检查碰撞时,就不会记录这两个对象发生了碰撞。有多种方法可以解决此问题,例如确保没有物体过快地移动并确定时间步长

  1. 扫频碰撞检测

我用这种方法取得了不同的成功。基本上,您可以将运动和碰撞检测阶段结合起来,以确定给定两个对象的速度矢量,如果它们完全发生碰撞,它们将在什么时间发生碰撞。对于这个已经很长的响应,深入探讨如何完成此操作超出了范围,但这是一篇不错的文章

该方法通过纸张问题解决了项目符号,但更难于理解/实现,并且计算量更大。

可能有更多的方法可以通过在Internet上搜索碰撞检测来使您受益。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.