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(); } }
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(); }
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); }
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); }
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); }
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(); } }
/// <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(); }
/// <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(); } }
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(); }
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); } }
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(); }