/************************************************************************************ See SampleFramework license.txt for license terms. Unless required by applicable law or agreed to in writing, the sample code is provided “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the license for specific language governing permissions and limitations under the license. ************************************************************************************/ using UnityEngine; using System.Collections.Generic; /// /// Procedurally generated capsule mesh which matches the character controller size. /// This was originally created for visualizing the capsule in the HMD but it could be adapted to other purposes. /// [ExecuteInEditMode] public class CharacterCapsule : MonoBehaviour { private CharacterController _character; private MeshFilter _meshFilter; private float _height; private float _radius; [Range(4,32)] public int SubdivisionsU; [Range(4, 32)] public int SubdivisionsV; private int _subdivisionU; private int _subdivisionV; private Vector3[] _vertices; private int[] _triangles; // Update is called once per frame void Update () { if (_character == null) { _character = GetComponentInParent(); if (_character == null) { return; } } if (_height == _character.height && _radius == _character.radius && _subdivisionU == SubdivisionsU && _subdivisionV == SubdivisionsV) { return; } _height = _character.height; _radius = _character.radius; _subdivisionU = SubdivisionsU; _subdivisionV = SubdivisionsV; List verts = new List(); var vector = new Vector3(1,0,0); // Generate the mesh var topOffset = new Vector3(0, _height/2.0f - _radius, 0); var bottomOffset = new Vector3(0, _radius - _height/2.0f, 0); // Add all the necessary vertices verts.Add(new Vector3(0, _height/2.0f, 0)); for (int u = SubdivisionsU - 1; u >= 0; u--) { float uf = (float) u / (float) SubdivisionsU; for (int v = 0; v < SubdivisionsV; v++) { float vf = (float) v / (float) SubdivisionsV; var q = Quaternion.Euler(0, vf * 360.0f, uf * 90.0f); var vert = q * vector; vert *= _radius; var v1 = vert + topOffset; verts.Add(v1); } } for (int u = 0; u < SubdivisionsU; u++) { float uf = (float)u / (float)SubdivisionsU; for (int v = 0; v < SubdivisionsV; v++) { float vf = (float)v / (float)SubdivisionsV; var q = Quaternion.Euler(0, vf * 360.0f + 180.0f, uf * 90.0f); var vert = q * vector; vert *= _radius; var v2 = bottomOffset - vert; verts.Add(v2); } } verts.Add(new Vector3(0, -_height / 2.0f, 0)); // Setup all the triangles List tris = new List(); int index; int i; // top cap for (int v = 0; v < SubdivisionsV; v++) { i = 0; tris.Add(i); tris.Add(v); tris.Add(v+1); } tris.Add(0); tris.Add(SubdivisionsV); tris.Add(1); // top hemisphere for (int u = 0; u < SubdivisionsU - 1; u++) { index = u * SubdivisionsV + 1; for (int v = 0; v < SubdivisionsV - 1; v++) { i = index + v; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1); tris.Add(i + 1); tris.Add(i + SubdivisionsV); tris.Add(i + SubdivisionsV + 1); } i = index + SubdivisionsV - 1; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + SubdivisionsV); tris.Add(i + 1); } // center tube index = (SubdivisionsU - 1) * SubdivisionsV + 1; for (int v = 0; v < SubdivisionsV - 1; v++) { i = index + v; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1); tris.Add(i + 1); tris.Add(i + SubdivisionsV); tris.Add(i + SubdivisionsV + 1); } i = index + SubdivisionsV - 1; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + SubdivisionsV); tris.Add(i + 1); // bottom hemisphere for (int u = 0; u < SubdivisionsU - 1; u++) { index = u * SubdivisionsV + (SubdivisionsU * SubdivisionsV) + 1; for (int v = 0; v < SubdivisionsV - 1; v++) { i = index + v; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1); tris.Add(i + 1); tris.Add(i + SubdivisionsV); tris.Add(i + SubdivisionsV + 1); } i = index + SubdivisionsV - 1; tris.Add(i); tris.Add(i + SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + 1 - SubdivisionsV); tris.Add(i + SubdivisionsV); tris.Add(i + 1); } // bottom cap var last = verts.Count - 1; var lastRow = last - SubdivisionsV; for (int v = 0; v < SubdivisionsV; v++) { i = 0; tris.Add(last); tris.Add(lastRow + v + 1); tris.Add(lastRow + v); } tris.Add(last); tris.Add(lastRow); tris.Add(last - 1); _vertices = verts.ToArray(); _triangles = tris.ToArray(); _meshFilter = gameObject.GetComponent(); _meshFilter.mesh = new Mesh(); _meshFilter.sharedMesh.vertices = _vertices; _meshFilter.sharedMesh.triangles = _triangles; _meshFilter.sharedMesh.RecalculateNormals(); } }