private void addGLTFChannelDataToClip(GLTF.Schema.AnimationChannel channel, AnimationClip clip) { int animatedNodeIndex = channel.Target.Node.Id; if (!_importedObjects.ContainsKey(animatedNodeIndex)) { Debug.Log("Node '" + animatedNodeIndex + "' found for animation, aborting."); } Transform animatedNode = _importedObjects[animatedNodeIndex].transform; string nodePath = AnimationUtility.CalculateTransformPath(animatedNode, _sceneObject.transform); bool isStepInterpolation = channel.Sampler.Value.Interpolation != InterpolationType.LINEAR; byte[] timeBufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] times = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Input.Value, timeBufferData); if (channel.Target.Path == GLTFAnimationChannelPath.translation || channel.Target.Path == GLTFAnimationChannelPath.scale) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; GLTF.Math.Vector3[] keyValues = GLTFHelpers.ParseVector3Keyframes(channel.Sampler.Value.Output.Value, bufferData); if (keyValues == null) { return; } Vector3[] values = keyValues.ToUnityVector3(); AnimationCurve[] vector3Curves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation, channel.Target.Path == GLTFAnimationChannelPath.translation); if (channel.Target.Path == GLTFAnimationChannelPath.translation) { GLTFUtils.addTranslationCurvesToClip(vector3Curves, nodePath, ref clip); } else { GLTFUtils.addScaleCurvesToClip(vector3Curves, nodePath, ref clip); } } else if (channel.Target.Path == GLTFAnimationChannelPath.rotation) { byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; Vector4[] values = GLTFHelpers.ParseRotationKeyframes(channel.Sampler.Value.Output.Value, bufferData).ToUnityVector4(); AnimationCurve[] rotationCurves = GLTFUtils.createCurvesFromArrays(times, values, isStepInterpolation); GLTFUtils.addRotationCurvesToClip(rotationCurves, nodePath, ref clip); } else if (channel.Target.Path == GLTFAnimationChannelPath.weights) { List <string> morphTargets = new List <string>(); int meshIndex = _root.Nodes[animatedNodeIndex].Mesh.Id; for (int i = 0; i < _root.Meshes[meshIndex].Primitives[0].Targets.Count; ++i) { morphTargets.Add(GLTFUtils.buildBlendShapeName(meshIndex, i)); } byte[] bufferData = _assetCache.BufferCache[channel.Sampler.Value.Output.Value.BufferView.Value.Buffer.Id]; float[] values = GLTFHelpers.ParseKeyframeTimes(channel.Sampler.Value.Output.Value, bufferData); AnimationCurve[] morphCurves = GLTFUtils.buildMorphAnimationCurves(times, values, morphTargets.Count); GLTFUtils.addMorphAnimationCurvesToClip(morphCurves, nodePath, morphTargets.ToArray(), ref clip); } else { Debug.Log("Unsupported animation channel target: " + channel.Target.Path); } }
protected virtual void CreateMeshPrimitive(MeshPrimitive primitive, string meshName, int meshID, int primitiveIndex) { var meshAttributes = BuildMeshAttributes(primitive, meshID, primitiveIndex); var vertexCount = primitive.Attributes[SemanticProperties.POSITION].Value.Count; UnityEngine.Mesh mesh = new UnityEngine.Mesh { vertices = primitive.Attributes.ContainsKey(SemanticProperties.POSITION) ? meshAttributes[SemanticProperties.POSITION].AccessorContent.AsVertices.ToUnityVector3() : null, normals = primitive.Attributes.ContainsKey(SemanticProperties.NORMAL) ? meshAttributes[SemanticProperties.NORMAL].AccessorContent.AsNormals.ToUnityVector3() : null, uv = primitive.Attributes.ContainsKey(SemanticProperties.TexCoord(0)) ? meshAttributes[SemanticProperties.TexCoord(0)].AccessorContent.AsTexcoords.ToUnityVector2() : null, uv2 = primitive.Attributes.ContainsKey(SemanticProperties.TexCoord(1)) ? meshAttributes[SemanticProperties.TexCoord(1)].AccessorContent.AsTexcoords.ToUnityVector2() : null, uv3 = primitive.Attributes.ContainsKey(SemanticProperties.TexCoord(2)) ? meshAttributes[SemanticProperties.TexCoord(2)].AccessorContent.AsTexcoords.ToUnityVector2() : null, uv4 = primitive.Attributes.ContainsKey(SemanticProperties.TexCoord(3)) ? meshAttributes[SemanticProperties.TexCoord(3)].AccessorContent.AsTexcoords.ToUnityVector2() : null, colors = primitive.Attributes.ContainsKey(SemanticProperties.Color(0)) ? meshAttributes[SemanticProperties.Color(0)].AccessorContent.AsColors.ToUnityColor() : null, triangles = primitive.Indices != null ? meshAttributes[SemanticProperties.INDICES].AccessorContent.AsTriangles : MeshPrimitive.GenerateTriangles(vertexCount), tangents = primitive.Attributes.ContainsKey(SemanticProperties.TANGENT) ? meshAttributes[SemanticProperties.TANGENT].AccessorContent.AsTangents.ToUnityVector4(true) : null }; if (primitive.Attributes.ContainsKey(SemanticProperties.JOINT) && primitive.Attributes.ContainsKey(SemanticProperties.WEIGHT)) { Vector4[] bones = new Vector4[1]; Vector4[] weights = new Vector4[1]; LoadSkinnedMeshAttributes(meshID, primitiveIndex, ref bones, ref weights); if (bones.Length != mesh.vertices.Length || weights.Length != mesh.vertices.Length) { Debug.LogError("Not enough skinning data (bones:" + bones.Length + " weights:" + weights.Length + " verts:" + mesh.vertices.Length + ")"); return; } BoneWeight[] bws = new BoneWeight[mesh.vertices.Length]; int maxBonesIndex = 0; for (int i = 0; i < bws.Length; ++i) { // Unity seems expects the the sum of weights to be 1. float[] normalizedWeights = GLTFUtils.normalizeBoneWeights(weights[i]); bws[i].boneIndex0 = (int)bones[i].x; bws[i].weight0 = normalizedWeights[0]; bws[i].boneIndex1 = (int)bones[i].y; bws[i].weight1 = normalizedWeights[1]; bws[i].boneIndex2 = (int)bones[i].z; bws[i].weight2 = normalizedWeights[2]; bws[i].boneIndex3 = (int)bones[i].w; bws[i].weight3 = normalizedWeights[3]; maxBonesIndex = (int)Mathf.Max(maxBonesIndex, bones[i].x, bones[i].y, bones[i].z, bones[i].w); } mesh.boneWeights = bws; // initialize inverseBindMatrix array with identity matrix in order to output a valid mesh object Matrix4x4[] bindposes = new Matrix4x4[maxBonesIndex + 1]; for (int j = 0; j <= maxBonesIndex; ++j) { bindposes[j] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one); } mesh.bindposes = bindposes; } if (primitive.Targets != null && primitive.Targets.Count > 0) { for (int b = 0; b < primitive.Targets.Count; ++b) { Vector3[] deltaVertices = new Vector3[primitive.Targets[b]["POSITION"].Value.Count]; Vector3[] deltaNormals = new Vector3[primitive.Targets[b]["POSITION"].Value.Count]; Vector3[] deltaTangents = new Vector3[primitive.Targets[b]["POSITION"].Value.Count]; if (primitive.Targets[b].ContainsKey("POSITION")) { NumericArray num = new NumericArray(); deltaVertices = primitive.Targets[b]["POSITION"].Value.AsVector3Array(ref num, _assetCache.BufferCache[0], false).ToUnityVector3(true); } if (primitive.Targets[b].ContainsKey("NORMAL")) { NumericArray num = new NumericArray(); deltaNormals = primitive.Targets[b]["NORMAL"].Value.AsVector3Array(ref num, _assetCache.BufferCache[0], true).ToUnityVector3(true); } //if (primitive.Targets[b].ContainsKey("TANGENT")) //{ // deltaTangents = primitive.Targets[b]["TANGENT"].Value.AsVector3Array(ref num, _assetCache.BufferCache[0], true).ToUnityVector3(true); //} mesh.AddBlendShapeFrame(GLTFUtils.buildBlendShapeName(meshID, b), 1.0f, deltaVertices, deltaNormals, deltaTangents); } } mesh.RecalculateBounds(); mesh.RecalculateTangents(); mesh = _assetManager.saveMesh(mesh, meshName + "_" + meshID + "_" + primitiveIndex); UnityEngine.Material material = primitive.Material != null && primitive.Material.Id >= 0 ? getMaterial(primitive.Material.Id) : defaultMaterial; _assetManager.addPrimitiveMeshData(meshID, primitiveIndex, mesh, material); }