Як викликати події зіткнення в 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 на його швидкість)
Артикул

Відповіді:


1

Двигуни фізики, про які я написав, працюють у три етапи

Кожен кадр:

  1. Всі об'єкти фізики обчислюють власний вектор швидкості
  2. Двигун фізики проходить через об'єкти та оновлює їхні нові позиції на основі

    положення + = швидкість * deltaTime;

  3. Фізичний двигун вирішує всі зіткнення

По-перше, я пропоную замість того, щоб ваш FirstPersonCameraController встановив положення камери, перетворіть камеру на об'єкт фізики, надавши FirstPersonCameraController керувати швидкістю камери, а не положенням, а потім дозволити фізичному двигуну оновити положення камери.

Написання двигуна фізики може здатися страшним, але це дійсно лише метод, який переміщує всі об'єкти на сцені і потім гарантує, що тверді об'єкти не перетинаються.

Нарешті, залежно від ваших потреб, є два підходи, які я використав для вирішення колізій.

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

Після того, як ваш двигун фізики перемістив кожен об'єкт. Потім проведіть через об'єкти, щоб побачити, які перекриваються. Якщо такі перекриваються, то вони зіткнулися. Ви повинні вирішити, як вирішуватиметься це зіткнення, але зазвичай це означає, що ви рухаєте один або обидва об'єкти назад, поки вони більше не перетинаються.

Найбільшим недоліком такого підходу називається куля через проблему з папером. Якщо ваша камера рухається досить швидко, що проходить через весь куб в одному кадрі, тоді, коли ви перевірите на зіткнення, ви не зареєструєте, що два об'єкти зіткнулися. Існують способи подолати це, наприклад, переконатися, що жоден об'єкт не йде жахливо швидко, і виправити часовий крок

  1. Швидке виявлення зіткнення

Я мав різноманітний успіх у цьому методі. По суті, ідея полягає в тому, що ви можете поєднати фазу виявлення руху та зіткнення, щоб визначити, які дані векторів швидкості руху двох об’єктів, який час вони зіткнуться, якщо вони зіткнуться взагалі. Поглиблення в глибину того, як це досягти, виходить за межі цієї вже тривалої реакції, але ось хороша стаття

Цей метод вирішує кулю через паперову проблему, але це важче зрозуміти / реалізувати, а також обчислювально дорожче.

Там може бути більше методів, які можуть вам принести користь, шукаючи Інтернет для виявлення зіткнень.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.