JME 3 入门教程 3 - Hello Assets

前一节:  Hello Node,下一节:  Hello Update Loop

本节教程中,我们将学习如何使用jME asset manager(jME资源管理器)向场景图加载3-D模型和文字,并将了解到如何使用正确的文件格式。

右键点击工程,选择“Properties”,选择“Libraries”,点击“Add Library”,将“jme3-test-data”库添加进去。这样,就可以在接下来的例子中使用其中的资源了。

样例代码

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);

 

    }

}

生成并运行样例代码。你将看到一个绿色的忍者和一个彩色的茶壶,忍者站在墙后。屏幕上的文字是“Hello World”。

Asset Manager资源管理器

JME3有一个很便捷的资源管理器,可以协助你结构化地组织游戏资源。项目中的资源是类似模型、材质、纹理、场景、着色器、声音和字体的媒体文件。资源管理器中的root存储了classpath,因此可以从当前classpath(工程的顶级目录)中加载任意文件。

除此之外,你还可以设置assetManager,在其root中添加任意路径,这样就可以从任意自定义路径中加载资源。在 jMonkeyPlatform工程中,jME3在工程中的assets目录下搜索模型。如下是推荐的一种存储资源的目录结构:

assets/Interface/

assets/MatDefs/

assets/Materials/

assets/Models/

assets/Scenes/

assets/Shaders/

assets/Sounds/

assets/Textures/

build.xml

src/...

dist/...

这只是一个最常见的例子,assets目录下的子目录名可以是任意的。

加载纹理

将纹理放在assets/Textures/的子目录下。先加载纹理,再设置材质。下面是simpleInitApp()方法中的示例代码:

        // 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);

大多数情况下,你可以像本例中一样使用类似“SimpleTextured.j3md”的默认材质。如果是高手,也可以创建自定义材质

加载文字和字体

本例中以默认字体在窗口下方边缘处显示了“Hello Text”。guiNode是一个用于显示平面(正投影)元素的特殊结点,可以把文字附加到guiNode上,这样就能在屏幕上显示该文字。移除guiNode上的孩子结点可以将已存在的文本全部清除。下面是simpleInitApp()方法中的示例代码:

        // 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);

加载Ogre XML 模型

将模型导出为OgreXML格式(包含.mesh.xml,.scene,.material,.skeleton.xml)并将其放在assets/Models/的子目录下。下面是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 light to make the model visible
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
        rootNode.addLight(sun);

如果使用的是 jMonkeyPlatform创建的build script,那么默认状态下,发布的游戏中将不会包含原始的OgreXML文件,加载时就会报错。

com.jme3.asset.DesktopAssetManager loadAsset
WARNING: Cannot locate resource: Scenes/town/main.scene
com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException

如果是release build,你只能使用.j3o文件。jMonkeyPlatform右键菜单中有“OgreXML模型转为.j3o格式”命令。

从自定义路径中加载资源

如果你的游戏依赖于用户提供的模型文件(显然你不可能在发布时把这些模型添加进去),那又该怎么办呢?如果文件不在默认路径下,你可以注册一个自定义Locator(定位器),这样就能从任意路径加载模型文件。

如下是使用ZipLocator的例子,这个ZipLocator已注册了工程顶级目录下的town.zip这个文件:

    assetManager.registerLocator("town.zip", ZipLocator.class.getName());
    Spatial scene = assetManager.loadModel("main.scene");
    rootNode.attachChild(scene);

如下是一个能够下载压缩模型的HttpZipLocator:

    assetManager.registerLocator("http://jmonkeyengine.googlecode.com/files/wildhouse.zip",
                                 HttpZipLocator.class.getName());
    Spatial scene = assetManager.loadModel("main.scene");
    rootNode.attachChild(scene);

JME3 还提供了 ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, 和 UrlLocator (参见com.jme3.asset.plugins)。

创建模型和场景

为了创建3D模型和场景,你需要一款安装了OgreXML Exporter插件的3D模型编辑器,比如Blender。创建模型时,请使用UV纹理。你可以使用jMonkeyPlatform加载模型,并用这些模型创建场景

