Optimization to not render meshes. Better inspectors.

This commit is contained in:
NathanSweet 2014-04-27 00:23:11 +02:00
parent b316b8d3e1
commit 6983ec6fd3
9 changed files with 215 additions and 188 deletions

View File

@ -33,27 +33,24 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
[CustomEditor(typeof(SkeletonAnimation))] [CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : Editor { public class SkeletonAnimationInspector : SkeletonRendererInspector {
private SerializedProperty skeletonDataAsset, initialSkinName, timeScale, normals, tangents; protected SerializedProperty animationName, loop, timeScale;
private SerializedProperty animationName, loop;
void OnEnable () { protected override void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); base.OnEnable();
animationName = serializedObject.FindProperty("_animationName"); animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop"); loop = serializedObject.FindProperty("loop");
initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale"); timeScale = serializedObject.FindProperty("timeScale");
normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents");
} }
override public void OnInspectorGUI () { protected override void gui () {
serializedObject.Update(); base.gui();
SkeletonAnimation component = (SkeletonAnimation)target; SkeletonAnimation component = (SkeletonAnimation)target;
EditorGUILayout.PropertyField(skeletonDataAsset); EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) { if (component.valid) {
// Initial skin name. // Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count]; String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0; int skinIndex = 0;
@ -98,17 +95,5 @@ public class SkeletonAnimationInspector : Editor {
EditorGUILayout.LabelField("Loop"); EditorGUILayout.LabelField("Loop");
loop.boolValue = EditorGUILayout.Toggle(loop.boolValue); loop.boolValue = EditorGUILayout.Toggle(loop.boolValue);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(timeScale);
EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents);
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying) {
component.Reset();
}
}
} }
} }

View File

@ -34,23 +34,22 @@ using UnityEngine;
[CustomEditor(typeof(SkeletonRenderer))] [CustomEditor(typeof(SkeletonRenderer))]
public class SkeletonRendererInspector : Editor { public class SkeletonRendererInspector : Editor {
private SerializedProperty skeletonDataAsset, initialSkinName, timeScale, normals, tangents; protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes;
void OnEnable () { protected virtual void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
initialSkinName = serializedObject.FindProperty("initialSkinName"); initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale");
normals = serializedObject.FindProperty("calculateNormals"); normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents"); tangents = serializedObject.FindProperty("calculateTangents");
meshes = serializedObject.FindProperty("renderMeshes");
} }
override public void OnInspectorGUI () { protected virtual void gui () {
serializedObject.Update();
SkeletonRenderer component = (SkeletonRenderer)target; SkeletonRenderer component = (SkeletonRenderer)target;
EditorGUILayout.PropertyField(skeletonDataAsset); EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) { if (component.valid) {
// Initial skin name. // Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count]; String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0; int skinIndex = 0;
@ -60,26 +59,28 @@ public class SkeletonRendererInspector : Editor {
if (name == initialSkinName.stringValue) if (name == initialSkinName.stringValue)
skinIndex = i; skinIndex = i;
} }
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Initial Skin"); EditorGUILayout.LabelField("Initial Skin");
EditorGUIUtility.LookLikeControls(); EditorGUIUtility.LookLikeControls();
skinIndex = EditorGUILayout.Popup(skinIndex, skins); skinIndex = EditorGUILayout.Popup(skinIndex, skins);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
initialSkinName.stringValue = skins[skinIndex]; initialSkinName.stringValue = skins[skinIndex];
} }
EditorGUILayout.PropertyField(timeScale); EditorGUILayout.PropertyField(meshes);
EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents); EditorGUILayout.PropertyField(tangents);
}
override public void OnInspectorGUI () {
serializedObject.Update();
gui();
if (serializedObject.ApplyModifiedProperties() || if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed") (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) { ) {
if (!Application.isPlaying) { if (!Application.isPlaying) ((SkeletonRenderer)target).Reset();
component.Reset();
}
} }
} }
} }

View File

