Last active
August 3, 2022 06:25
-
-
Save nothke/8b9fae02ac50bbc0b04b98c98b10f3bb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
public static class ObjectPreviewer | |
{ | |
struct Node | |
{ | |
public Matrix4x4 transform; | |
public Mesh mesh; | |
public Material[] mats; | |
} | |
// Static cache | |
static List<MeshFilter> meshFiltersBuffer; | |
static List<Node> nodes; | |
/// <summary> | |
/// For performance reasons, the cache never deallocates. | |
/// So, call this to clear the cache only in the case the memory becomes a problem, such as with previewing objects with gigantic hierarchies. | |
/// (but even if they're gigantic it's quite unlikely it will be a problem) | |
/// </summary> | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] | |
public static void ReloadCache() | |
{ | |
meshFiltersBuffer = new List<MeshFilter>(); | |
nodes = new List<Node>(); | |
} | |
/// <summary> | |
/// Assigns object for rendering. Call this only once on preview object change. Pass null to clear the object. | |
/// </summary> | |
public static void SetObject(GameObject go) | |
{ | |
nodes.Clear(); | |
meshFiltersBuffer.Clear(); | |
if (go == null) | |
return; | |
Matrix4x4 rootW2L = go.transform.worldToLocalMatrix; | |
// We need to scale in case the root has non 1,1,1 scale | |
Matrix4x4 rootScaleMatrix = Matrix4x4.Scale(go.transform.localScale); | |
go.transform.GetComponentsInChildren(meshFiltersBuffer); | |
foreach (var mf in meshFiltersBuffer) | |
{ | |
Mesh mesh = mf.sharedMesh; | |
var mr = mf.GetComponent<MeshRenderer>(); | |
if (mesh == null) | |
continue; | |
// Un-transform by root | |
Matrix4x4 matrix = rootW2L * mf.transform.localToWorldMatrix * rootScaleMatrix; | |
Material[] mats = null; | |
if (mr != null) | |
mats = mr.sharedMaterials; | |
nodes.Add(new Node() | |
{ | |
mesh = mesh, | |
transform = matrix, | |
mats = mats, | |
}); | |
} | |
} | |
/// <summary> | |
/// Renders the preview object set with SetObject(). Call this every frame you want the object to be drawn. | |
/// </summary> | |
/// <param name="overrideMaterial">The replacement material that the previews will be drawn with. If not assigned, it will use the original material.</param> | |
public static void Render(Vector3 position, Quaternion rotation, Vector3 scale, Material overrideMaterial = null, int renderLayer = 0) | |
{ | |
Matrix4x4 previewTransform = Matrix4x4.TRS(position, rotation, scale); | |
foreach (var node in nodes) | |
{ | |
for (int subMeshIndex = 0; subMeshIndex < node.mesh.subMeshCount; subMeshIndex++) | |
{ | |
var mat = overrideMaterial != null ? overrideMaterial : node.mats[Mathf.Clamp(subMeshIndex, 0, node.mats.Length)]; | |
Graphics.DrawMesh(node.mesh, previewTransform * node.transform, mat, renderLayer, null, subMeshIndex); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public class ObjectPreviewerTest : MonoBehaviour | |
{ | |
public GameObject testObject; | |
public Material replacementMaterial; | |
public int renderLayer = 0; | |
private void Start() | |
{ | |
ObjectPreviewer.SetObject(testObject); | |
} | |
private void Update() | |
{ | |
ObjectPreviewer.Render(transform.position, transform.rotation, transform.localScale, replacementMaterial, renderLayer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment