第二十一章:资产配置文件

jME3允许开发者通过资产配置文件(AssetConfig)来管理 AssetLocator 和 AssetLoader 。本文将介绍 AssetConfig 的格式及用法。

繁琐的代码

第一章:多媒体资产管道 中列出了 jME3 支持的各种资产文件格式,每种格式都有对应的 AssetLoader 来进行解析。根据前几章的介绍,如果想让 AssetManager 能够加载这些文件,需要先调用 registerLoader 方法配置加载器。

下面的代码演示了如何配置这些 AssetLoader。 注意,有些文件在PC和Android系统中需要使用不同的类来加载。

package net.jmecn.assets;

import com.jme3.asset.AssetManager;
import com.jme3.asset.plugins.AndroidLocator;
import com.jme3.asset.plugins.ClasspathLocator;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.audio.plugins.NativeVorbisLoader;
import com.jme3.audio.plugins.OGGLoader;
import com.jme3.audio.plugins.WAVLoader;
import com.jme3.cursors.plugins.CursorLoader;
import com.jme3.export.binary.BinaryLoader;
import com.jme3.font.plugins.BitmapFontLoader;
import com.jme3.material.plugins.J3MLoader;
import com.jme3.scene.plugins.MTLLoader;
import com.jme3.scene.plugins.OBJLoader;
import com.jme3.scene.plugins.blender.BlenderLoader;
import com.jme3.scene.plugins.fbx.FbxLoader;
import com.jme3.scene.plugins.gltf.BinLoader;
import com.jme3.scene.plugins.gltf.GlbLoader;
import com.jme3.scene.plugins.gltf.GltfLoader;
import com.jme3.scene.plugins.ogre.MaterialLoader;
import com.jme3.scene.plugins.ogre.MeshLoader;
import com.jme3.scene.plugins.ogre.SceneLoader;
import com.jme3.scene.plugins.ogre.SkeletonLoader;
import com.jme3.shader.plugins.GLSLLoader;
import com.jme3.system.JmeSystem;
import com.jme3.texture.plugins.AWTLoader;
import com.jme3.texture.plugins.AndroidNativeImageLoader;
import com.jme3.texture.plugins.DDSLoader;
import com.jme3.texture.plugins.HDRLoader;
import com.jme3.texture.plugins.TGALoader;

public class TestAssetConfig {

    public static void main(String[] args) {

        AssetManager assetManager = JmeSystem.newAssetManager();

        /**
         * 注册资产定位器
         */
        assetManager.registerLocator("assets", FileLocator.class);
        assetManager.registerLocator("/", ClasspathLocator.class);
        // Android系统应该使用下面的定位器,依赖 jme3-android-{version}.jar
        // assetManager.registerLocator("/", AndroidLocator.class);

        /**
         * 注册资产加载器
         */
        
        /* 模型&材质 */
        assetManager.registerLoader(BinaryLoader.class, "j3o");
        assetManager.registerLoader(J3MLoader.class, "j3m");
        assetManager.registerLoader(J3MLoader.class, "j3md");
        
        assetManager.registerLoader(OBJLoader.class, "obj");
        assetManager.registerLoader(MTLLoader.class, "mtl");
        
        // Blender 格式,依赖jme3-blender-{version}.jar。{version} >= 3.0
        assetManager.registerLoader(BlenderLoader.class, "blend");
        // Orge 格式,依赖jme3-plugins-{version}.jar。 {version} >= 3.0
        assetManager.registerLoader(MeshLoader.class, "meshxml", "mesh.xml");
        assetManager.registerLoader(SkeletonLoader.class, "skeletonxml", "skeleton.xml");
        assetManager.registerLoader(MaterialLoader.class, "material");
        assetManager.registerLoader(SceneLoader.class, "scene");
        // FBX 格式,依赖 jme3-plugins-{version}.jar。{version} >= 3.1.0-stable
        assetManager.registerLoader(FbxLoader.class, "fbx");
        // glTF 格式,依赖jme3-plugins-{version}.jar。 {version} >= 3.2.0-stable
        assetManager.registerLoader(GltfLoader.class, "gltf");
        assetManager.registerLoader(BinLoader.class, "bin");
        assetManager.registerLoader(GlbLoader.class, "glb");
        
        /* 着色器 */
        assetManager.registerLoader(GLSLLoader.class, "vert", "frag", "geom", "tsctrl", "tseval", "glsl", "glsllib");
        
        /* 音频文件 */
        assetManager.registerLoader(WAVLoader.class, "wav");
        // Ogg格式,依赖jme3-jogg-{version}.jar。{version} >= 3.0
        assetManager.registerLoader(OGGLoader.class, "ogg");
        // Android系统,依赖jme3-android-{version.jar}。{version} >= 3.0
        // assetManager.registerLoader(NativeVorbisLoader.class, "ogg");
        
        /* 图片文件 */
        assetManager.registerLoader(TGALoader.class, "tga");
        assetManager.registerLoader(DDSLoader.class, "dds");
        assetManager.registerLoader(HDRLoader.class, "hdr");
        // java.awt 只在桌面平台有效,依赖 jme3-desktop-{version}.jar。{version} >= 3.0
        assetManager.registerLoader(AWTLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
        // Android 系统与桌面不同,依赖 jme3-android-{version}.jar。{version} >= 3.0
        // assetManager.registerLoader(AndroidNativeImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
        
        /* 鼠标光标 */
        // 鼠标只有桌面平台有效,依赖 jme3-desktop-{version}.jar。{version} >= 3.0
        assetManager.registerLoader(CursorLoader.class, "ico", "ani", "cur");
        
        /* 字体 */
        assetManager.registerLoader(BitmapFontLoader.class, "fnt");
    }

}

默认资产配置

上面的代码非常繁琐,jME3允许开发者通过资产配置文件(AssetConfig)来管理 AssetLocatorAssetLoader

下面是 jme3-core.jar 中内置的“通用资产配置” General.cfg

# Generic locators that should be supported on all platforms.
LOCATOR / com.jme3.asset.plugins.ClasspathLocator

# Generic loaders that should be supported on all platforms.
LOADER com.jme3.audio.plugins.WAVLoader : wav
LOADER com.jme3.cursors.plugins.CursorLoader : ani, cur, ico
LOADER com.jme3.material.plugins.J3MLoader : j3m
LOADER com.jme3.material.plugins.J3MLoader : j3md
LOADER com.jme3.material.plugins.ShaderNodeDefinitionLoader : j3sn
LOADER com.jme3.font.plugins.BitmapFontLoader : fnt
LOADER com.jme3.texture.plugins.DDSLoader : dds
LOADER com.jme3.texture.plugins.PFMLoader : pfm
LOADER com.jme3.texture.plugins.HDRLoader : hdr
LOADER com.jme3.texture.plugins.TGALoader : tga
LOADER com.jme3.export.binary.BinaryLoader : j3o
LOADER com.jme3.export.binary.BinaryLoader : j3f
LOADER com.jme3.scene.plugins.OBJLoader : obj
LOADER com.jme3.scene.plugins.MTLLoader : mtl
LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml
LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml
LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
LOADER com.jme3.scene.plugins.blender.BlenderLoader : blend
LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, geom, tsctrl, tseval, glsl, glsllib
LOADER com.jme3.scene.plugins.fbx.FbxLoader : fbx
LOADER com.jme3.scene.plugins.gltf.GltfLoader : gltf
LOADER com.jme3.scene.plugins.gltf.BinLoader : bin
LOADER com.jme3.scene.plugins.gltf.GlbLoader : glb

PC 和 Android 由于各自系统的特点,分别有不同的配置。

Desktop.cfg:

INCLUDE com/jme3/asset/General.cfg

# Desktop-specific loaders
LOADER com.jme3.texture.plugins.AWTLoader : jpg, bmp, gif, png, jpeg
LOADER com.jme3.audio.plugins.OGGLoader : ogg

Android.cfg:

INCLUDE com/jme3/asset/General.cfg

# Android specific locators
LOCATOR / com.jme3.asset.plugins.AndroidLocator

# Android specific loaders
LOADER com.jme3.texture.plugins.AndroidNativeImageLoader : jpg, bmp, gif, png, jpeg
LOADER com.jme3.audio.plugins.NativeVorbisLoader : ogg

jME3 应用程序启动时会自动读取上述的配置文件,因此开发者才可以直接使用 AssetManager 来加载各种资产。

配置文件的语法

基本规则:

