소스 검색

Fix EXT_mesh_gpu_instancing implementation

Gary Hsu 5 년 전
부모
커밋
1484c6735c
1개의 변경된 파일46개의 추가작업 그리고 41개의 파일을 삭제
  1. 46 41
      loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts

+ 46 - 41
loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts

@@ -7,6 +7,7 @@ import { Nullable } from "babylonjs/types";
 import { GLTFLoader, ArrayItem } from "../glTFLoader";
 import { IGLTFLoaderExtension } from "../glTFLoaderExtension";
 import { INode } from "../glTFLoaderInterfaces";
+import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
 
 const NAME = "EXT_mesh_gpu_instancing";
 
@@ -47,58 +48,62 @@ export class EXT_mesh_gpu_instancing implements IGLTFLoaderExtension {
     /** @hidden */
     public loadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {
         return GLTFLoader.LoadExtensionAsync<IEXTMeshGpuInstancing, TransformNode>(context, node, this.name, (extensionContext, extension) => {
-            return this._loader.loadNodeAsync(`#/nodes/${node.index}`, node, (babylonTransformNode) => {
-                assign(babylonTransformNode);
+            const promise = this._loader.loadNodeAsync(`#/nodes/${node.index}`, node, assign);
 
-                if (!node._primitiveBabylonMeshes) {
-                    return;
-                }
-
-                // Disable the source meshes.
-                for (const babylonMesh of node._primitiveBabylonMeshes) {
-                    babylonMesh.isVisible = false;
-                }
-
-                const promises = new Array<Promise<Nullable<Float32Array>>>();
-                let instanceCount = 0;
+            if (!node._primitiveBabylonMeshes) {
+                return promise;
+            }
 
-                const loadAttribute = (attribute: string) => {
-                    if (extension.attributes[attribute] == undefined) {
-                        promises.push(Promise.resolve(null));
-                        return;
-                    }
+            // Hide the source meshes.
+            for (const babylonMesh of node._primitiveBabylonMeshes) {
+                babylonMesh.isVisible = false;
+            }
 
-                    const accessor = ArrayItem.Get(`${extensionContext}/attributes/${attribute}`, this._loader.gltf.accessors, extension.attributes[attribute]);
-                    promises.push(this._loader._loadFloatAccessorAsync(`/accessors/${accessor.bufferView}`, accessor));
+            const promises = new Array<Promise<Nullable<Float32Array>>>();
+            let instanceCount = 0;
 
-                    if (instanceCount === 0) {
-                        instanceCount = accessor.count;
-                    } else if (instanceCount !== accessor.count) {
-                        throw new Error(`${extensionContext}/attributes: Instance buffer accessors do not have the same count.`);
-                    }
-                };
+            const loadAttribute = (attribute: string) => {
+                if (extension.attributes[attribute] == undefined) {
+                    promises.push(Promise.resolve(null));
+                    return;
+                }
 
-                loadAttribute("TRANSLATION");
-                loadAttribute("ROTATION");
-                loadAttribute("SCALE");
+                const accessor = ArrayItem.Get(`${extensionContext}/attributes/${attribute}`, this._loader.gltf.accessors, extension.attributes[attribute]);
+                promises.push(this._loader._loadFloatAccessorAsync(`/accessors/${accessor.bufferView}`, accessor));
 
-                if (instanceCount == 0) {
-                    return;
+                if (instanceCount === 0) {
+                    instanceCount = accessor.count;
+                } else if (instanceCount !== accessor.count) {
+                    throw new Error(`${extensionContext}/attributes: Instance buffer accessors do not have the same count.`);
+                }
+            };
+
+            loadAttribute("TRANSLATION");
+            loadAttribute("ROTATION");
+            loadAttribute("SCALE");
+
+            if (instanceCount == 0) {
+                return promise;
+            }
+
+            const digitLength = instanceCount.toString().length;
+            for (let i = 0; i < instanceCount; ++i) {
+                for (const babylonMesh of node._primitiveBabylonMeshes!) {
+                    const instanceName = `${babylonMesh.name || babylonMesh.id}_${StringTools.PadNumber(i, digitLength)}`;
+                    const babylonInstancedMesh = (babylonMesh as (InstancedMesh | Mesh)).createInstance(instanceName);
+                    babylonInstancedMesh.setParent(babylonMesh);
                 }
+            }
 
+            return promise.then((babylonTransformNode) => {
                 return Promise.all(promises).then(([translationBuffer, rotationBuffer, scaleBuffer]) => {
-                    const digitLength = instanceCount.toString().length;
                     for (let i = 0; i < instanceCount; ++i) {
                         for (const babylonMesh of node._primitiveBabylonMeshes!) {
-                            const instanceName = `${babylonMesh.name || babylonMesh.id}_${StringTools.PadNumber(i, digitLength)}`;
-                            const babylonInstancedMesh = (babylonMesh as (InstancedMesh | Mesh)).createInstance(instanceName);
-                            babylonInstancedMesh.setParent(babylonMesh);
-                            translationBuffer ? Vector3.FromArrayToRef(translationBuffer, i * 3, babylonInstancedMesh.position)
-                                : babylonInstancedMesh.position.set(0, 0, 0);
-                            rotationBuffer ? Quaternion.FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMesh.rotationQuaternion!)
-                                : babylonInstancedMesh.rotationQuaternion!.set(0, 0, 0, 1);
-                            scaleBuffer ? Vector3.FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMesh.scaling)
-                                : babylonInstancedMesh.scaling.set(1, 1, 1);
+                            const babylonInstancedMeshes = babylonMesh.getChildMeshes(true, (node) => (node as AbstractMesh).isAnInstance);
+                            translationBuffer && Vector3.FromArrayToRef(translationBuffer, i * 3, babylonInstancedMeshes[i].position);
+                            rotationBuffer && Quaternion.FromArrayToRef(rotationBuffer, i * 4, babylonInstancedMeshes[i].rotationQuaternion!);
+                            scaleBuffer && Vector3.FromArrayToRef(scaleBuffer, i * 3, babylonInstancedMeshes[i].scaling);
+                            babylonInstancedMeshes[i].refreshBoundingInfo();
                         }
                     }