Anterior: Hello Node pt, Próximo: Hello Update Loop pt

Neste tutorial nós aprenderemos a carregar modelos 3D e colcoar texto no grafo de cena, usando o Gerenciador de Ativo (Asset Manager) da JME. Você também aprenderá como determinar os caminhos corretos, e quais formatos de arquivo usar.

beginner-assets-models.png

Problema no achar os arquivos para executar a amostra?`jme3-test-data.jar`“““““““

Amostra de Código

package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapText;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;

/** Sample 3 - how to load an OBJ model, and OgreXML model,
 * a material/texture, or text. */
public class HelloAssets extends SimpleApplication {

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

    @Override
    public void simpleInitApp() {

        Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
        Material mat_default = new Material(
            assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
        teapot.setMaterial(mat_default);
        rootNode.attachChild(teapot);

        // Create a wall with a simple texture from test_data
        Box box = new Box(Vector3f.ZERO, 2.5f,2.5f,1.0f);
        Spatial wall = new Geometry("Box", box );
        Material mat_brick = new Material(
            assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat_brick.setTexture("ColorMap",
            assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg"));
        wall.setMaterial(mat_brick);
        wall.setLocalTranslation(2.0f,-2.5f,0.0f);
        rootNode.attachChild(wall);

        // Display a line of text with a default font
        guiNode.detachAllChildren();
        guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
        BitmapText helloText = new BitmapText(guiFont, false);
        helloText.setSize(guiFont.getCharSet().getRenderedSize());
        helloText.setText("Hello World");
        helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
        guiNode.attachChild(helloText);

        // Load a model from test_data (OgreXML + material + texture)
        Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
        ninja.scale(0.05f, 0.05f, 0.05f);
        ninja.rotate(0.0f, -3.0f, 0.0f);
        ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);
        rootNode.attachChild(ninja);
        // You must add a light to make the model visible
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
        rootNode.addLight(sun);

    }
}----
Compile e execute a amostra de código. Você deveria ver um ninja verde com um bule colorido permanecendo atrás de uma parede. O texto na tela deveria dizer Hello World.



== O gerenciador de ativo

*Por ativos de jogo nós queremos dizer todos os arquivos multimídia, tais como modelos, materiais e texturas, cenas inteiras, shaders customizados, música e arquivos de som, e fontes customizadas.* JME3 vem com um objeto AssetManager prático que ajuda você a acessar seus ativos.
O AssetManager pode carregar arquivos de:


*  O classpath atual (o nível do topo de seu diretório de projeto),
*  O diretório `ativos` de seu projeto, e
*  opcionalmente, caminhos persoanlizados que você registrar.

O seguinte é a estrutura de diretório recomendada em seu diretório de projeto:


[source]

MyGame/assets/Interface/ MyGame/assets/MatDefs/ MyGame/assets/Materials/ MyGame/assets/Models/ MyGame/assets/Scenes/ MyGame/assets/Shaders/ MyGame/assets/Sounds/ MyGame/assets/Textures/ MyGame/build.xml ←- Ant build script MyGame/src/…​ ←- Java sources go here MyGame/…​

Isto é apenas um melhor prática sugerida, e é o que você consegue por padrão quando criando um novo projeto Java no <<sdk#,SDK>> da jMokeyEngine. Você pode criar um diretório de ativos e tecnicamente nomear os subdiretórios da maneira que você gostar.



=== Carregando Texturas

Coloque suas texturas em um subdiretório de `assets/Textures/`. Carregue a textura em um material antes que você configure o Material. A seguinte amostra de código é do método `simpleInitApp()` e carrega um modelo de parede simples:


[source,java]

Box box = new Box(Vector3f.ZERO, 2.5f,2.5f,1.0f); Spatial wall = new Geometry("Box", box ); Material mat_brick = new Material( assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); mat_brick.setTexture("ColorMap", assetManager.loadTexture("Textures/Terrain/BrickWall/BrickWall.jpg")); wall.setMaterial(mat_brick); wall.setLocalTranslation(2.0f,-2.5f,0.0f); rootNode.attachChild(wall);

Neste caso, você <<hello_material#,cria seu próprio Material>> e aplica ele para a geometria (Geometry). Você baseia Materiais nas descrições de material padrão (por exemplo, “Unshaded.j3md), como mostrado neste exemplo.



=== Carregando Texto e Fontes

Este exemplo exibe o texto “Hello World na fonte padrão na aresta do fundo da janela. Você anexa texto para o nó da +++<abbr title="Graphical User Interface">GUI</abbr>+++ (`guiNode`) – isto é um nó especial para elementos de exibição plana (ortogonal). Você exibe texto para mostrar a pontuação do jogo, a saúde do jogador, etc.
A seguinte amostra de código vai no método `simpleInitApp()`.


[source,java]
----// Display a line of text with a default font
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
BitmapText helloText = new BitmapText(guiFont, false);
helloText.setSize(guiFont.getCharSet().getRenderedSize());
helloText.setText("Hello World");
helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
guiNode.attachChild(helloText);

Dica: Limpe o texto existente no nó da GUI (guiNode) por retirar todas as suas crianças.

Carregando um modelo

Exporte seu modelo 3D no formato OgreXML (.mesh.xml, .scene, .material, .skeleton.xml) e coloque ele em um subdiretório de assets/Models/. A seguinte amostra de código vai no método simpleInitApp().

// Load a model from test_data (OgreXML + material + texture)
Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
ninja.scale(0.05f, 0.05f, 0.05f);
ninja.rotate(0.0f, -3.0f, 0.0f);
ninja.setLocalTranslation(0.0f, -5.0f, -2.0f);
rootNode.attachChild(ninja);
// You must add a directional light to make the model visible!
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal());
rootNode.addLight(sun);

Note que você precisa criar um Material se você exportou o modelo com um material. Lembre-se de adicionar uma fonte de luz, como mostrado, de outra maneira o material (e o modelo inteiro) não estará visível!

Carregando Ativos de Caminhos Personalizados

E seu jogo dependen de arquivos de modelo fornecidos pelo usuário, que não estão inclusos na distribuição? Se um arquivo não é localizado no local padrão (e.g. diretório de ativos), você pode registrar um localizador (Locator) customizado e carregá-lo de qualquer caminho.

Aqui está um exemplo de uso de um ZipLocator que está registrado para um arquivo town.zip no nível topo de seu diretório de projeto:

    assetManager.registerLocator("town.zip", ZipLocator.class);
    Spatial scene = assetManager.loadModel("main.scene");
    rootNode.attachChild(scene);
Aque está um HttpZipLocator que pode baixar modelos zipados e carregá-los:
    assetManager.registerLocator(
      "http://jmonkeyengine.googlecode.com/files/wildhouse.zip",
      HttpZipLocator.class);
    Spatial scene = assetManager.loadModel("main.scene");
    rootNode.attachChild(scene);

JME3 oferece ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, e UrlLocator (Veja com.jme3.asset.plugins).

Criando Modelos e Cenas

Para criar modelos 3D e cenas, você precisa de um editor de malha 3D (3D Mesh Editor) com um plugin exportador (Exporter) OgreXML. Por exemplo, você pode criar modelos completamente texturizados com Blender.

Você pode usar o SDK para carregar modelos, converter modelos e criar cenas deles.

Se você usar Blender, exporte seus modelos como malhas Ogre XML com materiais como se segue:

  1. Abra o menu Arquivo (File) > Exportar (Export) > Exportador OgreXML (OgreXML Exporter) para abrir o diálogo do exportador.

  2. No campo Exportar Materiais (Export Materials): Dê ao material o mesmo nome que o modelo. Por exemplo, o modelo something.mesh.xml acompanha something.material, mais (opcionalmente) something.skeleton.xml e alguns arquivos de textura JPG.

  3. No campo Exportar Malhas (Export Meshes): Selecione um subdiretório de seu diretório assets/Models/ directory. E.g. assets/Models/something/.

  4. Ative as seguintes configurações do exportador:

