Jak indukować zdarzenia kolizji w LibGDX 3D?


9

W poniższym kodzie umieściłem przykład czegoś, co chcę zrobić. Mam aparat i chcę, aby przestał się poruszać, gdy trafi w jedno z pudeł, jak to zrobić?

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

Wynik:

Wynik


Możesz wykryć, czy jest on na polu (jeśli jego y wynosi <box.y && y> box.y + box.height i zrób to samo dla x i z, jeśli chcesz, to zmień jego Y o jego prędkość)
Artykuł

Odpowiedzi:


1

Silniki fizyki, które napisałem, działają w trzech krokach

Każda ramka:

  1. Wszystkie obiekty fizyki obliczają własny wektor prędkości
  2. Silnik fizyki zapętla obiekty i aktualizuje ich nowe pozycje na podstawie

    pozycja + = prędkość * deltaTime;

  3. Silnik fizyki rozwiązuje wszystkie kolizje

Po pierwsze, sugeruję, aby zamiast pozwalać Twojemu FirstPersonCameraControllerowi ustawić pozycję kamery, uczynić kamerę obiektem fizycznym, pozwalając FirstPersonCameraControllerowi kontrolować prędkość kamery, a nie pozycję, a następnie pozwolić silnikowi fizyki aktualizować pozycję kamery.

Pisanie silnika fizyki może brzmieć przerażająco, ale tak naprawdę jest to tylko metoda, która porusza wszystkie obiekty w scenie, a następnie upewnia się, że obiekty stałe nie nakładają się.

Wreszcie, w zależności od potrzeb, istnieją dwa podejścia, których użyłem do rozwiązania kolizji.

  1. Podstawowe nakładanie się

Po tym, jak silnik fizyki poruszy każdy obiekt. Następnie przejdź przez obiekty, aby zobaczyć, które się nakładają. Jeśli jakieś się pokrywają, to się zderzyły. Musisz zdecydować, w jaki sposób ta kolizja zostanie rozwiązana, ale zwykle oznacza to, że przesuwasz jeden lub oba obiekty do tyłu, aż przestaną się nakładać.

Największą wadą tego podejścia jest problem polegający na pocisku przez papier. Jeśli kamera porusza się wystarczająco szybko, aby przejść przez cały sześcian w jednej ramce, to podczas sprawdzania kolizji nie zarejestrujesz kolizji dwóch obiektów. Istnieją sposoby na przezwyciężenie tego, na przykład upewnienie się, że żaden przedmiot nie idzie okropnie szybko i ustalenie czasu

  1. Wykrywanie kolizji przeciągnięcia

Dzięki tej metodzie miałem różne sukcesy. Zasadniczo chodzi o to, że można połączyć fazę wykrywania ruchu i kolizji, aby ustalić, że biorąc pod uwagę wektory prędkości dwóch obiektów, o której godzinie się zderzą, jeśli w ogóle się zderzą. Zagłębianie się w to, jak to osiągnąć, jest poza zasięgiem tej i tak już długiej odpowiedzi, ale oto dobry artykuł

Ta metoda rozwiązuje problem polegający na problemie z papierem, ale trudniej jest go zrozumieć / wdrożyć, a także jest bardziej kosztowny obliczeniowo.

Może być więcej metod, które mogą przynieść ci korzyść, przeszukując Internet w celu wykrycia kolizji.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.