Come induco eventi di collisione in LibGDX 3D?


9

Nel codice qui sotto ho messo un esempio di qualcosa che voglio fare. Ho la fotocamera e voglio che smetta di muoversi ogni volta che colpisce una delle scatole, come posso fare?

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

Risultato:

Il risultato


Puoi rilevare se è su una scatola (Se il suo y è <box.y && y> box.y + box.height e fai lo stesso per xe z se vuoi, quindi cambia il suo Y in base alla sua velocità)
Artsicle

Risposte:


1

I motori fisici che ho scritto funzionano in tre fasi

Ogni frame:

  1. Tutti gli oggetti di fisica calcolano il proprio vettore di velocità
  2. Il motore fisico scorre gli oggetti e aggiorna le loro nuove posizioni in base

    posizione + = velocità * deltaTime;

  3. Il motore fisico risolve tutte le collisioni

Innanzitutto, suggerisco che invece di lasciare che FirstPersonCameraController imposti la posizione della videocamera, rendi la videocamera un oggetto fisico facendo in modo che FirstPersonCameraController controlli la velocità della videocamera, non la posizione, e poi lasci che il motore fisico aggiorni la posizione della videocamera.

Scrivere un motore fisico può sembrare spaventoso, ma in realtà è solo un metodo che sposta tutti gli oggetti in una scena e quindi si assicura che gli oggetti solidi non si sovrappongano.

Infine, a seconda delle tue esigenze, ci sono due approcci che ho usato per risolvere le collisioni.

  1. Sovrapposizione di base

Dopo che il tuo motore fisico ha spostato ogni oggetto. Quindi scorrere gli oggetti per vedere quali sono sovrapposti. Se qualcuno si sovrappone, si sono scontrati. Devi decidere come risolvere questa collisione, ma di solito questo significa che sposta uno o entrambi gli oggetti all'indietro fino a quando non si sovrappongono più.

Il più grande svantaggio di questo approccio è chiamato il problema dei proiettili attraverso la carta. Se la tua videocamera si sta muovendo abbastanza velocemente da attraversare un intero cubo in un fotogramma, quindi quando controlli le collisioni, non registrerai che i due oggetti si sono scontrati. Ci sono modi per ovviare a questo, come assicurarsi che nessun oggetto vada orribilmente veloce e fissare il tuo timestep

  1. Rilevamento delle collisioni spazzato

Ho avuto vari successi con questo metodo. Fondamentalmente l'idea è che è possibile combinare la fase di rilevamento del movimento e della collisione per determinare quei dati vettori di velocità di due oggetti, a che ora si scontreranno se si scontreranno affatto. Approfondire come realizzare questo obiettivo non rientra in questa risposta già lunga, ma ecco un buon articolo

Questo metodo risolve il problema con un problema cartaceo, ma è più difficile da capire / implementare e più costoso dal punto di vista computazionale.

Ci possono essere più metodi là fuori che possono trarre vantaggio dalla ricerca su Internet per il rilevamento delle collisioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.