protected override async Task OnLoadHierarchy(IAwaitCaller awaitCaller, Func <string, IDisposable> MeasureTime)
        {
            Root.name = "VRM";

            using (MeasureTime("VRM LoadMeta"))
            {
                await LoadMetaAsync();
            }
            await awaitCaller.NextFrame();

            using (MeasureTime("VRM LoadHumanoid"))
            {
                LoadHumanoid();
            }
            await awaitCaller.NextFrame();

            using (MeasureTime("VRM LoadBlendShapeMaster"))
            {
                LoadBlendShapeMaster();
            }
            await awaitCaller.NextFrame();

            using (MeasureTime("VRM LoadSecondary"))
            {
                VRMSpringUtility.LoadSecondary(Root.transform, Nodes,
                                               VRM.secondaryAnimation);
            }
            await awaitCaller.NextFrame();

            using (MeasureTime("VRM LoadFirstPerson"))
            {
                LoadFirstPerson();
            }
        }
示例#2
0
        protected virtual async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func <string, IDisposable> MeasureTime)
        {
            var inverter = InvertAxis.Create();

            var meshImporter = new MeshImporter();

            for (int i = 0; i < GLTF.meshes.Count; ++i)
            {
                var index = i;
                using (MeasureTime("ReadMesh"))
                {
                    var x = meshImporter.ReadMesh(GLTF, index, inverter);
                    var y = await BuildMeshAsync(awaitCaller, MeasureTime, x, index);

                    Meshes.Add(y);
                }
            }

            using (MeasureTime("LoadNodes"))
            {
                for (int i = 0; i < GLTF.nodes.Count; i++)
                {
                    Nodes.Add(NodeImporter.ImportNode(GLTF.nodes[i], i).transform);
                }
            }
            await awaitCaller.NextFrame();

            using (MeasureTime("BuildHierarchy"))
            {
                var nodes = new List <NodeImporter.TransformWithSkin>();
                for (int i = 0; i < Nodes.Count; ++i)
                {
                    nodes.Add(NodeImporter.BuildHierarchy(GLTF, i, Nodes, Meshes));
                }

                NodeImporter.FixCoordinate(GLTF, nodes, inverter);

                // skinning
                for (int i = 0; i < nodes.Count; ++i)
                {
                    NodeImporter.SetupSkinning(GLTF, nodes, i, inverter);
                }

                if (Root == null)
                {
                    Root = new GameObject("GLTF");
                }
                if (GLTF.rootnodes != null)
                {
                    // connect root
                    foreach (var x in GLTF.rootnodes)
                    {
                        var t = nodes[x].Transform;
                        t.SetParent(Root.transform, false);
                    }
                }
            }
            await awaitCaller.NextFrame();
        }
示例#3
0
        public async Task <Texture2D> LoadTextureAsync(DeserializingTextureInfo textureInfo, IAwaitCaller awaitCaller)
        {
            switch (textureInfo.DataMimeType)
            {
            case "image/png":
                break;

            case "image/jpeg":
                break;

            default:
                Debug.LogWarning($"Texture image MIME type `{textureInfo.DataMimeType}` is not supported.");
                break;
            }

            var texture = new Texture2D(2, 2, TextureFormat.ARGB32, textureInfo.UseMipmap, textureInfo.ColorSpace == ColorSpace.Linear);

            if (textureInfo.ImageData != null)
            {
                texture.LoadImage(textureInfo.ImageData);
                texture.wrapModeU  = textureInfo.WrapModeU;
                texture.wrapModeV  = textureInfo.WrapModeV;
                texture.filterMode = textureInfo.FilterMode;
                await awaitCaller.NextFrame();
            }

            return(texture);
        }
