/************************************************************************************
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();
}
}