    • Copiar Texturas (Copy Textures): YES

    • Renderizar materiais (Rendering Materials): YES

    • Virar Eixos (Flip Axis): YES

    • Requer Materiais (Require Materials): YES

    • Nome do Esqueleto segue o da malha (Skeleton name follows mesh): YES

  5. Clique em exportar.

Formatos de Arquivo de Modelo

JME3 pode carregar modelos Ogre XML + materials, Ogre DotScenes, bem como modelos Wavefront OBJ+MTL models. O código loadModel() trabalha com estes arquivos quando você executa o código diretamente do SDK da jMonkeyEngine SDK.

Se você construir os executáveis usando o scrit de construção padrão, então os arquivos de modelo originais (XML, OBJ, etc) não são inclusos. Quando você executar o executável, você obetrá uma mensagem de erro se você tentar carregar quaisquer modelos diretamente:

----com.jme3.asset.DesktopAssetManager loadAsset
WARNING: Cannot locate resource: Models/Ninja/Ninja.mesh.xml
com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
----
Carregando os arquivos XML/OBJ diretamente é somente aceitável durante a fase de desenvolvimento. Se seus projetista gráfico coloca arquivos atualizados para o diretório de ativos, você pode rapidamente revisar a versão mais recente em seu ambiente de desenvolvimento.

Para teste e para a construção de liberação final, voc~e usa arquivos .j3o exclusivamente. J3o é um formato binário otimizado para aplicações jME3, e arquivos .j3o são automaticamente inclusos no arquivo JAR distribuível pelo script de construção. Quando você faz construções de teste de QA (Quality and Assurance - Averiguação da Qualidade) ou está pronto para liberar, use o SDK para converter todos os arquivos .obj/.scene/.xml/.blend para .j3o, e somente carregue as versões .j3o.

Abra seu Projeto JME3 no SDK da jMonkeyEngine.

  1. Dê um clique com o botão direito em um arquivo .Blend, .OBJ, ou .mesh.xml file na janela Projetos (Projects), e escolha “converter para binário JME3 (“convert to JME3 binary)..

  2. O arquivo .j3o aparece próximo ao arquivo .mesh.xml file e tem o mesmo nome.

  3. Mude todas as linhas do seu loadModel() de acordo. Por exemplo:

    ----Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.j3o");----

Se seu executável dá uma exceção em tempo de execução, tenha certeza de que você converteu todos os modelos para .j3o!

Carregando Modelos e a Cena

tarefa? Solução!

Carregar um modelo com materiais

Use o método loadModel() do gerenciador de ativo (asset manager) e anexe o Spatial para o nó raiz (rootNode).

----Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
rootNode.attachChild(elephant);----
[source,java]
----Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.j3o");
rootNode.attachChild(elephant);----

carregar um modelo sem materiais

Se você tiver um modelo sem materiais, você tem de dár a ele um material para fazê-lo visível.

----Spatial teapot = assetManager.loadModel("Models/Teapot/Teapot.j3o");
Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md"); // default material
teapot.setMaterial(mat);
rootNode.attachChild(teapot);----

Carregar uma cena

Você carrega cenas da mesma forma que você carrega modelos:

----Spatial scene = assetManager.loadModel("Scenes/town/main.scene");
rootNode.attachChild(scene);----
[source,java]
----Spatial scene = assetManager.loadModel("Scenes/town/main.j3o");
rootNode.attachChild(scene);----

Exercício - Como Carregar Ativos

Como um exercício, vamos tentar diferentes maneiras de carregar uma cena. Você aprenderá a como carregar a cena diretamente, ou de um arquivo zip.

  1. baixe a cena de amostra town.zip.

  2. (Opcional:) Dezipe o arquivo town.zip para ver a estrutura da Ogre dotScene contida: Você terá um diretório chamado town. Ele contém arquivos XML e textura, e o arquivo chamado main.scene. (Isto é apenas para sua informação, você não precisa fazer nada com ele.)

  3. Coloque o arquivo town.zip no diretório topo de nível de seu projeto JME3, assim:

    ----jMonkeyProjects/MyGameProject/assets/
    jMonkeyProjects/MyGameProject/build.xml
    jMonkeyProjects/MyGameProject/src/
    jMonkeyProjects/MyGameProject/town.zip
    ...
Use o seguinte método para carregar modelos de um arquivo zip:


.  Verifique se `town.zip` está no diretório do projeto.
.  Registre um localizador de arquivo zip para o diretório do projeto: Adicione o seguinte código sobre `simpleInitApp(){`
[source,java]
----    assetManager.registerLocator("town.zip", ZipLocator.class);
    Spatial gameLevel = assetManager.loadModel("main.scene");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);----
O método loadModel() agora pesquisa pelo arquivo zip diretamente para carregar os arquivos (isto significa, não escreva `loadModel(town.zip/main.scene)` ou similar!)


.  Limpe, construa e execute o projeto. +
Você deveria agora ver o Ninja+parede+bule permanecendo em uma cidade.

*Dica:*  se você registrar novos localizadores, tenha certeza de que você não tenha quaisquer conflitos de nome: Não nomeie todas as cenas `main.scene` mas dê a cada cena um nome único.


Anteriormente neste tutorial, você carregou cenas e modelos do diretório de ativo. Isto é a maneira mais comum que você estará carregando cenas e modelos. Aqui está o procedimento típico:


.  Remova o código que você adicionou para o exercício anterior.
.  Mova o diretório dezipado `town/` no diretório `assets/Scenes/` de seu projeto.
.  Adicione o seguinte código sobre `simpleInitApp() {`
[source,java]
----    Spatial gameLevel = assetManager.loadModel("Scenes/town/main.scene");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);----
 Note que o caminho é relativo ao diretório `assets/…`.


.  Limpe, construa e execute o projeto. De novo, você deveria ver o Ninja+parede+bule em uma cidade.

Aqui está um terceiro método que você deve conhecer, carregando uma cena/modelo de um arquivo .j3o:


.  Remova o código do exercício anterior.
.  Se você j´pa não fez, abra o <<sdk#,SDK>> e abra o projeto que contém a classe HelloAsset..
.  Na janela de projetos, navegue para o diretório `assets/Scenes/town`.
.  Dê um clique com o botão direito em `main.scene` e converta a cena para binário: A jMonkeyPlatform gera um arquivo main.j3o.
.  Adicione o seguinte código em `simpleInitApp() {`
[source,java]
----    Spatial gameLevel = assetManager.loadModel("Scenes/town/main.j3o");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);----
 Novamente, note que o caminho é relativo ao diretório `assets/…` directory.


.  Limpe, construa e execute o projeto. +
De novo, você deveria ver o Ninja+parede+bule em uma cidade.


== Conclusão

Agora você sabe como popular o grafo de cena com modelos e formas estáticas, e como construir cenas. Você aprendeu como carregar ativos usando o `gerenciador de ativos (assetManager)` e você viu que os caminhos iniciam relativos ao seu diretório de projeto. Uma outra coisa importante que você aprendeu é converter modelos para o formato .j3o para os JARs executáveis etc.


Vamos adicionar alguma ação para a cena e continuar com o  <<jme3/beginner/hello_main_event_loop-pt#, Loop de Atualização pt>>!

'''

*See also:*


*  <<jme3/external/blender#,O tutorial de importação Blender definitivo>>
*  link:http://www.jmonkeyengine.com/forum/index.php?topic=14418.0[Instantâneos de um grande modelo carregado]
*  link:http://www.youtube.com/user/aramakara[Video tutoriais for obter OgreXML do 3DS Max usando OgreMax]
*  Se você quer aprender a como carregar sons, veja <<hello_audio_pt#,Hello Audio pt>>
*  Se você quer aprender mais sobre carregar materiais, veja <<hello_material_pt#,Hello Material pt>>
<tags><tag target="beginner" /><tag target="intro" /><tag target="documentation" /><tag target="lightnode" /><tag target="material" /><tag target="model" /><tag target="node" /><tag target="gui" /><tag target="hud" /><tag target="texture" /></tags>