示例#4
0
        internal static async Task <MeshWithMaterials> BuildMeshAsync(
            IAwaitCaller awaitCaller,
            Func <int, Material> ctx,
            MeshContext meshContext)
        {
            Profiler.BeginSample("MeshImporter.BuildMesh");
            var(mesh, recalculateTangents) = BuildMesh(meshContext);
            Profiler.EndSample();

            if (recalculateTangents)
            {
                await awaitCaller.NextFrame();

                mesh.RecalculateTangents();
                await awaitCaller.NextFrame();
            }

            // 先にすべてのマテリアルを作成済みなのでテクスチャーは生成済み。Resultを使ってよい
            var result = new MeshWithMaterials
            {
                Mesh      = mesh,
                Materials = meshContext.MaterialIndices.Select(ctx).ToArray()
            };

            await awaitCaller.NextFrame();

            if (meshContext.BlendShapes.Count > 0)
            {
                var emptyVertices = new Vector3[mesh.vertexCount];
                foreach (var blendShape in meshContext.BlendShapes)
                {
                    await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices);
                }
            }

            Profiler.BeginSample("Mesh.UploadMeshData");
            mesh.UploadMeshData(false);
            Profiler.EndSample();

            return(result);
        }
        public async Task <Texture2D> LoadTextureAsync(byte[] imageData, bool useMipmap, ColorSpace colorSpace, IAwaitCaller awaitCaller)
        {
            var texture = new Texture2D(2, 2, TextureFormat.ARGB32, useMipmap, colorSpace == ColorSpace.Linear);

            if (imageData != null)
            {
                texture.LoadImage(imageData);
                await awaitCaller.NextFrame();
            }

            return(texture);
        }
示例#6
0
        public static async Task <MeshWithMaterials> BuildMeshAndUploadAsync(
            IAwaitCaller awaitCaller,
            MeshData data,
            Func <int, Material> materialFromIndex)
        {
            Profiler.BeginSample("MeshUploader.BuildMesh");

            //Debug.Log(prims.ToJson());
            var mesh = new Mesh
            {
                name = data.Name
            };

            UploadMeshVertices(data, mesh);
            await awaitCaller.NextFrame();

            UploadMeshIndices(data, mesh);
            await awaitCaller.NextFrame();

            // NOTE: mesh.vertices では自動的に行われていたが、SetVertexBuffer では行われないため、明示的に呼び出す.
            mesh.RecalculateBounds();
            await awaitCaller.NextFrame();

            if (!data.HasNormal)
            {
                mesh.RecalculateNormals();
                await awaitCaller.NextFrame();
            }

            mesh.RecalculateTangents();
            await awaitCaller.NextFrame();

            var result = new MeshWithMaterials
            {
                Mesh      = mesh,
                Materials = data.MaterialIndices.Select(materialFromIndex).ToArray(),
                ShouldSetRendererNodeAsBone = data.AssignBoneWeight,
            };
            await awaitCaller.NextFrame();

            if (data.BlendShapes.Count > 0)
            {
                var emptyVertices = new Vector3[mesh.vertexCount];
                foreach (var blendShape in data.BlendShapes)
                {
                    await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices);
                }
            }
            Profiler.EndSample();

            Profiler.BeginSample("Mesh.UploadMeshData");
            mesh.UploadMeshData(false);
            Profiler.EndSample();

            return(result);
        }
示例#7
0
        public virtual async Task LoadAnimationAsync(IAwaitCaller awaitCaller)
        {
            if (GLTF.animations != null && GLTF.animations.Any())
            {
                foreach (var(key, gltfAnimation) in Enumerable.Zip(AnimationImporterUtil.EnumerateSubAssetKeys(GLTF), GLTF.animations, (x, y) => (x, y)))
                {
                    await AnimationClipFactory.LoadAnimationClipAsync(key, async() =>
                    {
                        return(AnimationImporterUtil.ConvertAnimationClip(GLTF, gltfAnimation, InvertAxis.Create()));
                    });
                }

                await awaitCaller.NextFrame();
            }
        }
示例#8
0
        /// <summary>
        /// AnimationClips を AnimationComponent に載せる
        /// </summary>
        protected virtual async Task SetupAnimationsAsync(IAwaitCaller awaitCaller)
        {
            if (AnimationClipFactory.LoadedClipKeys.Count == 0)
            {
                return;
            }

            var animation = Root.AddComponent <Animation>();

            for (var clipIdx = 0; clipIdx < AnimationClipFactory.LoadedClipKeys.Count; ++clipIdx)
            {
                var key  = AnimationClipFactory.LoadedClipKeys[clipIdx];
                var clip = AnimationClipFactory.GetAnimationClip(key);
                animation.AddClip(clip, key.Name);

                if (clipIdx == 0)
                {
                    animation.clip = clip;
                }
            }
            await awaitCaller.NextFrame();
        }
示例#9
0
        /// <summary>
        /// VrmLib.Model から 構築する
        /// </summary>
        /// <param name="MeasureTime"></param>
        /// <returns></returns>
        protected override async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func <string, IDisposable> MeasureTime)
        {
            // fill assets
            for (int i = 0; i < m_model.Materials.Count; ++i)
            {
                var src = m_model.Materials[i];
                var dst = MaterialFactory.Materials[i].Asset;
            }

            await awaitCaller.NextFrame();

            // mesh
            for (int i = 0; i < m_model.MeshGroups.Count; ++i)
            {
                var src = m_model.MeshGroups[i];
                UnityEngine.Mesh mesh = default;
                if (src.Meshes.Count == 1)
                {
                    mesh = MeshImporterShared.LoadSharedMesh(src.Meshes[0], src.Skin);
                }
                else
                {
                    // 頂点バッファの連結が必用
                    // VRM-1 はこっち
                    // https://github.com/vrm-c/UniVRM/issues/800
                    mesh = MeshImporterDivided.LoadDivided(src);
                }
                mesh.name = src.Name;

                m_map.Meshes.Add(src, mesh);
                Meshes.Add(new MeshWithMaterials
                {
                    Mesh      = mesh,
                    Materials = src.Meshes[0].Submeshes.Select(x => MaterialFactory.Materials[x.Material].Asset).ToArray(),
                });


                await awaitCaller.NextFrame();
            }

            // node: recursive
            CreateNodes(m_model.Root, null, m_map.Nodes);
            for (int i = 0; i < m_model.Nodes.Count; ++i)
            {
                Nodes.Add(m_map.Nodes[m_model.Nodes[i]].transform);
            }
            await awaitCaller.NextFrame();

            if (Root == null)
            {
                Root = m_map.Nodes[m_model.Root];
            }
            else
            {
                // replace
                var modelRoot = m_map.Nodes[m_model.Root];
                foreach (Transform child in modelRoot.transform)
                {
                    child.SetParent(Root.transform, true);
                }
                m_map.Nodes[m_model.Root] = Root;
            }
            await awaitCaller.NextFrame();

            // renderer
            var map = m_map;

            foreach (var(node, go) in map.Nodes.Select(kv => (kv.Key, kv.Value)))
            {
                if (node.MeshGroup is null)
                {
                    continue;
                }

                CreateRenderer(node, go, map, MaterialFactory.Materials);
                await awaitCaller.NextFrame();
            }
        }
