Comment induire des événements de collision dans LibGDX 3D?

9

Dans le code ci-dessous, j'ai mis un exemple de quelque chose que je veux faire. J'ai la caméra et je veux qu'elle cesse de bouger à chaque fois qu'elle touche une des boîtes, comment faire?

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

Résultat:

Le résultat

SirMathhman
la source
Vous pouvez détecter s'il est sur une boîte (si son y est <box.y && y> box.y + box.height et faire de même pour x et z si vous voulez, puis changer son Y en fonction de sa vitesse)
Artsicle

Réponses:

1

Les moteurs physiques que j'ai écrits fonctionnent en trois étapes

Chaque image:

  1. Tous les objets physiques calculent leur propre vecteur de vitesse
  2. Le moteur physique parcourt les objets et met à jour leurs nouvelles positions en fonction de

    position + = vitesse * deltaTime;

  3. Le moteur physique résout toutes les collisions

Tout d'abord, je suggère qu'au lieu de laisser votre FirstPersonCameraController définir la position de la caméra, faire de la caméra un objet physique en faisant en sorte que le FirstPersonCameraController contrôle la vitesse de la caméra, pas sa position, puis en laissant le moteur physique mettre à jour la position de la caméra.

L'écriture d'un moteur physique peut sembler effrayante, mais c'est vraiment juste une méthode qui déplace tous les objets d'une scène et s'assure ensuite que les objets solides ne se chevauchent pas.

Enfin, selon vos besoins, il y a deux approches que j'ai utilisées pour résoudre les collisions.

  1. Chevauchement de base

Une fois que votre moteur physique a déplacé chaque objet. Parcourez ensuite les objets pour voir ceux qui se chevauchent. Si certains se chevauchent, ils sont entrés en collision. Vous devez décider comment cette collision sera résolue, mais cela signifie généralement que vous déplacez un ou les deux objets vers l'arrière jusqu'à ce qu'ils ne se chevauchent plus.

Le plus gros inconvénient de cette approche est le problème du papier à travers le papier. Si votre caméra se déplace assez rapidement pour traverser un cube entier dans une seule image, alors lorsque vous vérifiez les collisions, vous n'enregistrez pas que les deux objets sont entrés en collision. Il existe des moyens de surmonter cela, par exemple en vous assurant qu'aucun objet ne va horriblement vite et en fixant votre pas de temps

  1. Détection de collision balayée

J'ai eu différents succès avec cette méthode. Fondamentalement, l'idée est que vous pouvez combiner la phase de détection de mouvement et de collision pour déterminer que, étant donné les vecteurs de vitesse de deux objets, à quelle heure vont-ils entrer en collision s'ils entrent en collision? Aller en profondeur sur la façon d'y parvenir est hors de portée pour cette réponse déjà longue, mais voici un bon article

Cette méthode résout la balle à travers un problème de papier, mais elle est plus difficile à comprendre / implémenter et plus coûteuse en calcul.

Il existe peut-être d'autres méthodes qui pourraient vous être utiles en recherchant sur Internet la détection des collisions.

spectaculaire
la source