Mercurial > hg > Game > Games
diff Orchestland/Assets/LeapMotion/Scripts/Hands/PolyFinger.cs @ 1:f7675884f2a1
Add Orchestland project
author | Daiki OYAKAWA <e135764@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2015 23:09:20 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Orchestland/Assets/LeapMotion/Scripts/Hands/PolyFinger.cs Fri Jul 17 23:09:20 2015 +0900 @@ -0,0 +1,230 @@ +/******************************************************************************\ +* Copyright (C) Leap Motion, Inc. 2011-2014. * +* Leap Motion proprietary. Licensed under Apache 2.0 * +* Available at http://www.apache.org/licenses/LICENSE-2.0.html * +\******************************************************************************/ + +using UnityEngine; +using System.Collections; +using System; +using Leap; + +/** Draws the bones of the finger as a polygonal tube. **/ +public class PolyFinger : FingerModel { + + const int MAX_SIDES = 30; + const int TRIANGLE_INDICES_PER_QUAD = 6; + const int VERTICES_PER_QUAD = 4; + + /** The number of sides for finger tube. */ + public int sides = 4; + /** Whether to smooth the mesh normals, providing a smoother appearance.*/ + public bool smoothNormals = false; + public float startingAngle = 0.0f; + /** An array containing the width of the finger at each joint. */ + public float[] widths = new float[NUM_JOINTS]; + + protected Vector3[] vertices_; + protected Vector3[] normals_; + protected Vector3[] joint_vertices_; + + protected Mesh mesh_; + protected Mesh cap_mesh_; + protected Vector3[] cap_vertices_; + + /** Creates the finger mesh. */ + public override void InitFinger() { + InitJointVertices(); + InitCapsMesh(); + InitMesh(); + GetComponent<MeshFilter>().mesh = new Mesh(); + + UpdateFinger(); + } + + /** Updates the mesh.*/ + public override void UpdateFinger() { + UpdateMesh(); + UpdateCapMesh(); + } + + void OnDestroy() { + Destroy(mesh_); + Destroy(cap_mesh_); + Destroy(GetComponent<MeshFilter>().mesh); + } + + void Update() { + if (vertices_ == null) + return; + + mesh_.vertices = vertices_; + + if (smoothNormals) + mesh_.normals = normals_; + else + mesh_.RecalculateNormals(); + + cap_mesh_.vertices = cap_vertices_; + cap_mesh_.RecalculateNormals(); + + CombineInstance[] combine = new CombineInstance[2]; + combine[0].mesh = mesh_; + combine[1].mesh = cap_mesh_; + + GetComponent<MeshFilter>().mesh.CombineMeshes(combine, true, false); + GetComponent<MeshFilter>().mesh.RecalculateBounds(); + } + + protected Quaternion GetJointRotation(int joint) { + if (joint <= 0) + return GetBoneRotation(joint); + if (joint >= NUM_BONES) + return GetBoneRotation(joint - 1); + + return Quaternion.Slerp(GetBoneRotation(joint - 1), GetBoneRotation(joint), 0.5f); + } + + protected void InitJointVertices() { + joint_vertices_ = new Vector3[sides]; + for (int s = 0; s < sides; ++s) { + float angle = startingAngle + s * 360.0f / sides; + joint_vertices_[s] = Quaternion.AngleAxis(angle, -Vector3.forward) * Vector3.up; + } + } + + protected void UpdateMesh() { + int vertex_index = 0; + + for (int i = 0; i < NUM_BONES; ++i) { + Vector3 joint_position = transform.InverseTransformPoint(GetJointPosition(i)); + Vector3 next_joint_position = transform.InverseTransformPoint(GetJointPosition(i + 1)); + Quaternion joint_rotation = Quaternion.Inverse(transform.rotation) * (GetJointRotation(i)); + Quaternion next_joint_rotation = Quaternion.Inverse(transform.rotation) * + GetJointRotation(i + 1); + + for (int s = 0; s < sides; ++s) { + int next_side = (s + 1) % sides; + + if (smoothNormals) { + Vector3 normal = joint_rotation * joint_vertices_[s]; + Vector3 next_normal = joint_rotation * joint_vertices_[next_side]; + + normals_[vertex_index] = normals_[vertex_index + 2] = normal; + normals_[vertex_index + 1] = normals_[vertex_index + 3] = next_normal; + } + + Vector3 offset = joint_rotation * (widths[i] * joint_vertices_[s]); + vertices_[vertex_index++] = joint_position + offset; + + offset = joint_rotation * (widths[i] * joint_vertices_[next_side]); + vertices_[vertex_index++] = joint_position + offset; + + offset = next_joint_rotation * (widths[i + 1] * joint_vertices_[s]); + vertices_[vertex_index++] = next_joint_position + offset; + + offset = next_joint_rotation * (widths[i + 1] * joint_vertices_[next_side]); + vertices_[vertex_index++] = next_joint_position + offset; + } + } + } + + protected void UpdateCapMesh() { + Vector3 base_position = transform.InverseTransformPoint(GetJointPosition(0)); + Vector3 tip_position = transform.InverseTransformPoint(GetJointPosition(NUM_JOINTS - 1)); + Quaternion base_rotation = Quaternion.Inverse(transform.rotation) * GetJointRotation(0); + Quaternion tip_rotation = Quaternion.Inverse(transform.rotation) * + GetJointRotation(NUM_JOINTS - 1); + + for (int s = 0; s < sides; ++s) { + cap_vertices_[s] = base_position + base_rotation * (widths[0] * joint_vertices_[s]); + cap_vertices_[sides + s] = tip_position + tip_rotation * + (widths[NUM_JOINTS - 1] * joint_vertices_[s]); + } + } + + protected void InitMesh() { + mesh_ = new Mesh(); + mesh_.MarkDynamic(); + + int vertex_index = 0; + int num_vertices = VERTICES_PER_QUAD * sides * NUM_BONES; + vertices_ = new Vector3[num_vertices]; + normals_ = new Vector3[num_vertices]; + Vector2[] uv = new Vector2[num_vertices]; + + int triangle_index = 0; + int num_triangles = TRIANGLE_INDICES_PER_QUAD * sides * NUM_BONES; + int[] triangles = new int[num_triangles]; + + for (int i = 0; i < NUM_BONES; ++i) { + for (int s = 0; s < sides; ++s) { + + triangles[triangle_index++] = vertex_index; + triangles[triangle_index++] = vertex_index + 2; + triangles[triangle_index++] = vertex_index + 1; + + triangles[triangle_index++] = vertex_index + 2; + triangles[triangle_index++] = vertex_index + 3; + triangles[triangle_index++] = vertex_index + 1; + + uv[vertex_index] = new Vector3((1.0f * s) / sides, (1.0f * i) / NUM_BONES); + uv[vertex_index + 1] = new Vector3((1.0f + s) / sides, (1.0f * i) / NUM_BONES); + uv[vertex_index + 2] = new Vector3((1.0f * s) / sides, (1.0f + i) / NUM_BONES); + uv[vertex_index + 3] = new Vector3((1.0f + s) / sides, (1.0f + i) / NUM_BONES); + + vertices_[vertex_index++] = new Vector3(0, 0, 0); + vertices_[vertex_index++] = new Vector3(0, 0, 0); + vertices_[vertex_index++] = new Vector3(0, 0, 0); + vertices_[vertex_index++] = new Vector3(0, 0, 0); + } + } + mesh_.vertices = vertices_; + mesh_.normals = normals_; + mesh_.uv = uv; + mesh_.triangles = triangles; + } + + protected void InitCapsMesh() { + cap_mesh_ = new Mesh(); + cap_mesh_.MarkDynamic(); + + cap_vertices_ = cap_mesh_.vertices; + int num_vertices = 2 * sides; + if (num_vertices != cap_vertices_.Length) + Array.Resize(ref cap_vertices_, num_vertices); + + Vector2[] uv = cap_mesh_.uv; + if (uv.Length != num_vertices) + Array.Resize(ref uv, num_vertices); + + int triangle_index = 0; + int[] triangles = cap_mesh_.triangles; + int num_triangles = 2 * 3 * (sides - 2); + if (num_triangles != triangles.Length) + Array.Resize(ref triangles, num_triangles); + + for (int i = 0; i < sides; ++i) { + cap_vertices_[i] = new Vector3(0, 0, 0); + cap_vertices_[i + sides] = new Vector3(0, 0, 0); + uv[i] = 0.5f * joint_vertices_[i]; + uv[i] += new Vector2(0.5f, 0.5f); + uv[i + sides] = 0.5f * joint_vertices_[i]; + uv[i + sides] += new Vector2(0.5f, 0.5f); + } + + for (int i = 0; i < sides - 2; ++i) { + triangles[triangle_index++] = 0; + triangles[triangle_index++] = i + 1; + triangles[triangle_index++] = i + 2; + + triangles[triangle_index++] = sides; + triangles[triangle_index++] = sides + i + 2; + triangles[triangle_index++] = sides + i + 1; + } + + cap_mesh_.vertices = cap_vertices_; + cap_mesh_.uv = uv; + cap_mesh_.triangles = triangles; + } +}