|
@@ -35,7 +35,9 @@ interface IFileRequestInfo extends IFileRequest {
|
|
|
}
|
|
|
|
|
|
interface ILoaderProperty extends IProperty {
|
|
|
- _activeLoaderExtensions: any;
|
|
|
+ _activeLoaderExtensionFunctions: {
|
|
|
+ [id: string]: boolean
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -74,12 +76,6 @@ export class ArrayItem {
|
|
|
* The glTF 2.0 loader
|
|
|
*/
|
|
|
export class GLTFLoader implements IGLTFLoader {
|
|
|
- /** The glTF object parsed from the JSON. */
|
|
|
- public gltf: IGLTF;
|
|
|
-
|
|
|
- /** The Babylon scene when loading the asset. */
|
|
|
- public babylonScene: Scene;
|
|
|
-
|
|
|
/** @hidden */
|
|
|
public _completePromises = new Array<Promise<any>>();
|
|
|
|
|
@@ -90,6 +86,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
private _rootUrl: string;
|
|
|
private _fileName: string;
|
|
|
private _uniqueRootUrl: string;
|
|
|
+ private _gltf: IGLTF;
|
|
|
+ private _babylonScene: Scene;
|
|
|
private _rootBabylonMesh: Mesh;
|
|
|
private _defaultBabylonMaterialData: { [drawMode: number]: Material } = {};
|
|
|
private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
|
|
@@ -143,6 +141,27 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return this._state;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * The glTF object parsed from the JSON.
|
|
|
+ */
|
|
|
+ public get gltf(): IGLTF {
|
|
|
+ return this._gltf;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The Babylon scene when loading the asset.
|
|
|
+ */
|
|
|
+ public get babylonScene(): Scene {
|
|
|
+ return this._babylonScene;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The root Babylon mesh when loading the asset.
|
|
|
+ */
|
|
|
+ public get rootBabylonMesh(): Mesh {
|
|
|
+ return this._rootBabylonMesh;
|
|
|
+ }
|
|
|
+
|
|
|
/** @hidden */
|
|
|
constructor(parent: GLTFFileLoader) {
|
|
|
this._parent = parent;
|
|
@@ -162,8 +181,6 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
this._requests.length = 0;
|
|
|
|
|
|
- delete this.gltf;
|
|
|
- delete this.babylonScene;
|
|
|
this._completePromises.length = 0;
|
|
|
|
|
|
for (const name in this._extensions) {
|
|
@@ -175,6 +192,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
this._extensions = {};
|
|
|
|
|
|
+ delete this._gltf;
|
|
|
+ delete this._babylonScene;
|
|
|
delete this._rootBabylonMesh;
|
|
|
delete this._progressCallback;
|
|
|
|
|
@@ -184,7 +203,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
/** @hidden */
|
|
|
public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
|
|
|
return Promise.resolve().then(() => {
|
|
|
- this.babylonScene = scene;
|
|
|
+ this._babylonScene = scene;
|
|
|
this._rootUrl = rootUrl;
|
|
|
this._fileName = fileName || "scene";
|
|
|
this._progressCallback = onProgress;
|
|
@@ -194,8 +213,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
if (meshesNames) {
|
|
|
const nodeMap: { [name: string]: number } = {};
|
|
|
- if (this.gltf.nodes) {
|
|
|
- for (const node of this.gltf.nodes) {
|
|
|
+ if (this._gltf.nodes) {
|
|
|
+ for (const node of this._gltf.nodes) {
|
|
|
if (node.name) {
|
|
|
nodeMap[node.name] = node.index;
|
|
|
}
|
|
@@ -227,7 +246,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
/** @hidden */
|
|
|
public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void, fileName?: string): Promise<void> {
|
|
|
return Promise.resolve().then(() => {
|
|
|
- this.babylonScene = scene;
|
|
|
+ this._babylonScene = scene;
|
|
|
this._rootUrl = rootUrl;
|
|
|
this._fileName = fileName || "scene";
|
|
|
this._progressCallback = onProgress;
|
|
@@ -257,8 +276,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
if (nodes) {
|
|
|
promises.push(this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
|
|
|
}
|
|
|
- else if (this.gltf.scene != undefined) {
|
|
|
- const scene = ArrayItem.Get(`/scene`, this.gltf.scenes, this.gltf.scene);
|
|
|
+ else if (this._gltf.scene != undefined) {
|
|
|
+ const scene = ArrayItem.Get(`/scene`, this._gltf.scenes, this._gltf.scene);
|
|
|
promises.push(this.loadSceneAsync(`/scenes/${scene.index}`, scene));
|
|
|
}
|
|
|
|
|
@@ -321,11 +340,11 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _loadData(data: IGLTFLoaderData): void {
|
|
|
- this.gltf = data.json as IGLTF;
|
|
|
+ this._gltf = data.json as IGLTF;
|
|
|
this._setupData();
|
|
|
|
|
|
if (data.bin) {
|
|
|
- const buffers = this.gltf.buffers;
|
|
|
+ const buffers = this._gltf.buffers;
|
|
|
if (buffers && buffers[0] && !buffers[0].uri) {
|
|
|
const binaryBuffer = buffers[0];
|
|
|
if (binaryBuffer.byteLength < data.bin.byteLength - 3 || binaryBuffer.byteLength > data.bin.byteLength) {
|
|
@@ -341,23 +360,23 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _setupData(): void {
|
|
|
- ArrayItem.Assign(this.gltf.accessors);
|
|
|
- ArrayItem.Assign(this.gltf.animations);
|
|
|
- ArrayItem.Assign(this.gltf.buffers);
|
|
|
- ArrayItem.Assign(this.gltf.bufferViews);
|
|
|
- ArrayItem.Assign(this.gltf.cameras);
|
|
|
- ArrayItem.Assign(this.gltf.images);
|
|
|
- ArrayItem.Assign(this.gltf.materials);
|
|
|
- ArrayItem.Assign(this.gltf.meshes);
|
|
|
- ArrayItem.Assign(this.gltf.nodes);
|
|
|
- ArrayItem.Assign(this.gltf.samplers);
|
|
|
- ArrayItem.Assign(this.gltf.scenes);
|
|
|
- ArrayItem.Assign(this.gltf.skins);
|
|
|
- ArrayItem.Assign(this.gltf.textures);
|
|
|
-
|
|
|
- if (this.gltf.nodes) {
|
|
|
+ ArrayItem.Assign(this._gltf.accessors);
|
|
|
+ ArrayItem.Assign(this._gltf.animations);
|
|
|
+ ArrayItem.Assign(this._gltf.buffers);
|
|
|
+ ArrayItem.Assign(this._gltf.bufferViews);
|
|
|
+ ArrayItem.Assign(this._gltf.cameras);
|
|
|
+ ArrayItem.Assign(this._gltf.images);
|
|
|
+ ArrayItem.Assign(this._gltf.materials);
|
|
|
+ ArrayItem.Assign(this._gltf.meshes);
|
|
|
+ ArrayItem.Assign(this._gltf.nodes);
|
|
|
+ ArrayItem.Assign(this._gltf.samplers);
|
|
|
+ ArrayItem.Assign(this._gltf.scenes);
|
|
|
+ ArrayItem.Assign(this._gltf.skins);
|
|
|
+ ArrayItem.Assign(this._gltf.textures);
|
|
|
+
|
|
|
+ if (this._gltf.nodes) {
|
|
|
const nodeParents: { [index: number]: number } = {};
|
|
|
- for (const node of this.gltf.nodes) {
|
|
|
+ for (const node of this._gltf.nodes) {
|
|
|
if (node.children) {
|
|
|
for (const index of node.children) {
|
|
|
nodeParents[index] = node.index;
|
|
@@ -366,9 +385,9 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
const rootNode = this._createRootNode();
|
|
|
- for (const node of this.gltf.nodes) {
|
|
|
+ for (const node of this._gltf.nodes) {
|
|
|
const parentIndex = nodeParents[node.index];
|
|
|
- node.parent = parentIndex === undefined ? rootNode : this.gltf.nodes[parentIndex];
|
|
|
+ node.parent = parentIndex === undefined ? rootNode : this._gltf.nodes[parentIndex];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -385,8 +404,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _checkExtensions(): void {
|
|
|
- if (this.gltf.extensionsRequired) {
|
|
|
- for (const name of this.gltf.extensionsRequired) {
|
|
|
+ if (this._gltf.extensionsRequired) {
|
|
|
+ for (const name of this._gltf.extensionsRequired) {
|
|
|
const extension = this._extensions[name];
|
|
|
if (!extension || !extension.enabled) {
|
|
|
throw new Error(`Require extension ${name} is not available`);
|
|
@@ -401,7 +420,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _createRootNode(): INode {
|
|
|
- this._rootBabylonMesh = new Mesh("__root__", this.babylonScene);
|
|
|
+ this._rootBabylonMesh = new Mesh("__root__", this._babylonScene);
|
|
|
this._rootBabylonMesh.setEnabled(false);
|
|
|
|
|
|
const rootNode: INode = {
|
|
@@ -411,7 +430,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
switch (this._parent.coordinateSystemMode) {
|
|
|
case GLTFLoaderCoordinateSystemMode.AUTO: {
|
|
|
- if (!this.babylonScene.useRightHandedSystem) {
|
|
|
+ if (!this._babylonScene.useRightHandedSystem) {
|
|
|
rootNode.rotation = [0, 1, 0, 0];
|
|
|
rootNode.scale = [1, 1, -1];
|
|
|
GLTFLoader._LoadTransform(rootNode, this._rootBabylonMesh);
|
|
@@ -419,7 +438,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
break;
|
|
|
}
|
|
|
case GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED: {
|
|
|
- this.babylonScene.useRightHandedSystem = true;
|
|
|
+ this._babylonScene.useRightHandedSystem = true;
|
|
|
break;
|
|
|
}
|
|
|
default: {
|
|
@@ -449,7 +468,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
if (scene.nodes) {
|
|
|
for (let index of scene.nodes) {
|
|
|
- const node = ArrayItem.Get(`${context}/nodes/${index}`, this.gltf.nodes, index);
|
|
|
+ const node = ArrayItem.Get(`${context}/nodes/${index}`, this._gltf.nodes, index);
|
|
|
promises.push(this.loadNodeAsync(`/nodes/${node.index}`, node, (babylonMesh) => {
|
|
|
babylonMesh.parent = this._rootBabylonMesh;
|
|
|
}));
|
|
@@ -458,8 +477,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
// Link all Babylon bones for each glTF node with the corresponding Babylon transform node.
|
|
|
// A glTF joint is a pointer to a glTF node in the glTF node hierarchy similar to Unity3D.
|
|
|
- if (this.gltf.nodes) {
|
|
|
- for (const node of this.gltf.nodes) {
|
|
|
+ if (this._gltf.nodes) {
|
|
|
+ for (const node of this._gltf.nodes) {
|
|
|
if (node._babylonTransformNode && node._babylonBones) {
|
|
|
for (const babylonBone of node._babylonBones) {
|
|
|
babylonBone.linkTransformNode(node._babylonTransformNode);
|
|
@@ -489,7 +508,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
// Root mesh is always first.
|
|
|
meshes.push(this._rootBabylonMesh);
|
|
|
|
|
|
- const nodes = this.gltf.nodes;
|
|
|
+ const nodes = this._gltf.nodes;
|
|
|
if (nodes) {
|
|
|
for (const node of nodes) {
|
|
|
this._forEachPrimitive(node, (babylonMesh) => {
|
|
@@ -504,7 +523,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
private _getSkeletons(): Skeleton[] {
|
|
|
const skeletons = new Array<Skeleton>();
|
|
|
|
|
|
- const skins = this.gltf.skins;
|
|
|
+ const skins = this._gltf.skins;
|
|
|
if (skins) {
|
|
|
for (const skin of skins) {
|
|
|
if (skin._data) {
|
|
@@ -519,7 +538,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
private _getAnimationGroups(): AnimationGroup[] {
|
|
|
const animationGroups = new Array<AnimationGroup>();
|
|
|
|
|
|
- const animations = this.gltf.animations;
|
|
|
+ const animations = this._gltf.animations;
|
|
|
if (animations) {
|
|
|
for (const animation of animations) {
|
|
|
if (animation._babylonAnimationGroup) {
|
|
@@ -584,7 +603,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
GLTFLoader._LoadTransform(node, babylonTransformNode);
|
|
|
|
|
|
if (node.camera != undefined) {
|
|
|
- const camera = ArrayItem.Get(`${context}/camera`, this.gltf.cameras, node.camera);
|
|
|
+ const camera = ArrayItem.Get(`${context}/camera`, this._gltf.cameras, node.camera);
|
|
|
promises.push(this.loadCameraAsync(`/cameras/${camera.index}`, camera, (babylonCamera) => {
|
|
|
babylonCamera.parent = babylonTransformNode;
|
|
|
}));
|
|
@@ -592,7 +611,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
if (node.children) {
|
|
|
for (const index of node.children) {
|
|
|
- const childNode = ArrayItem.Get(`${context}/children/${index}`, this.gltf.nodes, index);
|
|
|
+ const childNode = ArrayItem.Get(`${context}/children/${index}`, this._gltf.nodes, index);
|
|
|
promises.push(this.loadNodeAsync(`/nodes/${childNode.index}`, childNode, (childBabylonMesh) => {
|
|
|
childBabylonMesh.parent = babylonTransformNode;
|
|
|
}));
|
|
@@ -604,11 +623,11 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
if (node.mesh == undefined) {
|
|
|
const nodeName = node.name || `node${node.index}`;
|
|
|
- node._babylonTransformNode = new TransformNode(nodeName, this.babylonScene);
|
|
|
+ node._babylonTransformNode = new TransformNode(nodeName, this._babylonScene);
|
|
|
loadNode(node._babylonTransformNode);
|
|
|
}
|
|
|
else {
|
|
|
- const mesh = ArrayItem.Get(`${context}/mesh`, this.gltf.meshes, node.mesh);
|
|
|
+ const mesh = ArrayItem.Get(`${context}/mesh`, this._gltf.meshes, node.mesh);
|
|
|
promises.push(this._loadMeshAsync(`/meshes/${mesh.index}`, node, mesh, loadNode));
|
|
|
}
|
|
|
|
|
@@ -647,7 +666,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}));
|
|
|
}
|
|
|
else {
|
|
|
- node._babylonTransformNode = new TransformNode(name, this.babylonScene);
|
|
|
+ node._babylonTransformNode = new TransformNode(name, this._babylonScene);
|
|
|
node._primitiveBabylonMeshes = [];
|
|
|
for (const primitive of primitives) {
|
|
|
promises.push(this._loadMeshPrimitiveAsync(`${context}/primitives/${primitive.index}`, `${name}_primitive${primitive.index}`, node, mesh, primitive, (babylonMesh) => {
|
|
@@ -658,7 +677,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
if (node.skin != undefined) {
|
|
|
- const skin = ArrayItem.Get(`${context}/skin`, this.gltf.skins, node.skin);
|
|
|
+ const skin = ArrayItem.Get(`${context}/skin`, this._gltf.skins, node.skin);
|
|
|
promises.push(this._loadSkinAsync(`/skins/${skin.index}`, node, skin));
|
|
|
}
|
|
|
|
|
@@ -687,7 +706,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
else {
|
|
|
const promises = new Array<Promise<any>>();
|
|
|
|
|
|
- const babylonMesh = new Mesh(name, this.babylonScene);
|
|
|
+ const babylonMesh = new Mesh(name, this._babylonScene);
|
|
|
|
|
|
this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
|
|
|
promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then((babylonGeometry) => {
|
|
@@ -707,7 +726,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
babylonMesh.material = babylonMaterial;
|
|
|
}
|
|
|
else {
|
|
|
- const material = ArrayItem.Get(`${context}/material`, this.gltf.materials, primitive.material);
|
|
|
+ const material = ArrayItem.Get(`${context}/material`, this._gltf.materials, primitive.material);
|
|
|
promises.push(this._loadMaterialAsync(`/materials/${material.index}`, material, babylonMesh, babylonDrawMode, (babylonMaterial) => {
|
|
|
babylonMesh.material = babylonMaterial;
|
|
|
}));
|
|
@@ -749,13 +768,13 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
const promises = new Array<Promise<any>>();
|
|
|
|
|
|
- const babylonGeometry = new Geometry(babylonMesh.name, this.babylonScene);
|
|
|
+ const babylonGeometry = new Geometry(babylonMesh.name, this._babylonScene);
|
|
|
|
|
|
if (primitive.indices == undefined) {
|
|
|
babylonMesh.isUnIndexed = true;
|
|
|
}
|
|
|
else {
|
|
|
- const accessor = ArrayItem.Get(`${context}/indices`, this.gltf.accessors, primitive.indices);
|
|
|
+ const accessor = ArrayItem.Get(`${context}/indices`, this._gltf.accessors, primitive.indices);
|
|
|
promises.push(this._loadIndicesAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
|
|
|
babylonGeometry.setIndices(data);
|
|
|
}));
|
|
@@ -771,7 +790,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
babylonMesh._delayInfo.push(kind);
|
|
|
}
|
|
|
|
|
|
- const accessor = ArrayItem.Get(`${context}/attributes/${attribute}`, this.gltf.accessors, attributes[attribute]);
|
|
|
+ const accessor = ArrayItem.Get(`${context}/attributes/${attribute}`, this._gltf.accessors, attributes[attribute]);
|
|
|
promises.push(this._loadVertexAccessorAsync(`/accessors/${accessor.index}`, accessor, kind).then((babylonVertexBuffer) => {
|
|
|
babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
|
|
|
}));
|
|
@@ -848,7 +867,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const accessor = ArrayItem.Get(`${context}/${attribute}`, this.gltf.accessors, attributes[attribute]);
|
|
|
+ const accessor = ArrayItem.Get(`${context}/${attribute}`, this._gltf.accessors, attributes[attribute]);
|
|
|
promises.push(this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
|
|
|
setData(babylonVertexBuffer, data);
|
|
|
}));
|
|
@@ -925,7 +944,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
const skeletonId = `skeleton${skin.index}`;
|
|
|
- const babylonSkeleton = new Skeleton(skin.name || skeletonId, skeletonId, this.babylonScene);
|
|
|
+ const babylonSkeleton = new Skeleton(skin.name || skeletonId, skeletonId, this._babylonScene);
|
|
|
|
|
|
// See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
|
|
|
babylonSkeleton.overrideMesh = this._rootBabylonMesh;
|
|
@@ -948,7 +967,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
private _loadBones(context: string, skin: ISkin, babylonSkeleton: Skeleton): void {
|
|
|
const babylonBones: { [index: number]: Bone } = {};
|
|
|
for (const index of skin.joints) {
|
|
|
- const node = ArrayItem.Get(`${context}/joints/${index}`, this.gltf.nodes, index);
|
|
|
+ const node = ArrayItem.Get(`${context}/joints/${index}`, this._gltf.nodes, index);
|
|
|
this._loadBone(node, skin, babylonSkeleton, babylonBones);
|
|
|
}
|
|
|
}
|
|
@@ -980,7 +999,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return Promise.resolve(null);
|
|
|
}
|
|
|
|
|
|
- const accessor = ArrayItem.Get(`${context}/inverseBindMatrices`, this.gltf.accessors, skin.inverseBindMatrices);
|
|
|
+ const accessor = ArrayItem.Get(`${context}/inverseBindMatrices`, this._gltf.accessors, skin.inverseBindMatrices);
|
|
|
return this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor);
|
|
|
}
|
|
|
|
|
@@ -1029,7 +1048,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
this.logOpen(`${context} ${camera.name || ""}`);
|
|
|
|
|
|
- const babylonCamera = new FreeCamera(camera.name || `camera${camera.index}`, Vector3.Zero(), this.babylonScene, false);
|
|
|
+ const babylonCamera = new FreeCamera(camera.name || `camera${camera.index}`, Vector3.Zero(), this._babylonScene, false);
|
|
|
babylonCamera.rotation = new Vector3(0, Math.PI, 0);
|
|
|
|
|
|
switch (camera.type) {
|
|
@@ -1073,7 +1092,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _loadAnimationsAsync(): Promise<void> {
|
|
|
- const animations = this.gltf.animations;
|
|
|
+ const animations = this._gltf.animations;
|
|
|
if (!animations) {
|
|
|
return Promise.resolve();
|
|
|
}
|
|
@@ -1100,7 +1119,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return promise;
|
|
|
}
|
|
|
|
|
|
- const babylonAnimationGroup = new AnimationGroup(animation.name || `animation${animation.index}`, this.babylonScene);
|
|
|
+ const babylonAnimationGroup = new AnimationGroup(animation.name || `animation${animation.index}`, this._babylonScene);
|
|
|
animation._babylonAnimationGroup = babylonAnimationGroup;
|
|
|
|
|
|
const promises = new Array<Promise<any>>();
|
|
@@ -1123,7 +1142,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return Promise.resolve();
|
|
|
}
|
|
|
|
|
|
- const targetNode = ArrayItem.Get(`${context}/target/node`, this.gltf.nodes, channel.target.node);
|
|
|
+ const targetNode = ArrayItem.Get(`${context}/target/node`, this._gltf.nodes, channel.target.node);
|
|
|
|
|
|
// Ignore animations that have no animation targets.
|
|
|
if ((channel.target.path === AnimationChannelTargetPath.WEIGHTS && !targetNode._numMorphTargets) ||
|
|
@@ -1281,8 +1300,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const inputAccessor = ArrayItem.Get(`${context}/input`, this.gltf.accessors, sampler.input);
|
|
|
- const outputAccessor = ArrayItem.Get(`${context}/output`, this.gltf.accessors, sampler.output);
|
|
|
+ const inputAccessor = ArrayItem.Get(`${context}/input`, this._gltf.accessors, sampler.input);
|
|
|
+ const outputAccessor = ArrayItem.Get(`${context}/output`, this._gltf.accessors, sampler.output);
|
|
|
sampler._data = Promise.all([
|
|
|
this._loadFloatAccessorAsync(`/accessors/${inputAccessor.index}`, inputAccessor),
|
|
|
this._loadFloatAccessorAsync(`/accessors/${outputAccessor.index}`, outputAccessor)
|
|
@@ -1306,7 +1325,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
throw new Error(`${context}/uri: Value is missing`);
|
|
|
}
|
|
|
|
|
|
- buffer._data = this.loadUriAsync(`${context}/uri`, buffer.uri);
|
|
|
+ buffer._data = this.loadUriAsync(`${context}/uri`, buffer, buffer.uri);
|
|
|
|
|
|
return buffer._data;
|
|
|
}
|
|
@@ -1322,7 +1341,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return bufferView._data;
|
|
|
}
|
|
|
|
|
|
- const buffer = ArrayItem.Get(`${context}/buffer`, this.gltf.buffers, bufferView.buffer);
|
|
|
+ const buffer = ArrayItem.Get(`${context}/buffer`, this._gltf.buffers, bufferView.buffer);
|
|
|
bufferView._data = this._loadBufferAsync(`/buffers/${buffer.index}`, buffer).then((data) => {
|
|
|
try {
|
|
|
return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
|
|
@@ -1350,7 +1369,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
return accessor._data as Promise<IndicesArray>;
|
|
|
}
|
|
|
|
|
|
- const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, accessor.bufferView);
|
|
|
+ const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);
|
|
|
accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
|
|
|
return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
|
|
|
});
|
|
@@ -1376,7 +1395,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
accessor._data = Promise.resolve(new Float32Array(length));
|
|
|
}
|
|
|
else {
|
|
|
- const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, accessor.bufferView);
|
|
|
+ const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);
|
|
|
accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
|
|
|
return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
|
|
|
});
|
|
@@ -1386,8 +1405,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
const sparse = accessor.sparse;
|
|
|
accessor._data = accessor._data.then((view: ArrayBufferView) => {
|
|
|
const data = view as Float32Array;
|
|
|
- const indicesBufferView = ArrayItem.Get(`${context}/sparse/indices/bufferView`, this.gltf.bufferViews, sparse.indices.bufferView);
|
|
|
- const valuesBufferView = ArrayItem.Get(`${context}/sparse/values/bufferView`, this.gltf.bufferViews, sparse.values.bufferView);
|
|
|
+ const indicesBufferView = ArrayItem.Get(`${context}/sparse/indices/bufferView`, this._gltf.bufferViews, sparse.indices.bufferView);
|
|
|
+ const valuesBufferView = ArrayItem.Get(`${context}/sparse/values/bufferView`, this._gltf.bufferViews, sparse.values.bufferView);
|
|
|
return Promise.all([
|
|
|
this.loadBufferViewAsync(`/bufferViews/${indicesBufferView.index}`, indicesBufferView),
|
|
|
this.loadBufferViewAsync(`/bufferViews/${valuesBufferView.index}`, valuesBufferView)
|
|
@@ -1417,7 +1436,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
bufferView._babylonBuffer = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
|
|
|
- return new Buffer(this.babylonScene.getEngine(), data, false);
|
|
|
+ return new Buffer(this._babylonScene.getEngine(), data, false);
|
|
|
});
|
|
|
|
|
|
return bufferView._babylonBuffer;
|
|
@@ -1430,21 +1449,21 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
if (accessor.sparse) {
|
|
|
accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
|
|
|
- return new VertexBuffer(this.babylonScene.getEngine(), data, kind, false);
|
|
|
+ return new VertexBuffer(this._babylonScene.getEngine(), data, kind, false);
|
|
|
});
|
|
|
}
|
|
|
// HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
|
|
|
else if (accessor.byteOffset && accessor.byteOffset % VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
|
|
|
Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
|
|
|
accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
|
|
|
- return new VertexBuffer(this.babylonScene.getEngine(), data, kind, false);
|
|
|
+ return new VertexBuffer(this._babylonScene.getEngine(), data, kind, false);
|
|
|
});
|
|
|
}
|
|
|
else {
|
|
|
- const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, accessor.bufferView);
|
|
|
+ const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, accessor.bufferView);
|
|
|
accessor._babylonVertexBuffer = this._loadVertexBufferViewAsync(bufferView, kind).then((babylonBuffer) => {
|
|
|
const size = GLTFLoader._GetNumComponents(context, accessor.type);
|
|
|
- return new VertexBuffer(this.babylonScene.getEngine(), babylonBuffer, kind, false, false, bufferView.byteStride,
|
|
|
+ return new VertexBuffer(this._babylonScene.getEngine(), babylonBuffer, kind, false, false, bufferView.byteStride,
|
|
|
false, accessor.byteOffset, size, accessor.componentType, accessor.normalized, true);
|
|
|
});
|
|
|
}
|
|
@@ -1538,8 +1557,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _createDefaultMaterial(name: string, babylonDrawMode: number): Material {
|
|
|
- const babylonMaterial = new PBRMaterial(name, this.babylonScene);
|
|
|
- babylonMaterial.sideOrientation = this.babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
|
|
|
+ const babylonMaterial = new PBRMaterial(name, this._babylonScene);
|
|
|
+ babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
|
|
|
babylonMaterial.fillMode = babylonDrawMode;
|
|
|
babylonMaterial.enableSpecularAntiAliasing = true;
|
|
|
babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage;
|
|
@@ -1621,8 +1640,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
babylonMaterial.bumpTexture = texture;
|
|
|
}));
|
|
|
|
|
|
- babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
|
|
|
- babylonMaterial.invertNormalMapY = this.babylonScene.useRightHandedSystem;
|
|
|
+ babylonMaterial.invertNormalMapX = !this._babylonScene.useRightHandedSystem;
|
|
|
+ babylonMaterial.invertNormalMapY = this._babylonScene.useRightHandedSystem;
|
|
|
if (material.normalTexture.scale != undefined) {
|
|
|
babylonMaterial.bumpTexture.level = material.normalTexture.scale;
|
|
|
}
|
|
@@ -1707,7 +1726,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
this.logOpen(`${context}`);
|
|
|
|
|
|
- const texture = ArrayItem.Get(`${context}/index`, this.gltf.textures, textureInfo.index);
|
|
|
+ const texture = ArrayItem.Get(`${context}/index`, this._gltf.textures, textureInfo.index);
|
|
|
const promise = this._loadTextureAsync(`/textures/${textureInfo.index}`, texture, (babylonTexture) => {
|
|
|
babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
|
|
|
|
|
@@ -1726,23 +1745,23 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
this.logOpen(`${context} ${texture.name || ""}`);
|
|
|
|
|
|
- const sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(`${context}/sampler`, this.gltf.samplers, texture.sampler));
|
|
|
+ const sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(`${context}/sampler`, this._gltf.samplers, texture.sampler));
|
|
|
const samplerData = this._loadSampler(`/samplers/${sampler.index}`, sampler);
|
|
|
|
|
|
- const image = ArrayItem.Get(`${context}/source`, this.gltf.images, texture.source);
|
|
|
+ const image = ArrayItem.Get(`${context}/source`, this._gltf.images, texture.source);
|
|
|
let url: Nullable<string> = null;
|
|
|
if (image.uri) {
|
|
|
if (Tools.IsBase64(image.uri)) {
|
|
|
url = image.uri;
|
|
|
}
|
|
|
- else if (this.babylonScene.getEngine().textureFormatInUse) {
|
|
|
+ else if (this._babylonScene.getEngine().textureFormatInUse) {
|
|
|
// If an image uri and a texture format is set like (eg. KTX) load from url instead of blob to support texture format and fallback
|
|
|
url = this._rootUrl + image.uri;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const deferred = new Deferred<void>();
|
|
|
- const babylonTexture = new Texture(url, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, () => {
|
|
|
+ const babylonTexture = new Texture(url, this._babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, () => {
|
|
|
if (!this._disposed) {
|
|
|
deferred.resolve();
|
|
|
}
|
|
@@ -1796,10 +1815,10 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
this.logOpen(`${context} ${image.name || ""}`);
|
|
|
|
|
|
if (image.uri) {
|
|
|
- image._data = this.loadUriAsync(`${context}/uri`, image.uri);
|
|
|
+ image._data = this.loadUriAsync(`${context}/uri`, image, image.uri);
|
|
|
}
|
|
|
else {
|
|
|
- const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, image.bufferView);
|
|
|
+ const bufferView = ArrayItem.Get(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);
|
|
|
image._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView);
|
|
|
}
|
|
|
|
|
@@ -1812,11 +1831,12 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
/**
|
|
|
* Loads a glTF uri.
|
|
|
* @param context The context when loading the asset
|
|
|
+ * @param property The glTF property associated with the uri
|
|
|
* @param uri The base64 or relative uri
|
|
|
* @returns A promise that resolves with the loaded data when the load is complete
|
|
|
*/
|
|
|
- public loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
|
|
|
- const extensionPromise = this._extensionsLoadUriAsync(context, uri);
|
|
|
+ public loadUriAsync(context: string, property: IProperty, uri: string): Promise<ArrayBufferView> {
|
|
|
+ const extensionPromise = this._extensionsLoadUriAsync(context, property, uri);
|
|
|
if (extensionPromise) {
|
|
|
return extensionPromise;
|
|
|
}
|
|
@@ -1859,7 +1879,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }, this.babylonScene.offlineProvider, true, (request, exception) => {
|
|
|
+ }, this._babylonScene.offlineProvider, true, (request, exception) => {
|
|
|
if (!this._disposed) {
|
|
|
reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
|
|
|
}
|
|
@@ -2016,8 +2036,8 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
const promises = new Array<Promise<any>>();
|
|
|
|
|
|
- if (this.gltf.materials) {
|
|
|
- for (const material of this.gltf.materials) {
|
|
|
+ if (this._gltf.materials) {
|
|
|
+ for (const material of this._gltf.materials) {
|
|
|
if (material._data) {
|
|
|
for (const babylonDrawMode in material._data) {
|
|
|
const babylonData = material._data[babylonDrawMode];
|
|
@@ -2046,7 +2066,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
|
|
|
const promises = new Array<Promise<any>>();
|
|
|
|
|
|
- const lights = this.babylonScene.lights;
|
|
|
+ const lights = this._babylonScene.lights;
|
|
|
for (let light of lights) {
|
|
|
let generator = light.getShadowGenerator();
|
|
|
if (generator) {
|
|
@@ -2068,15 +2088,16 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private _applyExtensions<T>(property: IProperty, actionAsync: (extension: IGLTFLoaderExtension) => Nullable<T> | undefined): Nullable<T> {
|
|
|
+ private _applyExtensions<T>(property: IProperty, functionName: string, actionAsync: (extension: IGLTFLoaderExtension) => Nullable<T> | undefined): Nullable<T> {
|
|
|
for (const name of GLTFLoader._ExtensionNames) {
|
|
|
const extension = this._extensions[name];
|
|
|
if (extension.enabled) {
|
|
|
+ const id = `${name}.${functionName}`;
|
|
|
const loaderProperty = property as ILoaderProperty;
|
|
|
- loaderProperty._activeLoaderExtensions = loaderProperty._activeLoaderExtensions || {};
|
|
|
- const activeLoaderExtensions = loaderProperty._activeLoaderExtensions;
|
|
|
- if (!activeLoaderExtensions[name]) {
|
|
|
- activeLoaderExtensions[name] = true;
|
|
|
+ loaderProperty._activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions || {};
|
|
|
+ const activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions;
|
|
|
+ if (!activeLoaderExtensionFunctions[id]) {
|
|
|
+ activeLoaderExtensionFunctions[id] = true;
|
|
|
|
|
|
try {
|
|
|
const result = actionAsync(extension);
|
|
@@ -2085,7 +2106,7 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
}
|
|
|
finally {
|
|
|
- delete activeLoaderExtensions[name];
|
|
|
+ delete activeLoaderExtensionFunctions[id];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2103,43 +2124,43 @@ export class GLTFLoader implements IGLTFLoader {
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadSceneAsync(context: string, scene: IScene): Nullable<Promise<void>> {
|
|
|
- return this._applyExtensions(scene, (extension) => extension.loadSceneAsync && extension.loadSceneAsync(context, scene));
|
|
|
+ return this._applyExtensions(scene, "loadScene", (extension) => extension.loadSceneAsync && extension.loadSceneAsync(context, scene));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadNodeAsync(context: string, node: INode, assign: (babylonTransformNode: TransformNode) => void): Nullable<Promise<TransformNode>> {
|
|
|
- return this._applyExtensions(node, (extension) => extension.loadNodeAsync && extension.loadNodeAsync(context, node, assign));
|
|
|
+ return this._applyExtensions(node, "loadNode", (extension) => extension.loadNodeAsync && extension.loadNodeAsync(context, node, assign));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadCameraAsync(context: string, camera: ICamera, assign: (babylonCamera: Camera) => void): Nullable<Promise<Camera>> {
|
|
|
- return this._applyExtensions(camera, (extension) => extension.loadCameraAsync && extension.loadCameraAsync(context, camera, assign));
|
|
|
+ return this._applyExtensions(camera, "loadCamera", (extension) => extension.loadCameraAsync && extension.loadCameraAsync(context, camera, assign));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadVertexDataAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
|
|
|
- return this._applyExtensions(primitive, (extension) => extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh));
|
|
|
+ return this._applyExtensions(primitive, "loadVertexData", (extension) => extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadMaterialAsync(context: string, material: IMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<Material>> {
|
|
|
- return this._applyExtensions(material, (extension) => extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign));
|
|
|
+ return this._applyExtensions(material, "loadMaterial", (extension) => extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign));
|
|
|
}
|
|
|
|
|
|
private _extensionsCreateMaterial(context: string, material: IMaterial, babylonDrawMode: number): Nullable<Material> {
|
|
|
- return this._applyExtensions({}, (extension) => extension.createMaterial && extension.createMaterial(context, material, babylonDrawMode));
|
|
|
+ return this._applyExtensions(material, "createMaterial", (extension) => extension.createMaterial && extension.createMaterial(context, material, babylonDrawMode));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>> {
|
|
|
- return this._applyExtensions(material, (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial));
|
|
|
+ return this._applyExtensions(material, "loadMaterialProperties", (extension) => extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>> {
|
|
|
- return this._applyExtensions(textureInfo, (extension) => extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign));
|
|
|
+ return this._applyExtensions(textureInfo, "loadTextureInfo", (extension) => extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign));
|
|
|
}
|
|
|
|
|
|
private _extensionsLoadAnimationAsync(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>> {
|
|
|
- return this._applyExtensions(animation, (extension) => extension.loadAnimationAsync && extension.loadAnimationAsync(context, animation));
|
|
|
+ return this._applyExtensions(animation, "loadAnimation", (extension) => extension.loadAnimationAsync && extension.loadAnimationAsync(context, animation));
|
|
|
}
|
|
|
|
|
|
- private _extensionsLoadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> {
|
|
|
- return this._applyExtensions({}, (extension) => extension._loadUriAsync && extension._loadUriAsync(context, uri));
|
|
|
+ private _extensionsLoadUriAsync(context: string, property: IProperty, uri: string): Nullable<Promise<ArrayBufferView>> {
|
|
|
+ return this._applyExtensions(property, "loadUri", (extension) => extension._loadUriAsync && extension._loadUriAsync(context, property, uri));
|
|
|
}
|
|
|
|
|
|
/**
|