= jMonkeyEngine 3 Tutorial (2) - Hello Node
:author: 
:revnumber: 
:revdate: 2016/03/17 20:48
:keywords: beginner, rootNode, node, intro, documentation, color, spatial, geometry, scenegraph, mesh
:relfileprefix: ../../
:imagesdir: ../..
ifdef::env-github,env-browser[:outfilesuffix: .adoc]


Anterior: <<jme3/beginner/hello_simpleapplication_pt#,Hello SimpleApplication pt>>,
Próximo: <<jme3/beginner/hello_asset_pt#,Hello Assets pt>>. 

Neste tutorial nós daremos uma olhada na criação de uma cena 3D.

*  Este tutorial assume que você save o que o <<jme3/the_scene_graph#, grafo de cena>> é. is.
*  Para uma introdução visual, cheque o <<jme3/scenegraph_for_dummies#, Grafo de Cena para Novatos>>.

Quando criando um jogo 3D

.  Você cria alguns objetos como jogadores, edifícios, etc.
.  Você adiciona os objetos para a cena.
.  Você move, redimensiona, rotaciona, colore, e anima eles.

Você aprendera que o grafo de cena representa o mundo 3D, e porque o nó raiz (rootNode) é importante. Você aprenderá como criar objetos simples, como deixá-los transportar dados customizados (como, por exemplo, pontos de saúde), e como “transformá-los por mover, escalonar e rotacionar. Você compreenderá a diferença entre os dois tipos de “Espaciais no grafo de cena: nós (Nodes) e geometrias (Geometries).


== Amostra de código

[source,java]
----
package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Node;

/** Sample 2 - Como usar os nós como agrupamentos para manipular os objetos da cena.
 * Você pode rotacionar, mover, e redimensionar manipulando os nós pai.
 * O nó raiz (rootNode) é especial: Somente o que está ligado ao nó raiz aparece na cena. */

public class HelloNode extends SimpleApplication {

    public static void main(String[] args){
        HelloNode app = new HelloNode();
        app.start();
    }

    @Override
    public void simpleInitApp() {

        /** cria uma caixa azul nas coordenadas (1,-1,1) */
        Box box1 = new Box( Vector3f.ZERO, 1,1,1);
        Geometry blue = new Geometry("Box", box1);
        Material mat1 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        blue.setMaterial(mat1);
        blue.move(1,-1,1);

        /** cria uma caixa vermelha logo acima da caixa azul em (1,3,1) */
        Box box2 = new Box( Vector3f.ZERO, 1,1,1);
        Geometry red = new Geometry("Box", box2);
        Material mat2 = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Red);
        red.setMaterial(mat2);
        red.move(1,3,1);
        
        /** Cria um nó pivô em (0,0,0) e liga ele ao nó raiz(rootNode) */
        Node pivot = new Node("pivot");
        rootNode.attachChild(pivot); // põe este nó na cena

        /** Liga os dois cubos ao nó *pivot*. */
        pivot.attachChild(blue);
        pivot.attachChild(red);
        /** Rotaciona o nó pivô: Veja que ambas as caixas rotacionaram! */
        pivot.rotate(.4f,.4f,0f);
    }
}
----

Construa e execute a amostra de código. Você deveria ver duas caixas coloridas inclinadas no mesmo ângulo.


== Entendendo a Terminologia

Neste tutorial você aprenderá alguns novos termos:
[cols="2", options="header"]
|===

a|O que você quer fazer 
a| Como você diz isso na terminologia JME3

a|Colocar a disposição da cena 3D 
a| Popular o grafo de cena

a|Criar objetos da cena 
a| Criar espaciais (Spatials) (e.g. criar geometrias (Geometries) )

a|Fazer um objeto aparecer na cena 
a| Anexar um espacial (Spatial) para o nó raiz rootNode

a|Fazer um objeto desaparecer da cena 
a| Retirar um espacial (Spatial) do nó raiz rootNode

a|Posicionar/mover, virar, ou redimensionar um objeto 
a| Transladar, ou rotacionar, ou escalar um objeto = transformar um objeto

|===

Toda aplicação JME3 tem um nó raiz (rootNode): Seu jogo automaticamente herda o objeto `rootNode` de SimpleApplication. Tudo anexado ao nó raiz (rootNode) é parte do grafo de cena. Os elementos do grafo de cena são os espaciais (Spatials).

*  Um Spatial contém a localização, rotação e escala de um objeto.
*  Um Spatial pode ser carregado, transformado, e salvo.
*  Há dois tipos de Spatials: nós (Nodes) e geometrias (Geometries).
[cols="3", options="header"]
|===

<a|  
a| Geometria (Geometry) 
a| Nó (Node) 

a| Visibilidade: 
a| Uma geometria (Geometry) é um objeto de cena visível 
a| Um nó (Node) é uma “alavanca invisível para objetos da cena. 

a| Propósito: 
a| Uma geometria (Geometry) armazena a aparência de um objeto. 
a| Um nó (Node) agrupa geometrias (Geometries) e outros nós (Nodes) juntos. 

a| Exemplos: 
a| Uma caixa, uma esfera, um jogador, um edifício, um pedaço de terreno, um veículo, mísseis, NPCs, etc… 
a| O `nó raiz (rootNode)`, um nó de chão agrupando vários terrenos, um nó veículo-com-passageiros customizado, um nó jogador-com-arma, um nó de aúdio, etc… 

|===


== Entendendo o Código

O que acontece no trecho de código? Você usa o método `simpleInitApp()` que foi introduzido no primeiro tutorial para inicializar a cena.

.  Você cria a primeira geometria caixa.
**  Crie uma forma caixa (Box) com extensões de (1,1,1), isto faz a caixa 2x2x2 unidades do mundo grande.
**  Posicione a caixa em (1,-1,1) usando o método move() method. (Não mude o Vector3f.ZERO a menos que você queira mudar o centro de rotação)
**  Envolva a forma caixa (Box) em uma geometria (Geometry).
**  Crie um material azul
**  Aplique o material azul para a geometria da caixa (Box Geometry). 
[source,java]
----

    Box box1 = new Box( Vector3f.ZERO, 1,1,1);
    Geometry blue = new Geometry("Box", box1);
    Material mat1 = new Material(assetManager,
      "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", ColorRGBA.Blue);
    blue.setMaterial(mat1);
    blue.move(1,-1,1);
----


.  Você cria uma segunda geometria (Geometry) de caixa.
**  Crie uma segunda forma caixa (Box) com o mesmo tamanho.
**  Posicione a segunda caixa em (1,3,1). Isto é imediatamente acima da primeira caixa, com uma lacuna de 2 unidades do mundo entre elas.
**  Envolva a forma caixa (Box) em uma geometria (Geometry).
**  Crie um material vermelho
**  Aplique o material vermelho para a geometria caixa (Box Geometry). 
[source,java]
----

    Box box2 = new Box( Vector3f.ZERO, 1,1,1);
    Geometry red = new Geometry("Box", box2);
    Material mat2 = new Material(assetManager,
      "Common/MatDefs/Misc/Unshaded.j3md");
    mat2.setColor("Color", ColorRGBA.Red);
    red.setMaterial(mat2);
    red.move(1,3,1);
----


.  Você cria um nó (Node) pivô. 
**  Nomeie o nó “pivot.
**  Por padrão o nó (Node) é posicionado em (0,0,0).
**  Anexe o nó (Node) ao nó raiz (rootNode).
**  O nó (Node) não tem aparência visível na cena. 
[source,java]
----

    Node pivot = new Node("pivot");
    rootNode.attachChild(pivot);
----

Se você executar a aplicação somente com o código dado até aqui, a cena parece vazia. Isto é porque o nó (Node) está invisível, e você não tem ainda anexado quaisquer geometrias (Geometries) visíveis para o nó raiz (rootNode).. 


.  Anexe as duas caixas para o nó pivô 
[source,java]
----

        pivot.attachChild(blue);
        pivot.attachChild(red);
----

Se você executar o aplicativo com somente o código dado até aqui, você vê dois cubos: Um vermelho imediatamente acima de um azul.

.  Rotacione o nó pivô.
[source,java]
----
        pivot.rotate( 0.4f , 0.4f , 0.0f );
----

 Se você executar o aplicativo agora, você verá duas caixas uma no topo da outra - ambas inclinadas no mesmo ângulo.



=== O que é um nó pivô (Pivot Node)?

Você pode transformar (e.g. rotacionar) geometrias (Geometries) ao redor do próprio centro delas, ou ao redor de um ponto central definido pelo usuário. Um ponto central definido pelo usuário para um ou mais geometrias (Geometries) é chamado pivô.

*  Neste exemplo, você agrupou duas geometrias (Geometries) por anexá-las para um nó pivô (Node). Você vê o nó (Node) pivô como um instrumento para rotacionar as duas geometrias (Geometries) ao mesmo tempo ao redor de um centro em comum. Rotacionar o nó (Node) pivô rotaciona todas as geometrias (Geometries) anexadas, de uma única vez. O nó pivô é o centro da rotação. Antes de anexar as outras geometrias (Geometries), tenha certeza que o nó pivô está em (0,0,0). Transformar um nó (Node) pai para transformar todas as crianças espaciais (Spatials) anexadas é uma tarefa comum. Você usará este método muito em seus jogos quando você mover espaciais (Spatials).

