mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
update and set mesh triangles only when it's required
This commit is contained in:
parent
c7644ec0ad
commit
be7480bca4
@ -29,7 +29,6 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Spine;
|
using Spine;
|
||||||
@ -65,15 +64,14 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
private Mesh mesh1, mesh2;
|
private Mesh mesh1, mesh2;
|
||||||
private bool useMesh1;
|
private bool useMesh1;
|
||||||
private float[] tempVertices = new float[8];
|
private float[] tempVertices = new float[8];
|
||||||
private int lastVertexCount;
|
|
||||||
private Vector3[] vertices;
|
private Vector3[] vertices;
|
||||||
private Color32[] colors;
|
private Color32[] colors;
|
||||||
private Vector2[] uvs;
|
private Vector2[] uvs;
|
||||||
private Material[] sharedMaterials = new Material[0];
|
private Material[] sharedMaterials = new Material[0];
|
||||||
|
private LastState lastState = new LastState();
|
||||||
private readonly ExposedList<Material> submeshMaterials = new ExposedList<Material>();
|
private readonly ExposedList<Material> submeshMaterials = new ExposedList<Material>();
|
||||||
private readonly ExposedList<Submesh> submeshes = new ExposedList<Submesh>();
|
private readonly ExposedList<Submesh> submeshes = new ExposedList<Submesh>();
|
||||||
|
|
||||||
|
|
||||||
public virtual void Reset () {
|
public virtual void Reset () {
|
||||||
if (meshFilter != null)
|
if (meshFilter != null)
|
||||||
meshFilter.sharedMesh = null;
|
meshFilter.sharedMesh = null;
|
||||||
@ -95,9 +93,9 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
DestroyImmediate(mesh2);
|
DestroyImmediate(mesh2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastState = new LastState();
|
||||||
mesh1 = null;
|
mesh1 = null;
|
||||||
mesh2 = null;
|
mesh2 = null;
|
||||||
lastVertexCount = 0;
|
|
||||||
vertices = null;
|
vertices = null;
|
||||||
colors = null;
|
colors = null;
|
||||||
uvs = null;
|
uvs = null;
|
||||||
@ -176,11 +174,18 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
int vertexCount = 0;
|
int vertexCount = 0;
|
||||||
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
|
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
|
||||||
Material lastMaterial = null;
|
Material lastMaterial = null;
|
||||||
submeshMaterials.Clear();
|
|
||||||
ExposedList<Slot> drawOrder = skeleton.drawOrder;
|
ExposedList<Slot> drawOrder = skeleton.drawOrder;
|
||||||
int drawOrderCount = drawOrder.Count;
|
int drawOrderCount = drawOrder.Count;
|
||||||
int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
|
int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
|
||||||
bool renderMeshes = this.renderMeshes;
|
bool renderMeshes = this.renderMeshes;
|
||||||
|
|
||||||
|
// Clear last state of attachments and submeshes
|
||||||
|
ExposedList<int> attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp;
|
||||||
|
attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount);
|
||||||
|
attachmentsTriangleCountTemp.Count = drawOrderCount;
|
||||||
|
|
||||||
|
ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp;
|
||||||
|
addSubmeshArgumentsTemp.Clear(false);
|
||||||
for (int i = 0; i < drawOrderCount; i++) {
|
for (int i = 0; i < drawOrderCount; i++) {
|
||||||
Slot slot = drawOrder.Items[i];
|
Slot slot = drawOrder.Items[i];
|
||||||
Attachment attachment = slot.attachment;
|
Attachment attachment = slot.attachment;
|
||||||
@ -188,6 +193,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
object rendererObject;
|
object rendererObject;
|
||||||
int attachmentVertexCount, attachmentTriangleCount;
|
int attachmentVertexCount, attachmentTriangleCount;
|
||||||
|
|
||||||
|
attachmentsTriangleCountTemp.Items[i] = -1;
|
||||||
RegionAttachment regionAttachment = attachment as RegionAttachment;
|
RegionAttachment regionAttachment = attachment as RegionAttachment;
|
||||||
if (regionAttachment != null) {
|
if (regionAttachment != null) {
|
||||||
rendererObject = regionAttachment.RendererObject;
|
rendererObject = regionAttachment.RendererObject;
|
||||||
@ -216,7 +222,9 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
|
Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
|
||||||
if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) ||
|
if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) ||
|
||||||
(submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) {
|
(submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) {
|
||||||
AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
|
addSubmeshArgumentsTemp.Add(
|
||||||
|
new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false)
|
||||||
|
);
|
||||||
submeshTriangleCount = 0;
|
submeshTriangleCount = 0;
|
||||||
submeshFirstVertex = vertexCount;
|
submeshFirstVertex = vertexCount;
|
||||||
submeshStartSlotIndex = i;
|
submeshStartSlotIndex = i;
|
||||||
@ -225,15 +233,36 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
|
|
||||||
submeshTriangleCount += attachmentTriangleCount;
|
submeshTriangleCount += attachmentTriangleCount;
|
||||||
vertexCount += attachmentVertexCount;
|
vertexCount += attachmentVertexCount;
|
||||||
}
|
|
||||||
AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true);
|
|
||||||
|
|
||||||
// Set materials.
|
attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount;
|
||||||
if (submeshMaterials.Count == sharedMaterials.Length)
|
}
|
||||||
submeshMaterials.CopyTo(sharedMaterials);
|
addSubmeshArgumentsTemp.Add(
|
||||||
else
|
new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true)
|
||||||
sharedMaterials = submeshMaterials.ToArray();
|
);
|
||||||
meshRenderer.sharedMaterials = sharedMaterials;
|
|
||||||
|
bool mustUpdateMeshStructure = MustUpdateMeshStructure(attachmentsTriangleCountTemp, addSubmeshArgumentsTemp);
|
||||||
|
if (mustUpdateMeshStructure) {
|
||||||
|
submeshMaterials.Clear();
|
||||||
|
for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) {
|
||||||
|
LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i];
|
||||||
|
AddSubmesh(
|
||||||
|
arguments.material,
|
||||||
|
arguments.startSlot,
|
||||||
|
arguments.endSlot,
|
||||||
|
arguments.triangleCount,
|
||||||
|
arguments.firstVertex,
|
||||||
|
arguments.lastSubmesh
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set materials.
|
||||||
|
if (submeshMaterials.Count == sharedMaterials.Length)
|
||||||
|
submeshMaterials.CopyTo(sharedMaterials);
|
||||||
|
else
|
||||||
|
sharedMaterials = submeshMaterials.ToArray();
|
||||||
|
|
||||||
|
meshRenderer.sharedMaterials = sharedMaterials;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure mesh data is the right size.
|
// Ensure mesh data is the right size.
|
||||||
Vector3[] vertices = this.vertices;
|
Vector3[] vertices = this.vertices;
|
||||||
@ -248,10 +277,10 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
} else {
|
} else {
|
||||||
// Too many vertices, zero the extra.
|
// Too many vertices, zero the extra.
|
||||||
Vector3 zero = Vector3.zero;
|
Vector3 zero = Vector3.zero;
|
||||||
for (int i = vertexCount, n = lastVertexCount; i < n; i++)
|
for (int i = vertexCount, n = lastState.vertexCount ; i < n; i++)
|
||||||
vertices[i] = zero;
|
vertices[i] = zero;
|
||||||
}
|
}
|
||||||
lastVertexCount = vertexCount;
|
lastState.vertexCount = vertexCount;
|
||||||
|
|
||||||
// Setup mesh.
|
// Setup mesh.
|
||||||
Vector3 meshBoundsMin;
|
Vector3 meshBoundsMin;
|
||||||
@ -440,13 +469,16 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
mesh.colors32 = colors;
|
mesh.colors32 = colors;
|
||||||
mesh.uv = uvs;
|
mesh.uv = uvs;
|
||||||
|
|
||||||
int submeshCount = submeshMaterials.Count;
|
if (mustUpdateMeshStructure) {
|
||||||
mesh.subMeshCount = submeshCount;
|
int submeshCount = submeshMaterials.Count;
|
||||||
for (int i = 0; i < submeshCount; ++i)
|
mesh.subMeshCount = submeshCount;
|
||||||
mesh.SetTriangles(submeshes.Items[i].triangles, i);
|
for (int i = 0; i < submeshCount; ++i)
|
||||||
|
mesh.SetTriangles(submeshes.Items[i].triangles, i);
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
|
Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
|
||||||
mesh.bounds = new Bounds(meshBoundsMin + meshBoundsExtents * 0.5f, meshBoundsExtents);
|
Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f;
|
||||||
|
mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
|
||||||
|
|
||||||
if (newTriangles && calculateNormals) {
|
if (newTriangles && calculateNormals) {
|
||||||
Vector3[] normals = new Vector3[vertexCount];
|
Vector3[] normals = new Vector3[vertexCount];
|
||||||
@ -467,9 +499,85 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update previous state
|
||||||
|
ExposedList<int> attachmentsTriangleCountCurrentMesh =
|
||||||
|
useMesh1 ?
|
||||||
|
lastState.attachmentsTriangleCountMesh1 :
|
||||||
|
lastState.attachmentsTriangleCountMesh2;
|
||||||
|
ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh =
|
||||||
|
useMesh1 ?
|
||||||
|
lastState.addSubmeshArgumentsMesh1 :
|
||||||
|
lastState.addSubmeshArgumentsMesh2;
|
||||||
|
|
||||||
|
attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity);
|
||||||
|
attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count;
|
||||||
|
attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0);
|
||||||
|
|
||||||
|
addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count);
|
||||||
|
addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count;
|
||||||
|
addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items);
|
||||||
|
|
||||||
|
lastState.frontFacing = frontFacing;
|
||||||
|
lastState.immutableTriangles = immutableTriangles;
|
||||||
|
|
||||||
useMesh1 = !useMesh1;
|
useMesh1 = !useMesh1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool MustUpdateMeshStructure(ExposedList<int> attachmentsTriangleCountTemp, ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp) {
|
||||||
|
// Check if any mesh settings were changed
|
||||||
|
bool mustUpdateMeshStructure =
|
||||||
|
frontFacing != lastState.frontFacing ||
|
||||||
|
immutableTriangles != lastState.immutableTriangles;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
mustUpdateMeshStructure |= !Application.isPlaying;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mustUpdateMeshStructure)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check if any attachments were enabled/disabled
|
||||||
|
// or submesh structures has changed
|
||||||
|
ExposedList<int> attachmentsTriangleCountCurrentMesh =
|
||||||
|
useMesh1 ?
|
||||||
|
lastState.attachmentsTriangleCountMesh1 :
|
||||||
|
lastState.attachmentsTriangleCountMesh2;
|
||||||
|
ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh =
|
||||||
|
useMesh1 ?
|
||||||
|
lastState.addSubmeshArgumentsMesh1 :
|
||||||
|
lastState.addSubmeshArgumentsMesh2;
|
||||||
|
|
||||||
|
// Check attachments
|
||||||
|
int attachmentCount = attachmentsTriangleCountTemp.Count;
|
||||||
|
if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount) {
|
||||||
|
mustUpdateMeshStructure = true;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < attachmentCount; i++) {
|
||||||
|
if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i]) {
|
||||||
|
mustUpdateMeshStructure = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mustUpdateMeshStructure)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check submeshes
|
||||||
|
int submeshCount = addSubmeshArgumentsTemp.Count;
|
||||||
|
if (addSubmeshArgumentsCurrentMesh.Count != submeshCount) {
|
||||||
|
mustUpdateMeshStructure = true;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < submeshCount; i++) {
|
||||||
|
if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(addSubmeshArgumentsTemp.Items[i])) {
|
||||||
|
mustUpdateMeshStructure = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mustUpdateMeshStructure;
|
||||||
|
}
|
||||||
|
|
||||||
/** 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;
|
||||||
@ -593,6 +701,47 @@ public class SkeletonRenderer : MonoBehaviour {
|
|||||||
Gizmos.DrawCube(meshBounds.center, meshBounds.size);
|
Gizmos.DrawCube(meshBounds.center, meshBounds.size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private class LastState {
|
||||||
|
public bool frontFacing;
|
||||||
|
public bool immutableTriangles;
|
||||||
|
public int vertexCount;
|
||||||
|
public readonly ExposedList<int> attachmentsTriangleCountTemp = new ExposedList<int>();
|
||||||
|
public readonly ExposedList<int> attachmentsTriangleCountMesh1 = new ExposedList<int>();
|
||||||
|
public readonly ExposedList<int> attachmentsTriangleCountMesh2 = new ExposedList<int>();
|
||||||
|
public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsTemp = new ExposedList<AddSubmeshArguments>();
|
||||||
|
public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh1 = new ExposedList<AddSubmeshArguments>();
|
||||||
|
public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh2 = new ExposedList<AddSubmeshArguments>();
|
||||||
|
|
||||||
|
public struct AddSubmeshArguments {
|
||||||
|
public Material material;
|
||||||
|
public int startSlot;
|
||||||
|
public int endSlot;
|
||||||
|
public int triangleCount;
|
||||||
|
public int firstVertex;
|
||||||
|
public bool lastSubmesh;
|
||||||
|
|
||||||
|
public AddSubmeshArguments(Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {
|
||||||
|
this.material = material;
|
||||||
|
this.startSlot = startSlot;
|
||||||
|
this.endSlot = endSlot;
|
||||||
|
this.triangleCount = triangleCount;
|
||||||
|
this.firstVertex = firstVertex;
|
||||||
|
this.lastSubmesh = lastSubmesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(AddSubmeshArguments other) {
|
||||||
|
return
|
||||||
|
!ReferenceEquals(material, null) &&
|
||||||
|
!ReferenceEquals(other.material, null) &&
|
||||||
|
material.GetInstanceID() == other.material.GetInstanceID() &&
|
||||||
|
startSlot == other.startSlot &&
|
||||||
|
endSlot == other.endSlot &&
|
||||||
|
triangleCount == other.triangleCount &&
|
||||||
|
firstVertex == other.firstVertex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Submesh {
|
class Submesh {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user