Wie induziere ich Kollisionsereignisse in LibGDX 3D?

9

Im folgenden Code habe ich ein Beispiel für etwas angegeben, das ich tun möchte. Ich habe die Kamera und möchte, dass sie sich nicht mehr bewegt, wenn sie auf eine der Boxen trifft. Wie mache ich das?

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

Ergebnis:

Das Ergebnis

SirMathhman
quelle
Sie können erkennen, ob er sich auf einer Box befindet (Wenn sein y <box.y && y> box.y + box.height ist und für x und z ungefähr dasselbe tun, wenn Sie möchten, ändern Sie sein Y um seine Geschwindigkeit)
Artikel

Antworten:

1

Die Physik-Engines, die ich geschrieben habe, arbeiten in drei Schritten

Jeder Frame:

  1. Alle Physikobjekte berechnen ihren eigenen Geschwindigkeitsvektor
  2. Die Physik-Engine durchläuft die Objekte und aktualisiert ihre neuen Positionen basierend auf

    Position + = Geschwindigkeit * DeltaTime;

  3. Die Physik-Engine löst alle Kollisionen auf

Zunächst schlage ich vor, dass Ihr FirstPersonCameraController nicht die Position der Kamera festlegt, sondern die Kamera zu einem Physikobjekt macht, indem der FirstPersonCameraController die Geschwindigkeit der Kamera und nicht die Position steuert und die Physik-Engine dann die Position der Kamera aktualisiert.

Das Schreiben einer Physik-Engine mag beängstigend klingen, aber es ist wirklich nur eine Methode, die alle Objekte in einer Szene verschiebt und dann sicherstellt, dass sich feste Objekte nicht überlappen.

Schließlich gibt es je nach Ihren Anforderungen zwei Ansätze, die ich zur Lösung der Kollisionen verwendet habe.

  1. Grundlegende Überlappung

Nachdem Ihre Physik-Engine jedes Objekt bewegt hat. Durchlaufen Sie dann die Objekte, um zu sehen, welche sich überlappen. Wenn sich welche überlappen, sind sie kollidiert. Sie müssen entscheiden, wie diese Kollision gelöst werden soll. In der Regel bedeutet dies jedoch, dass Sie ein oder beide Objekte rückwärts verschieben, bis sie sich nicht mehr überlappen.

Der größte Nachteil dieses Ansatzes ist das Bullet-Through-Paper-Problem. Wenn sich Ihre Kamera schnell genug bewegt, um einen ganzen Würfel in einem Bild zu durchlaufen, werden Sie beim Überprüfen auf Kollisionen nicht registrieren, dass die beiden Objekte kollidiert sind. Es gibt Möglichkeiten, dies zu überwinden, z. B. sicherzustellen, dass kein Objekt schrecklich schnell ist, und Ihren Zeitschritt zu korrigieren

  1. Swept-Kollisionserkennung

Ich habe mit dieser Methode unterschiedliche Erfolge erzielt. Grundsätzlich besteht die Idee darin, dass Sie die Bewegungs- und Kollisionserkennungsphase kombinieren können, um zu bestimmen, zu welcher Zeit die Geschwindigkeitsvektoren zweier Objekte kollidieren, wenn sie überhaupt kollidieren. Eine eingehende Beschreibung, wie dies erreicht werden kann, ist für diese bereits lange Antwort nicht möglich, aber hier ist ein guter Artikel

Diese Methode löst das Problem durch ein Papierproblem, ist jedoch schwieriger zu verstehen / zu implementieren und rechenintensiver.

Möglicherweise gibt es weitere Methoden, von denen Sie profitieren können, wenn Sie im Internet nach Kollisionserkennung suchen.

spektakulärer Bob
quelle