示例#1
0
文件: gltfExporter.cs 项目: bmjoy/VGO
        void FromGameObject(glTF gltf, GameObject go, bool useSparseAccessorForMorphTarget = false)
        {
            var bytesBuffer = new ArrayByteBuffer(new byte[50 * 1024 * 1024]);
            var bufferIndex = gltf.AddBuffer(bytesBuffer);

            GameObject tmpParent = null;

            if (go.transform.childCount == 0)
            {
                tmpParent = new GameObject("tmpParent");
                go.transform.SetParent(tmpParent.transform, true);
                go = tmpParent;
            }

            try
            {
                Nodes = go.transform.Traverse()
                        .Skip(1) // exclude root object for the symmetry with the importer
                        .ToList();

                #region Materials and Textures
                //Materials = Nodes.SelectMany(x => x.GetSharedMaterials()).Where(x => x != null).Distinct().ToList();
                //var unityTextures = Materials.SelectMany(x => TextureIO.GetTextures(x)).Where(x => x.Texture != null).Distinct().ToList();

                //TextureManager = new TextureExportManager(unityTextures.Select(x => x.Texture));

                //var materialExporter = CreateMaterialExporter();
                //gltf.materials = Materials.Select(x => materialExporter.ExportMaterial(x, TextureManager)).ToList();

                //for (int i = 0; i < unityTextures.Count; ++i)
                //{
                //    var unityTexture = unityTextures[i];
                //    TextureIO.ExportTexture(gltf, bufferIndex, TextureManager.GetExportTexture(i), unityTexture.TextureType);
                //}
                FromGameObjectMaterialsAndTextures(gltf, go, bufferIndex);
                #endregion


                #region Meshes
                var unityMeshes = Nodes
                                  .Select(x => new MeshWithRenderer
                {
                    Mesh     = x.GetSharedMesh(),
                    Renderer = x.GetComponent <Renderer>(),
                })
                                  .Where(x =>
                {
                    if (x.Mesh == null)
                    {
                        return(false);
                    }
                    if (x.Renderer.sharedMaterials == null ||
                        x.Renderer.sharedMaterials.Length == 0)
                    {
                        return(false);
                    }

                    return(true);
                })
                                  .ToList();
                MeshExporter.ExportMeshes(gltf, bufferIndex, unityMeshes, Materials, useSparseAccessorForMorphTarget, ExportOnlyBlendShapePosition);
                Meshes = unityMeshes.Select(x => x.Mesh).ToList();
                #endregion

                #region Nodes and Skins
                var unitySkins = Nodes
                                 .Select(x => x.GetComponent <SkinnedMeshRenderer>()).Where(x =>
                                                                                            x != null &&
                                                                                            x.bones != null &&
                                                                                            x.bones.Length > 0)
                                 .ToList();
                gltf.nodes  = Nodes.Select(x => ExportNode(x, Nodes, unityMeshes.Select(y => y.Renderer).ToList(), unitySkins)).ToList();
                gltf.scenes = new List <glTFScene>
                {
                    new glTFScene
                    {
                        nodes = go.transform.GetChildren().Select(x => Nodes.IndexOf(x)).ToArray(),
                    }
                };

                foreach (var x in unitySkins)
                {
                    var matrices = x.sharedMesh.bindposes.Select(y => y.ReverseZ()).ToArray();
                    var accessor = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, matrices, glBufferTarget.NONE);

                    var skin = new glTFSkin
                    {
                        inverseBindMatrices = accessor,
                        joints   = x.bones.Select(y => Nodes.IndexOf(y)).ToArray(),
                        skeleton = Nodes.IndexOf(x.rootBone),
                    };
                    var skinIndex = gltf.skins.Count;
                    gltf.skins.Add(skin);

                    foreach (var z in Nodes.Where(y => y.Has(x)))
                    {
                        var nodeIndex = Nodes.IndexOf(z);
                        var node      = gltf.nodes[nodeIndex];
                        node.skin = skinIndex;
                    }
                }
                #endregion

#if UNITY_EDITOR
                #region Animations

                var clips     = new List <AnimationClip>();
                var animator  = go.GetComponent <Animator>();
                var animation = go.GetComponent <Animation>();
                if (animator != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animator);
                }
                else if (animation != null)
                {
                    clips = AnimationExporter.GetAnimationClips(animation);
                }

                if (clips.Any())
                {
                    foreach (AnimationClip clip in clips)
                    {
                        var animationWithCurve = AnimationExporter.Export(clip, go.transform, Nodes);

                        foreach (var kv in animationWithCurve.SamplerMap)
                        {
                            var sampler = animationWithCurve.Animation.samplers[kv.Key];

                            var inputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Input);
                            sampler.input = inputAccessorIndex;

                            var outputAccessorIndex = gltf.ExtendBufferAndGetAccessorIndex(bufferIndex, kv.Value.Output);
                            sampler.output = outputAccessorIndex;

                            // modify accessors
                            var outputAccessor = gltf.accessors[outputAccessorIndex];
                            var channel        = animationWithCurve.Animation.channels.First(x => x.sampler == kv.Key);
                            switch (glTFAnimationTarget.GetElementCount(channel.target.path))
                            {
                            case 1:
                                outputAccessor.type = "SCALAR";
                                //outputAccessor.count = ;
                                break;

                            case 3:
                                outputAccessor.type   = "VEC3";
                                outputAccessor.count /= 3;
                                break;

                            case 4:
                                outputAccessor.type   = "VEC4";
                                outputAccessor.count /= 4;
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                        }
                        animationWithCurve.Animation.name = clip.name;
                        gltf.animations.Add(animationWithCurve.Animation);
                    }
                }
                #endregion