Exemplos: Um veículo e seu motorista movem juntos; um planeta com sua lua orbitam o sol.

*  Contraste este caso com a outra opção: Se você não criar um nó pivô extra e transformar uma geometria (Geometry), então toda transformação é feita relativa a origem da geometria (Geometry) (tipicamente o centro dela). +*Exemplos:*  Se você rotacionar cada cubo diretamente (usando `red.rotate(0.1f , 0.2f , 0.3f);` e `blue.rotate(0.5f , 0.0f , 0.25f);`), então cada cubo é rotacionado individualmente ao redor do seu centro. Isto é similar a um planeta rotacionando ao redor de seu próprio centro.


== Como eu Populo o Grafo de Cena?
[cols="2", options="header"]
|===

a| Tarefa…? 
a| Solução! 

a| Crie um espacial (Spatial) 
a| Crie uma forma malha (Mesh), envolva ela em uma geometria (Geometry), e dê a ela um Material. Por exemplo: 
[source,java]
----
Box mesh = new Box(Vector3f.ZERO, 1, 1, 1); // a cuboid default mesh
Geometry thing = new Geometry("thing", mesh); 
Material mat = new Material(assetManager,
   "Common/MatDefs/Misc/ShowNormals.j3md");
thing.setMaterial(mat);
----


a| Faça um objeto aparecer na cena 
a| Anexe o espacial (Spatial) para o `nó raiz (rootNode)`, ou para qualquer no que esteja anexado para o nó raiz (rootNode). 
[source,java]
----
rootNode.attachChild(thing);
----


a| Remova objetos da cena 
a| Retire o nó espacial (Spatial) do `nó raiz (rootNode)`, e de qualquer nó que esteja vinculado ao nó raiz (rootNode). 
[source,java]
----
rootNode.detachChild(thing);
----

[source,java]
----
rootNode.detachAllChildren();
----


a| Ache um nó espacial na cena pelo nome do objeto, ou ID, ou por sua posição na hierarquia pai-criança. 
a| Olhe na criança ou pai do nó:  
[source,java]
----
Spatial thing = rootNode.getChild("thing");
----

[source,java]
----
Spatial twentyThird = rootNode.getChild(22);
----

[source,java]
----
Spatial parent = myNode.getParent();
----


a| Especifique o que deveria ser carregado no início 
a| Tudo que você inicializa e anexa ao `nó raiz (rootNode)` no método `simpleInitApp()` é parte da cena no início do jogo. 

|===


== Como eu transformo espaciais (Spatials)?

Há três tipos de transformação 3D: Translação, Escalonamento, e Rotação.
[cols="4", options="header"]
|===

a| Translação move espaciais (Spatials ) 
a| eixo X-
a| eixo Y 
a| eixo Z 

a|
a|
a|
a|

|===

Para mover um espacial (Spatial) para coordenadas específicas, tais como (0,40.2f,-2), use:  

[source,java]
----
thing.setLocalTranslation( new Vector3f( 0.0f, 40.2f, -2.0f ) );
----

 Para mover um espacial (Spatial) por uma certa quantia, e.g. mais acima (y=40.2f) e mais atrás (z=-2.0f): 

[source,java]
----
thing.move( 0.0f, 40.2f, -2.0f );
----

 |+right -left|+up -down|+forward -backward|
[cols="4", options="header"]
|===

a| Escalonamento redimensiona espaciais (Spatials) 
a| eixo X-
a| eixo Y 
a| eixo Z 

a|Especifique o fator de escalonamento em cada dimensão: tamanho, altura, comprimento. + um valor entre 0.0f e 1.0f diminue o espacial (Spatial); maior que 1.0f estica ele; 1.0f mantém ele o mesmo. + Usando o mesmo valor para cada dimensão escalona proporcionalmente, valor diferentes esticam ele. + Para escalonar um espacial (Spatial) 10 vezes mais longo, um décimo da altura, e manter o mesmo comprimento:  
[source,java]
----
thing.scale( 10.0f, 0.1f, 1.0f );
----

a|length
a|height
a|width

|===
[cols="4", options="header"]
|===

a| Rotação gira espaciais (Spatials) 
a| eixo X-
a| eixo Y 
a| eixo Z 

