Como induzir eventos de colisão no LibGDX 3D?


9

No código abaixo, coloquei um exemplo de algo que quero fazer. Eu tenho a câmera e quero que ela pare de se mover sempre que atingir uma das caixas, como faço isso?

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

Resultado:

O resultado


Você pode detectar se ele está em uma caixa (se o y é <box.y && y> box.y + box.height e faz o mesmo para x e z, se você quiser, então mude seu Y pela velocidade)
Artes

Respostas:


1

Os mecanismos de física que escrevi funcionam em três etapas

Cada quadro:

  1. Todos os objetos de física calculam seu próprio vetor de velocidade
  2. O mecanismo de física percorre os objetos e atualiza suas novas posições com base em

    posição + = velocidade * deltaTime;

  3. O mecanismo de física resolve todas as colisões

Primeiro, sugiro que, em vez de permitir que o FirstPersonCameraController defina a posição da câmera, torne a câmera um objeto físico, fazendo com que o FirstPersonCameraController controle a velocidade da câmera, não a posição, e deixe o mecanismo físico atualizar a posição da câmera.

Escrever um mecanismo de física pode parecer assustador, mas é realmente apenas um método que move todos os objetos em uma cena e garante que objetos sólidos não se sobreponham.

Por fim, dependendo de suas necessidades, existem duas abordagens que eu usei para resolver as colisões.

  1. Sobreposição básica

Depois que seu mecanismo de física moveu todos os objetos. Em seguida, faça um loop pelos objetos para ver quais estão sobrepostos. Se houver sobreposição, eles colidiram. Você precisa decidir como essa colisão será resolvida, mas geralmente isso significa que você move um ou ambos os objetos para trás até que eles não se sobreponham mais.

A maior desvantagem dessa abordagem é chamada de problema da bala através do papel. Se sua câmera estiver se movendo rápido o suficiente para atravessar um cubo inteiro em um quadro, quando você verificar colisões, não registrará se os dois objetos colidiram. Existem maneiras de superar isso, como garantir que nenhum objeto avance terrivelmente rápido e corrigir o timestep

  1. Detecção de colisão varrida

Eu tive sucesso variado com este método. Basicamente, a idéia é que você pode combinar a fase de detecção de movimento e colisão para determinar que, considerando os vetores de velocidade de dois objetos, a que horas eles colidirão se realmente colidirem. Entrar em detalhes sobre como fazer isso está fora do escopo para esta resposta já longa, mas aqui está um bom artigo

Esse método resolve o problema através de um problema de papel, mas é mais difícil de entender / implementar, além de mais caro em termos de computação.

Pode haver mais métodos por aí que podem beneficiá-lo pesquisando na Internet para detecção de colisão.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.