Как вызвать события столкновения в 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();
    }
}

Результат:

Результат

SirMathhman
источник
Вы можете определить, находится ли он в боксе (если его y равен <box.y && y> box.y + box.height и делать то же самое для x и z, если хотите, тогда измените его Y на его скорость)
Artsicle

Ответы:

1

Физические движки, которые я написал, работают в три этапа.

Каждый кадр:

  1. Все физические объекты вычисляют свой собственный вектор скорости
  2. Физический движок проходит по объектам и обновляет их новые позиции на основе

    положение + = скорость * deltaTime;

  3. Физический движок разрешает все столкновения

Во-первых, я предлагаю вместо того, чтобы позволить FirstPersonCameraController установить положение камеры, сделать камеру физическим объектом, установив FirstPersonCameraController для управления скоростью камеры, а не положением, а затем позволить физическому движку обновить положение камеры.

Написание физического движка может показаться пугающим, но на самом деле это просто метод, который перемещает все объекты в сцене и затем гарантирует, что твердые объекты не перекрываются.

Наконец, в зависимости от ваших потребностей, для разрешения коллизий я использовал два подхода.

  1. Основное перекрытие

После того, как ваш физический движок переместил каждый объект. Затем переберите объекты, чтобы увидеть, какие из них перекрываются. Если они совпадают, то они столкнулись. Вы должны решить, как будет разрешаться это столкновение, но обычно это означает, что вы перемещаете один или оба объекта назад, пока они больше не перекрываются.

Самый большой недостаток этого подхода - проблема с бумагой. Если ваша камера движется достаточно быстро и проходит через весь куб в одном кадре, то при проверке столкновений вы не заметите, что два объекта столкнулись. Есть способы преодолеть это, например, убедиться, что ни один объект не идет ужасно быстро, и исправить свой временной шаг.

  1. Заметное столкновение

Я имел различные успехи с этим методом. По сути, идея заключается в том, что вы можете объединить фазу обнаружения движения и столкновения, чтобы определить, что для заданных векторов скорости двух объектов, в какое время они столкнутся, если столкнутся вообще. Углубление того, как этого добиться, выходит за рамки этого длинного ответа, но вот хорошая статья

Этот метод решает проблему с помощью бумаги, но его труднее понять / реализовать, а также он требует больших вычислительных затрат.

Там может быть больше методов, которые могут быть полезны вам, ища в Интернете для обнаружения столкновений.

spectacularbob
источник