-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRepeatMesh.cs
163 lines (128 loc) · 4.48 KB
/
RepeatMesh.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
[ExecuteInEditMode]
[RequireComponent (typeof(MeshFilter))]
public class RepeatMesh : MonoBehaviour {
[Header("Mesh")]
[Tooltip("The base mesh beeing used")]
public Mesh BaseMesh;
[Header("Values")]
[Tooltip("How often the mesh will be repeated on the X axis")]
public int AmountX = 4;
[Tooltip("How often the mesh will be repeated on the Y axis")]
public int AmountY = 1;
[Tooltip("How often the mesh will be repeated on the Z axis")]
public int AmountZ = 1;
[Tooltip("The distance between the repeated meshes on each axis")]
public Vector3 Offsets = Vector3.one;
[Header("Other")]
[Tooltip("Create a box collider around all the resulting mesh")]
public bool CreateBoxCollider = false;
[Tooltip("Stops the mesh from rebuilding")]
public bool Lock = false;
[Space]
[Tooltip("Save mesh as asset into the project folder")]
public bool SaveMesh = false;
// On value change
void OnValidate(){
if(Lock || Application.isPlaying) return;
if(!BaseMesh){
Debug.LogError(transform.name + ": The reference mesh has not been assigned.");
return;
}
// Make it so that the values can't go below 1
AmountX = Mathf.Max(1, AmountX);
AmountY = Mathf.Max(1, AmountY);
AmountZ = Mathf.Max(1, AmountZ);
// Set up the lists for building our new mesh
List <Vector3> vertices = new List<Vector3>();
List <Vector2> uvs = new List<Vector2>();
List<Vector3> normals = new List<Vector3>();
List<Vector4> tangents = new List<Vector4>();
List<Color> colors = new List<Color>();
List<int>[] triangles = new List<int>[BaseMesh.subMeshCount];
for(int i = 0; i < triangles.Length; i++) triangles[i] = new List<int>();
// Index for triangle calculation
int index = 0;
// Repeat for x Times on the different axis (Create new instance and calculate the relative transform)
for(int x = 0; x < AmountX; x++){
for(int y = 0; y < AmountY; y++){
for(int z = 0; z < AmountZ; z++){
// Add vertices
for(int i = 0; i < BaseMesh.vertices.Length; i++){
vertices.Add(BaseMesh.vertices[i] + Vector3.Scale(Offsets, new Vector3(x, y, z)));
}
// Add uvs
for(int i = 0; i < BaseMesh.uv.Length; i++){
uvs.Add(BaseMesh.uv[i]);
}
// Add normals
for(int i = 0; i < BaseMesh.normals.Length; i++){
normals.Add(BaseMesh.normals[i]);
}
// Add tangents
for(int i = 0; i < BaseMesh.tangents.Length; i++){
tangents.Add(BaseMesh.tangents[i]);
}
// Add colors
for(int i = 0; i < BaseMesh.colors.Length; i++){
colors.Add(BaseMesh.colors[i]);
}
// Calculate the base tri
int baseTri = index * BaseMesh.vertices.Length;
// Go through submeshes
for(int i = 0; i < BaseMesh.subMeshCount; i++){
int[] tris = BaseMesh.GetTriangles(i);
// Add triangles
for(int j = 0; j < tris.Length; j++){
triangles[i].Add(tris[j] + baseTri);
}
}
// Count up index
index++;
}
}
}
// Combine and assign the mesh and also try optimize it
Mesh mesh = new Mesh();
mesh.name = gameObject.name + "_mesh";
mesh.subMeshCount = BaseMesh.subMeshCount;
// add the arrays to the new mesh
mesh.vertices = vertices.ToArray();
mesh.uv = uvs.ToArray();
mesh.normals = normals.ToArray();
mesh.tangents = tangents.ToArray();
mesh.colors = colors.ToArray();
// Add sub mesh tris
for(int i = 0; i < mesh.subMeshCount; i++){
mesh.SetTriangles(triangles[i].ToArray(), i);
}
// Assign the mesh to the filter
mesh.Optimize();
mesh.RecalculateBounds();
transform.GetComponent<MeshFilter>().mesh = mesh;
// Create collider
if(CreateBoxCollider){
// Add a collider if it is missing
if(!gameObject.GetComponent<BoxCollider>()) gameObject.AddComponent(typeof (BoxCollider));
// Set the collider to the recalculated bounds
gameObject.GetComponent<BoxCollider>().center = mesh.bounds.center;
gameObject.GetComponent<BoxCollider>().size = mesh.bounds.extents * 2;
}
}
// Update
void Update(){
// Saves mesh once and then resets
if(SaveMesh){
Mesh mesh = GetComponent<MeshFilter>().sharedMesh;
if(!AssetDatabase.IsValidFolder("Assets/RepeatMesh")) AssetDatabase.CreateFolder("Assets", "RepeatMesh");
AssetDatabase.CreateAsset(mesh, "Assets/RepeatMesh/" + mesh.name + ".asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log("Created asset: Assets/RepeatMesh/" + mesh.name + ".asset");
SaveMesh = false;
}
}
}