将模型导出为带材质的Ogre XML模型格式。

  1. 打开菜单File > Export > OgreXML Exporter,弹出导出器(exporter)对话框。
  2. 在导出材质(Export Matertials)栏将材质命名为与模型同样的名称。例如,模型的名称为something.mesh.xml,那么材质的名称就应当是something.material,也许还有something.skeleton.xml以及一些JPG文件。
  3. 在导出模型(Export Meshes)栏,选择您assets/Models/目录下的一个子目录。例如,assets/Models/something/。
  4. 勾选下列导出选项:
  • § Copy Textures: YES
  • § Rendering Materials: YES
  • § Flip Axis: YES
  • § Require Materials: YES
  • § Skeleton name follows mesh: YES
  1. 点击导出(export)。

文件格式:JME3可以加载Ogre XML模型、材质、场景,还能有加载Wavefront OBJ+MTL格式的模型。发布游戏时,您应该把所有的模型转换为JME3的.j3o格式,这样才能优化模型加载过程。我们推荐您使用jMonkeyPlatform创建工程,它集成了一个.j3o转换器。

  1. 在jMonkeyplatform中打开您的JME3工程。
  2. 在Projects(或者Favorites)视图中右击一个.mesh.xml文件,然后选择“convert to JME3 binary”。
  3. .j3o文件将出现在.mesh.xml文件旁边,文件名保持相同。
  4. 如果您使用jMonkeyPlatform生成的build script,那么mesh.xml文件和obj文件将不会包含在可执行JAR文件中。如果您碰到了运行时异常,请确保您已经把所有的模型都转换成了.j3o格式。

加载模型和场景

任务?

解决方案!

加载有材质的模型

使用资源管理器的loadModel() 方法,将这一Spatial附加到rootNode。

Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
rootNode.attachChild(elephant);
Spatial elephant = assetManager.loadModel("Models/Elephant/Elephant.j3o");
rootNode.attachChild(elephant);

加载无材质的模型

如果您有无材质的模型,您应当添加一个默认的材质,以使模型可见。

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

加载场景

您可以像加载模型一样加载场景:

Spatial scene = assetManager.loadModel("Scenes/house/main.scene");
rootNode.attachChild(scene);

练习 - 怎样加载资源

作为练习,不妨尝试一下用不同的方法加载场景。可以直接加载场景,也可以从zip文件中加载:

  1. 下载town.zip示例场景。
  2. (可选:)解压town.zip可以观察到其中的文档结构:您将看到一个名为town文件夹包含了main.scene、XML、纹理等文件。(这里仅仅是介绍一下,您不需要对模型文件做任何操作。)
  3. 将wildhouse.zip放在工程顶级目录,比如这样:

jMonkeyProjects/MyGameProject/assets/

jMonkeyProjects/MyGameProject/build.xml

jMonkeyProjects/MyGameProject/src/

jMonkeyProjects/MyGameProject/town.zip

...

用如下方法从zip文件中加载模型:

  1.  确保town.zip在工程目录中 。
  2. 我们把zip文件定位器注册到工程目录。loadModel() 方法将直接在zip文件中搜索需要加载的文件。
    (也就是说,不要写出town.zip/main.scene这样的路径
  3. simpleInitApp() 中添加如下代码
  4. 清理、生成并运行此工程。您将看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。
assetManager.registerLocator("town.zip", ZipLocator.class.getName());
Spatial gameLevel = assetManager.loadModel("main.scene");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);

如果你注册了一个新的定位器,请确保无文件名冲突:每个场景都有一个独一无二的名字。

在本教程的前面部分,您是从资源目录下加载的模型和场景。这是加载模型和场景的一般方法。如下是一个典型的过程:

  1. 删除前面练习中输入的代码。
  2. 将解压后的 town/ 目录拷贝到 您工程目录下的assets/Scenes/ 。
  3. simpleInitApp() 中添加如下代码
  4. 注意,这些路径都是相对于assets/…目录的
  5. 清理、生成并运行此工程。您将再次看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。
    Spatial gameLevel = assetManager.loadModel("Scenes/town/main.scene");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);