示例#10
0
        protected virtual async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func <string, IDisposable> MeasureTime)
        {
            var inverter = InvertAxis.Create();

            if (GLTF.meshes.Count > 0)
            {
                var maxVertexCapacity = 0;
                var maxIndexCapacity  = 0;
                foreach (var gltfMesh in GLTF.meshes)
                {
                    var(vertexCapacity, indexCapacity) = MeshData.GetCapacity(Data, gltfMesh);
                    maxVertexCapacity = Math.Max(maxVertexCapacity, vertexCapacity);
                    maxIndexCapacity  = Math.Max(maxIndexCapacity, indexCapacity);
                }

                // 一番長い VertexBuffer, IndexBuffer の長さでNativeArray を確保し、
                // 最後に Dispose する
                using (var meshData = new MeshData(maxVertexCapacity, maxIndexCapacity))
                {
                    for (var i = 0; i < GLTF.meshes.Count; ++i)
                    {
                        var index    = i;
                        var gltfMesh = Data.GLTF.meshes[index];

                        using (MeasureTime("ReadMesh"))
                            await awaitCaller.Run(() => meshData.LoadFromGltf(Data, index, inverter));
                        var meshWithMaterials = await BuildMeshAsync(awaitCaller, MeasureTime, meshData, index);

                        Meshes.Add(meshWithMaterials);
                    }
                }
                await awaitCaller.NextFrame();
            }

            if (GLTF.nodes.Count > 0)
            {
                using (MeasureTime("LoadNodes"))
                {
                    Profiler.BeginSample("ImporterContext.LoadNodes");
                    for (var i = 0; i < GLTF.nodes.Count; i++)
                    {
                        Nodes.Add(NodeImporter.ImportNode(GLTF.nodes[i], i).transform);
                    }
                    Profiler.EndSample();
                }

                await awaitCaller.NextFrame();
            }

            using (MeasureTime("BuildHierarchy"))
            {
                var nodes = new List <NodeImporter.TransformWithSkin>();
                if (Nodes.Count > 0)
                {
                    Profiler.BeginSample("NodeImporter.BuildHierarchy");
                    for (var i = 0; i < Nodes.Count; ++i)
                    {
                        nodes.Add(NodeImporter.BuildHierarchy(GLTF, i, Nodes, Meshes));
                    }
                    Profiler.EndSample();

                    await awaitCaller.NextFrame();
                }

                NodeImporter.FixCoordinate(GLTF, nodes, inverter);

                // skinning
                if (nodes.Count > 0)
                {
                    Profiler.BeginSample("NodeImporter.SetupSkinning");
                    for (var i = 0; i < nodes.Count; ++i)
                    {
                        NodeImporter.SetupSkinning(Data, nodes, i, inverter);
                    }
                    Profiler.EndSample();

                    await awaitCaller.NextFrame();
                }

                if (Root == null)
                {
                    Root = new GameObject("GLTF");
                }
                if (GLTF.rootnodes != null)
                {
                    // connect root
                    foreach (var x in GLTF.rootnodes)
                    {
                        var t = nodes[x].Transform;
                        t.SetParent(Root.transform, false);
                    }
                }
            }
            await awaitCaller.NextFrame();
        }
示例#11
0
        public static async Task ReplaceAsync(GameObject gameObject, IAwaitCaller awaitCaller = null, CancellationToken token = default)
        {
            var service     = FastSpringBoneService.Instance;
            var springBones = gameObject.GetComponentsInChildren <VRMSpringBone>();
            var disposer    = gameObject.AddComponent <FastSpringBoneDisposer>();

            // VRMSpringBoneで動いた後の状態がFastSpringBoneの初期状態にならないようにするためawait UniTask.Yield()する前にVRMSpringBoneをdisableにしておく
            foreach (var springBone in springBones)
            {
                springBone.enabled = false;
            }
            ;

            if (awaitCaller != null)
            {
                await awaitCaller.NextFrame();

                token.ThrowIfCancellationRequested();
            }

            var vrmColliderGroups       = gameObject.GetComponentsInChildren <VRMSpringBoneColliderGroup>();
            var colliderGroupDictionary = new Dictionary <VRMSpringBoneColliderGroup, FastSpringBoneColliderGroup>();

            // Colliderを差し替える
            foreach (var vrmColliderGroup in vrmColliderGroups)
            {
                if (awaitCaller != null)
                {
                    await awaitCaller.NextFrame();

                    token.ThrowIfCancellationRequested();
                }

                var fastSpringBoneCollider = vrmColliderGroup.gameObject.AddComponent <FastSpringBoneColliderGroup>();
                fastSpringBoneCollider.Initialize(
                    service.TransformRegistry,
                    vrmColliderGroup.Colliders
                    .Select(data => new BlittableCollider(data.Offset, data.Radius))
                    .ToArray()
                    );
                colliderGroupDictionary[vrmColliderGroup] = fastSpringBoneCollider;
            }

            var springRootBones =
                (
                    from springBone in springBones
                    from rootBone in springBone.RootBones
                    select(springBone, rootBone)
                ).ToList();

            for (var i = 0; i < springRootBones.Count; i++)
            {
                var current = springRootBones[i];

                // 他のRootBoneのどれかが、自分の親(もしくは同じTransform)なら自分自身を削除する
                if (springRootBones
                    .Where(other => other != current)
                    .Any(other => current.rootBone.IsChildOf(other.rootBone)))
                {
                    springRootBones.RemoveAt(i);
                    --i;
                }
            }

            if (awaitCaller != null)
            {
                await awaitCaller.NextFrame();

                token.ThrowIfCancellationRequested();
            }
            token.ThrowIfCancellationRequested();

            foreach (var(vrmSpringBone, rootBoneTransform) in springRootBones)
            {
                // FastSpringRootBoneに差し替える
                var fastSpringRootBone =
                    new FastSpringRootBone(
                        service.TransformRegistry,
                        rootBoneTransform,
                        service.RootBoneRegistry,
                        service.ColliderGroupRegistry);
                disposer.Add(fastSpringRootBone);

                var colliderGroups =
                    vrmSpringBone.ColliderGroups != null
                        ? vrmSpringBone.ColliderGroups.Select(group => colliderGroupDictionary[@group]).ToArray()
                        : Array.Empty <FastSpringBoneColliderGroup>();

                fastSpringRootBone.Initialize(
                    vrmSpringBone.m_gravityPower,
                    vrmSpringBone.m_gravityDir,
                    vrmSpringBone.m_dragForce,
                    vrmSpringBone.m_stiffnessForce,
                    colliderGroups,
                    vrmSpringBone.m_hitRadius,
                    vrmSpringBone.m_center
                    );

                Object.Destroy(vrmSpringBone);

                if (awaitCaller != null)
                {
                    await awaitCaller.NextFrame();

                    token.ThrowIfCancellationRequested();
                }
                token.ThrowIfCancellationRequested();
            }

            // Colliderを削除
            foreach (var vrmSpringBoneColliderGroup in vrmColliderGroups)
            {
                Object.Destroy(vrmSpringBoneColliderGroup);
            }
        }
