JME 3 入门教程 3 | 您所在的位置:网站首页 › jme游戏 › JME 3 入门教程 3 |
前一节: 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模型格式。 打开菜单File > Export > OgreXML Exporter,弹出导出器(exporter)对话框。 在导出材质(Export Matertials)栏将材质命名为与模型同样的名称。例如,模型的名称为something.mesh.xml,那么材质的名称就应当是something.material,也许还有something.skeleton.xml以及一些JPG文件。 在导出模型(Export Meshes)栏,选择您assets/Models/目录下的一个子目录。例如,assets/Models/something/。 勾选下列导出选项: § Copy Textures: YES § Rendering Materials: YES § Flip Axis: YES § Require Materials: YES § Skeleton name follows mesh: YES 点击导出(export)。文件格式:JME3可以加载Ogre XML模型、材质、场景,还能有加载Wavefront OBJ+MTL格式的模型。发布游戏时,您应该把所有的模型转换为JME3的.j3o格式,这样才能优化模型加载过程。我们推荐您使用jMonkeyPlatform创建工程,它集成了一个.j3o转换器。 在jMonkeyplatform中打开您的JME3工程。 在Projects(或者Favorites)视图中右击一个.mesh.xml文件,然后选择“convert to JME3 binary”。 .j3o文件将出现在.mesh.xml文件旁边,文件名保持相同。 如果您使用jMonkeyPlatform生成的build script,那么mesh.xml文件和obj文件将不会包含在可执行JAR文件中。如果您碰到了运行时异常,请确保您已经把所有的模型都转换成了.j3o格式。 加载模型和场景任务? 解决方案! 加载有材质的模型 使用资源管理器的loadModel() 方法,将这一Spatial附加到rootNode。 Spatial elephant = assetManager.loadModel("Models/Elephant/Elephansh.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文件中加载: 下载town.zip示例场景。 (可选:)解压town.zip可以观察到其中的文档结构:您将看到一个名为town文件夹,包含了main.scene、XML、纹理等文件。(这里仅仅是介绍一下,您不需要对模型文件做任何操作。) 将wildhouse.zip放在工程顶级目录,比如这样:jMonkeyProjects/MyGameProject/assets/ jMonkeyProjects/MyGameProject/build.xml jMonkeyProjects/MyGameProject/src/ jMonkeyProjects/MyGameProject/town.zip ... 用如下方法从zip文件中加载模型: 确保town.zip在工程目录中 。 我们把zip文件定位器注册到工程目录。loadModel() 方法将直接在zip文件中搜索需要加载的文件。 (也就是说,不要写出town.zip/main.scene这样的路径) 在simpleInitApp() 中添加如下代码 清理、生成并运行此工程。您将看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。 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);如果你注册了一个新的定位器,请确保无文件名冲突:每个场景都有一个独一无二的名字。 在本教程的前面部分,您是从资源目录下加载的模型和场景。这是加载模型和场景的一般方法。如下是一个典型的过程: 删除前面练习中输入的代码。 将解压后的 town/ 目录拷贝到 您工程目录下的assets/Scenes/ 。 在simpleInitApp() 中添加如下代码: 注意,这些路径都是相对于assets/…目录的。 清理、生成并运行此工程。您将再次看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。 Spatial gameLevel = assetManager.loadModel("Scenes/town/main.scene"); gameLevel.setLocalTranslation(0, -5.2f, 0); gameLevel.setLocalScale(2); rootNode.attachChild(gameLevel);:如下这个方法您一定得知道。从.j3o文件加载场景或模型: 删除前面练习中输入的代码。 请打开jMonkeyPlatform,打开包含HelloAsset类的工程。 在工程窗口中,浏览 assets/Scenes/town目录。 右击main.scene 将其转换为二进制格式::jMoneyPlatform会生成一个main.j3o文件。 在simpleInitApp() 中添加如下代码: 再次提醒,这些路径都是相对于assets/…目录的。 清理、生成并运行此工程。您将再次看到小镇里树立着一堵墙,上面有一个水壶,墙后是一个忍者。 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。 另请参阅: 将Blender中的Ogre XML格式的场景导出到JME 一个很棒的加载模型的截图 欲了解如何加载声音,请参阅Hello Audio 欲进一步了解纹理和材质,请参阅Hello Material
|
CopyRight 2018-2019 实验室设备网 版权所有 |