private GLTFSkin ExportSkin(BabylonSkeleton babylonSkeleton, GLTF gltf, GLTFNode gltfNode, GLTFMesh gltfMesh) { logger.RaiseMessage("GLTFExporter.Skin | Export skin of node '" + gltfNode.name + "' based on skeleton '" + babylonSkeleton.name + "'", 2); // Retreive gltf skeleton data if babylon skeleton has already been exported if (!alreadyExportedSkeletons.ContainsKey(babylonSkeleton)) { alreadyExportedSkeletons.Add(babylonSkeleton, new BabylonSkeletonExportData()); // Switch coordinate system at object level foreach (var babylonBone in babylonSkeleton.bones) { var boneLocalMatrix = new BabylonMatrix(); boneLocalMatrix.m = babylonBone.matrix; var translationBabylon = new BabylonVector3(); var rotationQuatBabylon = new BabylonQuaternion(); var scale = new BabylonVector3(); boneLocalMatrix.decompose(scale, rotationQuatBabylon, translationBabylon); translationBabylon *= exportParameters.scaleFactor; translationBabylon.Z *= -1; rotationQuatBabylon.X *= -1; rotationQuatBabylon.Y *= -1; boneLocalMatrix = BabylonMatrix.Compose(scale, rotationQuatBabylon, translationBabylon); babylonBone.matrix = boneLocalMatrix.m; } } var babylonSkeletonExportData = alreadyExportedSkeletons[babylonSkeleton]; // Skin // if this mesh is sharing a skin with another mesh, use the already exported skin var sharedSkinnedMeshesByOriginalPair = sharedSkinnedMeshesByOriginal.Where(skinSharingMeshPair => skinSharingMeshPair.Value.Contains(gltfMesh)).Select(kvp => (KeyValuePair <GLTFMesh, List <GLTFMesh> >?)kvp).FirstOrDefault(); if (sharedSkinnedMeshesByOriginalPair != null) { logger.RaiseMessage("GLTFExporter.Skin | Sharing skinning information from mesh '" + sharedSkinnedMeshesByOriginalPair.Value.Key.name + "'", 3); var skeletonExportData = alreadyExportedSkeletons[babylonSkeleton]; gltfNode.skin = skeletonExportData.skinIndex; return(gltf.SkinsList[(int)gltfNode.skin]); } // otherwise create a new GLTFSkin var nameSuffix = babylonSkeletonExportData.nb != 0 ? "_" + babylonSkeletonExportData.nb : ""; GLTFSkin gltfSkin = new GLTFSkin { name = babylonSkeleton.name + nameSuffix }; gltfSkin.index = gltf.SkinsList.Count; gltf.SkinsList.Add(gltfSkin); babylonSkeletonExportData.nb++; babylonSkeletonExportData.skinIndex = gltfSkin.index; var bones = new List <BabylonBone>(babylonSkeleton.bones); // Compute and store world matrix of each bone var bonesWorldMatrices = new Dictionary <int, BabylonMatrix>(); foreach (var babylonBone in babylonSkeleton.bones) { if (!bonesWorldMatrices.ContainsKey(babylonBone.index)) { var nodePair = nodeToGltfNodeMap.First(pair => pair.Key.id.Equals(babylonBone.id)); BabylonMatrix boneWorldMatrix = _getNodeWorldMatrix(nodePair.Value); bonesWorldMatrices.Add(babylonBone.index, boneWorldMatrix); } } // Buffer var buffer = GLTFBufferService.Instance.GetBuffer(gltf); // Accessor - InverseBindMatrices var accessorInverseBindMatrices = GLTFBufferService.Instance.CreateAccessor( gltf, GLTFBufferService.Instance.GetBufferViewFloatMat4(gltf, buffer), "accessorInverseBindMatrices", GLTFAccessor.ComponentType.FLOAT, GLTFAccessor.TypeEnum.MAT4 ); gltfSkin.inverseBindMatrices = accessorInverseBindMatrices.index; // World matrix of the node var nodeWorldMatrix = _getNodeWorldMatrix(gltfNode); var gltfJoints = new List <int>(); foreach (var babylonBone in babylonSkeleton.bones) { GLTFNode gltfBoneNode = null; if (!babylonSkeletonExportData.nodeByBone.ContainsKey(babylonBone)) { // Export bone as a new node gltfBoneNode = nodeToGltfNodeMap.FirstOrDefault(pair => pair.Key.id.Equals(babylonBone.id)).Value;//_exportBone(babylonBone, gltf, babylonSkeleton, bones); babylonSkeletonExportData.nodeByBone.Add(babylonBone, gltfBoneNode); } gltfBoneNode = babylonSkeletonExportData.nodeByBone[babylonBone]; gltfJoints.Add(gltfBoneNode.index); // Set this bone as skeleton if it is a root // Meaning of 'skeleton' here is the top root bone if (babylonBone.parentBoneIndex == -1) { gltfSkin.skeleton = gltfBoneNode.index; } // Compute inverseBindMatrice for this bone when attached to this node var boneLocalMatrix = new BabylonMatrix(); boneLocalMatrix.m = babylonBone.matrix; //printMatrix("boneLocalMatrix[" + babylonBone.name + "]", boneLocalMatrix); BabylonMatrix boneWorldMatrix = null; if (babylonBone.parentBoneIndex == -1) { boneWorldMatrix = boneLocalMatrix; } else { var parentWorldMatrix = bonesWorldMatrices[babylonBone.parentBoneIndex]; // Remove scale of parent // This actually enable to take into account the scale of the bones, except for the root one parentWorldMatrix = _removeScale(parentWorldMatrix); boneWorldMatrix = boneLocalMatrix * parentWorldMatrix; } //printMatrix("boneWorldMatrix[" + babylonBone.name + "]", boneWorldMatrix); var inverseBindMatrices = nodeWorldMatrix * BabylonMatrix.Invert(boneWorldMatrix); // Populate accessor List <float> matrix = new List <float>(inverseBindMatrices.m); matrix.ForEach(n => accessorInverseBindMatrices.bytesList.AddRange(BitConverter.GetBytes(n))); accessorInverseBindMatrices.count++; } gltfSkin.joints = gltfJoints.ToArray(); ExportGLTFExtension(babylonSkeleton, ref gltfNode, gltf); return(gltfSkin); }
private GLTFSkin ExportSkin(BabylonSkeleton babylonSkeleton, GLTF gltf, GLTFNode gltfNode) { RaiseMessage("GLTFExporter.Skin | Export skin of node '" + gltfNode.name + "' based on skeleton '" + babylonSkeleton.name + "'", 2); // Retreive gltf skeleton data if babylon skeleton has already been exported if (!alreadyExportedSkeletons.ContainsKey(babylonSkeleton)) { alreadyExportedSkeletons.Add(babylonSkeleton, new BabylonSkeletonExportData()); } var babylonSkeletonExportData = alreadyExportedSkeletons[babylonSkeleton]; // Skin var nameSuffix = babylonSkeletonExportData.nb != 0 ? "_" + babylonSkeletonExportData.nb : ""; GLTFSkin gltfSkin = new GLTFSkin { name = babylonSkeleton.name + nameSuffix }; gltfSkin.index = gltf.SkinsList.Count; gltf.SkinsList.Add(gltfSkin); babylonSkeletonExportData.nb++; var bones = new List <BabylonBone>(babylonSkeleton.bones); // Compute and store world matrix of each bone var bonesWorldMatrices = new Dictionary <int, BabylonMatrix>(); foreach (var babylonBone in babylonSkeleton.bones) { if (!bonesWorldMatrices.ContainsKey(babylonBone.index)) { BabylonMatrix boneWorldMatrix = _getBoneWorldMatrix(babylonBone, bones); bonesWorldMatrices.Add(babylonBone.index, boneWorldMatrix); } } // Buffer var buffer = GLTFBufferService.Instance.GetBuffer(gltf); // Accessor - InverseBindMatrices var accessorInverseBindMatrices = GLTFBufferService.Instance.CreateAccessor( gltf, GLTFBufferService.Instance.GetBufferViewFloatMat4(gltf, buffer), "accessorInverseBindMatrices", GLTFAccessor.ComponentType.FLOAT, GLTFAccessor.TypeEnum.MAT4 ); gltfSkin.inverseBindMatrices = accessorInverseBindMatrices.index; // World matrix of the node var nodeWorldMatrix = _getNodeWorldMatrix(gltfNode); //printMatrix("nodeWorldMatrix[" + gltfNode.name + "]", nodeWorldMatrix); var gltfJoints = new List <int>(); alreadyExportedBones = new Dictionary <BabylonBone, GLTFNode>(); foreach (var babylonBone in babylonSkeleton.bones) { GLTFNode gltfBoneNode = null; if (!babylonSkeletonExportData.nodeByBone.ContainsKey(babylonBone)) { // Export bone as a new node gltfBoneNode = _exportBone(babylonBone, gltf, babylonSkeleton, bones); babylonSkeletonExportData.nodeByBone.Add(babylonBone, gltfBoneNode); } gltfBoneNode = babylonSkeletonExportData.nodeByBone[babylonBone]; gltfJoints.Add(gltfBoneNode.index); // Set this bone as skeleton if it is a root // Meaning of 'skeleton' here is the top root bone if (babylonBone.parentBoneIndex == -1) { gltfSkin.skeleton = gltfBoneNode.index; } // Compute inverseBindMatrice for this bone when attached to this node var boneLocalMatrix = new BabylonMatrix(); boneLocalMatrix.m = babylonBone.matrix; //printMatrix("boneLocalMatrix[" + babylonBone.name + "]", boneLocalMatrix); BabylonMatrix boneWorldMatrix = null; if (babylonBone.parentBoneIndex == -1) { boneWorldMatrix = boneLocalMatrix; } else { var parentWorldMatrix = bonesWorldMatrices[babylonBone.parentBoneIndex]; // Remove scale of parent // This actually enable to take into account the scale of the bones, except for the root one parentWorldMatrix = _removeScale(parentWorldMatrix); boneWorldMatrix = boneLocalMatrix * parentWorldMatrix; } //printMatrix("boneWorldMatrix[" + babylonBone.name + "]", boneWorldMatrix); var inverseBindMatrices = nodeWorldMatrix * BabylonMatrix.Invert(boneWorldMatrix); // Populate accessor List <float> matrix = new List <float>(inverseBindMatrices.m); matrix.ForEach(n => accessorInverseBindMatrices.bytesList.AddRange(BitConverter.GetBytes(n))); accessorInverseBindMatrices.count++; } gltfSkin.joints = gltfJoints.ToArray(); return(gltfSkin); }
private GLTFSkin ExportSkin(BabylonSkeleton babylonSkeleton, GLTF gltf, GLTFNode gltfNode) { // Skin GLTFSkin gltfSkin = new GLTFSkin { name = babylonSkeleton.name }; gltfSkin.index = gltf.SkinsList.Count; gltf.SkinsList.Add(gltfSkin); var bones = new List <BabylonBone>(babylonSkeleton.bones); // Compute and store world matrix of each bone var bonesWorldMatrices = new Dictionary <int, BabylonMatrix>(); foreach (var babylonBone in babylonSkeleton.bones) { if (!bonesWorldMatrices.ContainsKey(babylonBone.index)) { BabylonMatrix boneWorldMatrix = _getBoneWorldMatrix(babylonBone, bones); bonesWorldMatrices.Add(babylonBone.index, boneWorldMatrix); } } // Buffer var buffer = GLTFBufferService.Instance.GetBuffer(gltf); // Accessor - InverseBindMatrices var accessorInverseBindMatrices = GLTFBufferService.Instance.CreateAccessor( gltf, GLTFBufferService.Instance.GetBufferViewFloatMat4(gltf, buffer), "accessorInverseBindMatrices", GLTFAccessor.ComponentType.FLOAT, GLTFAccessor.TypeEnum.MAT4 ); gltfSkin.inverseBindMatrices = accessorInverseBindMatrices.index; // World matrix of the node var invNodeWorldMatrix = BabylonMatrix.Invert(_getNodeWorldMatrix(gltfNode)); // inverted var gltfJoints = new List <int>(); alreadyExportedBones = new Dictionary <BabylonBone, GLTFNode>(); foreach (var babylonBone in babylonSkeleton.bones) { // Export bone as a new node var gltfBoneNode = _exportBone(babylonBone, gltf, babylonSkeleton, bones); gltfJoints.Add(gltfBoneNode.index); // Set this bone as skeleton if it is a root if (babylonBone.parentBoneIndex == -1) { gltfSkin.skeleton = gltfBoneNode.index; } // Compute inverseBindMatrice for this bone when attached to this node var boneLocalMatrix = new BabylonMatrix(); boneLocalMatrix.m = babylonBone.matrix; BabylonMatrix boneWorldMatrix = null; if (babylonBone.parentBoneIndex == -1) { boneWorldMatrix = boneLocalMatrix; } else { var parentWorldMatrix = bonesWorldMatrices[babylonBone.parentBoneIndex]; // Remove scale of parent // This actually enable to take into account the scale of the bones, except for the root one parentWorldMatrix = _removeScale(parentWorldMatrix); boneWorldMatrix = boneLocalMatrix * parentWorldMatrix; } var inverseBindMatrices = BabylonMatrix.Invert(boneWorldMatrix * invNodeWorldMatrix); // Populate accessor List <float> matrix = new List <float>(inverseBindMatrices.m); matrix.ForEach(n => accessorInverseBindMatrices.bytesList.AddRange(BitConverter.GetBytes(n))); accessorInverseBindMatrices.count++; } gltfSkin.joints = gltfJoints.ToArray(); return(gltfSkin); }