This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
SHI-GIS/Assets/Scripts/ExternalAssets/ThumbnailGenerator.cs

83 lines
2.8 KiB
C#

using UnityEngine;
public class ThumbnailGenerator
{
private readonly IBackgroundStrategy backgroundStrategy;
private static readonly Vector3 offScreenPosition = new Vector3(-1000f, -1000f, -1000f);
public ThumbnailGenerator(IBackgroundStrategy _backgroundStrategy)
{
backgroundStrategy = _backgroundStrategy;
}
public Texture2D Generate(GameObject prefab, int width, int height)
{
if (prefab == null)
{
Debug.LogError("프리팹이 null");
return null;
}
GameObject studio = new GameObject("ThumbnailStudio");
studio.transform.position = offScreenPosition;
Light light = new GameObject("ThumbnailLight").AddComponent<Light>();
light.transform.SetParent(studio.transform);
light.type = LightType.Directional;
light.transform.rotation = Quaternion.Euler(50f, -30f, 0);
Camera camera = new GameObject("ThumbnailCamera").AddComponent<Camera>();
camera.transform.SetParent(studio.transform);
backgroundStrategy.ConfigCamera(camera);
camera.cullingMask = 1 << prefab.layer;
GameObject instance = Object.Instantiate(prefab, studio.transform);
Bounds bounds = GetTotalBounds(instance.transform);
PositionCamera(camera, bounds);
RenderTexture rt = RenderTexture.GetTemporary(width, height, 24);
camera.targetTexture = rt;
camera.Render();
RenderTexture.active = rt;
Texture2D thumbnail = new Texture2D(width, height, TextureFormat.RGBA32, false);
thumbnail.ReadPixels(new Rect(0, 0, width, height), 0, 0);
thumbnail.Apply();
RenderTexture.active = null;
camera.targetTexture = null;
RenderTexture.ReleaseTemporary(rt);
Object.DestroyImmediate(studio);
return thumbnail;
}
/// <summary>
/// 자식들을 포함한 전체 Bounds 계산
/// </summary>
private static Bounds GetTotalBounds(Transform target)
{
Bounds bounds = new Bounds(target.position, Vector3.zero);
Renderer[] renderers = target.GetComponentsInChildren<Renderer>();
foreach (Renderer renderer in renderers)
{
bounds.Encapsulate(renderer.bounds);
}
return bounds;
}
/// <summary>
/// Bounds에 맞춰 카메라의 위치와 줌(FOV) 조절
/// </summary>
private static void PositionCamera(Camera camera, Bounds bounds)
{
float maxExtent = Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z);
float distance = maxExtent / Mathf.Sin(camera.fieldOfView * 0.5f * Mathf.Deg2Rad) * 1.2f; // 여백(1.2f) 추가
camera.transform.position = bounds.center - camera.transform.forward * distance;
camera.transform.LookAt(bounds.center);
camera.nearClipPlane = distance - maxExtent;
camera.farClipPlane = distance + maxExtent;
}
}