示例#12
0
        protected virtual async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func <string, IDisposable> MeasureTime)
        {
            var inverter = InvertAxis.Create();

            var meshImporter = new MeshImporter();

            if (GLTF.meshes.Count > 0)
            {
                for (var i = 0; i < GLTF.meshes.Count; ++i)
                {
                    var index = i;
                    using (MeasureTime("ReadMesh"))
                    {
                        var meshContext = await awaitCaller.Run(() => meshImporter.ReadMesh(Data, index, inverter));

                        var meshWithMaterials = await BuildMeshAsync(awaitCaller, MeasureTime, meshContext, index);

                        Meshes.Add(meshWithMaterials);
                    }
                }

                await awaitCaller.NextFrame();
            }

            if (GLTF.nodes.Count > 0)
            {
                using (MeasureTime("LoadNodes"))
                {
                    Profiler.BeginSample("ImporterContext.LoadNodes");
                    for (var i = 0; i < GLTF.nodes.Count; i++)
                    {
                        Nodes.Add(NodeImporter.ImportNode(GLTF.nodes[i], i).transform);
                    }
                    Profiler.EndSample();
                }

                await awaitCaller.NextFrame();
            }

            using (MeasureTime("BuildHierarchy"))
            {
                var nodes = new List <NodeImporter.TransformWithSkin>();
                if (Nodes.Count > 0)
                {
                    Profiler.BeginSample("NodeImporter.BuildHierarchy");
                    for (var i = 0; i < Nodes.Count; ++i)
                    {
                        nodes.Add(NodeImporter.BuildHierarchy(GLTF, i, Nodes, Meshes));
                    }
                    Profiler.EndSample();

                    await awaitCaller.NextFrame();
                }

                NodeImporter.FixCoordinate(GLTF, nodes, inverter);

                // skinning
                if (nodes.Count > 0)
                {
                    Profiler.BeginSample("NodeImporter.SetupSkinning");
                    for (var i = 0; i < nodes.Count; ++i)
                    {
                        NodeImporter.SetupSkinning(Data, nodes, i, inverter);
                    }
                    Profiler.EndSample();

                    await awaitCaller.NextFrame();
                }

                if (Root == null)
                {
                    Root = new GameObject("GLTF");
                }
                if (GLTF.rootnodes != null)
                {
                    // connect root
                    foreach (var x in GLTF.rootnodes)
                    {
                        var t = nodes[x].Transform;
                        t.SetParent(Root.transform, false);
                    }
                }
            }
            await awaitCaller.NextFrame();
        }