J2ME/Lições/M3G/Colisões

Colisões podem parecer simples em 2D, mas são um pouco mais complicadas no mundo em 3D, vamos ver aqui como fazer colisões da câmera para as meshes do cenário.

Checando colisões

editar

Vamos ver como checar colisões, primeiramente devemos criar um objeto do tipo RayIntersection, é ele que vai armazenar todos os dados da colisão.

import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}

Agora vamos criar 2 arrays de float, um irá pegar a posição X, Y, Z da câmera, o outro irá pegar a oriêntação da câmera. Essas variáveis devem ser obrigatoriamente iniciadas.

import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
        float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}

Agora vamos criar uma variável booleana para checar se houve uma colisão, vamos coloca-la inicialmente como false.


import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
        float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
        boolean colisao = false;
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}

Agora dentro do loop principal, vamos usar os métodos getTranslation() e getOrientation() para armazenar nas variáveis translacaoCamera e rotacaoCamera, os atributos da nossa câmera.

import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
        float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
        boolean colisao = false;
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                
                minhaCamera.getTranslation(translacaoCamera);
                minhaCamera.getOrientation(orientacaoCamera);
                    
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}

Agora vamos testar a colisão através do método pick(), que terá como enrada os seguintes valores:

  1. escopo - sempre será -1
  2. posição X - a posição X da câmera que foi pega no getTranslation()
  3. posição Y - a posição Y da câmera que foi pega no getTranslation()
  4. posição Z - a posição Z da câmera que foi pega no getTranslation()
  5. orientação X - a orientação X da câmera que foi pega no getOrientation()
  6. orientação Y - a orientação Y da câmera que foi pega no getOrientation()
  7. orientação Z - a orientação Z da câmera que foi pega no getOrientation()
  8. RayIntersection - o objeto RayIntersection que criamos anteriormente

Esse método pick() irá retornar a condição true ou false para a nossa variável booleana colisao;


import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
        float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
        boolean colisao = false;
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                
                minhaCamera.getTranslation(translacaoCamera);
                minhaCamera.getOrientation(orientacaoCamera);
                colisao = meuMundo.pick(-1, 
                                        translacaoCamera[0],
                                        translacaoCamera[1],
                                        translacaoCamera[2],
                                        orientacaoCamera[1],
                                        orientacaoCamera[2],
                                        orientacaoCamera[3],
                                        meuRayIntersection);
                    
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}

Agora, vamos criar um if para caso a colisão seja verdadeira mostrar uma mensagem no console.

import javax.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import javax.microedition.game.*;

public class ClasseMeuGameCanvas extends GameCanvas implements Runnable {
    Thread meuThread;
    Graphics meuGrafico = this.getGraphics();
    Graphics3D meuGrafico3D = Graphics3D.getInstance();
    Object3D[] meuObjeto3D;
    World meuMundo;
    Camera minhaCamera = new Camera();
    RayIntersection meuRayIntersection;
    
    public ClasseMeuGameCanvas(){
        super(false);
        meuThread = new Thread(this);
        meuThread.start();
    }
    public void run(){
        try{
            meuObjeto3D = Loader.load("/Meu Objeto 3D.m3g");
            meuMundo = (World) meuObjeto3D[0];
            minhaCamera = meuMundo.getActiveCamera();
        }catch(Exception minhaExcessao){
            minhaExcessao.printStackTrance();
        }
        
        float[] translacaoCamera = {0.0f, 0.0f, 0.0f}
        float[] orientacaoCamera = {0.0f, 0.0f, 0.0f, 0.0f}
        boolean colisao = false;
        boolean gameOver = false;
        while(gameOver == false){
            try {
                meuGrafico3D.bindTarget(meuGrafico);
                
                minhaCamera.getTranslation(translacaoCamera);
                minhaCamera.getOrientation(orientacaoCamera);
                colisao = meuMundo.pick(-1, 
                                        translacaoCamera[0],
                                        translacaoCamera[1],
                                        translacaoCamera[2],
                                        orientacaoCamera[1],
                                        orientacaoCamera[2],
                                        orientacaoCamera[3],
                                        meuRayIntersection);
                if (colisao == true){
                    System.out.println("Colisão verdadeira");
                }
                
                meuGrafico3D.render(meuMundo);
            } catch (Exception minhaExcecao) {
                minhaExcecao.printStackTrance)();
            } finally {
                meuGrafico3D.releaseTarget();
                flushGraphics();
            }
        }
    }
}