|
@@ -1,29 +1,47 @@
|
|
|
/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
|
|
|
|
|
|
module BABYLON.GLTF2 {
|
|
|
+ class GLTFLoaderTracker {
|
|
|
+ private _pendingCount = 0;
|
|
|
+ private _callback: () => void;
|
|
|
+
|
|
|
+ constructor(onComplete: () => void) {
|
|
|
+ this._callback = onComplete;
|
|
|
+ }
|
|
|
+
|
|
|
+ public _addPendingData(data: any): void {
|
|
|
+ this._pendingCount++;
|
|
|
+ }
|
|
|
+
|
|
|
+ public _removePendingData(data: any): void {
|
|
|
+ if (--this._pendingCount === 0) {
|
|
|
+ this._callback();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
export class GLTFLoader implements IGLTFLoader, IDisposable {
|
|
|
+ public _gltf: IGLTF;
|
|
|
+ public _babylonScene: Scene;
|
|
|
+
|
|
|
private _parent: GLTFFileLoader;
|
|
|
- private _gltf: IGLTF;
|
|
|
- private _babylonScene: Scene;
|
|
|
private _rootUrl: string;
|
|
|
private _defaultMaterial: PBRMaterial;
|
|
|
private _successCallback: () => void;
|
|
|
private _progressCallback: (event: ProgressEvent) => void;
|
|
|
private _errorCallback: (message: string) => void;
|
|
|
- private _renderReady: boolean = false;
|
|
|
- private _disposed: boolean = false;
|
|
|
- private _blockPendingTracking: boolean = false;
|
|
|
- private _nonBlockingData: Array<any>;
|
|
|
- private _rootMesh: Mesh;
|
|
|
+ private _renderReady = false;
|
|
|
+ private _disposed = false;
|
|
|
|
|
|
- // Observable with boolean indicating success or error.
|
|
|
private _renderReadyObservable = new Observable<GLTFLoader>();
|
|
|
|
|
|
// Count of pending work that needs to complete before the asset is rendered.
|
|
|
- private _renderPendingCount: number = 0;
|
|
|
+ private _renderPendingCount = 0;
|
|
|
|
|
|
- // Count of pending work that needs to complete before the loader is cleared.
|
|
|
- private _loaderPendingCount: number = 0;
|
|
|
+ // Count of pending work that needs to complete before the loader is disposed.
|
|
|
+ private _loaderPendingCount = 0;
|
|
|
+
|
|
|
+ private _loaderTrackers = new Array<GLTFLoaderTracker>();
|
|
|
|
|
|
public static Extensions: { [name: string]: GLTFLoaderExtension } = {};
|
|
|
|
|
@@ -39,23 +57,6 @@ module BABYLON.GLTF2 {
|
|
|
GLTFLoaderExtension._Extensions.push(extension);
|
|
|
}
|
|
|
|
|
|
- public get gltf(): IGLTF {
|
|
|
- return this._gltf;
|
|
|
- }
|
|
|
-
|
|
|
- public get babylonScene(): Scene {
|
|
|
- return this._babylonScene;
|
|
|
- }
|
|
|
-
|
|
|
- public executeWhenRenderReady(func: () => void) {
|
|
|
- if (this._renderReady) {
|
|
|
- func();
|
|
|
- }
|
|
|
- else {
|
|
|
- this._renderReadyObservable.add(func);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
public constructor(parent: GLTFFileLoader) {
|
|
|
this._parent = parent;
|
|
|
}
|
|
@@ -107,57 +108,54 @@ module BABYLON.GLTF2 {
|
|
|
this._progressCallback = onProgress;
|
|
|
this._errorCallback = onError;
|
|
|
|
|
|
- this.addPendingData(this);
|
|
|
+ this._addPendingData(this);
|
|
|
this._loadScene(nodeNames);
|
|
|
this._loadAnimations();
|
|
|
- this.removePendingData(this);
|
|
|
+ this._removePendingData(this);
|
|
|
}
|
|
|
|
|
|
private _onError(message: string): void {
|
|
|
if (this._errorCallback) {
|
|
|
this._errorCallback(message);
|
|
|
}
|
|
|
+
|
|
|
this.dispose();
|
|
|
}
|
|
|
|
|
|
private _onProgress(event: ProgressEvent): void {
|
|
|
- this._progressCallback(event);
|
|
|
+ if (this._progressCallback) {
|
|
|
+ this._progressCallback(event);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private _onRenderReady(): void {
|
|
|
- switch (this._parent.coordinateSystemMode) {
|
|
|
- case GLTFLoaderCoordinateSystemMode.AUTO:
|
|
|
- if (!this._babylonScene.useRightHandedSystem) {
|
|
|
- this._addRightHandToLeftHandRootTransform();
|
|
|
- }
|
|
|
- break;
|
|
|
- case GLTFLoaderCoordinateSystemMode.PASS_THROUGH:
|
|
|
- // do nothing
|
|
|
- break;
|
|
|
- case GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED:
|
|
|
- this._babylonScene.useRightHandedSystem = true;
|
|
|
- break;
|
|
|
- default:
|
|
|
- Tools.Error("Invalid coordinate system mode (" + this._parent.coordinateSystemMode + ")");
|
|
|
- break;
|
|
|
+ public _executeWhenRenderReady(func: () => void): void {
|
|
|
+ if (this._renderReady) {
|
|
|
+ func();
|
|
|
}
|
|
|
+ else {
|
|
|
+ this._renderReadyObservable.add(func);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private _onRenderReady(): void {
|
|
|
+ var rootNode = this._gltf.nodes[this._gltf.nodes.length - 1];
|
|
|
+ rootNode.babylonMesh.setEnabled(true);
|
|
|
|
|
|
- this._showMeshes();
|
|
|
this._startAnimations();
|
|
|
this._successCallback();
|
|
|
this._renderReadyObservable.notifyObservers(this);
|
|
|
+
|
|
|
+ if (this._parent.onReady) {
|
|
|
+ this._parent.onReady();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private _onLoaderComplete(): void {
|
|
|
+ private _onComplete(): void {
|
|
|
if (this._parent.onComplete) {
|
|
|
this._parent.onComplete();
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- private _onLoaderFirstLODComplete(): void {
|
|
|
- if (this._parent.onFirstLODComplete) {
|
|
|
- this._parent.onFirstLODComplete();
|
|
|
- }
|
|
|
+ this.dispose();
|
|
|
}
|
|
|
|
|
|
private _loadData(data: IGLTFLoaderData): void {
|
|
@@ -183,30 +181,9 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private _addRightHandToLeftHandRootTransform(): void {
|
|
|
- this._rootMesh = new Mesh("root", this._babylonScene);
|
|
|
- this._rootMesh.isVisible = false;
|
|
|
- this._rootMesh.scaling = new Vector3(1, 1, -1);
|
|
|
- this._rootMesh.rotation.y = Math.PI;
|
|
|
-
|
|
|
- var nodes = this._gltf.nodes;
|
|
|
- if (nodes) {
|
|
|
- for (var i = 0; i < nodes.length; i++) {
|
|
|
- var mesh = nodes[i].babylonMesh;
|
|
|
- if (mesh && !mesh.parent) {
|
|
|
- mesh.parent = this._rootMesh;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private _getMeshes(): Mesh[] {
|
|
|
var meshes = [];
|
|
|
|
|
|
- if (this._rootMesh) {
|
|
|
- meshes.push(this._rootMesh);
|
|
|
- }
|
|
|
-
|
|
|
var nodes = this._gltf.nodes;
|
|
|
if (nodes) {
|
|
|
nodes.forEach(node => {
|
|
@@ -247,16 +224,38 @@ module BABYLON.GLTF2 {
|
|
|
return targets;
|
|
|
}
|
|
|
|
|
|
- private _showMeshes(): void {
|
|
|
- this._getMeshes().forEach(mesh => mesh.isVisible = true);
|
|
|
- }
|
|
|
-
|
|
|
private _startAnimations(): void {
|
|
|
this._getAnimationTargets().forEach(target => this._babylonScene.beginAnimation(target, 0, Number.MAX_VALUE, true));
|
|
|
}
|
|
|
|
|
|
private _loadScene(nodeNames: any): void {
|
|
|
var scene = this._gltf.scenes[this._gltf.scene || 0];
|
|
|
+
|
|
|
+ var rootNode = { name: "root", children: scene.nodes } as IGLTFNode;
|
|
|
+
|
|
|
+ switch (this._parent.coordinateSystemMode) {
|
|
|
+ case GLTFLoaderCoordinateSystemMode.AUTO:
|
|
|
+ if (!this._babylonScene.useRightHandedSystem) {
|
|
|
+ rootNode.rotation = [0, 1, 0, 0];
|
|
|
+ rootNode.scale = [1, 1, -1];
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case GLTFLoaderCoordinateSystemMode.PASS_THROUGH:
|
|
|
+ // do nothing
|
|
|
+ break;
|
|
|
+ case GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED:
|
|
|
+ this._babylonScene.useRightHandedSystem = true;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ Tools.Error("Invalid coordinate system mode (" + this._parent.coordinateSystemMode + ")");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Inject a root node into the scene.
|
|
|
+ this._gltf.nodes = this._gltf.nodes || [];
|
|
|
+ scene.nodes = [this._gltf.nodes.length];
|
|
|
+ this._gltf.nodes.push(rootNode);
|
|
|
+
|
|
|
var nodeIndices = scene.nodes;
|
|
|
|
|
|
this._traverseNodes(nodeIndices, (node, index, parentNode) => {
|
|
@@ -277,23 +276,31 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
var filteredNodeIndices = new Array<number>();
|
|
|
this._traverseNodes(nodeIndices, node => {
|
|
|
- if (nodeNames.indexOf(node.name) === -1) {
|
|
|
- return true;
|
|
|
+ if (nodeNames.indexOf(node.name) !== -1) {
|
|
|
+ filteredNodeIndices.push(node.index);
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- filteredNodeIndices.push(node.index);
|
|
|
- return false;
|
|
|
+ return true;
|
|
|
});
|
|
|
|
|
|
nodeIndices = filteredNodeIndices;
|
|
|
}
|
|
|
|
|
|
- this._traverseNodes(nodeIndices, node => this._loadNode(node));
|
|
|
+ for (var i = 0; i < nodeIndices.length; i++) {
|
|
|
+ this._loadNode(this._gltf.nodes[nodeIndices[i]]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Disable the root mesh until the asset is ready to render.
|
|
|
+ rootNode.babylonMesh.setEnabled(false);
|
|
|
}
|
|
|
|
|
|
- private _loadNode(node: IGLTFNode): boolean {
|
|
|
+ public _loadNode(node: IGLTFNode): void {
|
|
|
+ if (GLTFLoaderExtension.LoadNode(this, node)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
node.babylonMesh = new Mesh(node.name || "mesh" + node.index, this._babylonScene);
|
|
|
- node.babylonMesh.isVisible = false;
|
|
|
|
|
|
this._loadTransform(node);
|
|
|
|
|
@@ -317,7 +324,11 @@ module BABYLON.GLTF2 {
|
|
|
// TODO: handle cameras
|
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
+ if (node.children) {
|
|
|
+ for (var i = 0; i < node.children.length; i++) {
|
|
|
+ this._loadNode(this._gltf.nodes[node.children[i]]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private _loadMesh(node: IGLTFNode, mesh: IGLTFMesh): void {
|
|
@@ -356,25 +367,25 @@ module BABYLON.GLTF2 {
|
|
|
loadMaterial: () => {
|
|
|
if (primitive.material === undefined) {
|
|
|
babylonMultiMaterial.subMaterials[i] = this._getDefaultMaterial();
|
|
|
+ return;
|
|
|
}
|
|
|
- else {
|
|
|
- var material = this._gltf.materials[primitive.material];
|
|
|
- this.loadMaterial(material, (babylonMaterial, isNew) => {
|
|
|
- if (isNew && this._parent.onMaterialLoaded) {
|
|
|
- this._parent.onMaterialLoaded(babylonMaterial);
|
|
|
- }
|
|
|
-
|
|
|
- if (this._parent.onBeforeMaterialReadyAsync) {
|
|
|
- this.addLoaderPendingData(material);
|
|
|
- this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, babylonMultiMaterial.subMaterials[i] != null, () => {
|
|
|
- babylonMultiMaterial.subMaterials[i] = babylonMaterial;
|
|
|
- this.removeLoaderPendingData(material);
|
|
|
- });
|
|
|
- } else {
|
|
|
+
|
|
|
+ var material = this._gltf.materials[primitive.material];
|
|
|
+ this._loadMaterial(material, (babylonMaterial, isNew) => {
|
|
|
+ if (isNew && this._parent.onMaterialLoaded) {
|
|
|
+ this._parent.onMaterialLoaded(babylonMaterial);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this._parent.onBeforeMaterialReadyAsync) {
|
|
|
+ this._addLoaderPendingData(material);
|
|
|
+ this._parent.onBeforeMaterialReadyAsync(babylonMaterial, node.babylonMesh, babylonMultiMaterial.subMaterials[i] != null, () => {
|
|
|
babylonMultiMaterial.subMaterials[i] = babylonMaterial;
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ this._removeLoaderPendingData(material);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ babylonMultiMaterial.subMaterials[i] = babylonMaterial;
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -456,7 +467,7 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private _createMorphTargets(node: IGLTFNode, mesh: IGLTFMesh, primitive: IGLTFMeshPrimitive, babylonMesh: Mesh) {
|
|
|
+ private _createMorphTargets(node: IGLTFNode, mesh: IGLTFMesh, primitive: IGLTFMeshPrimitive, babylonMesh: Mesh): void {
|
|
|
var targets = primitive.targets;
|
|
|
if (!targets) {
|
|
|
return;
|
|
@@ -618,17 +629,18 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private _traverseNode(index: number, action: (node: IGLTFNode, index: number, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
|
|
|
- var node = this._gltf.nodes[index];
|
|
|
+ public _traverseNode(index: number, action: (node: IGLTFNode, index: number, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
|
|
|
+ if (GLTFLoaderExtension.TraverseNode(this, index, action, parentNode)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
+ var node = this._gltf.nodes[index];
|
|
|
if (!action(node, index, parentNode)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (node.children) {
|
|
|
- for (var i = 0; i < node.children.length; i++) {
|
|
|
- this._traverseNode(node.children[i], action, node);
|
|
|
- }
|
|
|
+ this._traverseNodes(node.children, action, node);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -761,14 +773,12 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- this._loadAccessorAsync(this._gltf.accessors[sampler.input], data =>
|
|
|
- {
|
|
|
+ this._loadAccessorAsync(this._gltf.accessors[sampler.input], data => {
|
|
|
inputData = <Float32Array>data;
|
|
|
checkSuccess();
|
|
|
});
|
|
|
|
|
|
- this._loadAccessorAsync(this._gltf.accessors[sampler.output], data =>
|
|
|
- {
|
|
|
+ this._loadAccessorAsync(this._gltf.accessors[sampler.output], data => {
|
|
|
outputData = <Float32Array>data;
|
|
|
checkSuccess();
|
|
|
});
|
|
@@ -776,12 +786,12 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
private _loadBufferAsync(index: number, onSuccess: (data: ArrayBufferView) => void): void {
|
|
|
var buffer = this._gltf.buffers[index];
|
|
|
- this.addPendingData(buffer);
|
|
|
+ this._addPendingData(buffer);
|
|
|
|
|
|
if (buffer.loadedData) {
|
|
|
setTimeout(() => {
|
|
|
onSuccess(buffer.loadedData);
|
|
|
- this.removePendingData(buffer);
|
|
|
+ this._removePendingData(buffer);
|
|
|
});
|
|
|
}
|
|
|
else if (GLTFUtils.IsBase64(buffer.uri)) {
|
|
@@ -789,20 +799,20 @@ module BABYLON.GLTF2 {
|
|
|
buffer.loadedData = new Uint8Array(data);
|
|
|
setTimeout(() => {
|
|
|
onSuccess(buffer.loadedData);
|
|
|
- this.removePendingData(buffer);
|
|
|
+ this._removePendingData(buffer);
|
|
|
});
|
|
|
}
|
|
|
else if (buffer.loadedObservable) {
|
|
|
buffer.loadedObservable.add(buffer => {
|
|
|
onSuccess(buffer.loadedData);
|
|
|
- this.removePendingData(buffer);
|
|
|
+ this._removePendingData(buffer);
|
|
|
});
|
|
|
}
|
|
|
else {
|
|
|
buffer.loadedObservable = new Observable<IGLTFBuffer>();
|
|
|
buffer.loadedObservable.add(buffer => {
|
|
|
onSuccess(buffer.loadedData);
|
|
|
- this.removePendingData(buffer);
|
|
|
+ this._removePendingData(buffer);
|
|
|
});
|
|
|
|
|
|
Tools.LoadFile(this._rootUrl + buffer.uri, data => {
|
|
@@ -816,7 +826,7 @@ module BABYLON.GLTF2 {
|
|
|
}, this._babylonScene.database, true, request => {
|
|
|
if (!this._disposed) {
|
|
|
this._onError("Failed to load file '" + buffer.uri + "': " + request.status + " " + request.statusText);
|
|
|
- this.removePendingData(buffer);
|
|
|
+ this._removePendingData(buffer);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -832,7 +842,7 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride, targetBuffer.length);
|
|
|
|
|
|
- return targetBuffer;
|
|
|
+ return targetBuffer;
|
|
|
}
|
|
|
|
|
|
private _buildUint8ArrayBuffer(buffer: ArrayBuffer, byteOffset: number, byteLength: number, byteStride: number, bytePerComponent: number): Uint8Array {
|
|
@@ -845,8 +855,8 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride, targetBuffer.length);
|
|
|
|
|
|
- return targetBuffer;
|
|
|
- }
|
|
|
+ return targetBuffer;
|
|
|
+ }
|
|
|
|
|
|
private _buildInt16ArrayBuffer(buffer: ArrayBuffer, byteOffset: number, byteLength: number, byteStride: number, bytePerComponent: number): Int16Array {
|
|
|
if (!byteStride) {
|
|
@@ -858,8 +868,8 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride / 2, targetBuffer.length);
|
|
|
|
|
|
- return targetBuffer;
|
|
|
- }
|
|
|
+ return targetBuffer;
|
|
|
+ }
|
|
|
|
|
|
private _buildUint16ArrayBuffer(buffer: ArrayBuffer, byteOffset: number, byteLength: number, byteStride: number, bytePerComponent: number): Uint16Array {
|
|
|
if (!byteStride) {
|
|
@@ -871,9 +881,9 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride / 2, targetBuffer.length);
|
|
|
|
|
|
- return targetBuffer;
|
|
|
- }
|
|
|
-
|
|
|
+ return targetBuffer;
|
|
|
+ }
|
|
|
+
|
|
|
private _buildUint32ArrayBuffer(buffer: ArrayBuffer, byteOffset: number, byteLength: number, byteStride: number, bytePerComponent: number): Uint32Array {
|
|
|
if (!byteStride) {
|
|
|
return new Uint32Array(buffer, byteOffset, byteLength);
|
|
@@ -884,9 +894,9 @@ module BABYLON.GLTF2 {
|
|
|
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride / 4, targetBuffer.length);
|
|
|
|
|
|
- return targetBuffer;
|
|
|
- }
|
|
|
-
|
|
|
+ return targetBuffer;
|
|
|
+ }
|
|
|
+
|
|
|
private _buildFloat32ArrayBuffer(buffer: ArrayBuffer, byteOffset: number, byteLength: number, byteStride: number, bytePerComponent: number): Float32Array {
|
|
|
if (!byteStride) {
|
|
|
return new Float32Array(buffer, byteOffset, byteLength);
|
|
@@ -898,11 +908,11 @@ module BABYLON.GLTF2 {
|
|
|
this._extractInterleavedData(sourceBuffer, targetBuffer, bytePerComponent, byteStride / 4, targetBuffer.length);
|
|
|
|
|
|
return targetBuffer;
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
+
|
|
|
private _extractInterleavedData(sourceBuffer: ArrayBufferView, targetBuffer: ArrayBufferView, bytePerComponent: number, stride: number, length: number): void {
|
|
|
let tempIndex = 0;
|
|
|
- let sourceIndex = 0;
|
|
|
+ let sourceIndex = 0;
|
|
|
let storageSize = bytePerComponent;
|
|
|
|
|
|
while (tempIndex < length) {
|
|
@@ -978,19 +988,15 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public set blockPendingTracking(value: boolean) {
|
|
|
- this._blockPendingTracking = value;
|
|
|
- }
|
|
|
-
|
|
|
- public addPendingData(data: any) {
|
|
|
+ public _addPendingData(data: any): void {
|
|
|
if (!this._renderReady) {
|
|
|
this._renderPendingCount++;
|
|
|
}
|
|
|
|
|
|
- this.addLoaderPendingData(data);
|
|
|
+ this._addLoaderPendingData(data);
|
|
|
}
|
|
|
|
|
|
- public removePendingData(data: any) {
|
|
|
+ public _removePendingData(data: any): void {
|
|
|
if (!this._renderReady) {
|
|
|
if (--this._renderPendingCount === 0) {
|
|
|
this._renderReady = true;
|
|
@@ -998,36 +1004,36 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- this.removeLoaderPendingData(data);
|
|
|
+ this._removeLoaderPendingData(data);
|
|
|
}
|
|
|
|
|
|
- public addLoaderNonBlockingPendingData(data: any): void {
|
|
|
- if (!this._nonBlockingData) {
|
|
|
- this._nonBlockingData = new Array<any>();
|
|
|
- }
|
|
|
- this._nonBlockingData.push(data);
|
|
|
+ public _addLoaderPendingData(data: any): void {
|
|
|
+ this._loaderPendingCount++;
|
|
|
+
|
|
|
+ this._loaderTrackers.forEach(tracker => tracker._addPendingData(data));
|
|
|
}
|
|
|
|
|
|
- public addLoaderPendingData(data: any) {
|
|
|
- if (this._blockPendingTracking) {
|
|
|
- this.addLoaderNonBlockingPendingData(data);
|
|
|
- return;
|
|
|
+ public _removeLoaderPendingData(data: any): void {
|
|
|
+ this._loaderTrackers.forEach(tracker => tracker._removePendingData(data));
|
|
|
+
|
|
|
+ if (--this._loaderPendingCount === 0) {
|
|
|
+ this._onComplete();
|
|
|
}
|
|
|
- this._loaderPendingCount++;
|
|
|
}
|
|
|
|
|
|
- public removeLoaderPendingData(data: any) {
|
|
|
- var indexInPending = this._nonBlockingData ? this._nonBlockingData.indexOf(data) : -1;
|
|
|
- if (indexInPending !== -1) {
|
|
|
- this._nonBlockingData.splice(indexInPending, 1);
|
|
|
- } else if (--this._loaderPendingCount === 0) {
|
|
|
- this._onLoaderFirstLODComplete();
|
|
|
- }
|
|
|
+ public _whenAction(action: () => void, onComplete: () => void): void {
|
|
|
+ var tracker = new GLTFLoaderTracker(() => {
|
|
|
+ this._loaderTrackers.splice(this._loaderTrackers.indexOf(tracker));
|
|
|
+ onComplete();
|
|
|
+ });
|
|
|
|
|
|
- if ((!this._nonBlockingData || this._nonBlockingData.length === 0) && this._loaderPendingCount === 0) {
|
|
|
- this._onLoaderComplete();
|
|
|
- this.dispose();
|
|
|
- }
|
|
|
+ this._loaderTrackers.push(tracker);
|
|
|
+
|
|
|
+ this._addLoaderPendingData(tracker);
|
|
|
+
|
|
|
+ action();
|
|
|
+
|
|
|
+ this._removeLoaderPendingData(tracker);
|
|
|
}
|
|
|
|
|
|
private _getDefaultMaterial(): Material {
|
|
@@ -1064,20 +1070,20 @@ module BABYLON.GLTF2 {
|
|
|
babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
|
|
|
|
|
|
if (properties.baseColorTexture) {
|
|
|
- babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
|
|
|
+ babylonMaterial.albedoTexture = this._loadTexture(properties.baseColorTexture);
|
|
|
}
|
|
|
|
|
|
if (properties.metallicRoughnessTexture) {
|
|
|
- babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
|
|
|
+ babylonMaterial.metallicTexture = this._loadTexture(properties.metallicRoughnessTexture);
|
|
|
babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
|
|
|
babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
|
|
|
babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
|
|
|
}
|
|
|
|
|
|
- this.loadMaterialAlphaProperties(material, properties.baseColorFactor);
|
|
|
+ this._loadMaterialAlphaProperties(material, properties.baseColorFactor);
|
|
|
}
|
|
|
|
|
|
- public loadMaterial(material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): void {
|
|
|
+ public _loadMaterial(material: IGLTFMaterial, assign: (babylonMaterial: Material, isNew: boolean) => void): void {
|
|
|
if (material.babylonMaterial) {
|
|
|
assign(material.babylonMaterial, false);
|
|
|
return;
|
|
@@ -1087,19 +1093,19 @@ module BABYLON.GLTF2 {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- this.createPbrMaterial(material);
|
|
|
- this.loadMaterialBaseProperties(material);
|
|
|
+ this._createPbrMaterial(material);
|
|
|
+ this._loadMaterialBaseProperties(material);
|
|
|
this._loadMaterialMetallicRoughnessProperties(material);
|
|
|
assign(material.babylonMaterial, true);
|
|
|
}
|
|
|
|
|
|
- public createPbrMaterial(material: IGLTFMaterial): void {
|
|
|
+ public _createPbrMaterial(material: IGLTFMaterial): void {
|
|
|
var babylonMaterial = new PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
|
|
|
babylonMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
|
|
|
material.babylonMaterial = babylonMaterial;
|
|
|
}
|
|
|
|
|
|
- public loadMaterialBaseProperties(material: IGLTFMaterial): void {
|
|
|
+ public _loadMaterialBaseProperties(material: IGLTFMaterial): void {
|
|
|
var babylonMaterial = material.babylonMaterial as PBRMaterial;
|
|
|
|
|
|
babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
|
|
@@ -1109,7 +1115,7 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
|
|
|
if (material.normalTexture) {
|
|
|
- babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
|
|
|
+ babylonMaterial.bumpTexture = this._loadTexture(material.normalTexture);
|
|
|
babylonMaterial.invertNormalMapX = !this._babylonScene.useRightHandedSystem;
|
|
|
babylonMaterial.invertNormalMapY = this._babylonScene.useRightHandedSystem;
|
|
|
if (material.normalTexture.scale !== undefined) {
|
|
@@ -1118,7 +1124,7 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
|
|
|
if (material.occlusionTexture) {
|
|
|
- babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
|
|
|
+ babylonMaterial.ambientTexture = this._loadTexture(material.occlusionTexture);
|
|
|
babylonMaterial.useAmbientInGrayScale = true;
|
|
|
if (material.occlusionTexture.strength !== undefined) {
|
|
|
babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
|
|
@@ -1126,11 +1132,11 @@ module BABYLON.GLTF2 {
|
|
|
}
|
|
|
|
|
|
if (material.emissiveTexture) {
|
|
|
- babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
|
|
|
+ babylonMaterial.emissiveTexture = this._loadTexture(material.emissiveTexture);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public loadMaterialAlphaProperties(material: IGLTFMaterial, colorFactor?: number[]): void {
|
|
|
+ public _loadMaterialAlphaProperties(material: IGLTFMaterial, colorFactor?: number[]): void {
|
|
|
var babylonMaterial = material.babylonMaterial as PBRMaterial;
|
|
|
|
|
|
var alphaMode = material.alphaMode || "OPAQUE";
|
|
@@ -1157,7 +1163,7 @@ module BABYLON.GLTF2 {
|
|
|
babylonMaterial.alphaCutOff = material.alphaCutoff === undefined ? 0.5 : material.alphaCutoff;
|
|
|
}
|
|
|
|
|
|
- public loadTexture(textureInfo: IGLTFTextureInfo): Texture {
|
|
|
+ public _loadTexture(textureInfo: IGLTFTextureInfo): Texture {
|
|
|
var texture = this._gltf.textures[textureInfo.index];
|
|
|
var texCoord = textureInfo.texCoord || 0;
|
|
|
|
|
@@ -1170,15 +1176,15 @@ module BABYLON.GLTF2 {
|
|
|
var noMipMaps = (sampler.minFilter === ETextureMinFilter.NEAREST || sampler.minFilter === ETextureMinFilter.LINEAR);
|
|
|
var samplingMode = GLTFUtils.GetTextureSamplingMode(sampler.magFilter, sampler.minFilter);
|
|
|
|
|
|
- this.addPendingData(texture);
|
|
|
+ this._addPendingData(texture);
|
|
|
var babylonTexture = new Texture(null, this._babylonScene, noMipMaps, false, samplingMode, () => {
|
|
|
if (!this._disposed) {
|
|
|
- this.removePendingData(texture);
|
|
|
+ this._removePendingData(texture);
|
|
|
}
|
|
|
}, () => {
|
|
|
if (!this._disposed) {
|
|
|
this._onError("Failed to load texture '" + source.uri + "'");
|
|
|
- this.removePendingData(texture);
|
|
|
+ this._removePendingData(texture);
|
|
|
}
|
|
|
});
|
|
|
|