Skip to content

Instantly share code, notes, and snippets.

@bruce965
Created November 12, 2015 13:02
Show Gist options
  • Save bruce965/3297aea04d59f5344381 to your computer and use it in GitHub Desktop.
Save bruce965/3297aea04d59f5344381 to your computer and use it in GitHub Desktop.
Unity ModelPreview
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace SandWar.Unity.Tools
{
[AddComponentMenu("")]
public sealed class ModelPreview : Singleton<ModelPreview>
{
static readonly int TemporaryLayer = 31;
protected override bool Persistent {
get { return true; }
}
protected override bool Visible {
get { return false; }
}
Camera myCamera;
Light myLight;
private ModelPreview() { }
/// <summary>Render a the preview of a model to a <see cref="Texture" />.</summary>
/// <param name="model">The model to generate the preview of.</param>
/// <param name="width">The width of the .</param>
/// <param name="height">Height.</param>
public static RenderTexture Render(Transform model, int width, int height) {
var myModel = Object.Instantiate(model);
var texture = Instance.renderModel(myModel, width, height);
Object.Destroy(myModel.gameObject);
return texture;
}
RenderTexture renderModel(Transform model, int width, int height) {
var texture = new RenderTexture(width, height, 16) {
name = model.name.Substring(0, model.name.Length - "(Clone)".Length),
wrapMode = TextureWrapMode.Clamp,
antiAliasing = 4
};
var lights = new List<Light> ();
foreach (var light in GameObject.FindObjectsOfType<Light>())
if (light.enabled)
lights.Add(light);
foreach (var light in lights)
light.enabled = false;
model.SetParent(transform);
model.localPosition = Vector3.zero;
model.localRotation = Quaternion.identity;
model.localScale = Vector3.one;
model.gameObject.layer = TemporaryLayer;
var bounds = new Bounds();
foreach (var renderer in model.GetComponentsInChildren<Renderer>().Concat(model.GetComponents<Renderer>())) {
bounds.Encapsulate(renderer.bounds);
renderer.gameObject.layer = TemporaryLayer;
}
var dimension = Vector3.Distance(bounds.min, bounds.max);
var scale = 1f / dimension;
model.localPosition = -(bounds.center * scale);
model.localScale = Vector3.one * scale;
myCamera.transform.LookAt(Vector3.zero);
myCamera.enabled = true;
myLight.enabled = true;
myCamera.targetTexture = texture;
myCamera.Render();
myCamera.targetTexture = null;
myLight.enabled = false;
myCamera.enabled = false;
foreach (var light in lights)
light.enabled = true;
return texture;
}
protected override void Awake() {
myCamera = new GameObject("Camera").AddComponent<Camera>();
myCamera.transform.SetParent(transform);
myCamera.transform.localPosition = new Vector3(5f, 2f, 3f);
myCamera.cullingMask = 1 << TemporaryLayer;
myCamera.useOcclusionCulling = false;
myCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
myCamera.clearFlags = CameraClearFlags.SolidColor;
myCamera.fieldOfView = 8.5f;
myCamera.enabled = false;
myLight = new GameObject("Light").AddComponent<Light>();
myLight.transform.SetParent(transform);
myLight.transform.position = new Vector3(3f, 1.5f, -1.5f);
myLight.cullingMask = 1 << TemporaryLayer;
myLight.enabled = false;
}
}
}
using UnityEngine;
namespace SandWar.Unity.Tools
{
/// <summary>
/// Provides a way to quickly instantiate singletons.
///
/// Always seal the inheritor class.
/// </summary>
[AddComponentMenu("")]
public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
static object @lock = new object();
static bool instantiated = false;
static bool quitting = false;
static T instance = null;
/// <summary>Determines if the instance of this <see cref="Singleton" /> should persist between scene changes.</summary>
protected virtual bool Persistent {
get { return false; }
}
/// <summary>Determines if the instance of this <see cref="Singleton" /> should be visible in Hierarchy.</summary>
protected virtual bool Visible {
get { return true; }
}
/// <summary>Holds a reference to the instance of this <see cref="Singleton" />.</summary>
protected static T Instance {
get {
EnsureInstantiated();
return instance;
}
}
/// <summary>Intantiates a <see cref="Singleton" /> of type <typeparamref>T</typeparamref> if not already in the scene.</summary>
protected static void EnsureInstantiated() {
lock (@lock) {
if (!instantiated) {
if (quitting)
return;
instantiated = true;
instance = GameObject.FindObjectOfType<T>();
if (instance == null) {
var singleton = new GameObject(typeof(T).FullName + "(Singleton)");
instance = singleton.AddComponent<T>();
if (!instance.Visible)
singleton.hideFlags = HideFlags.HideInHierarchy;
}
if (instance.Persistent)
GameObject.DontDestroyOnLoad(instance.gameObject);
}
}
}
/// <summary>
/// Used by Unity to initialize the <see cref="GameObject" />.
///
/// Always call this method if overriding.
/// </summary>
protected virtual void Awake() {
if (instance != null && instance != this) {
// Do not log anything, because switching scene triggers this code if there is an instance of the Singleton
//Debug.LogWarningFormat(this, "Multiple instances of Singleton<{0}> found on the scene.", typeof(T).FullName);
GameObject.Destroy(gameObject);
}
}
/// <summary>
/// Used by Unity to destroy the <see cref="GameObject" />.
///
/// Always call this method if overriding.
/// </summary>
protected virtual void OnDestroy() {
lock (@lock) {
if (instance == this) {
instantiated = false;
instance = null;
}
}
}
/// <summary>
/// Called by Unity when the application is quitting.
///
/// Always call this method if overriding.
/// </summary>
protected virtual void OnApplicationQuit() {
lock (@lock) {
quitting = true;
}
}
}
}
using UnityEngine;
using SandWar.Unity.Tools;
public class TestScript : MonoBehaviour {
public Transform TestModel;
public Texture Result;
void Start() {
Result = ModelPreview.Render(TestModel, 256, 256);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment