¿Cómo induzco eventos de colisión en LibGDX 3D?


9

En el siguiente código, he puesto un ejemplo de algo que quiero hacer. Tengo la cámara y quiero que deje de moverse cada vez que golpea una de las cajas, ¿cómo hago esto?

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:

El resultado


Puede detectar si se está en una caja (Si su ey es <&& y box.y> box.y + box.height y hacer en mismo para x y z si se quiere, a continuación, cambiar de Y por su velocidad)
Artsicle

Respuestas:


1

Los motores de física que he escrito funcionan en tres pasos.

Cada cuadro:

  1. Todos los objetos de física calculan su propio vector de velocidad
  2. El motor de física recorre los objetos y actualiza sus nuevas posiciones según

    posición + = velocidad * deltaTime;

  3. El motor de física resuelve todas las colisiones.

Primero, sugiero que en lugar de dejar que su FirstPersonCameraController establezca la posición de la cámara, haga que la cámara sea un objeto físico haciendo que FirstPersonCameraController controle la velocidad de la cámara, no la posición, y luego deje que el motor físico actualice la posición de la cámara.

Escribir un motor de física puede sonar aterrador, pero en realidad es solo un método que mueve todos los objetos de una escena y luego se asegura de que los objetos sólidos no se superpongan.

Por último, dependiendo de sus necesidades, hay dos enfoques que he utilizado para resolver las colisiones.

  1. Superposición básica

Después de que su motor de física haya movido todos los objetos. Luego recorra los objetos para ver cuáles se superponen. Si alguno se superpone, entonces han chocado. Debe decidir cómo se resolverá esta colisión, pero generalmente esto significa que mueve uno o ambos objetos hacia atrás hasta que ya no se superponen.

El mayor inconveniente de este enfoque se llama el problema de bala a través del papel. Si su cámara se mueve lo suficientemente rápido como para atravesar un cubo entero en un cuadro, cuando compruebe las colisiones, no registrará que los dos objetos colisionaron. Hay maneras de superar esto, como asegurarse de que ningún objeto vaya horriblemente rápido y arreglar su paso temporal

  1. Detección de colisión barrida

He tenido un éxito variado con este método. Básicamente, la idea es que puede combinar la fase de detección de movimiento y colisión para determinar que dados los vectores de velocidad de dos objetos, a qué hora colisionarán si lo hacen. Profundizar en cómo lograr esto está fuera del alcance de esta respuesta ya larga, pero aquí hay un buen artículo

Este método resuelve la viñeta a través de un problema en papel, pero es más difícil de entender / implementar y más costoso desde el punto de vista computacional.

Puede haber más métodos disponibles que pueden beneficiarlo al buscar en Internet la detección de colisiones.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.