LIBGDX Carga Modelos3D

De MediaWiki
Saltar a: navegación, buscar

UNIDADE 4: Carga de Modelos 3D


Deseñando os nosos modelos 3D

Loxicamente os nosos modelos 3D non vai ser creados 'manualmente', se non utilizando programas gráficos.

Algún deles:

Moi completo pero tamén bastante complexo.
Bastante máis sinxelo.

Nos imos usar o wings3d aínda que os alumnos podedes utilizar calquera que manexedes.


A continuación tedes un enlace con tres vídeos (e o códec de vídeo por se non o visualizades) de como se manexa o Wings3D e como podemos crear un obxecto 3D e asinarlle unha textura.


Enlace a vídeos explicativos Wings3D



Conversión de formatos en 3D

En canto os formatos gráficos que podemos cargar están, entre outros:


Para pasar dun formato a outro podemos utilizar unha ferramenta: fbx-conv.

Podemos ver o código fonte en: https://github.com/libgdx/fbx-conv

Podemos descargar a versión compilada en: http://libgdx.badlogicgames.com/fbx-conv/

Información na wiki: https://github.com/libgdx/fbx-conv


O proceso para pasar dun obj a un g3db sería:

  • Descargar a versión compilada do enlace anterior.
  • Descomprimide e abride unha consola.
  • Vos situades onde se atopan os executables e escolledes a versión correspondente ó voso S.O.:
    • fbx-conv-win32.exe: Windows
    • fbx-conv-lin64: Linux
    • fbx-conv-mac: Mac




  • A orde para pasar por exemplo de obj a g3db seria:
  1. fbx-conv-win32.exe modelo_entrada.obj modelo_saida.g3db


NOTA: Sempre que queiramos acelerar a carga dos modelos deberemos de pasalos a binario.

Carga de Modelos 3D

Nota: O que imos ver aquí é unha forma de cargar os Mesh cun formato obj. Dito formato non leva información de cor en cada vértice como vimos nos anteriores puntos, e polo tanto o ShaderProgram non ten que recoller o parámetro de cor.

Polo tanto os arquivos vertex.vrt e fragment.frag quedarían da seguinte maneira:

Arquivo vertext.vert

  1.     attribute vec3 a_position;
  2.     attribute vec2 a_texCoord0;
  3.     varying vec2 v_textCoord;
  4.     uniform mat4 u_worldView;
  5.     void main()
  6.     {
  7.       gl_Position =  u_worldView *vec4(a_position,1);
  8.  
  9.       v_textCoord = a_texCoord0;
  10.     }


Arquivo fragment.frag

  1.     #ifdef GL_ES
  2.       precision mediump float;
  3.     #endif
  4.     varying vec2 v_textCoord;
  5.     uniform sampler2D u_texture;
  6.     void main()
  7.     {
  8.       vec4 texColor = texture2D(u_texture, v_textCoord);
  9.       gl_FragColor = texColor;
  10.     }


Para cargar e manexar os modelos dunha forma máis sinxela mirade o punto: Programación avanzada 3D. De todas formas recomendo a lectura desta parte para entender os principios básicos.

Carga Modelos obj

Para cargar un modelo obj temos que facer uso da clase ModelLoader.

O proceso sería:

  • Crear unha instancia de dita clase:
  1.                 ModelLoader loader = new ObjLoader();
  1.         Model model = loader.loadModel(Gdx.files.internal("modelos/ship.obj"));

Dito método espera recibir como parámetro o arquivo obj.

Este método devolve un obxecto da clase Model.

Para nos un Model ven ser como un Mesh, o que sucede é que nun model poden ser cargados moitos Mesh de vez, polo que para ter unha referencia a un concreto faremos o seguinte:

  • Cargamos o Mesh:
  1.         private Mesh meshNave;
  2.         .............
  3.         meshNave = model.meshes.get(0);

No noso caso só temos un Mesh no obj.


Exemplo:

