|
@@ -2434,203 +2434,146 @@ var BABYLON;
|
|
(function (BABYLON) {
|
|
(function (BABYLON) {
|
|
var GLTF2;
|
|
var GLTF2;
|
|
(function (GLTF2) {
|
|
(function (GLTF2) {
|
|
- /**
|
|
|
|
- * Values
|
|
|
|
- */
|
|
|
|
- var glTFAnimationPaths = ["translation", "rotation", "scale", "weights"];
|
|
|
|
- var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling", "influence"];
|
|
|
|
- /**
|
|
|
|
- * Utils
|
|
|
|
- */
|
|
|
|
- var normalizeUVs = function (buffer) {
|
|
|
|
- if (!buffer) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- for (var i = 0; i < buffer.length / 2; i++) {
|
|
|
|
- buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1];
|
|
|
|
- }
|
|
|
|
- };
|
|
|
|
- var createStringId = function (index) {
|
|
|
|
|
|
+ var getNodeID = function (index) {
|
|
return "node" + index;
|
|
return "node" + index;
|
|
};
|
|
};
|
|
- /**
|
|
|
|
- * Returns the animation path (glTF -> Babylon)
|
|
|
|
- */
|
|
|
|
- var getAnimationPath = function (path) {
|
|
|
|
- var index = glTFAnimationPaths.indexOf(path);
|
|
|
|
- if (index !== -1) {
|
|
|
|
- return babylonAnimationPaths[index];
|
|
|
|
|
|
+ var loadAnimation = function (runtime, animation, animationIndex) {
|
|
|
|
+ for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
|
|
|
|
+ var channel = animation.channels[channelIndex];
|
|
|
|
+ if (!channel) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + "] Channel " + channelIndex + " does not exist");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var samplerIndex = channel.sampler;
|
|
|
|
+ if (samplerIndex === undefined) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + samplerIndex + "] Sampler is not defined");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var sampler = animation.samplers[samplerIndex];
|
|
|
|
+ if (!sampler) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler " + samplerIndex + " does not exist");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if (!channel.target) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target does not exist");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var targetNode = runtime.babylonScene.getNodeByID(getNodeID(channel.target.node));
|
|
|
|
+ if (!targetNode) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target node " + channel.target.node + " does not exist");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var targetPath = {
|
|
|
|
+ "translation": "position",
|
|
|
|
+ "rotation": "rotationQuaternion",
|
|
|
|
+ "scale": "scaling",
|
|
|
|
+ "weights": "influence"
|
|
|
|
+ }[channel.target.path];
|
|
|
|
+ if (!targetPath) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Target path " + channel.target.path + " is invalid");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var inputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.input]);
|
|
|
|
+ var outputBuffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[sampler.output]);
|
|
|
|
+ var outputBufferOffset = 0;
|
|
|
|
+ var animationType = {
|
|
|
|
+ "position": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
|
|
|
|
+ "rotationQuaternion": BABYLON.Animation.ANIMATIONTYPE_QUATERNION,
|
|
|
|
+ "scale": BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
|
|
|
|
+ "influence": BABYLON.Animation.ANIMATIONTYPE_FLOAT,
|
|
|
|
+ }[targetPath];
|
|
|
|
+ var getNextOutputValue = {
|
|
|
|
+ "position": function () {
|
|
|
|
+ var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
|
|
|
|
+ outputBufferOffset += 3;
|
|
|
|
+ return value;
|
|
|
|
+ },
|
|
|
|
+ "rotationQuaternion": function () {
|
|
|
|
+ var value = BABYLON.Quaternion.FromArray(outputBuffer, outputBufferOffset);
|
|
|
|
+ outputBufferOffset += 4;
|
|
|
|
+ return value;
|
|
|
|
+ },
|
|
|
|
+ "scale": function () {
|
|
|
|
+ var value = BABYLON.Vector3.FromArray(outputBuffer, outputBufferOffset);
|
|
|
|
+ outputBufferOffset += 3;
|
|
|
|
+ return value;
|
|
|
|
+ },
|
|
|
|
+ "influence": function () {
|
|
|
|
+ var numTargets = targetNode.morphTargetManager.numTargets;
|
|
|
|
+ var value = new Array(numTargets);
|
|
|
|
+ for (var i = 0; i < numTargets; i++) {
|
|
|
|
+ value[i] = outputBuffer[outputBufferOffset++];
|
|
|
|
+ }
|
|
|
|
+ return value;
|
|
|
|
+ },
|
|
|
|
+ }[targetPath];
|
|
|
|
+ var getNextKey = {
|
|
|
|
+ "LINEAR": function (frameIndex) { return ({
|
|
|
|
+ frame: inputBuffer[frameIndex],
|
|
|
|
+ value: getNextOutputValue()
|
|
|
|
+ }); },
|
|
|
|
+ "CUBICSPLINE": function (frameIndex) { return ({
|
|
|
|
+ frame: inputBuffer[frameIndex],
|
|
|
|
+ inTangent: getNextOutputValue(),
|
|
|
|
+ value: getNextOutputValue(),
|
|
|
|
+ outTangent: getNextOutputValue()
|
|
|
|
+ }); },
|
|
|
|
+ }[sampler.interpolation];
|
|
|
|
+ if (!getNextKey) {
|
|
|
|
+ BABYLON.Tools.Warn("[Animation " + animationIndex + ", Channel + " + channelIndex + "] Sampler interpolation '" + sampler.interpolation + "' is invalid");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var keys = new Array(inputBuffer.length);
|
|
|
|
+ for (var frameIndex = 0; frameIndex < inputBuffer.length; frameIndex++) {
|
|
|
|
+ keys[frameIndex] = getNextKey(frameIndex);
|
|
|
|
+ }
|
|
|
|
+ if (targetPath === "influence") {
|
|
|
|
+ var targetMesh = targetNode;
|
|
|
|
+ for (var targetIndex = 0; targetIndex < targetMesh.morphTargetManager.numTargets; targetIndex++) {
|
|
|
|
+ var morphTarget = targetMesh.morphTargetManager.getTarget(targetIndex);
|
|
|
|
+ var animationName = (animation.name || "anim" + animationIndex) + "_" + targetIndex;
|
|
|
|
+ var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
|
|
|
|
+ babylonAnimation.setKeys(keys.map(function (key) { return ({
|
|
|
|
+ frame: key.frame,
|
|
|
|
+ inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined,
|
|
|
|
+ value: key.value[targetIndex],
|
|
|
|
+ outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
|
|
|
|
+ }); }));
|
|
|
|
+ morphTarget.animations.push(babylonAnimation);
|
|
|
|
+ runtime.babylonScene.beginAnimation(morphTarget, 0, inputBuffer[inputBuffer.length - 1], true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ var animationName = animation.name || "anim" + animationIndex;
|
|
|
|
+ var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
|
|
|
|
+ babylonAnimation.setKeys(keys);
|
|
|
|
+ targetNode.animations.push(babylonAnimation);
|
|
|
|
+ runtime.babylonScene.beginAnimation(targetNode, 0, inputBuffer[inputBuffer.length - 1], true);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- return path;
|
|
|
|
};
|
|
};
|
|
/**
|
|
/**
|
|
* Loads and creates animations
|
|
* Loads and creates animations
|
|
*/
|
|
*/
|
|
var loadAnimations = function (runtime) {
|
|
var loadAnimations = function (runtime) {
|
|
var animations = runtime.gltf.animations;
|
|
var animations = runtime.gltf.animations;
|
|
- if (!animations) {
|
|
|
|
|
|
+ if (!animations || animations.length === 0) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
for (var animationIndex = 0; animationIndex < animations.length; animationIndex++) {
|
|
for (var animationIndex = 0; animationIndex < animations.length; animationIndex++) {
|
|
var animation = animations[animationIndex];
|
|
var animation = animations[animationIndex];
|
|
- if (!animation || !animation.channels || !animation.samplers) {
|
|
|
|
|
|
+ if (!animation) {
|
|
|
|
+ BABYLON.Tools.Warn("Animation " + animationIndex + " not found");
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- var lastAnimation = null;
|
|
|
|
- for (var channelIndex = 0; channelIndex < animation.channels.length; channelIndex++) {
|
|
|
|
- var channel = animation.channels[channelIndex];
|
|
|
|
- if (!channel) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- var sampler = animation.samplers[channel.sampler];
|
|
|
|
- if (!sampler) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- var inputData = sampler.input;
|
|
|
|
- var outputData = sampler.output;
|
|
|
|
- var bufferInput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[inputData]);
|
|
|
|
- var bufferOutput = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, runtime.gltf.accessors[outputData]);
|
|
|
|
- var targetID = channel.target.node;
|
|
|
|
- var targetNode = runtime.babylonScene.getNodeByID(createStringId(targetID));
|
|
|
|
- if (targetNode === null) {
|
|
|
|
- BABYLON.Tools.Warn("Creating animation index " + animationIndex + " but cannot find node index " + targetID + " to attach to");
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- var isBone = targetNode instanceof BABYLON.Bone;
|
|
|
|
- var numTargets = 0;
|
|
|
|
- // Get target path (position, rotation, scaling, or weights)
|
|
|
|
- var targetPath = channel.target.path;
|
|
|
|
- var targetPathIndex = glTFAnimationPaths.indexOf(targetPath);
|
|
|
|
- if (targetPathIndex !== -1) {
|
|
|
|
- targetPath = babylonAnimationPaths[targetPathIndex];
|
|
|
|
- }
|
|
|
|
- var isMorph = targetPath === "influence";
|
|
|
|
- // Determine animation type
|
|
|
|
- var animationType = BABYLON.Animation.ANIMATIONTYPE_MATRIX;
|
|
|
|
- if (!isBone) {
|
|
|
|
- if (targetPath === "rotationQuaternion") {
|
|
|
|
- animationType = BABYLON.Animation.ANIMATIONTYPE_QUATERNION;
|
|
|
|
- targetNode.rotationQuaternion = new BABYLON.Quaternion();
|
|
|
|
- }
|
|
|
|
- else if (isMorph) {
|
|
|
|
- animationType = BABYLON.Animation.ANIMATIONTYPE_FLOAT;
|
|
|
|
- numTargets = targetNode.morphTargetManager.numTargets;
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- animationType = BABYLON.Animation.ANIMATIONTYPE_VECTOR3;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // Create animation and key frames
|
|
|
|
- var babylonAnimation = null;
|
|
|
|
- var keys = [];
|
|
|
|
- var arrayOffset = 0;
|
|
|
|
- var modifyKey = false;
|
|
|
|
- if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) {
|
|
|
|
- babylonAnimation = lastAnimation;
|
|
|
|
- modifyKey = true;
|
|
|
|
- }
|
|
|
|
- // Each morph animation may have more than one more, so we need a
|
|
|
|
- // multi dimensional array.
|
|
|
|
- if (isMorph) {
|
|
|
|
- for (var influence = 0; influence < numTargets; influence++) {
|
|
|
|
- keys[influence] = [];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // For each frame
|
|
|
|
- for (var frameIndex = 0; frameIndex < bufferInput.length; frameIndex++) {
|
|
|
|
- var value = null;
|
|
|
|
- if (targetPath === "rotationQuaternion") {
|
|
|
|
- value = BABYLON.Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]);
|
|
|
|
- arrayOffset += 4;
|
|
|
|
- }
|
|
|
|
- else if (isMorph) {
|
|
|
|
- value = [];
|
|
|
|
- // There is 1 value for each morph target for each frame
|
|
|
|
- for (var influence = 0; influence < numTargets; influence++) {
|
|
|
|
- value.push(bufferOutput[arrayOffset + influence]);
|
|
|
|
- }
|
|
|
|
- arrayOffset += numTargets;
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- value = BABYLON.Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]);
|
|
|
|
- arrayOffset += 3;
|
|
|
|
- }
|
|
|
|
- if (isBone) {
|
|
|
|
- var bone = targetNode;
|
|
|
|
- var translation = BABYLON.Vector3.Zero();
|
|
|
|
- var rotationQuaternion = new BABYLON.Quaternion();
|
|
|
|
- var scaling = BABYLON.Vector3.Zero();
|
|
|
|
- // Warning on decompose
|
|
|
|
- var mat = bone.getBaseMatrix();
|
|
|
|
- if (modifyKey) {
|
|
|
|
- mat = lastAnimation.getKeys()[frameIndex].value;
|
|
|
|
- }
|
|
|
|
- mat.decompose(scaling, rotationQuaternion, translation);
|
|
|
|
- if (targetPath === "position") {
|
|
|
|
- translation = value;
|
|
|
|
- }
|
|
|
|
- else if (targetPath === "rotationQuaternion") {
|
|
|
|
- rotationQuaternion = value;
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- scaling = value;
|
|
|
|
- }
|
|
|
|
- value = BABYLON.Matrix.Compose(scaling, rotationQuaternion, translation);
|
|
|
|
- }
|
|
|
|
- if (!modifyKey) {
|
|
|
|
- if (isMorph) {
|
|
|
|
- for (var influence = 0; influence < numTargets; influence++) {
|
|
|
|
- keys[influence].push({
|
|
|
|
- frame: bufferInput[frameIndex],
|
|
|
|
- value: value[influence]
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- keys.push({
|
|
|
|
- frame: bufferInput[frameIndex],
|
|
|
|
- value: value
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- lastAnimation.getKeys()[frameIndex].value = value;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- // Finish
|
|
|
|
- if (!modifyKey) {
|
|
|
|
- if (isMorph) {
|
|
|
|
- for (var influence = 0; influence < numTargets; influence++) {
|
|
|
|
- var morphTarget = targetNode.morphTargetManager.getTarget(influence);
|
|
|
|
- if (morphTarget.animations === undefined) {
|
|
|
|
- morphTarget.animations = [];
|
|
|
|
- }
|
|
|
|
- var animationName = (animation.name || "anim" + animationIndex) + "_" + influence;
|
|
|
|
- babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
|
|
|
|
- babylonAnimation.setKeys(keys[influence]);
|
|
|
|
- morphTarget.animations.push(babylonAnimation);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- var animationName = animation.name || "anim" + animationIndex;
|
|
|
|
- babylonAnimation = new BABYLON.Animation(animationName, isBone ? "_matrix" : targetPath, 1, animationType, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
|
|
|
|
- babylonAnimation.setKeys(keys);
|
|
|
|
- targetNode.animations.push(babylonAnimation);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- lastAnimation = babylonAnimation;
|
|
|
|
- if (isMorph) {
|
|
|
|
- for (var influence = 0; influence < numTargets; influence++) {
|
|
|
|
- var morph = targetNode.morphTargetManager.getTarget(influence);
|
|
|
|
- runtime.babylonScene.stopAnimation(morph);
|
|
|
|
- runtime.babylonScene.beginAnimation(morph, 0, bufferInput[bufferInput.length - 1], true, 1.0);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- runtime.babylonScene.stopAnimation(targetNode);
|
|
|
|
- runtime.babylonScene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0);
|
|
|
|
- }
|
|
|
|
|
|
+ if (!animation.channels || animation.channels.length === 0) {
|
|
|
|
+ BABYLON.Tools.Warn("Animation " + animationIndex + " has no channels");
|
|
}
|
|
}
|
|
|
|
+ if (!animation.samplers || animation.samplers.length === 0) {
|
|
|
|
+ BABYLON.Tools.Warn("Animation " + animationIndex + " has no samplers");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ loadAnimation(runtime, animation, animationIndex);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
/**
|
|
/**
|
|
@@ -2654,7 +2597,7 @@ var BABYLON;
|
|
*/
|
|
*/
|
|
var getParentBone = function (runtime, skin, index, newSkeleton) {
|
|
var getParentBone = function (runtime, skin, index, newSkeleton) {
|
|
// Try to find
|
|
// Try to find
|
|
- var nodeStringID = createStringId(index);
|
|
|
|
|
|
+ var nodeStringID = getNodeID(index);
|
|
for (var i = 0; i < newSkeleton.bones.length; i++) {
|
|
for (var i = 0; i < newSkeleton.bones.length; i++) {
|
|
if (newSkeleton.bones[i].id === nodeStringID) {
|
|
if (newSkeleton.bones[i].id === nodeStringID) {
|
|
return newSkeleton.bones[i].getParent();
|
|
return newSkeleton.bones[i].getParent();
|
|
@@ -2674,8 +2617,8 @@ var BABYLON;
|
|
}
|
|
}
|
|
if (childID === index) {
|
|
if (childID === index) {
|
|
var mat = configureBoneTransformation(parent);
|
|
var mat = configureBoneTransformation(parent);
|
|
- var bone = new BABYLON.Bone(parent.name || createStringId(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
|
|
|
|
- bone.id = createStringId(parentID);
|
|
|
|
|
|
+ var bone = new BABYLON.Bone(parent.name || getNodeID(parentID), newSkeleton, getParentBone(runtime, skin, parentID, newSkeleton), mat);
|
|
|
|
+ bone.id = getNodeID(parentID);
|
|
return bone;
|
|
return bone;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -2735,8 +2678,8 @@ var BABYLON;
|
|
}
|
|
}
|
|
// Create node to root bone
|
|
// Create node to root bone
|
|
var mat = configureBoneTransformation(node);
|
|
var mat = configureBoneTransformation(node);
|
|
- var bone = new BABYLON.Bone(node.name || createStringId(i), newSkeleton, null, mat);
|
|
|
|
- bone.id = createStringId(i);
|
|
|
|
|
|
+ var bone = new BABYLON.Bone(node.name || getNodeID(i), newSkeleton, null, mat);
|
|
|
|
+ bone.id = getNodeID(i);
|
|
nodesToRoot.push({ bone: bone, node: node, index: i });
|
|
nodesToRoot.push({ bone: bone, node: node, index: i });
|
|
}
|
|
}
|
|
// Parenting
|
|
// Parenting
|
|
@@ -2789,7 +2732,7 @@ var BABYLON;
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
var index = jointNode.index;
|
|
var index = jointNode.index;
|
|
- var stringID = createStringId(index);
|
|
|
|
|
|
+ var stringID = getNodeID(index);
|
|
// Optimize, if the bone already exists...
|
|
// Optimize, if the bone already exists...
|
|
var existingBone = runtime.babylonScene.getBoneByID(stringID);
|
|
var existingBone = runtime.babylonScene.getBoneByID(stringID);
|
|
if (existingBone) {
|
|
if (existingBone) {
|
|
@@ -2839,7 +2782,7 @@ var BABYLON;
|
|
if (!jointNode) {
|
|
if (!jointNode) {
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- var jointNodeStringId = createStringId(jointNode.index);
|
|
|
|
|
|
+ var jointNodeStringId = getNodeID(jointNode.index);
|
|
for (var j = 0; j < bones.length; j++) {
|
|
for (var j = 0; j < bones.length; j++) {
|
|
if (bones[j].id === jointNodeStringId) {
|
|
if (bones[j].id === jointNodeStringId) {
|
|
babylonSkeleton.bones.push(bones[j]);
|
|
babylonSkeleton.bones.push(bones[j]);
|
|
@@ -2894,7 +2837,7 @@ var BABYLON;
|
|
var verticesCounts = [];
|
|
var verticesCounts = [];
|
|
var indexStarts = [];
|
|
var indexStarts = [];
|
|
var indexCounts = [];
|
|
var indexCounts = [];
|
|
- var morphTargetManager = new BABYLON.MorphTargetManager();
|
|
|
|
|
|
+ var morphTargetManager;
|
|
// Positions, normals and UVs
|
|
// Positions, normals and UVs
|
|
for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
|
|
for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
|
|
// Temporary vertex data
|
|
// Temporary vertex data
|
|
@@ -2912,37 +2855,28 @@ var BABYLON;
|
|
accessor = runtime.gltf.accessors[attributes[semantic]];
|
|
accessor = runtime.gltf.accessors[attributes[semantic]];
|
|
buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
if (semantic === "NORMAL") {
|
|
if (semantic === "NORMAL") {
|
|
- tempVertexData.normals = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.normals.set(buffer);
|
|
|
|
|
|
+ tempVertexData.normals = buffer;
|
|
}
|
|
}
|
|
else if (semantic === "POSITION") {
|
|
else if (semantic === "POSITION") {
|
|
- tempVertexData.positions = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.positions.set(buffer);
|
|
|
|
|
|
+ tempVertexData.positions = buffer;
|
|
verticesCounts.push(tempVertexData.positions.length);
|
|
verticesCounts.push(tempVertexData.positions.length);
|
|
}
|
|
}
|
|
else if (semantic === "TANGENT") {
|
|
else if (semantic === "TANGENT") {
|
|
- tempVertexData.tangents = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.tangents.set(buffer);
|
|
|
|
|
|
+ tempVertexData.tangents = buffer;
|
|
}
|
|
}
|
|
else if (semantic.indexOf("TEXCOORD_") !== -1) {
|
|
else if (semantic.indexOf("TEXCOORD_") !== -1) {
|
|
var channel = Number(semantic.split("_")[1]);
|
|
var channel = Number(semantic.split("_")[1]);
|
|
var uvKind = BABYLON.VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
|
|
var uvKind = BABYLON.VertexBuffer.UVKind + (channel === 0 ? "" : (channel + 1));
|
|
- var uvs = new Float32Array(buffer.length);
|
|
|
|
- uvs.set(buffer);
|
|
|
|
- normalizeUVs(uvs);
|
|
|
|
- tempVertexData.set(uvs, uvKind);
|
|
|
|
|
|
+ tempVertexData.set(buffer, uvKind);
|
|
}
|
|
}
|
|
else if (semantic === "JOINT") {
|
|
else if (semantic === "JOINT") {
|
|
- tempVertexData.matricesIndices = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.matricesIndices.set(buffer);
|
|
|
|
|
|
+ tempVertexData.matricesIndices = buffer;
|
|
}
|
|
}
|
|
else if (semantic === "WEIGHT") {
|
|
else if (semantic === "WEIGHT") {
|
|
- tempVertexData.matricesWeights = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.matricesWeights.set(buffer);
|
|
|
|
|
|
+ tempVertexData.matricesWeights = buffer;
|
|
}
|
|
}
|
|
else if (semantic === "COLOR_0") {
|
|
else if (semantic === "COLOR_0") {
|
|
- tempVertexData.colors = new Float32Array(buffer.length);
|
|
|
|
- tempVertexData.colors.set(buffer);
|
|
|
|
|
|
+ tempVertexData.colors = buffer;
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
|
|
BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
|
|
@@ -2952,17 +2886,15 @@ var BABYLON;
|
|
accessor = runtime.gltf.accessors[primitive.indices];
|
|
accessor = runtime.gltf.accessors[primitive.indices];
|
|
if (accessor) {
|
|
if (accessor) {
|
|
buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
- tempVertexData.indices = new Int32Array(buffer.length);
|
|
|
|
- tempVertexData.indices.set(buffer);
|
|
|
|
|
|
+ tempVertexData.indices = buffer;
|
|
indexCounts.push(tempVertexData.indices.length);
|
|
indexCounts.push(tempVertexData.indices.length);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
// Set indices on the fly
|
|
// Set indices on the fly
|
|
- var indices = [];
|
|
|
|
- for (var index = 0; index < tempVertexData.positions.length / 3; index++) {
|
|
|
|
- indices.push(index);
|
|
|
|
|
|
+ tempVertexData.indices = new Uint32Array(tempVertexData.positions.length / 3);
|
|
|
|
+ for (var index = 0; index < tempVertexData.indices.length; index++) {
|
|
|
|
+ tempVertexData.indices[index] = index;
|
|
}
|
|
}
|
|
- tempVertexData.indices = new Int32Array(indices);
|
|
|
|
indexCounts.push(tempVertexData.indices.length);
|
|
indexCounts.push(tempVertexData.indices.length);
|
|
}
|
|
}
|
|
vertexData.merge(tempVertexData);
|
|
vertexData.merge(tempVertexData);
|
|
@@ -2971,22 +2903,22 @@ var BABYLON;
|
|
var material = getMaterial(runtime, primitive.material);
|
|
var material = getMaterial(runtime, primitive.material);
|
|
multiMat.subMaterials.push(material);
|
|
multiMat.subMaterials.push(material);
|
|
// Morph Targets
|
|
// Morph Targets
|
|
- if (primitive.targets !== undefined) {
|
|
|
|
|
|
+ if (primitive.targets) {
|
|
for (var targetsIndex = 0; targetsIndex < primitive.targets.length; targetsIndex++) {
|
|
for (var targetsIndex = 0; targetsIndex < primitive.targets.length; targetsIndex++) {
|
|
var target = primitive.targets[targetsIndex];
|
|
var target = primitive.targets[targetsIndex];
|
|
var weight = 0.0;
|
|
var weight = 0.0;
|
|
- if (node.weights !== undefined) {
|
|
|
|
|
|
+ if (node.weights) {
|
|
weight = node.weights[targetsIndex];
|
|
weight = node.weights[targetsIndex];
|
|
}
|
|
}
|
|
- else if (mesh.weights !== undefined) {
|
|
|
|
|
|
+ else if (mesh.weights) {
|
|
weight = mesh.weights[targetsIndex];
|
|
weight = mesh.weights[targetsIndex];
|
|
}
|
|
}
|
|
var morph = new BABYLON.MorphTarget("morph" + targetsIndex, weight);
|
|
var morph = new BABYLON.MorphTarget("morph" + targetsIndex, weight);
|
|
for (var semantic in target) {
|
|
for (var semantic in target) {
|
|
// Link accessor and buffer view
|
|
// Link accessor and buffer view
|
|
accessor = runtime.gltf.accessors[target[semantic]];
|
|
accessor = runtime.gltf.accessors[target[semantic]];
|
|
- buffer = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
|
|
- if (accessor.name !== undefined) {
|
|
|
|
|
|
+ var values = GLTF2.GLTFUtils.GetBufferFromAccessor(runtime, accessor);
|
|
|
|
+ if (accessor.name) {
|
|
morph.name = accessor.name;
|
|
morph.name = accessor.name;
|
|
}
|
|
}
|
|
// glTF stores morph target information as deltas
|
|
// glTF stores morph target information as deltas
|
|
@@ -2994,34 +2926,38 @@ var BABYLON;
|
|
// As a result we have to add the original data to the delta to calculate
|
|
// As a result we have to add the original data to the delta to calculate
|
|
// the final data.
|
|
// the final data.
|
|
if (semantic === "NORMAL") {
|
|
if (semantic === "NORMAL") {
|
|
- for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
|
|
|
|
- buffer[bufferIndex] += vertexData.normals[bufferIndex];
|
|
|
|
|
|
+ for (var i = 0; i < values.length; i++) {
|
|
|
|
+ values[i] += vertexData.normals[i];
|
|
}
|
|
}
|
|
- morph.setNormals(buffer);
|
|
|
|
|
|
+ morph.setNormals(values);
|
|
}
|
|
}
|
|
else if (semantic === "POSITION") {
|
|
else if (semantic === "POSITION") {
|
|
- for (var bufferIndex = 0; bufferIndex < buffer.length; bufferIndex++) {
|
|
|
|
- buffer[bufferIndex] += vertexData.positions[bufferIndex];
|
|
|
|
|
|
+ for (var i = 0; i < values.length; i++) {
|
|
|
|
+ values[i] += vertexData.positions[i];
|
|
}
|
|
}
|
|
- morph.setPositions(buffer);
|
|
|
|
|
|
+ morph.setPositions(values);
|
|
}
|
|
}
|
|
else if (semantic === "TANGENT") {
|
|
else if (semantic === "TANGENT") {
|
|
// Tangent data for morph targets is stored as xyz delta.
|
|
// Tangent data for morph targets is stored as xyz delta.
|
|
// The vertexData.tangent is stored as xyzw.
|
|
// The vertexData.tangent is stored as xyzw.
|
|
// So we need to skip every fourth vertexData.tangent.
|
|
// So we need to skip every fourth vertexData.tangent.
|
|
- for (var bufferIndex = 0, tangentsIndex = 0; bufferIndex < buffer.length; bufferIndex++, tangentsIndex++) {
|
|
|
|
- buffer[bufferIndex] += vertexData.tangents[tangentsIndex];
|
|
|
|
- if ((bufferIndex + 1) % 3 == 0) {
|
|
|
|
- tangentsIndex++;
|
|
|
|
|
|
+ for (var i = 0, j = 0; i < values.length; i++, j++) {
|
|
|
|
+ values[i] += vertexData.tangents[j];
|
|
|
|
+ if ((i + 1) % 3 == 0) {
|
|
|
|
+ j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- morph.setTangents(buffer);
|
|
|
|
|
|
+ morph.setTangents(values);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
|
|
BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (morph.getPositions() !== undefined) {
|
|
|
|
|
|
+ if (morph.getPositions()) {
|
|
|
|
+ if (!morphTargetManager) {
|
|
|
|
+ morphTargetManager = new BABYLON.MorphTargetManager();
|
|
|
|
+ babylonMesh.morphTargetManager = morphTargetManager;
|
|
|
|
+ }
|
|
morphTargetManager.addTarget(morph);
|
|
morphTargetManager.addTarget(morph);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
@@ -3036,10 +2972,6 @@ var BABYLON;
|
|
// Apply geometry
|
|
// Apply geometry
|
|
geometry.setAllVerticesData(vertexData, false);
|
|
geometry.setAllVerticesData(vertexData, false);
|
|
babylonMesh.computeWorldMatrix(true);
|
|
babylonMesh.computeWorldMatrix(true);
|
|
- // Set morph target manager after all vertices data has been processed
|
|
|
|
- if (morphTargetManager !== undefined && morphTargetManager.numTargets > 0) {
|
|
|
|
- babylonMesh.morphTargetManager = morphTargetManager;
|
|
|
|
- }
|
|
|
|
// Apply submeshes
|
|
// Apply submeshes
|
|
babylonMesh.subMeshes = [];
|
|
babylonMesh.subMeshes = [];
|
|
for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
|
|
for (var primitiveIndex = 0; primitiveIndex < mesh.primitives.length; primitiveIndex++) {
|
|
@@ -3167,7 +3099,7 @@ var BABYLON;
|
|
if (meshIncluded) {
|
|
if (meshIncluded) {
|
|
newNode = importNode(runtime, node);
|
|
newNode = importNode(runtime, node);
|
|
if (newNode !== null) {
|
|
if (newNode !== null) {
|
|
- newNode.id = createStringId(index);
|
|
|
|
|
|
+ newNode.id = getNodeID(index);
|
|
newNode.parent = parent;
|
|
newNode.parent = parent;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -3438,7 +3370,7 @@ var BABYLON;
|
|
var sampler = (texture.sampler === undefined ? {} : runtime.gltf.samplers[texture.sampler]);
|
|
var sampler = (texture.sampler === undefined ? {} : runtime.gltf.samplers[texture.sampler]);
|
|
var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
|
|
var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
|
|
var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
|
|
var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
|
|
- var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, true, samplingMode, function () {
|
|
|
|
|
|
+ var babylonTexture = new BABYLON.Texture(url, runtime.babylonScene, noMipMaps, false, samplingMode, function () {
|
|
onSuccess(babylonTexture);
|
|
onSuccess(babylonTexture);
|
|
}, onError);
|
|
}, onError);
|
|
babylonTexture.coordinatesIndex = texCoord;
|
|
babylonTexture.coordinatesIndex = texCoord;
|
|
@@ -3555,7 +3487,7 @@ var BABYLON;
|
|
};
|
|
};
|
|
GLTFLoader._loadMaterialsAsync = function (runtime, onSuccess, onError) {
|
|
GLTFLoader._loadMaterialsAsync = function (runtime, onSuccess, onError) {
|
|
var materials = runtime.gltf.materials;
|
|
var materials = runtime.gltf.materials;
|
|
- if (!materials) {
|
|
|
|
|
|
+ if (!materials || materials.length === 0) {
|
|
onSuccess();
|
|
onSuccess();
|
|
return;
|
|
return;
|
|
}
|
|
}
|