83 lines
2.8 KiB
C#
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;
|
|
}
|
|
} |