LIBGDX ModelBuilder

De MediaWiki
Saltar a: navegación, buscar

UNIDADE 5: ModelBuilder. Primeiros modelos 3D


Introdución

A clase ModelBuilder vainos permitir crear modelos en execución (por programación).

Como novidade con respecto ó dado na Unidade 4 imos engadir o uso de luces.


Preparación: Empezamos co primeiro exercicio.

Preparación: Creade unha nova clase que implemente a interface Screen.

Código da clase EX_1_DefinicionLuz
Obxectivo: Cargar o noso primeiro modelo.

  1. import com.badlogic.gdx.Gdx;
  2. import com.badlogic.gdx.Screen;
  3. import com.badlogic.gdx.graphics.GL20;
  4. import com.badlogic.gdx.graphics.PerspectiveCamera;
  5.  
  6.  
  7. public class EX_1_DefinicionLuz implements Screen {
  8.  
  9.         private PerspectiveCamera camara3d;
  10.        
  11.         public EX_1_DefinicionLuzInicial(){
  12.                 camara3d = new PerspectiveCamera();
  13.  
  14.         }
  15.        
  16.         @Override
  17.         public void render(float delta) {
  18.                 // TODO Auto-generated method stub
  19.                 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
  20.                  
  21.         }
  22.  
  23.         @Override
  24.         public void resize(int width, int height) {
  25.                 // TODO Auto-generated method stub
  26.                
  27.                 camara3d.fieldOfView=67;
  28.                 camara3d.viewportWidth=width;
  29.                 camara3d.viewportHeight=height;
  30.                
  31.                 camara3d.position.set(0f,0f,15f);
  32.                 camara3d.lookAt(0,0,0);
  33.                 camara3d.near=1;
  34.                 camara3d.far=300f;
  35.                 camara3d.update();
  36.                
  37.  
  38.  
  39.         }
  40.  
  41.         @Override
  42.         public void show() {
  43.                 // TODO Auto-generated method stub
  44.         }
  45.  
  46.         @Override
  47.         public void hide() {
  48.                 // TODO Auto-generated method stub
  49.                
  50.         }
  51.  
  52.         @Override
  53.         public void pause() {
  54.                 // TODO Auto-generated method stub
  55.                
  56.         }
  57.  
  58.         @Override
  59.         public void resume() {
  60.                 // TODO Auto-generated method stub
  61.                
  62.         }
  63.  
  64.         @Override
  65.         public void dispose() {
  66.                 // TODO Auto-generated method stub
  67.                
  68.         }
  69.  
  70. }


Como vemos nesta clase só definimos unha cámara en perspectiva como xa fixemos anteriormente.


Código da clase PracticasNovaApi3D
Obxectivo: Chamamos á clase anterior

  1. import com.badlogic.gdx.Game;
  2. import com.plategaxogo3davanzado.pantallas.EX_1_DefinicionLuzInicial;
  3.  
  4. public class PracticasNovaApi3D extends Game {
  5.  
  6.         private EX_1_DefinicionLuz pantallaxogo;
  7.        
  8.         @Override
  9.         public void create() {
  10.                 // TODO Auto-generated method stub
  11.                
  12.                 pantallaxogo = new EX_1_DefinicionLuz();
  13.                 setScreen(pantallaxogo);
  14.         }
  15.  
  16.         @Override
  17.         public void dispose(){
  18.                 super.dispose();
  19.                 pantallaxogo.dispose();
  20.         }
  21. }


Modificade ás clases principais das diferentes plataformas para que chamen a esta clase.

A partires de aquí todos os exercicios levarán consigo a creación dunha clase que implemente a interface Screen e será necesario modificar a clase PracticasNovaApi3D para que chame ó novo exercicio.


ModelBuilder

O obxectivo deste punto vai consistir en xerar unha figura xeométrica por programación e asinarlle unha cor, textura e unha luz á escena

Clase ModelBuilder. Información relacionada na wiki: https://github.com/libgdx/libgdx/wiki/Material-and-environment

O proceso é o seguinte:

  • Instanciamos un obxecto da clase ModelBuilder:
  1. ModelBuilder modelBuilder = new ModelBuilder();
  • Chamamos ó método createXXXXX indicando o tipo de figura que queremos crear.

Pero....non todo vai ser tan fácil :)

Cando creamos unha figura temos que asinarlle un material (ven así no constructor). E para que serve un material ?

Os materiais están relacionados coa luz e como se reflexa nela. Dependendo do tipo de material a luz pode reflectirse dunha forma ou outra.


Tedes neste enlace máis información sobre o uso de Materiais e Luces.



Por exemplo, neste caso imos crear un cilindro:

  1.         private Model modelCilindro;
  2.  
  3.         ............
  4.         modelCilindro = modelBuilder.createCylinder(5f,5f, 10f, 10,                    
  5.                         new Material(ColorAttribute.createDiffuse(Color.RED)),
  6.                         Usage.Position | Usage.Normal);

Como xa vimos anteriormente, cando creamos unha figura sempre temos que enviarlle a lo menos á posición. Iso o indicamos có atributo Usage.position. O outro atributo, Ussage.Normal fai referencia a que calcule os vectores que son asociados á figura e que van indicar cara onde se vai a reflectir a luz (normal vector).


Nota: Podedes crear un cubo ou outras figuras para facer probas.


Tedes máis información neste enlace sobre os Vector Normal.


Neste caso estamos a definir un cilindro de dimensións alto=5,ancho=5,profundo=5 e 10 divisións, que veñen a ser o número de partes en que está dividido o cilindro (a mais partes máis 'calidade' visual do cilindro). Ademais o estamos pintando de vermello.

Nota: Débese liberar a memoria do modelo chamando ó método dispose.

Agora ben, có Model non indicamos onde ten que colocarse o figura. Para iso temos que crear unha instancia da clase ModelInstance.

  • Creamos por tanto unha instancia da clase ModelInstance, pasando como parámetro o obxecto da clase Model.
  1.         private ModelInstance modeloInstanciaCilindro;
  2.  
  3.         ............
  4.         public EX_1_DefinicionLuzInicial(){
  5.                 modeloInstanciaCilindro = new ModelInstance(modelCilindro);
  6.                 .....
  7.         }


Nota:Por defecto os obxectos son posicionados na posición (0,0,0).

  • Agora necesitamos renderizar o modelo. Para facelo debemos facer uso da clase ModelBatch, chamando ó método render e pasándolle como argumento o ModelInstance:
  1.         private ModelBatch modelBatch;
  2.  
  3.         .....
  4.         public EX_1_DefinicionLuzInicial(){
  5.                 modelBatch = new ModelBatch();
  6.                 .....
  7.         }
  8.         .....
  9.         @Override
  10.         public void render(float delta) {
  11.                 // TODO Auto-generated method stub
  12.                 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
  13.                  
  14.                 modelBatch.begin(camara3d);
  15.                
  16.                 modelBatch.render(modeloInstanciaCilindro);
  17.                
  18.                 modelBatch.end();
  19.         }

O código completo:

Código da clase EX_1_DefinicionLuzInicial
Obxectivo: Visualiza un cilindro utilizando a clase ModelBuilder.

  1. import com.badlogic.gdx.Gdx;
  2. import com.badlogic.gdx.Screen;
  3. import com.badlogic.gdx.graphics.Color;
  4. import com.badlogic.gdx.graphics.GL20;
  5. import com.badlogic.gdx.graphics.PerspectiveCamera;
  6. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
  7. import com.badlogic.gdx.graphics.g3d.Material;
  8. import com.badlogic.gdx.graphics.g3d.Model;
  9. import com.badlogic.gdx.graphics.g3d.ModelBatch;
  10. import com.badlogic.gdx.graphics.g3d.ModelInstance;
  11. import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
  12. import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
  13.  
  14.  
  15. public class EX_1_DefinicionLuzInicial implements Screen {
  16.  
  17.         private PerspectiveCamera camara3d;
  18.         private Model modelCilindro;
  19.         private ModelInstance modeloInstanciaCilindro;
  20.         private ModelBatch modelBatch;
  21.  
  22.        
  23.         public EX_1_DefinicionLuzInicial(){
  24.                 camara3d = new PerspectiveCamera();
  25.  
  26.  
  27.         ModelBuilder modelBuilder = new ModelBuilder();
  28.  
  29.  
  30.         modelCilindro = modelBuilder.createCylinder(5f,5f, 10f, 10,                    
  31.                         new Material(ColorAttribute.createDiffuse(Color.RED)),
  32.                         Usage.Position | Usage.Normal);
  33.        
  34.         modeloInstanciaCilindro = new ModelInstance(modelCilindro);
  35.         modelBatch = new ModelBatch();
  36.        
  37.         }
  38.        
  39.         @Override
  40.         public void render(float delta) {
  41.                 // TODO Auto-generated method stub
  42.                 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
  43.                  
  44.                 modelBatch.begin(camara3d);
  45.                
  46.                 modelBatch.render(modeloInstanciaCilindro);
  47.                
  48.                 modelBatch.end();
  49.         }
  50.  
  51.         @Override
  52.         public void resize(int width, int height) {
  53.                 // TODO Auto-generated method stub
  54.                
  55.                 camara3d.fieldOfView=67;
  56.                 camara3d.viewportWidth=width;
  57.                 camara3d.viewportHeight=height;
  58.                
  59.                 camara3d.position.set(0f,0f,15f);
  60.                 camara3d.lookAt(0,0,0);
  61.                 camara3d.near=1;
  62.                 camara3d.far=300f;
  63.                 camara3d.update();
  64.                
  65.  
  66.  
  67.         }
  68.  
  69.         @Override
  70.         public void show() {
  71.                 // TODO Auto-generated method stub
  72.         }
  73.  
  74.         @Override
  75.         public void hide() {
  76.                 // TODO Auto-generated method stub
  77.                
  78.         }
  79.  
  80.         @Override
  81.         public void pause() {
  82.                 // TODO Auto-generated method stub
  83.                
  84.         }
  85.  
  86.         @Override
  87.         public void resume() {
  88.                 // TODO Auto-generated method stub
  89.                
  90.         }
  91.  
  92.         @Override
  93.         public void dispose() {
  94.                 // TODO Auto-generated method stub
  95.                 modelCilindro.dispose();
  96.                 modelBatch.dispose();
  97.                
  98.                
  99.         }
  100.  
  101. }

Resultado:

LIBGDX UD5 ModelBuilder 1.jpg


Non é moi espectacular o resultado verdade ? :)


Para facelo un pouco máis bonito (con texturas mellora a cousa) imos darlle un pouco de luz.

Luces

Existen diferentes tipos de fontes de luz:

  • Luces de ambiente (ambient lights): Non é un tipo de luz direccional (que veña dun sitio concreto) pero fai que todos os obxectos se iluminen por igual.
  • Puntos de luz (point lights): A luz parte dun punto no espazo e todas as direccións (coma unha bombilla).
  • Luces direccionais (directional lights): A luz ven dunha dirección. Por exemplo o Sol (aínda que non sexa realmente así). A súa luz 'golpea' toda a superficie da Terra no mesmo ángulo pola distancia tan grande que hai.
  • Spotlights: Parecidas ós puntos de luz pero cunha dirección formando un cono de luz, como por exemplo a luz dun farol da rúa.


A maiores da posición e dirección da luz, OPEN GL nos permite definir a intensidade da mesma. Esta é expresada en forma de cor RGBA, e especifica catro tipos diferentes de cor (intensidade) da mesma:

  • Ambiente (ambient): A luz é uniforme en todo o obxecto.
  • Difusa (diffuse): As caras do obxectos que non son iluminadas aparecen máis escuras.
  • Especular (specular): Parecida á difusa pero só afecta a certos puntos que teñen unha determinada orientación entre a luz e o obxecto.
  • Emisiva (emissive): Non se utiliza.

Como comentario, indicar que os materias poden ter a mesma cor/intensidade que os tipos indicados anteriormente.


Unha vez vista a teoría imos coa práctica.

Imos engadir á nosa escena unha luz ambiente e unha luz direccional.

Nota: As luces consumen bastantes recursos polo que non se debe abusar delas.

Para facer uso das luces debemos usar a clase Environment.

O proceso é o seguinte:

  • Instanciamos un obxecto de dita clase:
  1.         private Environment environment;
  2.          .............
  3.         public EX_1_DefinicionLuzInicial(){
  4.          .............
  5.         environment = new Environment();
  6.  
  7.         }
  • Definimos os dous tipos de luz.
  1.         environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
  2.         environment.add(new DirectionalLight().set(1f, 1f, 1f, 1f, 0f, 0f));
  • Renderizamos enviando o environment creado:
  1.         public void render(float delta) {
  2.                 // TODO Auto-generated method stub
  3.                 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
  4.                  
  5.                 modelBatch.begin(camara3d);
  6.                
  7.                 modelBatch.render(modeloInstanciaCilindro,environment);
  8.                
  9.                 modelBatch.end();
  10.         }


Como vemos na definición do tipo de luz, a luz ambiente xa está creada. Cambiamos a súa intensidade e non leva posición (ven de todos lados). A luz direccional a engadimos:

  1.         environment.add(new DirectionalLight().set(1f, 1f, 1f, 1f, 0f, 0f));

Indicamos a súa cor/intensidade(RGBA) e posición.


Resultado:

LIBGDX UD5 ModelBuilder 2.jpg



Controlando a escena

Clase CameraInputController.

Para 'xogar' un pouco coa escena imos a engadir un control da cámara co rato, de tal forma que poderemos rotar a cámara e afastala coa roda do rato.

Código da clase EX_1_DefinicionLuz
Obxectivo: Poder mover a cámara premendo co rato o botón esquerdo e movendo o rato ó mesmo tempo. Coa roda achegamos ou afastamos a cámara.

  1. import com.badlogic.gdx.Gdx;
  2. import com.badlogic.gdx.Screen;
  3. import com.badlogic.gdx.graphics.Color;
  4. import com.badlogic.gdx.graphics.GL20;
  5. import com.badlogic.gdx.graphics.PerspectiveCamera;
  6. import com.badlogic.gdx.graphics.VertexAttributes.Usage;
  7. import com.badlogic.gdx.graphics.g3d.Environment;
  8. import com.badlogic.gdx.graphics.g3d.Material;
  9. import com.badlogic.gdx.graphics.g3d.Model;
  10. import com.badlogic.gdx.graphics.g3d.ModelBatch;
  11. import com.badlogic.gdx.graphics.g3d.ModelInstance;
  12. import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
  13. import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
  14. import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
  15. import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
  16.  
  17.  
  18. public class EX_1_DefinicionLuz implements Screen {
  19.  
  20.         private PerspectiveCamera camara3d;
  21.         private Model modelCilindro;
  22.         private ModelInstance modeloInstanciaCilindro;
  23.         private ModelBatch modelBatch;
  24.         private Environment environment;
  25.  
  26.         private CameraInputController camController;
  27.        
  28.         public EX_1_DefinicionLuzInicial(){
  29.                 camara3d = new PerspectiveCamera();
  30.  
  31.  
  32.         ModelBuilder modelBuilder = new ModelBuilder();
  33.  
  34.  
  35.         modelCilindro = modelBuilder.createCylinder(5f,5f, 10f, 10,                    
  36.                         new Material(ColorAttribute.createDiffuse(Color.RED)),
  37.                         Usage.Position | Usage.Normal);
  38.        
  39.         modeloInstanciaCilindro = new ModelInstance(modelCilindro);
  40.         modelBatch = new ModelBatch();
  41.        
  42.         environment = new Environment();
  43.         environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
  44.         environment.add(new DirectionalLight().set(1f, 1f, 1f, 1f, 0f, 0f));
  45.        
  46.                 camController = new CameraInputController(camara3d);
  47.                 Gdx.input.setInputProcessor(camController);
  48.        
  49.         }
  50.        
  51.         @Override
  52.         public void render(float delta) {
  53.                 // TODO Auto-generated method stub
  54.                 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
  55.                  
  56.                 modelBatch.begin(camara3d);
  57.                
  58.                 modelBatch.render(modeloInstanciaCilindro,environment);
  59.                
  60.                 modelBatch.end();
  61.         }
  62.  
  63.         @Override
  64.         public void resize(int width, int height) {
  65.                 // TODO Auto-generated method stub
  66.                
  67.                 camara3d.fieldOfView=67;
  68.                 camara3d.viewportWidth=width;
  69.                 camara3d.viewportHeight=height;
  70.                
  71.                 camara3d.position.set(0f,0f,15f);
  72.                 camara3d.lookAt(0,0,0);
  73.                 camara3d.near=1;
  74.                 camara3d.far=300f;
  75.                 camara3d.update();
  76.                
  77.  
  78.  
  79.         }
  80.  
  81.         @Override
  82.         public void show() {
  83.                 // TODO Auto-generated method stub
  84.         }
  85.  
  86.         @Override
  87.         public void hide() {
  88.                 // TODO Auto-generated method stub
  89.                
  90.         }
  91.  
  92.         @Override
  93.         public void pause() {
  94.                 // TODO Auto-generated method stub
  95.                
  96.         }
  97.  
  98.         @Override
  99.         public void resume() {
  100.                 // TODO Auto-generated method stub
  101.                
  102.         }
  103.  
  104.         @Override
  105.         public void dispose() {
  106.                 // TODO Auto-generated method stub
  107.                 modelCilindro.dispose();
  108.                 modelBatch.dispose();
  109.                
  110.                
  111.         }
  112.  
  113. }



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