#endif
            }
            finally
            {
                if (tmpParent != null)
                {
                    tmpParent.transform.GetChild(0).SetParent(null);
                    if (Application.isPlaying)
                    {
                        GameObject.Destroy(tmpParent);
                    }
                    else
                    {
                        GameObject.DestroyImmediate(tmpParent);
                    }
                }
            }
        }
示例#2
0
        public static AnimationWithSampleCurves Export(AnimationClip clip, Transform root, List <Transform> nodes)
        {
            var animation = new AnimationWithSampleCurves
            {
                Animation = new glTFAnimation(),
            };

#if UNITY_5_6_OR_NEWER
            List <AnimationCurveData> curveDatum = new List <AnimationCurveData>();

            foreach (var binding in AnimationUtility.GetCurveBindings(clip))
            {
                var curve = AnimationUtility.GetEditorCurve(clip, binding);

                var property = AnimationExporter.PropertyToTarget(binding.propertyName);
                if (property == glTFAnimationTarget.AnimationProperties.NotImplemented)
                {
                    Debug.LogWarning("Not Implemented keyframe property : " + binding.propertyName);
                    continue;
                }
                if (property == glTFAnimationTarget.AnimationProperties.EulerRotation)
                {
                    Debug.LogWarning("Interpolation setting of AnimationClip should be Quaternion");
                    continue;
                }

                var nodeIndex    = GetNodeIndex(root, nodes, binding.path);
                var samplerIndex = AddChannelAndGetSampler(animation.Animation, nodeIndex, property);
                var elementCount = 0;
                if (property == glTFAnimationTarget.AnimationProperties.BlendShape)
                {
                    var mesh = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    elementCount = mesh.blendShapeCount;
                }
                else
                {
                    elementCount = glTFAnimationTarget.GetElementCount(property);
                }

                // 同一のsamplerIndexが割り当てられているcurveDataがある場合はそれを使用し、無ければ作る
                var curveData = curveDatum.FirstOrDefault(x => x.SamplerIndex == samplerIndex);
                if (curveData == null)
                {
                    curveData = new AnimationCurveData(AnimationUtility.GetKeyRightTangentMode(curve, 0), property, samplerIndex, elementCount);
                    curveDatum.Add(curveData);
                }

                // 全てのキーフレームを回収
                int   elementOffset = 0;
                float valueFactor   = 1.0f;
                if (property == glTFAnimationTarget.AnimationProperties.BlendShape)
                {
                    var mesh           = nodes[nodeIndex].GetComponent <SkinnedMeshRenderer>().sharedMesh;
                    var blendShapeName = binding.propertyName.Replace("blendShape.", "");
                    elementOffset = mesh.GetBlendShapeIndex(blendShapeName);
                    valueFactor   = 0.01f;
                }
                else
                {
                    elementOffset = AnimationExporter.GetElementOffset(binding.propertyName);
                }

                if (elementOffset >= 0 && elementOffset < elementCount)
                {
                    for (int i = 0; i < curve.keys.Length; i++)
                    {
                        curveData.SetKeyframeData(curve.keys[i].time, curve.keys[i].value * valueFactor, elementOffset);
                    }
                }
            }

            //キー挿入
            foreach (var curve in curveDatum)
            {
                if (curve.Keyframes.Count == 0)
                {
                    continue;
                }

                curve.RecountEmptyKeyframe();

                var elementNum = curve.Keyframes.First().Values.Length;
                var values     = default(InputOutputValues);
                if (!animation.SamplerMap.TryGetValue(curve.SamplerIndex, out values))
                {
                    values        = new InputOutputValues();
                    values.Input  = new float[curve.Keyframes.Count];
                    values.Output = new float[curve.Keyframes.Count * elementNum];
                    animation.SamplerMap[curve.SamplerIndex] = values;
                    animation.Animation.samplers[curve.SamplerIndex].interpolation = curve.GetInterpolation();
                }

                int keyframeIndex = 0;
                foreach (var keyframe in curve.Keyframes)
                {
                    values.Input[keyframeIndex] = keyframe.Time;
                    Buffer.BlockCopy(keyframe.GetRightHandCoordinate(), 0, values.Output, keyframeIndex * elementNum * sizeof(float), elementNum * sizeof(float));
                    keyframeIndex++;
                }
            }
#endif

            return(animation);
        }