Imos ver un exemplo completo, engadindo un modelo dunha nave e movéndoa cara a cámara, facendo que a cámara siga a nave cando a pase.


Preparación: Crear unha clase de nome UD4_6_CargaModelos3D, que derive da clase Game e sexa chamada pola clase principal das diferentes versións (desktop, android,...).


Crea un cartafol de nome modelos dentro do cartafol assets da versión Android.

Leva ó cartafol assets/modelos os arquivos ship.mtl, ship.obj e ship.png que se atopan no seguinte arquivo comprimido:

Media:Ship.zip


Creamos unha clase Elementos3D que garde a información de calquera elemento 3D. É igual á clase Cubo que utilizamos no exercicio anterior:

Código da clase Elementos3D
Obxectivo: Definir unha clase que garde o que necesitamos dun obxecto 3d.

  1. import com.badlogic.gdx.math.Matrix4;
  2. import com.badlogic.gdx.math.Vector3;
  3.  
  4. public class Elemento3D {
  5.        
  6.         public Matrix4 matriz;
  7.         public Vector3 posicion;
  8.         public float escala;
  9.         public Vector3 velocidade;
  10.         private Vector3 temp;
  11.        
  12.         public Elemento3D(Vector3 pos, float escala,Vector3 velocidade){
  13.                 matriz = new Matrix4();
  14.                 posicion = pos;
  15.                 this.escala=escala;
  16.                 this.velocidade = velocidade;
  17.                
  18.                 temp = new Vector3();
  19.                
  20.         }
  21.        
  22.         public void update(float delta){
  23.                
  24.                 temp.set(velocidade);
  25.                 posicion.add(temp.scl(delta));
  26.                
  27.  
  28.                 matriz.idt();
  29.                 matriz.translate(posicion);
  30.                 matriz.scl(escala);
  31.                
  32.                
  33.         }
  34.  
  35. }


