I have written some code that generates a simple quad, then I borrowed code from the UnifyCommunity that subdivides meshes and keeps the vertices shared, then modified it to subdivide a very specific way, and finally I added another static function that splits the mesh into four separate meshes. The function that splits the subdivided quad runs fine up until the quad has more than 1k vertices, then it’s lack of optimization begins to really show. Basically I want to know how I can get my split function to run far faster than it does as I will have to be splitting several high vertex count meshes frequently. Code to reproduce what I am doing can be found below.
Mesh Controller Script: Add this code to an empty gameObject and assign a material for the objectMaterial variable.
A quad will be generated in play mode and the “u” key can be used to subdivide the quad and the “i” key can be used to split it.
using UnityEngine;
using System.Collections;
public class MeshController : MonoBehaviour {
public Material objectMaterial; //assign a material here
void Start () {
if(transform.parent == null){
gameObject.AddComponent("MeshRenderer");
gameObject.AddComponent("MeshFilter");
gameObject.AddComponent("MeshCollider");
Mesh mesh = new Mesh();
Vector3[] vertices = new Vector3[]
{
new Vector3(1, 0, 1),
new Vector3(1, 0, -1),
new Vector3(-1, 0, 1),
new Vector3(-1, 0, -1),
};
Color[] colors = new Color[]
{
Color.white,
Color.white,
Color.white,
Color.white,
};
Vector2[] uv = new Vector2[]
{
new Vector2(1, 1),
new Vector2(1, 0),
new Vector2(0, 1),
new Vector2(0, 0),
};
int[] triangles = new int[]
{
0, 1, 2,
2, 1, 3,
};
Vector3[] normals = new Vector3[ vertices.Length ];
for( int n = 0; n < normals.Length; n++ )
normals[n] = Vector3.up;
mesh.vertices = vertices;
mesh.normals = normals;
mesh.colors = colors;
mesh.uv = uv;
mesh.triangles = triangles;
GetComponent<MeshFilter>().mesh = mesh;
GetComponent<MeshCollider>().mesh = mesh;
gameObject.renderer.material = objectMaterial;
}
}
void Update () {
if(Input.GetKeyDown("u")){
MeshSubdiv.Subdivide(gameObject.GetComponent<MeshFilter>().mesh);
}
if(Input.GetKeyDown("i")){
if(GetComponent<MeshRenderer>().enabled == true){
Mesh[] splitFaces = new Mesh[4];
splitFaces = MeshSubdiv.Split(gameObject.GetComponent<MeshFilter>().mesh);
for(int i = 0; i < 4; i++){
GameObject newFace = new GameObject();
newFace.transform.position = transform.position;
newFace.transform.rotation = transform.rotation;
newFace.name = "Face" + (i +1);
newFace.transform.parent = gameObject.transform;
newFace.AddComponent("MeshRenderer");
newFace.AddComponent("MeshFilter");
newFace.GetComponent<MeshFilter>().mesh = splitFaces*;*
-
newFace.AddComponent("MeshController");*
-
newFace.renderer.material = gameObject.renderer.material;*
-
newFace.AddComponent("MeshCollider");*
_ newFace.GetComponent().mesh = splitFaces*;*_
* }*
* GetComponent().enabled = false;*
* GetComponent().enabled = false;*
* //gameObject.tag = (“Untagged”);*
* }*
* }*
* }*
}
MeshSubdiv Script: This script is where all the subdivision and splitting happens.
The “Split” function is where things get slow, after some testing I think that using “list.IndexOf” and “list.Contains” are what’s making it slow…
A quad will be generated in play mode and the “u” key can be used to subdivide the quad and the “i” key can be used to split it.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public static class MeshSubdiv
{
* static List vertices;*
* static List normals;*
* static List colors;*
* static List uv;*
* static List uv1;*
* static List uv2;*
* static List indices;*
* static Dictionary<uint,int> newVectices;*
* static Dictionary<int,int> newVectices2;*
* static void InitArrays(Mesh mesh) //for subdivision*
* {*
* vertices = new List(mesh.vertices);*
* normals = new List(mesh.normals);*
* colors = new List(mesh.colors);*
* uv = new List(mesh.uv);*
* uv1 = new List(mesh.uv1);*
* uv2 = new List(mesh.uv2);*
* indices = new List();*
* }*
* static void InitArrays2(Mesh mesh) //for mesh splitting*
* {*
* vertices = new List(mesh.vertices);*
* normals = new List(mesh.normals);*
* colors = new List(mesh.colors);*
* uv = new List(mesh.uv);*
* uv1 = new List(mesh.uv1);*
* uv2 = new List(mesh.uv2);*
* indices = new List(mesh.triangles);*
* }*
* static void CleanUp()*
* {*
* vertices = null;*
* normals = null;*
* colors = null;*
* uv = null;*
* uv1 = null;*
* uv2 = null;*
* indices = null;*
* }*
* static int GetNewVertex(int i1, int i2)*
* {*
* int newIndex = vertices.Count;*
* uint t1 = ((uint)i1 << 16) | (uint)i2;*
* uint t2 = ((uint)i2 << 16) | (uint)i1;*
* if (newVectices.ContainsKey(t2))*
* return newVectices[t2];*
* if (newVectices.ContainsKey(t1))*
* return newVectices[t1];*
* newVectices.Add(t1,newIndex);*
_ vertices.Add((vertices[i1] + vertices[i2]) * 0.5f);
* if (normals.Count>0)*
* normals.Add((normals[i1] + normals[i2]).normalized);*
* if (colors.Count>0)*
colors.Add((colors[i1] + colors[i2]) * 0.5f);
* if (uv.Count>0)*
uv.Add((uv[i1] + uv[i2])0.5f);_
_ if (uv1.Count>0)_
_ uv1.Add((uv1[i1] + uv1[i2])0.5f);_
_ if (uv2.Count>0)_
_ uv2.Add((uv2[i1] + uv2[i2])*0.5f);_
* return newIndex;*
* }*
* public static void Subdivide(Mesh mesh)*
* {*
* newVectices = new Dictionary<uint,int>();*
* InitArrays(mesh);*
* int[] triangles = mesh.triangles;*
* for (int i = 0; i < triangles.Length; i += 6)*
* {*
* int i0 = triangles[i + 0];*
* int i1 = triangles[i + 1];*
* int i2 = triangles[i + 2];*
* int i3 = triangles[i + 3];*
* int i4 = triangles[i + 4];*
* int i5 = triangles[i + 5];*
* int m0 = GetNewVertex(i0, i1);*
* int m1 = GetNewVertex(i1, i2);*
* int m2 = GetNewVertex(i0, i2);*
* int m3 = GetNewVertex(i3, i4);*
* int m4 = GetNewVertex(i4, i5);*
* int m5 = GetNewVertex(i3, i5);*
* indices.Add(m0); indices.Add(i1); indices.Add(m1);*
* indices.Add(m3); indices.Add(i4); indices.Add(m4);*
* indices.Add(m3); indices.Add(m4); indices.Add(m5);*
* indices.Add(m5); indices.Add(m4); indices.Add(i5);*
* indices.Add(i0); indices.Add(m0); indices.Add(m2);*
* indices.Add(m2); indices.Add(m0); indices.Add(m1);*
* indices.Add(m2); indices.Add(m1); indices.Add(i2);*
* indices.Add(i3); indices.Add(m3); indices.Add(m5);*
* }*
* mesh.vertices = vertices.ToArray();*
* if (normals.Count > 0)*
* mesh.normals = normals.ToArray();*
* if (colors.Count>0)*
* mesh.colors = colors.ToArray();*
* if (uv.Count>0)*
* mesh.uv = uv.ToArray();*
* if (uv1.Count>0)*
* mesh.uv1 = uv1.ToArray();*
* if (uv2.Count>0)*
* mesh.uv2 = uv2.ToArray();*
* mesh.triangles = indices.ToArray();*
* CleanUp();*
* }*
* //Mesh Split Function*
* public static Mesh[] Split(Mesh mesh)*
* {*
* InitArrays2(mesh);*
* Mesh[] meshList = new Mesh[4];*
* for(int n = 0; n < 4; n++){*
* List newVertices = new List();*
* List newNormals = new List();*
* List newColors = new List();*
* List newUv = new List();*
* List newUv1 = new List();*
* List newUv2 = new List();*
* List newIndices = new List();*
* newVectices2 = new Dictionary<int,int>();*
_ for(int i = 0 + (n * (indices.Count/4)); i < ((indices.Count/4) * (n + 1)); i += 6){_
* for(int x = 0; x < 6; x++){*
* int curIndex = indices[i+x];*
* if(!newVectices2.ContainsKey(curIndex)){*
* newVertices.Add (vertices[indices[i+x]]);*
* newNormals.Add (normals[indices[i+x]]);*
* //newColors.Add (colors[indices[i+x]]); no mesh colors*
* newUv.Add (uv[indices[i+x]]);*
* //newUv1.Add (uv1[indices[i+x]]); no uv1*
* //newUv2.Add (uv2[indices[i+x]]); no uv2*
* newIndices.Add (newVertices.Count-1);*
* newVectices2.Add (curIndex, newVertices.Count-1);*
* }else{*
* newIndices.Add ((int)newVectices2[curIndex]);*
* }*
* }*
* }*
* Mesh newMesh = new Mesh();*
* newMesh.vertices = newVertices.ToArray();*
* if(newNormals.Count > 0)*
* newMesh.normals = newNormals.ToArray();*
* if(newColors.Count > 0)*
* newMesh.colors = newColors.ToArray();*
* if(newUv.Count > 0)*
* newMesh.uv = newUv.ToArray();*
* if(newUv1.Count > 0)*
* newMesh.uv1 = newUv1.ToArray();*
* if(newUv2.Count > 0)*
* newMesh.uv2 = newUv2.ToArray();*
* newMesh.triangles = newIndices.ToArray();*
* meshList[n] = newMesh;*
* }*
* CleanUp();*
* return meshList;*
* }*
* //Mesh Split Function*
* public static Mesh DuplicateMesh(Mesh mesh)*
* {*
* return (Mesh)UnityEngine.Object.Instantiate(mesh);*
* }*
}