Skip to content

Instantly share code, notes, and snippets.

@pharan
Created April 13, 2016 19:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pharan/f1e28ada3e2b7107b435200f37008c0f to your computer and use it in GitHub Desktop.
Save pharan/f1e28ada3e2b7107b435200f37008c0f to your computer and use it in GitHub Desktop.
Sample ISimpleMeshGenerator implementation using Unity's VertexHelper. Very slow.
/******************************************************************************
* Spine Runtimes Software License
* Version 2.3
*
* Copyright (c) 2013-2015, Esoteric Software
* All rights reserved.
*
* You are granted a perpetual, non-exclusive, non-sublicensable and
* non-transferable license to use, install, execute and perform the Spine
* Runtimes Software (the "Software") and derivative works solely for personal
* or internal use. Without the written permission of Esoteric Software (see
* Section 2 of the Spine Software License Agreement), you may not (a) modify,
* translate, adapt or otherwise create derivative works, improvements of the
* Software or develop new applications using the Software or (b) remove,
* delete, alter or obscure any trademarks or any copyright, trademark, patent
* or other intellectual property or proprietary rights notices on or in the
* Software, including any copy thereof. Redistributions in binary or source
* form must include this license and terms.
*
* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if (UNITY_5_0 || UNITY_5_1 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7)
#define PREUNITY_5_2
#endif
using UnityEngine;
using System.Collections.Generic;
#if !(PREUNITY_5_2)
namespace Spine.Unity.MeshGeneration {
/// <summary>This is for testing and educational purposes only. This takes about 10 times longer to render than the Arrays implementations.</summary>
public class VertexHelperSpineMeshGenerator : ISimpleMeshGenerator {
public float scale = 1f;
public float Scale { get { return scale; } set { scale = value; } }
public bool premultiplyAlpha = true;
public bool PremultiplyAlpha { get { return premultiplyAlpha; } set { premultiplyAlpha = value; } }
public int CurrentVertexCount { get { return this.positions.Count; } }
private Mesh lastGeneratedMesh;
public Mesh LastGeneratedMesh { get { return lastGeneratedMesh; } }
public Mesh GenerateMesh (Skeleton skeleton) {
skeletonColor.r = skeleton.r;
skeletonColor.g = skeleton.g;
skeletonColor.b = skeleton.b;
skeletonColor.a = skeleton.a;
ClearBuffers();
var drawOrderItems = skeleton.drawOrder.Items;
for (int i = 0, n = skeleton.drawOrder.Count; i < n; i++) {
AddSlot(drawOrderItems[i]);
}
Mesh currentMesh = doubleBufferedMesh.GetNextMesh();
FillMesh(currentMesh);
lastGeneratedMesh = currentMesh;
return currentMesh;
}
#region Internals
private DoubleBufferedMesh doubleBufferedMesh = new DoubleBufferedMesh();
protected Color skeletonColor = Color.white;
protected List<Vector3> positions = new List<Vector3>();
//protected List<Color> colors = new List<Color>(); // 5.3 mesh.SetColors(Color) is broken in UI.
protected List<Color32> colors32 = new List<Color32>();
protected List<Vector2> uvs = new List<Vector2>();
protected List<int> indices = new List<int>();
protected List<Vector3> normals = new List<Vector3>();
// Buffers
protected float[] tempVertices = new float[8];
static readonly Vector3 DefaultNormal = Vector3.back;
const float Z = 0f;
protected void FillMesh (Mesh mesh) {
mesh.Clear();
if (positions.Count > 65000)
throw new System.ArgumentException("Mesh cannot have more than 65000 vertices."); // Limitation based on UnityEngine.UI.VertexHelper
mesh.SetVertices(positions);
//mesh.SetColors(colors); // 5.3 mesh.SetColors(Color) is broken in UI.
mesh.SetColors(colors32);
mesh.SetUVs(0, uvs);
mesh.SetNormals(normals);
mesh.SetTriangles(indices, 0);
mesh.RecalculateBounds();
}
protected void ClearBuffers () {
positions.Clear();
//colors.Clear(); // 5.3 mesh.SetColors(Color) is broken.
colors32.Clear();
uvs.Clear();
indices.Clear();
normals.Clear();
}
protected void AddVert (Vector3 position, Color color, Vector2 uv) {
positions.Add(position);
//colors.Add(color); // 5.3 mesh.SetColors(Color) is broken in UI.
Color32 c; c.r = (byte)(color.r * 255); c.g = (byte)(color.g * 255); c.b = (byte)(color.b * 255); c.a = (byte)(color.a * 255);
colors32.Add(c);
uvs.Add(uv);
normals.Add(DefaultNormal);
}
protected void AddTriangle (int id0, int id1, int id2) {
indices.Add(id0);
indices.Add(id1);
indices.Add(id2);
}
protected void AddSlot (Slot slot) {
var a = slot.attachment;
var regionAttachment = a as RegionAttachment;
if (regionAttachment != null) {
AddAttachment(slot, regionAttachment);
return;
}
var meshAttachment = a as MeshAttachment;
if (meshAttachment != null) {
AddAttachment(slot, meshAttachment);
return;
}
var skinnedMeshAttachment = a as WeightedMeshAttachment;
if (skinnedMeshAttachment != null) {
AddAttachment(slot, skinnedMeshAttachment);
return;
}
}
// RegionAttachment
protected void AddAttachment (Slot slot, RegionAttachment attachment) {
var tempVertices = this.tempVertices;
attachment.ComputeWorldVertices(slot.bone, tempVertices);
float[] regionUVs = attachment.uvs;
Color color = skeletonColor;
color.r = color.r * attachment.r * slot.r;
color.g = color.g * attachment.g * slot.g;
color.b = color.b * attachment.b * slot.b;
color.a = color.a * attachment.a * slot.a;
if (premultiplyAlpha) {
color.r *= color.a; color.g *= color.a; color.b *= color.a;
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
}
int fv = positions.Count; // first vertex index
AddVert(new Vector3(tempVertices[RegionAttachment.X1] * scale, tempVertices[RegionAttachment.Y1] * scale), color, new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]));
AddVert(new Vector3(tempVertices[RegionAttachment.X4] * scale, tempVertices[RegionAttachment.Y4] * scale), color, new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]));
AddVert(new Vector3(tempVertices[RegionAttachment.X2] * scale, tempVertices[RegionAttachment.Y2] * scale), color, new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]));
AddVert(new Vector3(tempVertices[RegionAttachment.X3] * scale, tempVertices[RegionAttachment.Y3] * scale), color, new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]));
AddTriangle(fv, fv+2, fv+1);
AddTriangle(fv+2, fv+3, fv+1);
}
// MeshAttachment
protected void AddAttachment (Slot slot, MeshAttachment attachment) {
var tempVertices = this.tempVertices;
var meshUVs = attachment.uvs;
int meshVertexCount = attachment.vertices.Length;
if (tempVertices.Length < meshVertexCount)
this.tempVertices = tempVertices = new float[meshVertexCount];
attachment.ComputeWorldVertices(slot, tempVertices);
Color color = skeletonColor;
color.r = color.r * attachment.r * slot.r;
color.g = color.g * attachment.g * slot.g;
color.b = color.b * attachment.b * slot.b;
color.a = color.a * attachment.a * slot.a;
if (premultiplyAlpha) {
color.r *= color.a; color.g *= color.a; color.b *= color.a;
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
}
int fv = positions.Count; // first vertex index
for (int ii = 0; ii < meshVertexCount; ii += 2)
AddVert(new Vector3(tempVertices[ii], tempVertices[ii + 1]) * scale, color, new Vector2(meshUVs[ii], meshUVs[ii + 1]));
var attachmentTriangles = attachment.triangles;
for (int ii = 0, n = attachmentTriangles.Length; ii < n; ii++)
indices.Add(attachmentTriangles[ii] + fv);
}
// SkinnedMeshAttachment
protected void AddAttachment (Slot slot, WeightedMeshAttachment attachment) {
var tempVertices = this.tempVertices;
float[] meshUVs = attachment.uvs;
int meshVertexCount = attachment.uvs.Length;
if (tempVertices.Length < meshVertexCount)
this.tempVertices = tempVertices = new float[meshVertexCount];
attachment.ComputeWorldVertices(slot, tempVertices);
Color color = skeletonColor;
color.r = color.r * attachment.r * slot.r;
color.g = color.g * attachment.g * slot.g;
color.b = color.b * attachment.b * slot.b;
color.a = color.a * attachment.a * slot.a;
if (premultiplyAlpha) {
color.r *= color.a; color.g *= color.a; color.b *= color.a;
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
}
int fv = positions.Count; // first vertex index
for (int ii = 0; ii < meshVertexCount; ii += 2)
AddVert(new Vector3(tempVertices[ii], tempVertices[ii + 1]) * scale, color, new Vector2(meshUVs[ii], meshUVs[ii + 1]));
var attachmentTriangles = attachment.triangles;
for (int ii = 0, n = attachmentTriangles.Length; ii < n; ii++)
indices.Add(attachmentTriangles[ii] + fv);
}
#endregion
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment