#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;
}
}
}
}