:如下这个方法您一定得知道。从.j3o文件加载场景或模型:

  1. 删除前面练习中输入的代码。
  2. 请打开jMonkeyPlatform,打开包含HelloAsset类的工程。
  3. 在工程窗口中,浏览 assets/Scenes/town目录。
  4. 右击main.scene 将其转换为二进制格式::jMoneyPlatform会生成一个main.j3o文件。
  5. simpleInitApp() 中添加如下代码:
  6. 再次提醒,这些路径都是相对于assets/…目录的。
  7. 清理、生成并运行此工程。您将再次看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。
    Spatial gameLevel = assetManager.loadModel("Scenes/town/main.j3o");
    gameLevel.setLocalTranslation(0, -5.2f, 0);
    gameLevel.setLocalScale(2);
    rootNode.attachChild(gameLevel);

加载Scenes/town/main.j3o 和加载Scenes/town/main.scene有什么不同?

  • 在开发阶段你可以使用*.scene.xml文件:您的设计师会不断更新资源目录下的文件,在开发阶段您能够快速查看最新版本的资源目录。 
  • 在测试和发布阶段,请创建和加载*.j3o 文件:.j3o是jME3应用程序的二进制格式,.j3o文件会自动包含在发布的JAR文件中。测试或者发布时,请使用jMonkeyPlatform把所有的.scene和.xml文件转换成.j3o文件,然后再加载。

小结

您已经知道在场景图中摆放静态形状和模型了,也知道如何创建场景了。您学习了如何使用assetManager来加载资源,知道资源在您工程目录下的存放路径。还有重要的一点就是,您学会了如何把模型转换为.j3o格式,使其包含在发布的JAR文件中。

让我们给场景增添一点“动静”,请继续学习Update Loop


另请参阅:

 

转载于:https://www.cnblogs.com/cybercser/archive/2012/02/03/2337212.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
com.jme3.animation com.jme3.app com.jme3.app.state com.jme3.asset com.jme3.asset.pack com.jme3.asset.plugins com.jme3.audio com.jme3.audio.joal com.jme3.audio.lwjgl com.jme3.audio.plugins com.jme3.bounding com.jme3.bullet com.jme3.bullet.collision com.jme3.bullet.collision.shapes com.jme3.bullet.control com.jme3.bullet.joints com.jme3.bullet.joints.motors com.jme3.bullet.nodes com.jme3.bullet.nodes.infos com.jme3.bullet.util com.jme3.collision com.jme3.collision.bih com.jme3.effect com.jme3.export com.jme3.export.binary com.jme3.export.xml com.jme3.font com.jme3.font.plugins com.jme3.input com.jme3.input.awt com.jme3.input.binding com.jme3.input.dummy com.jme3.input.event com.jme3.input.lwjgl com.jme3.light com.jme3.material com.jme3.material.plugins com.jme3.math com.jme3.niftygui com.jme3.post com.jme3.renderer com.jme3.renderer.jogl com.jme3.renderer.layer com.jme3.renderer.lwjgl com.jme3.renderer.queue com.jme3.scene com.jme3.scene.control com.jme3.scene.debug com.jme3.scene.mesh com.jme3.scene.plugins com.jme3.scene.plugins.ogre com.jme3.scene.shape com.jme3.shader com.jme3.shader.plugins com.jme3.shadow com.jme3.system com.jme3.system.jogl com.jme3.system.lwjgl com.jme3.terrain com.jme3.texture com.jme3.texture.plugins com.jme3.ui com.jme3.util com.jme3.util.xml com.jme3.video com.jme3.video.plugins.jheora jme3game.cubefield jme3test jme3test.app jme3test.asset jme3test.audio jme3test.awt jme3test.bounding jme3test.bullet jme3test.collision jme3test.conversion jme3test.effect jme3test.export jme3test.gui jme3test.light jme3test.material jme3test.math jme3test.model jme3test.model.anim jme3test.model.shape jme3test.niftygui jme3test.post jme3test.scene jme3test.stress jme3test.texture jme3tools.converters jme3tools.converters.model jme3tools.converters.model.strip jme3tools.nvtex jme3tools.optimize jme3tools.preview

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值