a|Rotação 3-D é um pouco complicado (<<jme3/rotate#,aprenda os detalhes aqui>>)). em breve: Você pode rotacionar ao redor de três eixos: Pitch (X), yaw (Y), e roll (Z). Você pode especificar ângulos em graus por multiplicar o valor de graus com `FastMath.DEG_TO_RAD`. + Para rolar um objeto 180° ao redor do z axis: : 
[source,java]
----
thing.rotate( 0f , 0f , 180*FastMath.DEG_TO_RAD );
----

 Tip: Dica: Se sua idéia de jogo pede uma quantidade séria de rotações, é merecedor dar uma olhada em <<jme3/quaternion#,quaternion>>s, uma estrutura de dado que pode combinar e armazenar rotações eficientemente. 

[source,java]
----
thing.setLocalRotation( 
  new Quaternion().fromAngleAxis(180*FastMath.DEG_TO_RAD, new Vector3f(1,0,0)));
----

a|pitch = fazer um sinal de sim com sua cabeça
a|yaw = agitar sua cabeça
a|roll = inclinar sua cabeça

|===


== Como eu Resolvo Problemas com espaciais (Spatials)?

Se você obtém resultados inesperados, cheque se você fez os seguintes enganos frequentes:
[cols="2", options="header"]
|===

a| Problema? 
a| Solução! 

a| Geometria (Geometry) criada não aparece na cena. 
a| Você anexou ela a (um nó que está vinculado a) o nó raiz (rootNode)? + Ela tem um Material? + Qual é sua translação (posição)? Ela está atrás da câmera ou coberta por uma outra geometria (Geometry)? + Ela é tão minúscula ou tão gigante para ver? + Ela está tão distante da câmera? (Tente link:http://jmonkeyengine.org/javadoc/com/jme3/renderer/Camera.html#setFrustumFar%28float%29[cam.setFrustumFar](111111f); para ver mais distante) 

a| Um espacial (Spatial) rotaciona em maneiras inesperadas. 
a| Você usou os valores em radianos, e não em graus? (Se você usou graus, multiplique eles com FastMath.DEG_TO_RAD para convertê-los para radianos) + Você criou o espacial (Spatial) na origem (Vector.ZERO) antes de movê-lo? + Você rotacionou ao redor do nó pivô ou ao redor de algo mais? + Você rotacionou ao redor do eixo certo? 

a| Uma geometria (Geometry) tem cor (Color) ou Material inepserado. 
<a| Você reusou um Material de uma outra geometria (Geometry) e tem inadvertidamente mudado suas propriedades? (Se sim, considere cloná-lo: mat2 = mat.clone(); )  

|===


== Como eu Adiciono um Dado Customizado para espaciais (Spatials)?

Muitos espaciais (Spatials) representam personagens ou outras entidades que o jogador pode interagir. O código acima que rotaciona as duas caixas ao redor de um centro em comum (pivô) poderia ser usado para uma espaçonave estacionada em uma estação espacial orbital, por exemplo.

Dependendo do seu jogo, entidades de jogo não somente mudam a posição delas, rotação ou escala (as transformações que você aprendeu). Entidades de jogo também têm propriedades personalizadas, como saúde, inventário carregado, equipamento usado para um personagem, ou força do casco e combustível restante para uma aeronave. Em Java, você representa dados de entidade como variáveis de classe, e.g. floats, Strings, ou Arrays.

Você pode adicionar dados personalizados diretamente para qualquer nó (Node) ou geometria (Geometry). * Você não precisa estender a classe nó (Node) para incluir variáveis! *

Por exemplo, para adicionar um número de id customizado para um nó, você usaria:

[source,java]
----
pivot.setUserData( "pivot id", 42 );
----

Para ler o id do nó (Node) em outro lugar, você usaria:

[source,java]
----
int id = pivot.getUserData( "pivot id" ); 
----

Por usar diferentes chaves de Strings (aqui a chave é o `id do pivô`), você pode recuperar e configurar vários valores para quaisquer dados que o espacial (Spatial) precisa carregar. Quando você iniciar a escrever seu jogo, você talvez adicione um valor de combustível para um nó carro, valor de velocidade para um nó avião, ou número de moedas douradas para um nó jogador, e muito mais. Entretanto, deve-se notar que somente objetos customizados que implementam Savable podem ser passados.


== Conclusão

Você aprenderu que sua cena 3D é um grafo de cena composto de espaciais (Spatials): Geometrias (Geometries) visíveis e nós (Nodes) invisíveis. Você pode transformar espaciais (Spatials), ou anexá-los a nós e transformar os nós. Você sabe a maneira mais fácil de como adicionar propriedades de entidade customizadas (tais como a saúde do jogador ou a velocidade do veículo) para espaciais (Spatials).

Desde que formas padrões como esferas e caixas ficam velhas rápido, continue com o próximo capítulo onde você aprenderá a <<jme3/beginner/hello_asset#, carregar ativos, como por exemplo, modelos 3-D>>.