Agora imos ver o código de carga da nave.

  1. import com.badlogic.gdx.Game;
  2. import com.badlogic.gdx.Gdx;
  3. import com.badlogic.gdx.assets.loaders.ModelLoader;
  4. import com.badlogic.gdx.files.FileHandle;
  5. import com.badlogic.gdx.graphics.GL20;
  6. import com.badlogic.gdx.graphics.Mesh;
  7. import com.badlogic.gdx.graphics.PerspectiveCamera;
  8. import com.badlogic.gdx.graphics.Texture;
  9. import com.badlogic.gdx.graphics.g3d.Model;
  10. import com.badlogic.gdx.graphics.g3d.loader.ObjLoader;
  11. import com.badlogic.gdx.graphics.glutils.ShaderProgram;
  12. import com.badlogic.gdx.math.Vector3;
  13.  
  14. /**
  15.  * Cargando modelos 3D
  16.  * @author ANGEL
  17.  */
  18.  
  19. public class UD4_6_CargaModelos3D extends Game {
  20.  
  21.         private Mesh meshNave;
  22.         private Elemento3D nave;
  23.         private ShaderProgram shaderProgram;
  24.  
  25.         private Texture textura;
  26.         private PerspectiveCamera camara3d;
  27.        
  28.  
  29.        
  30.         @Override
  31.         public void create() {
  32.                 // TODO Auto-generated method stub
  33.  
  34.                 shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
  35.                 if (shaderProgram.isCompiled() == false) {
  36.                         Gdx.app.log("ShaderError", shaderProgram.getLog());
  37.                         System.exit(0);
  38.                 }
  39.        
  40.  
  41.                 ModelLoader loader = new ObjLoader();
  42.                 Model model = loader.loadModel(Gdx.files.internal("modelos/ship.obj"));
  43.                 meshNave = model.meshes.get(0);
  44.        
  45.                 FileHandle imageFileHandle = Gdx.files.internal("modelos/ship.png");
  46.                 textura = new Texture(imageFileHandle);
  47.                
  48.                 camara3d = new PerspectiveCamera();
  49.                 nave = new Elemento3D(new Vector3(0,-1f,-20f), 2f, new Vector3(0.1f,0.1f,2f));
  50.                
  51.         }
  52.        
  53.        
  54.         @Override
  55.         public void render() {
  56.  
  57.                 Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
  58.                 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
  59.  
  60.                 Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
  61.                 Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);         
  62.  
  63.                 nave.update(Gdx.graphics.getDeltaTime());
  64.                
  65.                 camara3d.lookAt(nave.posicion);
  66.                 camara3d.update();
  67.                
  68.                 shaderProgram.begin();
  69.                 textura.bind(0);
  70.                 shaderProgram.setUniformi("u_texture", 0);
  71.                 shaderProgram.setUniformMatrix("u_worldView", camara3d.combined.cpy().mul(nave.matriz));
  72.                 meshNave.render(shaderProgram, GL20.GL_TRIANGLES);
  73.                        
  74.                        
  75.  
  76.                 shaderProgram.end();
  77.                
  78.                 Gdx.gl20.glDisable(GL20.GL_TEXTURE_2D);
  79.                 Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
  80.  
  81.         }
  82.        
  83.         @Override
  84.         public void resize (int width,int height){
  85.                 // Definimos os parámetros da cámara
  86.                 float aspectRatio = (float) width / (float) height;
  87.                 camara3d.viewportWidth=aspectRatio*1f;
  88.                 camara3d.viewportHeight=1f;
  89.                 camara3d.far=1000f;
  90.                 camara3d.near=0.1f;
  91.                 camara3d.lookAt(0,0,0);
  92.                 camara3d.position.set(0f,0f,5f);
  93.                 camara3d.update();
  94.         }
  95.        
  96.         @Override
  97.         public void dispose(){
  98.                 shaderProgram.dispose();
  99.                 meshNave.dispose();
  100.  
  101.         }
  102.  
  103. }
  • Liña 21: Definimos o obxecto Mesh que vai representar a nave.
  • Liñas 41-43: Cargamos o obj utilizando a clase ModelLoader.
  • Liña 49: Instanciamos a nave pasándolle uns datos concretos.
  • Liñas 65-66: Facemos que a cámara mire cara a nave. LEMBRAR CHAMAR AO UPDATE.
  • Liña 72: Renderizamos a nave.
  • Liña 99: Liberamos a memoria.



TAREFA 4.5 A FACER: Esta parte está asociada á realización dunha tarefa.


Carga Modelos g3db

Para cargar estes modelos debemos facer uso da clase AssetManager.

Como isto é optativo na parte 2D non fai falla que o provedes.


Para cargar un modelo g3db previamente obtido coa ferramenta fbx-conv debemos facer o seguinte:

  • Crear un obxecto da clase AssetManager (que xa podemos ter creado se utilizamos esta forma de carga dos gráficos do xogo):
  1.         AssetManager assetManager = new AssetManager();


  • Chamamos ó método load para cargar o modelo e esperamos a que remate de cargar.
  1.         assetManager.load("modelos/ship.g3db", Model.class);
  2.        
  3.         assetManager.finishLoading();
  • Obtemos o obxecto da clase Model como fixemos no caso anterior:
  1.         Model model = assetManager.get("modelos/ship.g3db", Model.class);
  • Cargamos o Mesh que se atopa no Model (só temos un).
  1.         meshNave = model.meshes.get(0);



O código completo:

  1.         AssetManager assetManager = new AssetManager();
  2.         assetManager.load("modelos/ship.g3db", Model.class);
  3.        
  4.         assetManager.finishLoading();
  5.        
  6.         Model model = assetManager.get("modelos/ship.g3db", Model.class);
  7.         meshNave = model.meshes.get(0);

Modelos 3D xa feitos

Temos diferentes sitios web onde obter modelos 3D.



-- Ángel D. Fernández González -- (2015).