Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
ProceduralCapsule.cs
Go to the documentation of this file.
1 //------------------------------//
2 // ProceduralCapsule.cs //
3 // Written by Jay Kay //
4 // 2016/05/27 //
5 //------------------------------//
6 
7 using UnityEngine;
8 
9 namespace droid.Runtime.Utilities.Misc.Procedural {
13  [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
14  [ExecuteInEditMode]
15  public class ProceduralCapsule : MonoBehaviour {
18  public float _Height = 2f;
19 
22  public float _Radius = 0.5f;
23 
26  public int _Segments = 24;
27  #if UNITY_EDITOR
28  [ContextMenu("Generate Procedural Capsule")]
31  public void GenerateProceduralCapsule() { this.CreateMesh(); }
32  #endif
33 
34  void Start() {
35  var mesh_filter = this.GetComponent<MeshFilter>();
36  if (!mesh_filter.sharedMesh
37  || mesh_filter.sharedMesh.vertexCount == 0
38  || mesh_filter.sharedMesh.name != "ProceduralCapsule") {
39  this.CreateMesh();
40  }
41  }
42 
45  public void CreateMesh() {
46  // make segments an even number
47  if (this._Segments % 2 != 0) {
48  this._Segments++;
49  }
50 
51  // extra vertex on the seam
52  var points = this._Segments + 1;
53 
54  // calculate points around a circle
55  var p_x = new float[points];
56  var p_z = new float[points];
57  var p_y = new float[points];
58  var p_r = new float[points];
59 
60  var calc_h = 0f;
61  var calc_v = 0f;
62 
63  for (var i = 0; i < points; i++) {
64  p_x[i] = Mathf.Sin(calc_h * Mathf.Deg2Rad);
65  p_z[i] = Mathf.Cos(calc_h * Mathf.Deg2Rad);
66  p_y[i] = Mathf.Cos(calc_v * Mathf.Deg2Rad);
67  p_r[i] = Mathf.Sin(calc_v * Mathf.Deg2Rad);
68 
69  calc_h += 360f / this._Segments;
70  calc_v += 180f / this._Segments;
71  }
72 
73  // - Vertices and UVs -
74 
75  var vertices = new Vector3[points * (points + 1)];
76  var uvs = new Vector2[vertices.Length];
77  var ind = 0;
78 
79  // Y-offset is half the height minus the diameter
80  // float yOff = ( height - ( radius * 2f ) ) * 0.5f;
81  var y_off = (this._Height - this._Radius) * 0.5f;
82  if (y_off < 0) {
83  y_off = 0;
84  }
85 
86  // uv calculations
87  var step_x = 1f / (points - 1);
88  float uv_x, uv_y;
89 
90  // Top Hemisphere
91  var top = Mathf.CeilToInt(points * 0.5f);
92 
93  for (var y = 0; y < top; y++) {
94  for (var x = 0; x < points; x++) {
95  vertices[ind] = new Vector3(p_x[x] * p_r[y], p_y[y], p_z[x] * p_r[y]) * this._Radius;
96  vertices[ind].y = y_off + vertices[ind].y;
97 
98  uv_x = 1f - step_x * x;
99  uv_y = (vertices[ind].y + this._Height * 0.5f) / this._Height;
100  uvs[ind] = new Vector2(uv_x, uv_y);
101 
102  ind++;
103  }
104  }
105 
106  // Bottom Hemisphere
107  var btm = Mathf.FloorToInt(points * 0.5f);
108 
109  for (var y = btm; y < points; y++) {
110  for (var x = 0; x < points; x++) {
111  vertices[ind] = new Vector3(p_x[x] * p_r[y], p_y[y], p_z[x] * p_r[y]) * this._Radius;
112  vertices[ind].y = -y_off + vertices[ind].y;
113 
114  uv_x = 1f - step_x * x;
115  uv_y = (vertices[ind].y + this._Height * 0.5f) / this._Height;
116  uvs[ind] = new Vector2(uv_x, uv_y);
117 
118  ind++;
119  }
120  }
121 
122  // - Triangles -
123 
124  var triangles = new int[this._Segments * (this._Segments + 1) * 2 * 3];
125 
126  for (int y = 0, t = 0; y < this._Segments + 1; y++) {
127  for (var x = 0; x < this._Segments; x++, t += 6) {
128  triangles[t + 0] = (y + 0) * (this._Segments + 1) + x + 0;
129  triangles[t + 1] = (y + 1) * (this._Segments + 1) + x + 0;
130  triangles[t + 2] = (y + 1) * (this._Segments + 1) + x + 1;
131 
132  triangles[t + 3] = (y + 0) * (this._Segments + 1) + x + 1;
133  triangles[t + 4] = (y + 0) * (this._Segments + 1) + x + 0;
134  triangles[t + 5] = (y + 1) * (this._Segments + 1) + x + 1;
135  }
136  }
137 
138  // - Assign Mesh -
139 
140  var mf = this.gameObject.GetComponent<MeshFilter>();
141  var mesh = mf.sharedMesh;
142  if (!mesh) {
143  mesh = new Mesh();
144  mf.sharedMesh = mesh;
145  }
146 
147  mesh.Clear();
148 
149  mesh.name = "ProceduralCapsule";
150 
151  mesh.vertices = vertices;
152  mesh.uv = uvs;
153  mesh.triangles = triangles;
154 
155  mesh.RecalculateBounds();
156  mesh.RecalculateNormals();
157  }
158  }
159 }