#nullable enable using GLTFast; using UnityEngine; using System; using System.Threading; using Cysharp.Threading.Tasks; using System.Collections.Generic; namespace UVC.GLTF { public static class GLTFImporter { /// /// glTF/glb 파일을 로드합니다. /// /// 파일 경로 /// 부모 Transform /// MSFT_lod 확장을 LODGroup으로 변환할지 여부 public static async UniTask ImportFromFile(string filePath, Transform parentTransform) { if (string.IsNullOrEmpty(filePath)) return null; Debug.Log($"ImportFromFile {filePath}"); var gltf = new GltfImport(); var importSettings = new ImportSettings(); var success = await gltf.Load(filePath, importSettings); if (!success) { Debug.LogError($"glTFast Load failed: {filePath}"); return null; } // MSFT_lod 사용 시 커스텀 인스턴시에이터 사용 GameObjectInstantiator instantiator; // if (useMsftLod) // { // // glb/gltf 파일에서 MSFT_lod 정보 파싱 // var lodInfos = MsftLodParser.ParseFromFile(filePath); // Debug.Log($"ImportFromFile: Found {lodInfos.Count} LOD definitions in {filePath}"); // var lodInstantiator = new LODGameObjectInstantiator(gltf, parentTransform); // lodInstantiator.SetLodInfo(lodInfos); // instantiator = lodInstantiator; // } // else // { instantiator = new GameObjectInstantiator(gltf, parentTransform); // } var sceneOk = await gltf.InstantiateMainSceneAsync(instantiator); if (!sceneOk) { Debug.LogError($"InstantiateMainSceneAsync failed: {filePath}"); return null; } return instantiator.SceneTransform != null ? instantiator.SceneTransform.gameObject : null; } /// /// 여러 LOD 레벨의 glTF/glb 파일을 로드하고 LODGroup으로 설정합니다. 사용않함 /// /// /// /// public static async UniTask ImportWithLOD(List paths, Transform parentTransform) { if (paths == null || paths.Count == 0) return null; // 1. 부모 객체 생성 (여기에 LODGroup 컴포넌트가 붙습니다) GameObject rootObject = new GameObject("Loaded_LOD_Model"); rootObject.transform.position = Vector3.zero; bool successAll = true; List loadedObjects = new List(); foreach (var path in paths) { if (string.IsNullOrEmpty(path)) continue; Debug.Log($"ImportFromWithLOD Loading {path}"); var gltf = new GltfImport(); var importSettings = new ImportSettings(); var success = await gltf.Load(path, importSettings); if (!success) { Debug.LogError($"glTFast Load failed: {path}"); successAll = false; break; } //path 이름만 string lodName = System.IO.Path.GetFileNameWithoutExtension(path); GameObject gameObject = new GameObject(lodName); gameObject.transform.SetParent(rootObject.transform, false); var instantiator = new GameObjectInstantiator(gltf, gameObject.transform); var sceneOk = await gltf.InstantiateMainSceneAsync(instantiator); if (!sceneOk) { Debug.LogError($"InstantiateMainSceneAsync failed: {path}"); successAll = false; break; } if(instantiator.SceneTransform != null){ loadedObjects.Add(gameObject); } } if (successAll) { // 3. LODGroup 설정 var lodGroup = rootObject.AddComponent(); LOD[] lods = new LOD[loadedObjects.Count]; float[] lodScreenPercentages = new float[] { 0.5f, 0.25f, 0.1f, 0f}; // 예시로 LOD 전환 비율 설정 for (int i = 0; i < loadedObjects.Count; i++) { Renderer? renderer = loadedObjects[i].GetComponent(); if(renderer == null) { renderer = loadedObjects[i].GetComponentInChildren(); } float screenRelativeTransitionHeight = lodScreenPercentages[Mathf.Min(i, lodScreenPercentages.Length - 1)]; // LOD 전환 비율 설정 사용 Debug.Log($"{loadedObjects[i].name} LOD {i}: screenRelativeTransitionHeight={screenRelativeTransitionHeight}"); lods[i] = new LOD(screenRelativeTransitionHeight, new Renderer[]{renderer!}); } lodGroup.SetLODs(lods); lodGroup.RecalculateBounds(); // 바운딩 박스 재계산 (필수) rootObject.transform.SetParent(parentTransform, false); return rootObject; } else { GameObject.Destroy(rootObject); return null; } } } }