@ -47,6 +47,7 @@ public class SkeletonRenderer : MonoBehaviour {
public bool calculateNormals; public bool calculateNormals;
public bool calculateTangents; public bool calculateTangents;
public float zSpacing; public float zSpacing;
public bool renderMeshes;
private MeshFilter meshFilter; private MeshFilter meshFilter;
private Mesh mesh, mesh1, mesh2; private Mesh mesh, mesh1, mesh2;
@ -108,9 +109,9 @@ public class SkeletonRenderer : MonoBehaviour {
return mesh; return mesh;
} }
public virtual void OnWillRenderObject () { public virtual void LateUpdate () {
if (!valid) return; if (!valid) return;
// Count vertices and submesh triangles. // Count vertices and submesh triangles.
int vertexCount = 0; int vertexCount = 0;
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
@ -118,6 +119,7 @@ public class SkeletonRenderer : MonoBehaviour {
submeshMaterials.Clear(); submeshMaterials.Clear();
List<Slot> drawOrder = skeleton.DrawOrder; List<Slot> drawOrder = skeleton.DrawOrder;
int drawOrderCount = drawOrder.Count; int drawOrderCount = drawOrder.Count;
bool renderMeshes = this.renderMeshes;
for (int i = 0; i < drawOrderCount; i++) { for (int i = 0; i < drawOrderCount; i++) {
Attachment attachment = drawOrder[i].attachment; Attachment attachment = drawOrder[i].attachment;
@ -128,23 +130,26 @@ public class SkeletonRenderer : MonoBehaviour {
rendererObject = ((RegionAttachment)attachment).RendererObject; rendererObject = ((RegionAttachment)attachment).RendererObject;
attachmentVertexCount = 4; attachmentVertexCount = 4;
attachmentTriangleCount = 6; attachmentTriangleCount = 6;
} else if (attachment is MeshAttachment) { } else {
MeshAttachment meshAttachment = (MeshAttachment)attachment; if (!renderMeshes) continue;
rendererObject = meshAttachment.RendererObject; if (attachment is MeshAttachment) {
attachmentVertexCount = meshAttachment.vertices.Length / 2; MeshAttachment meshAttachment = (MeshAttachment)attachment;
attachmentTriangleCount = meshAttachment.triangles.Length; rendererObject = meshAttachment.RendererObject;
} else if (attachment is SkinnedMeshAttachment) { attachmentVertexCount = meshAttachment.vertices.Length >> 1;
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; attachmentTriangleCount = meshAttachment.triangles.Length;
rendererObject = meshAttachment.RendererObject; } else if (attachment is SkinnedMeshAttachment) {
attachmentVertexCount = meshAttachment.uvs.Length / 2; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
attachmentTriangleCount = meshAttachment.triangles.Length; rendererObject = meshAttachment.RendererObject;
} else attachmentVertexCount = meshAttachment.uvs.Length >> 1;
continue; attachmentTriangleCount = meshAttachment.triangles.Length;
} else
continue;
}
// Populate submesh when material changes. // Populate submesh when material changes.
Material material = (Material)rendererObject; Material material = (Material)rendererObject;
if (lastMaterial != material && lastMaterial != null) { if (lastMaterial != material && lastMaterial != null) {
addSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false); AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
submeshTriangleCount = 0; submeshTriangleCount = 0;
submeshFirstVertex = vertexCount; submeshFirstVertex = vertexCount;
submeshStartSlotIndex = i; submeshStartSlotIndex = i;
@ -154,7 +159,7 @@ public class SkeletonRenderer : MonoBehaviour {
submeshTriangleCount += attachmentTriangleCount; submeshTriangleCount += attachmentTriangleCount;
vertexCount += attachmentVertexCount; vertexCount += attachmentVertexCount;
} }
addSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true); AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true);
// Set materials. // Set materials.
if (submeshMaterials.Count == sharedMaterials.Length) if (submeshMaterials.Count == sharedMaterials.Length)
@ -219,43 +224,46 @@ public class SkeletonRenderer : MonoBehaviour {
uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]);
vertexIndex += 4; vertexIndex += 4;
} else if (attachment is MeshAttachment) { } else {
MeshAttachment meshAttachment = (MeshAttachment)attachment; if (!renderMeshes) continue;
int meshVertexCount = meshAttachment.vertices.Length; if (attachment is MeshAttachment) {
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount]; MeshAttachment meshAttachment = (MeshAttachment)attachment;
meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices); int meshVertexCount = meshAttachment.vertices.Length;
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
color.a = (byte)(a * slot.a * meshAttachment.a); meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
if (slot.data.additiveBlending) color.a = 0; color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
float[] meshUVs = meshAttachment.uvs; if (slot.data.additiveBlending) color.a = 0;
float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float[] meshUVs = meshAttachment.uvs;
vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); float z = i * zSpacing;
colors[vertexIndex] = color; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
} colors[vertexIndex] = color;
} else if (attachment is SkinnedMeshAttachment) { uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; }
int meshVertexCount = meshAttachment.uvs.Length; } else if (attachment is SkinnedMeshAttachment) {
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount]; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices); int meshVertexCount = meshAttachment.uvs.Length;
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
color.a = (byte)(a * slot.a * meshAttachment.a); meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
if (slot.data.additiveBlending) color.a = 0; color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
float[] meshUVs = meshAttachment.uvs; if (slot.data.additiveBlending) color.a = 0;
float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float[] meshUVs = meshAttachment.uvs;
vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); float z = i * zSpacing;
colors[vertexIndex] = color; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
colors[vertexIndex] = color;
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
}
} }
} }
} }
@ -297,7 +305,7 @@ public class SkeletonRenderer : MonoBehaviour {
} }
/** Stores vertices and triangles for a single material. */ /** Stores vertices and triangles for a single material. */
private void addSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {
int submeshIndex = submeshMaterials.Count; int submeshIndex = submeshMaterials.Count;
submeshMaterials.Add(material); submeshMaterials.Add(material);
@ -317,6 +325,24 @@ public class SkeletonRenderer : MonoBehaviour {
submesh.triangleCount = 0; submesh.triangleCount = 0;
} }
if (!renderMeshes) {
// Use stored triangles if possible.
if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount) {
submesh.triangleCount = triangleCount;
submesh.firstVertex = firstVertex;
for (int i = 0; i < triangleCount; i += 6, firstVertex += 4) {
triangles[i] = firstVertex;
triangles[i + 1] = firstVertex + 2;
triangles[i + 2] = firstVertex + 1;
triangles[i + 3] = firstVertex + 2;
triangles[i + 4] = firstVertex + 3;
triangles[i + 5] = firstVertex + 1;
}
}
return;
}
// Store triangles.
List<Slot> drawOrder = skeleton.DrawOrder; List<Slot> drawOrder = skeleton.DrawOrder;
for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {
Attachment attachment = drawOrder[i].attachment; Attachment attachment = drawOrder[i].attachment;
@ -327,11 +353,11 @@ public class SkeletonRenderer : MonoBehaviour {
attachmentTriangles = quadTriangles; attachmentTriangles = quadTriangles;
} else if (attachment is MeshAttachment) { } else if (attachment is MeshAttachment) {
MeshAttachment meshAttachment = (MeshAttachment)attachment; MeshAttachment meshAttachment = (MeshAttachment)attachment;
attachmentVertexCount = meshAttachment.vertices.Length / 2; attachmentVertexCount = meshAttachment.vertices.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else if (attachment is SkinnedMeshAttachment) { } else if (attachment is SkinnedMeshAttachment) {
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
attachmentVertexCount = meshAttachment.uvs.Length / 2; attachmentVertexCount = meshAttachment.uvs.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else } else
continue; continue;
@ -367,4 +393,5 @@ public class SkeletonRenderer : MonoBehaviour {
class Submesh { class Submesh {
public int[] triangles = new int[0]; public int[] triangles = new int[0];
public int triangleCount; public int triangleCount;
public int firstVertex = -1;
} }

View File

@ -33,27 +33,24 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
[CustomEditor(typeof(SkeletonAnimation))] [CustomEditor(typeof(SkeletonAnimation))]
public class SkeletonAnimationInspector : Editor { public class SkeletonAnimationInspector : SkeletonRendererInspector {
private SerializedProperty skeletonDataAsset, initialSkinName, timeScale, normals, tangents; protected SerializedProperty animationName, loop, timeScale;
private SerializedProperty animationName, loop;
void OnEnable () { protected override void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); base.OnEnable();
animationName = serializedObject.FindProperty("_animationName"); animationName = serializedObject.FindProperty("_animationName");
loop = serializedObject.FindProperty("loop"); loop = serializedObject.FindProperty("loop");
initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale"); timeScale = serializedObject.FindProperty("timeScale");
normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents");
} }
override public void OnInspectorGUI () { protected override void gui () {
serializedObject.Update(); base.gui();
SkeletonAnimation component = (SkeletonAnimation)target; SkeletonAnimation component = (SkeletonAnimation)target;
EditorGUILayout.PropertyField(skeletonDataAsset); EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) { if (component.valid) {
// Initial skin name. // Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count]; String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0; int skinIndex = 0;
@ -98,17 +95,5 @@ public class SkeletonAnimationInspector : Editor {
EditorGUILayout.LabelField("Loop"); EditorGUILayout.LabelField("Loop");
loop.boolValue = EditorGUILayout.Toggle(loop.boolValue); loop.boolValue = EditorGUILayout.Toggle(loop.boolValue);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(timeScale);
EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents);
if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) {
if (!Application.isPlaying) {
component.Reset();
}
}
} }
} }

View File

@ -34,23 +34,22 @@ using UnityEngine;
[CustomEditor(typeof(SkeletonRenderer))] [CustomEditor(typeof(SkeletonRenderer))]
public class SkeletonRendererInspector : Editor { public class SkeletonRendererInspector : Editor {
private SerializedProperty skeletonDataAsset, initialSkinName, timeScale, normals, tangents; protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes;
void OnEnable () { protected virtual void OnEnable () {
skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
initialSkinName = serializedObject.FindProperty("initialSkinName"); initialSkinName = serializedObject.FindProperty("initialSkinName");
timeScale = serializedObject.FindProperty("timeScale");
normals = serializedObject.FindProperty("calculateNormals"); normals = serializedObject.FindProperty("calculateNormals");
tangents = serializedObject.FindProperty("calculateTangents"); tangents = serializedObject.FindProperty("calculateTangents");
meshes = serializedObject.FindProperty("renderMeshes");
} }
override public void OnInspectorGUI () { protected virtual void gui () {
serializedObject.Update();
SkeletonRenderer component = (SkeletonRenderer)target; SkeletonRenderer component = (SkeletonRenderer)target;
EditorGUILayout.PropertyField(skeletonDataAsset); EditorGUILayout.PropertyField(skeletonDataAsset);
if (component.skeleton != null) { if (component.valid) {
// Initial skin name. // Initial skin name.
String[] skins = new String[component.skeleton.Data.Skins.Count]; String[] skins = new String[component.skeleton.Data.Skins.Count];
int skinIndex = 0; int skinIndex = 0;
@ -60,26 +59,28 @@ public class SkeletonRendererInspector : Editor {
if (name == initialSkinName.stringValue) if (name == initialSkinName.stringValue)
skinIndex = i; skinIndex = i;
} }
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Initial Skin"); EditorGUILayout.LabelField("Initial Skin");
EditorGUIUtility.LookLikeControls(); EditorGUIUtility.LookLikeControls();
skinIndex = EditorGUILayout.Popup(skinIndex, skins); skinIndex = EditorGUILayout.Popup(skinIndex, skins);
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
initialSkinName.stringValue = skins[skinIndex]; initialSkinName.stringValue = skins[skinIndex];
} }
EditorGUILayout.PropertyField(timeScale); EditorGUILayout.PropertyField(meshes);
EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents); EditorGUILayout.PropertyField(tangents);
}
override public void OnInspectorGUI () {
serializedObject.Update();
gui();
if (serializedObject.ApplyModifiedProperties() || if (serializedObject.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed") (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
) { ) {
if (!Application.isPlaying) { if (!Application.isPlaying) ((SkeletonRenderer)target).Reset();
component.Reset();
}
} }
} }
} }

View File

@ -41,12 +41,13 @@ public class SkeletonRenderer : MonoBehaviour {
public bool valid; public bool valid;
[System.NonSerialized] [System.NonSerialized]
public Skeleton skeleton; public Skeleton skeleton;
public SkeletonDataAsset skeletonDataAsset; public SkeletonDataAsset skeletonDataAsset;
public String initialSkinName; public String initialSkinName;
public bool calculateNormals; public bool calculateNormals;
public bool calculateTangents; public bool calculateTangents;
public float zSpacing; public float zSpacing;
public bool renderMeshes;
private MeshFilter meshFilter; private MeshFilter meshFilter;
private Mesh mesh, mesh1, mesh2; private Mesh mesh, mesh1, mesh2;
@ -76,7 +77,7 @@ public class SkeletonRenderer : MonoBehaviour {
submeshMaterials.Clear(); submeshMaterials.Clear();
submeshes.Clear(); submeshes.Clear();
skeleton = null; skeleton = null;
valid = false; valid = false;
if (!skeletonDataAsset) { if (!skeletonDataAsset) {
Debug.LogError("Missing SkeletonData asset.", this); Debug.LogError("Missing SkeletonData asset.", this);
@ -84,7 +85,8 @@ public class SkeletonRenderer : MonoBehaviour {
} }
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false); SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
if (skeletonData == null) return; if (skeletonData == null) return;
valid = true;
meshFilter = GetComponent<MeshFilter>(); meshFilter = GetComponent<MeshFilter>();
mesh1 = newMesh(); mesh1 = newMesh();
mesh2 = newMesh(); mesh2 = newMesh();
@ -107,7 +109,7 @@ public class SkeletonRenderer : MonoBehaviour {
return mesh; return mesh;
} }
public virtual void OnWillRenderObject () { public virtual void LateUpdate () {
if (!valid) return; if (!valid) return;
// Count vertices and submesh triangles. // Count vertices and submesh triangles.
@ -117,6 +119,7 @@ public class SkeletonRenderer : MonoBehaviour {
submeshMaterials.Clear(); submeshMaterials.Clear();
List<Slot> drawOrder = skeleton.DrawOrder; List<Slot> drawOrder = skeleton.DrawOrder;
int drawOrderCount = drawOrder.Count; int drawOrderCount = drawOrder.Count;
bool renderMeshes = this.renderMeshes;
for (int i = 0; i < drawOrderCount; i++) { for (int i = 0; i < drawOrderCount; i++) {
Attachment attachment = drawOrder[i].attachment; Attachment attachment = drawOrder[i].attachment;
@ -127,23 +130,26 @@ public class SkeletonRenderer : MonoBehaviour {
rendererObject = ((RegionAttachment)attachment).RendererObject; rendererObject = ((RegionAttachment)attachment).RendererObject;
attachmentVertexCount = 4; attachmentVertexCount = 4;
attachmentTriangleCount = 6; attachmentTriangleCount = 6;
} else if (attachment is MeshAttachment) { } else {
MeshAttachment meshAttachment = (MeshAttachment)attachment; if (!renderMeshes) continue;
rendererObject = meshAttachment.RendererObject; if (attachment is MeshAttachment) {
attachmentVertexCount = meshAttachment.vertices.Length / 2; MeshAttachment meshAttachment = (MeshAttachment)attachment;
attachmentTriangleCount = meshAttachment.triangles.Length; rendererObject = meshAttachment.RendererObject;
} else if (attachment is SkinnedMeshAttachment) { attachmentVertexCount = meshAttachment.vertices.Length >> 1;
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; attachmentTriangleCount = meshAttachment.triangles.Length;
rendererObject = meshAttachment.RendererObject; } else if (attachment is SkinnedMeshAttachment) {
attachmentVertexCount = meshAttachment.uvs.Length / 2; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
attachmentTriangleCount = meshAttachment.triangles.Length; rendererObject = meshAttachment.RendererObject;
} else attachmentVertexCount = meshAttachment.uvs.Length >> 1;
continue; attachmentTriangleCount = meshAttachment.triangles.Length;
} else
continue;
}
// Populate submesh when material changes. // Populate submesh when material changes.
Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
if (lastMaterial != material && lastMaterial != null) { if (lastMaterial != material && lastMaterial != null) {
addSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false); AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
submeshTriangleCount = 0; submeshTriangleCount = 0;
submeshFirstVertex = vertexCount; submeshFirstVertex = vertexCount;
submeshStartSlotIndex = i; submeshStartSlotIndex = i;
@ -153,7 +159,7 @@ public class SkeletonRenderer : MonoBehaviour {
submeshTriangleCount += attachmentTriangleCount; submeshTriangleCount += attachmentTriangleCount;
vertexCount += attachmentVertexCount; vertexCount += attachmentVertexCount;
} }
addSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true); AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true);
// Set materials. // Set materials.
if (submeshMaterials.Count == sharedMaterials.Length) if (submeshMaterials.Count == sharedMaterials.Length)
@ -218,43 +224,46 @@ public class SkeletonRenderer : MonoBehaviour {
uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]);
vertexIndex += 4; vertexIndex += 4;
} else if (attachment is MeshAttachment) { } else {
MeshAttachment meshAttachment = (MeshAttachment)attachment; if (!renderMeshes) continue;
int meshVertexCount = meshAttachment.vertices.Length; if (attachment is MeshAttachment) {
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount]; MeshAttachment meshAttachment = (MeshAttachment)attachment;
meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices); int meshVertexCount = meshAttachment.vertices.Length;
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
color.a = (byte)(a * slot.a * meshAttachment.a); meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
if (slot.data.additiveBlending) color.a = 0; color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
float[] meshUVs = meshAttachment.uvs; if (slot.data.additiveBlending) color.a = 0;
float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float[] meshUVs = meshAttachment.uvs;
vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); float z = i * zSpacing;
colors[vertexIndex] = color; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
} colors[vertexIndex] = color;
} else if (attachment is SkinnedMeshAttachment) { uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; }
int meshVertexCount = meshAttachment.uvs.Length; } else if (attachment is SkinnedMeshAttachment) {
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount]; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices); int meshVertexCount = meshAttachment.uvs.Length;
if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
color.a = (byte)(a * slot.a * meshAttachment.a); meshAttachment.ComputeWorldVertices(x, y, slot, tempVertices);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
if (slot.data.additiveBlending) color.a = 0; color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
float[] meshUVs = meshAttachment.uvs; if (slot.data.additiveBlending) color.a = 0;
float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { float[] meshUVs = meshAttachment.uvs;
vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); float z = i * zSpacing;
colors[vertexIndex] = color; for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
colors[vertexIndex] = color;
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
}
} }
} }
} }
@ -296,7 +305,7 @@ public class SkeletonRenderer : MonoBehaviour {
} }
/** Stores vertices and triangles for a single material. */ /** Stores vertices and triangles for a single material. */
private void addSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {
int submeshIndex = submeshMaterials.Count; int submeshIndex = submeshMaterials.Count;
submeshMaterials.Add(material); submeshMaterials.Add(material);
@ -316,6 +325,24 @@ public class SkeletonRenderer : MonoBehaviour {
submesh.triangleCount = 0; submesh.triangleCount = 0;
} }
if (!renderMeshes) {
// Use stored triangles if possible.
if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount) {
submesh.triangleCount = triangleCount;
submesh.firstVertex = firstVertex;
for (int i = 0; i < triangleCount; i += 6, firstVertex += 4) {
triangles[i] = firstVertex;
triangles[i + 1] = firstVertex + 2;
triangles[i + 2] = firstVertex + 1;
triangles[i + 3] = firstVertex + 2;
triangles[i + 4] = firstVertex + 3;
triangles[i + 5] = firstVertex + 1;
}
}
return;
}
// Store triangles.
List<Slot> drawOrder = skeleton.DrawOrder; List<Slot> drawOrder = skeleton.DrawOrder;
for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {
Attachment attachment = drawOrder[i].attachment; Attachment attachment = drawOrder[i].attachment;
@ -326,11 +353,11 @@ public class SkeletonRenderer : MonoBehaviour {
attachmentTriangles = quadTriangles; attachmentTriangles = quadTriangles;
} else if (attachment is MeshAttachment) { } else if (attachment is MeshAttachment) {
MeshAttachment meshAttachment = (MeshAttachment)attachment; MeshAttachment meshAttachment = (MeshAttachment)attachment;
attachmentVertexCount = meshAttachment.vertices.Length / 2; attachmentVertexCount = meshAttachment.vertices.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else if (attachment is SkinnedMeshAttachment) { } else if (attachment is SkinnedMeshAttachment) {
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
attachmentVertexCount = meshAttachment.uvs.Length / 2; attachmentVertexCount = meshAttachment.uvs.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else } else
continue; continue;
@ -366,4 +393,5 @@ public class SkeletonRenderer : MonoBehaviour {
class Submesh { class Submesh {
public int[] triangles = new int[0]; public int[] triangles = new int[0];
public int triangleCount; public int triangleCount;
public int firstVertex = -1;
} }