浏览代码

Implement support for EXT_meshopt_compression

This change implements support for EXT_meshopt_compression extension
using the WebAssembly implementation from meshoptimizer repository.

To integrate the extension it's sufficient to override loadBufferView
and decode the provided buffer into a fresh Uint8Array. meshopt_decoder
module handles the relevant decoding procedure, including dynamic
dispatch to one of decodeVertexBuffer/decodeIndexBuffer/decodeIndexSequence
based on the mode.

The WebAssembly binary is embedded into the .js file, so no extra setup
is necessary; a .d.ts file is provided for type checking.

glTF files for this extension can be produced using gltfpack with -c/-cc
options.
Arseny Kapoulkine 4 年之前
父节点
当前提交
122d600854

+ 66 - 0
loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.ts

@@ -0,0 +1,66 @@
+import { Nullable } from "babylonjs/types";
+import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
+import { GLTFLoader } from "../glTFLoader";
+import { IBufferView } from "../glTFLoaderInterfaces";
+
+import { MeshoptDecoder } from "./meshopt_decoder.module.js";
+
+const NAME = "EXT_meshopt_compression";
+
+/**
+ * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression)
+ *
+ * This extension uses a WebAssembly decoder module from https://github.com/zeux/meshoptimizer/tree/master/js
+ */
+export class EXT_meshopt_compression implements IGLTFLoaderExtension {
+    /**
+     * The name of this extension.
+     */
+    public readonly name = NAME;
+
+    /**
+     * Defines whether this extension is enabled.
+     */
+    public enabled: boolean;
+
+    private _loader: GLTFLoader;
+
+    /** @hidden */
+    constructor(loader: GLTFLoader) {
+        this.enabled = loader.isExtensionUsed(NAME) && MeshoptDecoder.supported;
+        this._loader = loader;
+    }
+
+    /** @hidden */
+    public dispose() {
+    }
+
+    public loadBufferViewAsync(context: string, bufferView: IBufferView): Nullable<Promise<ArrayBufferView>> {
+        if (bufferView.extensions && bufferView.extensions[this.name]) {
+            var extensionDef = bufferView.extensions[this.name];
+            if (extensionDef._decoded) {
+                return extensionDef._decoded;
+            }
+
+            var view = this._loader.loadBufferViewAsync(context, extensionDef);
+            var decoder = MeshoptDecoder;
+
+            extensionDef._decoded = Promise.all([view, decoder.ready]).then(function (res) {
+                var source = res[0] as Uint8Array;
+                var count = extensionDef.count;
+                var stride = extensionDef.byteStride;
+                var result = new Uint8Array(new ArrayBuffer(count * stride));
+
+                decoder.decodeGltfBuffer(result, count, stride, source, extensionDef.mode, extensionDef.filter);
+
+                return Promise.resolve(result);
+            });
+
+            return extensionDef._decoded;
+        } else {
+            return null;
+        }
+    };
+}
+
+GLTFLoader.RegisterExtension(NAME, (loader) => new EXT_meshopt_compression(loader));

+ 1 - 0
loaders/src/glTF/2.0/Extensions/index.ts

@@ -1,5 +1,6 @@
 export * from "./EXT_lights_image_based";
 export * from "./EXT_mesh_gpu_instancing";
+export * from "./EXT_meshopt_compression";
 export * from "./EXT_texture_webp";
 export * from "./KHR_draco_mesh_compression";
 export * from "./KHR_lights_punctual";

+ 11 - 0
loaders/src/glTF/2.0/Extensions/meshopt_decoder.module.d.ts

@@ -0,0 +1,11 @@
+// This file is part of meshoptimizer library and is distributed under the terms of MIT License.
+// Copyright (C) 2016-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
+export const MeshoptDecoder: {
+    supported: boolean;
+    ready: Promise<void>;
+    
+    decodeVertexBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, filter?: string) => void;
+    decodeIndexBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array) => void;
+    decodeIndexSequence: (target: Uint8Array, count: number, size: number, source: Uint8Array) => void;
+    decodeGltfBuffer: (target: Uint8Array, count: number, size: number, source: Uint8Array, mode: string, filter?: string) => void;
+};

文件差异内容过多而无法显示
+ 113 - 0
loaders/src/glTF/2.0/Extensions/meshopt_decoder.module.js