  • AssetConfig 文件是纯文本文件,后缀名为 .cfg
  • 文件逐行解析,每行执行一条命令;
  • 空行将被忽略;
  • 文件中的字符串不需要引号;

注释

语法:# {contentx}

说明:井号开头的行是注释,解析时将会被忽略。

例子:# Desktop specific loaders

包含

语法:INCLUDE {url}

说明:包含另一个配置文件,{url} 是该文件的路径。

例子:INCLUDE com/jme3/asset/General.cfg

注意,INCLUDE 命令并不需要写在开头,它可以出现在文件中的任意位置。

注册定位器

语法:LOCATOR {rootPath} {AssetLocatorClass}

说明:注册一个资产定位器。 {rootPath} 表示资产根目录,{AssetLocatorClass} 表示对应 AssetLoader 类的全名。

这一行等同于执行下列语句:

assetManager.registerLocator("{rootPath}", {AssetLocatorClass});

例子:LOCATOR / com.jme3.asset.plugins.ClasspathLocator

注册加载器

语法:

  • LOADER {AssetLoaderClass} : {ext}
  • LOADER {AssetLoaderClass} : {ext1}, {ext2}, {ext3}

说明:注册一个资产加载器。{AssetLoaderClass} 表示对应 AssetLoader 类的全名,{ext} 表示文件后缀名;多个后缀名之间用逗号 (,) 隔开。

这一行等同于执行下一行语句:

assetManager.registerLoader({AssetLoaderClass}, {ext});

或:

assetManager.registerLoader({AssetLoaderClass}, {ext1}, {ext2}, {ext3});

例子:

  • LOADER com.jme3.export.binary.BinaryLoader : j3o
  • LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag, geom, tsctrl, tseval, glsl, glsllib

自定义配置文件

在工程的 net.jmecn.assets 包中创建 MyAssetConfig.cfg 文件,内容如下:

# 配置AssetLocator
LOCATOR sevenzipjbinding-9.20-2.00beta-AllWindows.zip net.jmecn.assets.SevenZAssetLocator

# 配置AssetLoader
LOADER net.jmecn.assets.TextLoader : txt

# 包含内置桌面配置文件
INCLUDE com/jme3/asset/Desktop.cfg

这个配置文件使用了前几章开发的 SevenZAssetLocatorTextLoader 类,并包含了 jME3 系统自带的 Desktop.cfg

独立使用

下面演示如何通过配置文件来创建 AssetManager 。

代码如下:

package net.jmecn.assets;

import java.net.URL;

import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetManager;
import com.jme3.system.JmeSystem;

/**
 * 测试自定义配置文件
 * @author yanmaoyuan
 *
 */
public class TestCustomConfig {
    public static void main(String[] args) {
        // 获得配置文件的URL
        URL url = TestCustomConfig.class.getResource("net/jmecn/assets/MyAssetConfig.cfg");
        // 使用URL来创建AssetManager
        AssetManager assetManager = JmeSystem.newAssetManager(url);//<--- 注意这里
        
        String str = assetManager.loadAsset(new AssetKey<String>("sevenzipjbinding-9.20-2.00beta-AllWindows/ReleaseNotes.txt"));
        System.out.println(str);
    }
}

关键代码就一行: JmeSystem.newAssetManager(url)

运行结果如下:

一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.MeshLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.SkeletonLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.MaterialLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.SceneLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.blender.BlenderModelLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.fbx.FbxLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.GltfLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.BinLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.GlbLoader
一月 15, 2018 12:15:16 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.audio.plugins.OGGLoader
7-Zip-JBinding Release Notes
============================

Main features of 9.20-2.00beta (Release candidate, extraction/compression/update, cross-platform, based on zip/p7zip 9.20)

    * Extraction of
        - 7z, Arj, BZip2, Cab, Chm, Cpio, Deb, GZip, HFS, Iso, Lzh,
          Lzma, Nsis, Rar, Rpm, Split, Tar, Udf, Wim, Xar, Z, Zip

        - Archive format auto detection
        - Support for password protected and volumed archives
        - Simple extraction interface

    * Compression & update of
        - 7z, Zip, Tar, GZip, BZip2
        - Archive format specific or generic compression API
        
        * 7-Zip-JBinding requires Java 1.5 or higher

        * Cross-platform. Binaries available for
            - Windows 32/64
            - Linux 32/64
            - Mac OS X 32/64
            - ARM (ASMv4+, small endian)

        * Multi-platform distributions (with platform auto-detection):
            - AllWindows - includes Win32 and Win64
            - AllLinux - includes Linux32 and Linux64 (ARM not included)
            - AllMax - includes Mac OS X 32 and Mac OS X 64
            - AllPlatforms - includes AllWindows, AllLinux and AllMac + build optimized for RaspberryPI

    * JavaDoc + Snippets (see documentation on the web: sevenzipjbind.sf.net)

        * Over 6900 JUnit tests:
            - 7z, Zip, Tar, Rar, Lzma, Iso, GZip, Cpio, BZIP2,
              Z, Arj, Lzh, Cab, Chm, Nsis, DEB, RPM, UDF

    * Available on the Maven Central (a week after the official release)
        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding</artifactId>
            <version>9.20-2.00beta</version>
        </dependency>
        <dependency>
            <groupId>net.sf.sevenzipjbinding</groupId>
            <artifactId>sevenzipjbinding-all-platforms</artifactId>
            <version>9.20-2.00beta</version>
        </dependency>

可以看到,ReleaseNodes.txt 的内容被打印出来了,但正文的前面部分有很多警告信息。

一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.MeshLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.SkeletonLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.MaterialLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.SceneLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.blender.BlenderModelLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.fbx.FbxLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.GltfLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.BinLoader
一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.gltf.GlbLoader
一月 15, 2018 12:15:16 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.audio.plugins.OGGLoader

AssetManager 在解析配置文件时,会根据类名去查找对应的 AssetLoader 类,并使用Java的反射机制来装载它。如果找不到这个类,就会在日志中打印出警告信息。例如:

一月 15, 2018 12:15:15 下午 com.jme3.asset.AssetConfig loadText
警告: Cannot find loader com.jme3.scene.plugins.ogre.MeshLoader

对于 AssetManager 来说,这并不是一个错误。AssetManager 会忽略这一行,继续执行配置文件中的其他的命令。

在本文的第一节已经介绍过,MeshLoaderGltfLoaderFbxLoader 等类,都依赖 jme3-plugins-{version}.jarOGGLoader 依赖 jme3-jogg-{version}.jar。如果项目的依赖中缺少对应的jar包,就无法解析对应格式的资产文件。

在SimpleApplication中使用

如果你想在 SimpleApplication 的子类中使用自定义资产配置,可以通过 AppSettings 来进行设置。

package net.jmecn.assets;

import java.net.URL;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetKey;
import com.jme3.system.AppSettings;

/**
 * 测试自定义配置文件
 * 
 * @author yanmaoyuan
 *
 */
public class TestCustomConfig extends SimpleApplication {
    public static void main(String[] args) {
        URL url = Thread.currentThread().getContextClassLoader()
                .getResource("net/jmecn/assets/MyAssetConfig.cfg");
        AppSettings settings = new AppSettings(true);
        settings.put("AssetConfigURL", url.toString());

        TestCustomConfig app = new TestCustomConfig();
        app.setSettings(settings);
        app.start();
    }

    @Override
    public void simpleInitApp() {
        AssetKey<String> key = new AssetKey<String>(
                "sevenzipjbinding-9.20-2.00beta-AllWindows/ReleaseNotes.txt");
        String str = assetManager.loadAsset(key);
        System.out.println(str);
    }
}

运行结果是一样的。