179 lines
5.0 KiB
C#
179 lines
5.0 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.IO;
|
|
using System.Collections;
|
|
|
|
namespace Obi{
|
|
[CustomEditor(typeof(ObiDistanceField))]
|
|
public class ObiDistanceFieldEditor : Editor
|
|
{
|
|
|
|
ObiDistanceField distanceField;
|
|
|
|
PreviewHelpers previewHelper;
|
|
Vector2 previewDir;
|
|
Material previewMaterial;
|
|
|
|
Mesh previewMesh;
|
|
Texture3D volumeTexture;
|
|
|
|
protected IEnumerator routine;
|
|
|
|
private void UpdatePreview(){
|
|
|
|
CleanupPreview();
|
|
|
|
if (distanceField.InputMesh != null){
|
|
|
|
previewMesh = CreateMeshForBounds(distanceField.FieldBounds);
|
|
previewMesh.hideFlags = HideFlags.HideAndDontSave;
|
|
|
|
volumeTexture = distanceField.GetVolumeTexture(64);
|
|
volumeTexture.hideFlags = HideFlags.HideAndDontSave;
|
|
|
|
previewMaterial = Resources.Load<Material>("DistanceFieldPreview");
|
|
previewMaterial.SetTexture("_Volume",volumeTexture);
|
|
previewMaterial.SetVector("_AABBMin",-distanceField.FieldBounds.extents);
|
|
previewMaterial.SetVector("_AABBMax",distanceField.FieldBounds.extents);
|
|
}
|
|
|
|
}
|
|
|
|
private void CleanupPreview(){
|
|
GameObject.DestroyImmediate(previewMesh);
|
|
GameObject.DestroyImmediate(volumeTexture);
|
|
}
|
|
|
|
public void OnEnable(){
|
|
distanceField = (ObiDistanceField) target;
|
|
previewHelper = new PreviewHelpers();
|
|
UpdatePreview();
|
|
}
|
|
|
|
public void OnDisable(){
|
|
EditorUtility.ClearProgressBar();
|
|
previewHelper.Cleanup();
|
|
CleanupPreview();
|
|
}
|
|
|
|
public override void OnInspectorGUI() {
|
|
|
|
serializedObject.UpdateIfRequiredOrScript();
|
|
|
|
Editor.DrawPropertiesExcluding(serializedObject,"m_Script");
|
|
|
|
GUI.enabled = (distanceField.InputMesh != null);
|
|
if (GUILayout.Button("Generate")){
|
|
// Start a coroutine job in the editor.
|
|
EditorUtility.SetDirty(target);
|
|
CoroutineJob job = new CoroutineJob();
|
|
routine = job.Start( distanceField.Generate());
|
|
EditorCoroutine.ShowCoroutineProgressBar("Generating distance field",ref routine);
|
|
UpdatePreview();
|
|
EditorGUIUtility.ExitGUI();
|
|
}
|
|
GUI.enabled = true;
|
|
|
|
int nodeCount = (distanceField.nodes != null ? distanceField.nodes.Count : 0);
|
|
float resolution = distanceField.FieldBounds.size.x / distanceField.EffectiveSampleSize;
|
|
EditorGUILayout.HelpBox("Nodes: "+ nodeCount+"\n"+
|
|
"Size in memory: "+ (nodeCount * 0.062f).ToString("0.#") +" kB\n"+
|
|
"Compressed to: " + (nodeCount / Mathf.Pow(resolution,3) * 100).ToString("0.##") + "%",MessageType.Info);
|
|
|
|
if (GUI.changed)
|
|
serializedObject.ApplyModifiedProperties();
|
|
|
|
}
|
|
|
|
public override bool HasPreviewGUI(){
|
|
return true;
|
|
}
|
|
|
|
public override void OnInteractivePreviewGUI(Rect region, GUIStyle background)
|
|
{
|
|
previewDir = PreviewHelpers.Drag2D(previewDir, region);
|
|
|
|
if (Event.current.type != EventType.Repaint || previewMesh == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Quaternion quaternion = Quaternion.Euler(this.previewDir.y, 0f, 0f) * Quaternion.Euler(0f, this.previewDir.x, 0f) * Quaternion.Euler(0, 120, -20f);
|
|
|
|
previewHelper.BeginPreview(region, background);
|
|
|
|
Bounds bounds = previewMesh.bounds;
|
|
float magnitude = Mathf.Sqrt(bounds.extents.sqrMagnitude);
|
|
float num = 4f * magnitude;
|
|
previewHelper.m_Camera.transform.position = -Vector3.forward * num;
|
|
previewHelper.m_Camera.transform.rotation = Quaternion.identity;
|
|
previewHelper.m_Camera.nearClipPlane = num - magnitude * 1.1f;
|
|
previewHelper.m_Camera.farClipPlane = num + magnitude * 1.1f;
|
|
|
|
// Compute matrix to rotate the mesh around the center of its bounds:
|
|
Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero,quaternion,Vector3.one) * Matrix4x4.TRS(-bounds.center,Quaternion.identity,Vector3.one);
|
|
|
|
Graphics.DrawMesh(previewMesh, matrix, previewMaterial,1, previewHelper.m_Camera, 0);
|
|
|
|
Texture texture = previewHelper.EndPreview();
|
|
GUI.DrawTexture(region, texture, ScaleMode.StretchToFill, true);
|
|
|
|
}
|
|
|
|
/**
|
|
* Creates a solid mesh from some Bounds. This is used to display the distance field volumetric preview.
|
|
*/
|
|
private Mesh CreateMeshForBounds(Bounds b){
|
|
Mesh m = new Mesh();
|
|
|
|
/** Indices of bounds corners:
|
|
|
|
Y
|
|
2 6
|
|
+------+
|
|
3 .'| 7 .'|
|
|
+---+--+' |
|
|
| | | |
|
|
| +--+---+ X
|
|
| .' 0 | .' 4
|
|
+------+'
|
|
Z 1 5
|
|
|
|
*/
|
|
Vector3[] vertices = new Vector3[8]{
|
|
b.center + new Vector3(-b.extents.x,-b.extents.y,-b.extents.z), //0
|
|
b.center + new Vector3(-b.extents.x,-b.extents.y,b.extents.z), //1
|
|
b.center + new Vector3(-b.extents.x,b.extents.y,-b.extents.z), //2
|
|
b.center + new Vector3(-b.extents.x,b.extents.y,b.extents.z), //3
|
|
b.center + new Vector3(b.extents.x,-b.extents.y,-b.extents.z), //4
|
|
b.center + new Vector3(b.extents.x,-b.extents.y,b.extents.z), //5
|
|
b.center + new Vector3(b.extents.x,b.extents.y,-b.extents.z), //6
|
|
b.center + new Vector3(b.extents.x,b.extents.y,b.extents.z) //7
|
|
};
|
|
int[] triangles = new int[36]{
|
|
2,3,7,
|
|
6,2,7,
|
|
|
|
7,5,4,
|
|
6,7,4,
|
|
|
|
3,1,5,
|
|
7,3,5,
|
|
|
|
2,0,3,
|
|
3,0,1,
|
|
|
|
6,4,2,
|
|
2,4,0,
|
|
|
|
4,5,0,
|
|
5,1,0
|
|
};
|
|
|
|
m.vertices = vertices;
|
|
m.triangles = triangles;
|
|
return m;
|
|
}
|
|
}
|
|
}
|