quarta-feira, 7 de janeiro de 2015

Exportando do Blender para o Web GL usando Collada e three.js (Parte 2)


Essa é a segunda parte do tutorial onde vou mostrar como criar nosso próprio visualizador Web GL.

Na primeira parte eu falei sobre os programas necessários e scripts.


Configurando o cenário básico para o three.js

Eu vou começar meu código para Web GL com dois scripts de suporte. Nós podíamos criar um script externo mas trabalhar com o HTML e o Javascript juntos fica melhor para entender.

Criando o cenário

A sequencia para renderizar a cena no three.js. Vamos precisar da própria cena, a câmera e o renderizador.


var scene, camera, renderer;
    init();
    animate();
    function init() {

      scene = new THREE.Scene();
      var WIDTH = window.innerWidth,
          HEIGHT = window.innerHeight;

      renderer = new THREE.WebGLRenderer({antialias:true});
      renderer.setSize(WIDTH, HEIGHT);
      document.body.appendChild(renderer.domElement);  
      camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
      camera.position.set(50,150,100);
      scene.add(camera);
      window.addEventListener('resize', function() {
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;
        renderer.setSize(WIDTH, HEIGHT);
        camera.aspect = WIDTH / HEIGHT;
        camera.updateProjectionMatrix();
      });
Primeiro, vamos criar a cena...

scene = new THREE.Scene();
      var WIDTH = window.innerWidth,
          HEIGHT = window.innerHeight;
Em seguida vamos criar o renderizador...

renderer = new THREE.WebGLRenderer({antialias:true});
      renderer.setSize(WIDTH, HEIGHT);
      document.body.appendChild(renderer.domElement);
Three.js também oferece outros motores de renderização além do Web GL que podem ser usados em navegadores mais defasados que não suportam o Web GL. Porém tenha em mente que o Web GL é um dos métodos mais rápidos uma vez que ele usa a sua placa de vídeo.

Para obter o máximo de resolução eu defino o tamanho em window.innerWidth e no window.innerHeight respectivamente. Você pode também cortar calculando as vezes que quer diminuir a resolução por exemplo window.innerHeight/2. O resultado final pode parecer um pouco embaçado quando ampliado. Finally podemos adicionar o elemento renderizador em nosso documento HTML.

Eu defini o antialias (antiserrilhamento) para "true". É "false" por padrão. Ao ativar o antialias obtemos bordas um pouco mais suaves.

O próximo passo é criar a câmera.

Câmera e ação..!! 

Criar a câmera é realmente muito importante, caso contrário não vamos enxergar nada. Three.js oferece maneiras de criar uma câmera em perspectivas ou ortogonal, que pode ser interessante especialmente para animações em 2D. No nosso caso vamos usar a câmera em perspectiva.

Existem algumas configurações que você queira ajustar. A primeira é a configuração do campo de visão. Eu defini o valor para 45º (˜50 mm). O próximo item que devemos definir é a proporção da tela para Width/Height. Geralmente se você definir a proporção da tela de outra maneira pode aparentar esmagado. O próximo está definido para um número muito pequeno e a base para câmera para um número bem elevado. Em seguida vamos definir a posição e adicionar ao nosso cenário. Se desejar aprender mais sobre a câmera do three.js clique aqui. Cole esse código dentro da função init.

       camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
      camera.position.set(50,150,100);
      scene.add(camera);

Atualizar o Viewport sobre o redimensionamento

Vamos adicionar um pequeno trecho de código dentro da function init() para que sempre que o usuário redimensionar a janela de seu navegador a projeção do modelo seja atualizada.

window.addEventListener('resize', function() {
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;
        renderer.setSize(WIDTH, HEIGHT);
        camera.aspect = WIDTH / HEIGHT;
        camera.updateProjectionMatrix();
      });

//more code to come...
}
Adicionando as funcionalidades do OrbitControls

Primeiramente temos que importar os scripts do OrbitControls. Cole o seguinte código depois de invocar o arquivo do three.min.js.

Adicione a linha de código a fim de rotacionar, agarrar or dar zoom dentro do view port. Cole este código dentro da função init() a fim de permitir as interações.

controls = new THREE.OrbitControls(camera, renderer.domElement);

Adicionando a função animate()

A fim de redesenhar a cena conforme rotacionamos a câmera vamos precisar adicionar o seguinte comando. Cole depois de acrescentar nossos controles e fora da função init().

  function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
      controls.update();
    }

Luzes

Agora é a hora de adicionar as luzes no nosso cenário. Considero o ideal iluminar em 3 pontos. Incluíndo a iluminação chave, a luz de fundo e uma luz de contorno para fazer o posicionamento mais facilmente. Eu adicionei uma pequena esfera para indicar onde as luzes irão ficar no espaço 3D. Sua opacidade muda de acordo com a força da luz. Tenha certeza de aplicar cores diferentes, para ter alguma variação na sua iluminação. Insira esse código depois do event listener e dentro da função init(). Os valores das cores nos código define a força dos pontos de luz.

  var light = new THREE.PointLight(0xfffff3, 0.8);
      light.position.set(-100,200,100);
      scene.add(light);

var sphereSize = 1; 
var pointLightHelper = new THREE.PointLightHelper( light, sphereSize ); 
scene.add( pointLightHelper );

      var light2 = new THREE.PointLight(0xd7f0ff, 0.2);
      light2.position.set(200,200,100);
      scene.add(light2);

var sphereSize = 1; 
var pointLightHelper2 = new THREE.PointLightHelper( light2, sphereSize ); 
scene.add( pointLightHelper2 );

var light3 = new THREE.PointLight(0xFFFFFF, 0.5);
      light3.position.set(150,200,-100);
      scene.add(light3);

var sphereSize = 1; 
var pointLightHelper3 = new THREE.PointLightHelper( light3, sphereSize ); 
scene.add( pointLightHelper3 );

Resultado provisório para um cenário básico criado em three.js

Tudo que temos é uma tela branca. Isso porquê se você não aplicar nenhuma cor de fundo específica o fundo será exibido branco como padrão. Futuramente vamos adicionar uma cúpula de céu com gradiente para deixar tudo mais bonito. Ainda não existe um modelo 3D para ser exibido, então vamos adicionar um.


Exportando um modelo Collada 3D do Blender

Primeiro vamos precisar de um modelo 3D que queremos ver. Se você não tiver nenhum fique a vontade para baixar o labirinto http://quaintproject.wordpress.com/download/. Se você estiver usando um modelo 3D próprio, certifique-se que o modelo esteja preparado para um Blender interno ao invés de ciclos. Isso garante que fique muito mais fácil exportar. Selecione o modelo que deseja exportar para o seu cenário. Certifique-se de sempre selecionar a superficie texturizada ao invés de colisão ou spec map. Também verifique se o seu "mapping" no UV-Channel está definido, a não ser que você esteja usando outros métodos de cartografia no lugar do UV-Map. Observe que há várias maneiras de mapear um objeto. Se você não sabe como fazer, assista alguns tutoriais do Blender Cookie.


Selecione o quadro e o mesh pressionando shift+botão direito, agora vamos no menu arquivo em seguida exportar, Collada. O Collada Exporter deve ser ativado em todas as últimas versões do Blender.

Collada é um formato de arquivo desenvolvido pela Khronos Group, assim como o Web GL. O consórcio industrial Khronos Group foi fundado em 2000, teve como objetivo estipular padrões para a área de multimídia. Entre seus famosos membros estão NVIDIA, Google, Apple, Unity 3D, Mozilla entre outros.

Dizem que o instituto Blender contratou um desenvolvedor pago para implementar o Collada Exporter no programa. Esta pode ser a razão por esse exportador ter tantas opções.

Estamos usando um Collada exportador. Você pode também experimentar usar o addon three.js para o Blender. O exportador está incluso na pasta de utilitários do three.js. Se você pretende usar o three.js para Blender, você vai precisar de um importador jason no seu javascript ao invés de Collada. Veja como exportar do Blender para o three.js aqui.


Salve o seu modelo dentro da pasta "models". Podemos chama-lo de dummy1. Isso vai facilitar nosso aprendizado. Claro que você pode escolher diferentes nomes, apenas lembre de mudar o nome escolhido no script a fim de exibir o mesh.

Selecione "Apply Modifiers" e "Selection Only". Logo abaixo em Textures Options escolha "Only Active UV layer", "include UV-Texture e "copy". Salve o arquivo ".dae".



Agora vamos codificar mais um pouco...

Vamos importar o script ColladaLoader, aquele que colocamos na pasta anteriormente. Cole o seguinte comando logo depois do script OrbitControls.

<script src="js/ColladaLoader.js"></script>
Adicione o seguinte código para carregar seu modela Collada incluindo as texturas. Você pode inserir o código depois das lâmpadas.

var loader = new THREE.ColladaLoader();

  loader.options.convertUpAxis = true;

  loader.load( 'models/dummy1.dae', function ( collada ) {
 //dummy1.dae

    var dae = collada.scene;

    var skin = collada.skins[ 0 ];

dae.position.set(0,0,0);//x,z,y- if you think in blender dimensions ;)
dae.scale.set(1.5,1.5,1.5);

scene.add(dae);

});
Atualize seu navegador e você verá algo semelhante a imagem abaixo.



Até o momento vamos ter o seguinte código:

<!--doctype html>


  Test von Web GL
  



  
  


  

    var scene, camera, renderer;

    init();
    animate();

    function init() {

      scene = new THREE.Scene();
      var WIDTH = window.innerWidth,
          HEIGHT = window.innerHeight;

      renderer = new THREE.WebGLRenderer({antialias:true});
      renderer.setSize(WIDTH, HEIGHT);
      document.body.appendChild(renderer.domElement);

      camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
      camera.position.set(50,150,100);
      scene.add(camera);

      window.addEventListener('resize', function() {
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;
        renderer.setSize(WIDTH, HEIGHT);
        camera.aspect = WIDTH / HEIGHT;
        camera.updateProjectionMatrix();
      });

      var light = new THREE.PointLight(0xfffff3, 0.8);
      light.position.set(-100,200,100);
      scene.add(light);

var sphereSize = 1; 
var pointLightHelper = new THREE.PointLightHelper( light, sphereSize ); 
scene.add( pointLightHelper );

      var light2 = new THREE.PointLight(0xd7f0ff, 0.2);
      light2.position.set(200,200,100);
      scene.add(light2);

var sphereSize = 1; 
var pointLightHelper2 = new THREE.PointLightHelper( light2, sphereSize ); 
scene.add( pointLightHelper2 );

var light3 = new THREE.PointLight(0xFFFFFF, 0.5);
      light3.position.set(150,200,-100);
      scene.add(light3);

var sphereSize = 1; 
var pointLightHelper3 = new THREE.PointLightHelper( light3, sphereSize ); 
scene.add( pointLightHelper3 );

  var loader = new THREE.ColladaLoader();

  loader.options.convertUpAxis = true;

  loader.load( 'models/dummy1.dae', function ( collada ) {
 //dummy1.dae

    var dae = collada.scene;

    var skin = collada.skins[ 0 ];

dae.position.set(0,0,0);//x,z,y- if you think in blender dimensions ;)
dae.scale.set(1.5,1.5,1.5);

scene.add(dae);

      });

      controls = new THREE.OrbitControls(camera, renderer.domElement);

    }

    function animate() {

      requestAnimationFrame(animate);

      renderer.render(scene, camera);
      controls.update();

    }

  


-->

Solucionando problemas do three.js

Caso não renderize o modelo conforme o esperado, você pode resolver o problema limpando o histórico, cache e cookies do seu navegador.


Adicionando a grade e os eixos auxiliares no three.js

Adicione o código para a grade e os eixos auxiliares logo após o código do importador Collada. Os eixos auxiliares vai nos ajudar a nos orientar no espaço 3D. Basicamente apenas criamos uma nova variável e definimos o comprimento para 50. A posição dos eixos será definida pelo seu modelo que foi importado. Você pode também usar o arrow helper como alternativa. Depois vamos adicionar uma grade horizontal em nosso cenário. Você pode também adicionar grades verticais mas talvez precisem ficar mais altas. Crie mais uma variável. O tamanho da grade deve ser definido 100 para 10 passos. A posição é definida como centro do mundo. Podemos deixar de fazer essa linha de código, porque por padrão sua grade está posicionada (0/0/0) ao menos que você aplique outra posição.

Há duas cores que precisamos estabelecer. A primeira é para as linhas de grade que cruzam o marco zero. Eu decidi usar o mesmo tom acizentado. Veja o resultado na imagem abaixo.

var axes = new THREE.AxisHelper(50);
 axes.position = dae.position;
 scene.add(axes);

 var gridXZ = new THREE.GridHelper(100, 10);
 gridXZ.setColors( new THREE.Color(0xFFC0CB), new THREE.Color(0x8f8f8f) );
 gridXZ.position.set(0,0,0 );
 scene.add(gridXZ);


Encerro a segunda parte. Em

Qualquer dúvida fique a vontade para deixar um comentário.



Nenhum comentário:

Postar um comentário