Tanoda
PolyFinger.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using UnityEngine;
10using System.Collections;
11using System;
12using Leap;
13
14namespace Leap.Unity{
16 public class PolyFinger : FingerModel {
17
18 const int MAX_SIDES = 30;
19 const int TRIANGLE_INDICES_PER_QUAD = 6;
20 const int VERTICES_PER_QUAD = 4;
21
23 public int sides = 4;
25 public bool smoothNormals = false;
26 public float startingAngle = 0.0f;
28 public float[] widths = new float[NUM_JOINTS];
29
30 protected Vector3[] vertices_;
31 protected Vector3[] normals_;
32 protected Vector3[] joint_vertices_;
33
34 protected Mesh mesh_;
35 protected Mesh cap_mesh_;
36 protected Vector3[] cap_vertices_;
37
39 public override void InitFinger() {
42 InitMesh();
43 GetComponent<MeshFilter>().mesh = new Mesh();
44
46 }
47
49 public override void UpdateFinger() {
50 UpdateMesh();
52
53 if (vertices_ == null)
54 return;
55
56 mesh_.vertices = vertices_;
57
58 if (smoothNormals)
59 mesh_.normals = normals_;
60 else
61 mesh_.RecalculateNormals();
62
63 cap_mesh_.vertices = cap_vertices_;
64 cap_mesh_.RecalculateNormals();
65
66 CombineInstance[] combine = new CombineInstance[2];
67 combine[0].mesh = mesh_;
68 combine[1].mesh = cap_mesh_;
69
70 GetComponent<MeshFilter>().sharedMesh.CombineMeshes(combine, true, false);
71 GetComponent<MeshFilter>().sharedMesh.RecalculateBounds();
72 }
73
74 void OnDestroy() {
75 Destroy(mesh_);
76 Destroy(cap_mesh_);
77 Destroy(GetComponent<MeshFilter>().mesh);
78 }
79
80 void Update() {
81
82 }
83
84 protected Quaternion GetJointRotation(int joint) {
85 if (joint <= 0)
86 return GetBoneRotation(joint);
87 if (joint >= NUM_BONES)
88 return GetBoneRotation(joint - 1);
89
90 return Quaternion.Slerp(GetBoneRotation(joint - 1), GetBoneRotation(joint), 0.5f);
91 }
92
93 protected void InitJointVertices() {
94 joint_vertices_ = new Vector3[sides];
95 for (int s = 0; s < sides; ++s) {
96 float angle = startingAngle + s * 360.0f / sides;
97 joint_vertices_[s] = Quaternion.AngleAxis(angle, -Vector3.forward) * Vector3.up;
98 }
99 }
100
101 protected void UpdateMesh() {
102
103 if (joint_vertices_ == null || joint_vertices_.Length != sides) {
105 }
106 if (normals_ == null || normals_.Length != VERTICES_PER_QUAD * sides * NUM_BONES
107 || vertices_ == null || vertices_.Length != VERTICES_PER_QUAD * sides * NUM_BONES) {
108 InitMesh();
109 }
110
111 int vertex_index = 0;
112
113 for (int i = 0; i < NUM_BONES; ++i) {
114 Vector3 joint_position = transform.InverseTransformPoint(GetJointPosition(i));
115 Vector3 next_joint_position = transform.InverseTransformPoint(GetJointPosition(i + 1));
116 Quaternion joint_rotation = Quaternion.Inverse(transform.rotation) * (GetJointRotation(i));
117 Quaternion next_joint_rotation = Quaternion.Inverse(transform.rotation) *
118 GetJointRotation(i + 1);
119
120 for (int s = 0; s < sides; ++s) {
121 int next_side = (s + 1) % sides;
122
123 if (smoothNormals) {
124 Vector3 normal = joint_rotation * joint_vertices_[s];
125 Vector3 next_normal = joint_rotation * joint_vertices_[next_side];
126
127 normals_[vertex_index] = normals_[vertex_index + 2] = normal;
128 normals_[vertex_index + 1] = normals_[vertex_index + 3] = next_normal;
129 }
130
131 Vector3 offset = joint_rotation * (widths[i] * joint_vertices_[s]);
132 vertices_[vertex_index++] = joint_position + offset;
133
134 offset = joint_rotation * (widths[i] * joint_vertices_[next_side]);
135 vertices_[vertex_index++] = joint_position + offset;
136
137 offset = next_joint_rotation * (widths[i + 1] * joint_vertices_[s]);
138 vertices_[vertex_index++] = next_joint_position + offset;
139
140 offset = next_joint_rotation * (widths[i + 1] * joint_vertices_[next_side]);
141 vertices_[vertex_index++] = next_joint_position + offset;
142 }
143 }
144 }
145
146 protected void UpdateCapMesh() {
147 Vector3 base_position = transform.InverseTransformPoint(GetJointPosition(0));
148 Vector3 tip_position = transform.InverseTransformPoint(GetJointPosition(NUM_JOINTS - 1));
149 Quaternion base_rotation = Quaternion.Inverse(transform.rotation) * GetJointRotation(0);
150 Quaternion tip_rotation = Quaternion.Inverse(transform.rotation) *
152
153 if (cap_vertices_ == null || cap_vertices_.Length != 2 * sides) {
154 InitCapsMesh();
155 }
156
157 for (int s = 0; s < sides; ++s) {
158 cap_vertices_[s] = base_position + base_rotation * (widths[0] * joint_vertices_[s]);
159 cap_vertices_[sides + s] = tip_position + tip_rotation *
161 }
162 }
163
164 protected void InitMesh() {
165 mesh_ = new Mesh();
166 mesh_.MarkDynamic();
167
168 int vertex_index = 0;
169 int num_vertices = VERTICES_PER_QUAD * sides * NUM_BONES;
170 vertices_ = new Vector3[num_vertices];
171 normals_ = new Vector3[num_vertices];
172 Vector2[] uv = new Vector2[num_vertices];
173
174 int triangle_index = 0;
175 int num_triangles = TRIANGLE_INDICES_PER_QUAD * sides * NUM_BONES;
176 int[] triangles = new int[num_triangles];
177
178 for (int i = 0; i < NUM_BONES; ++i) {
179 for (int s = 0; s < sides; ++s) {
180
181 triangles[triangle_index++] = vertex_index;
182 triangles[triangle_index++] = vertex_index + 2;
183 triangles[triangle_index++] = vertex_index + 1;
184
185 triangles[triangle_index++] = vertex_index + 2;
186 triangles[triangle_index++] = vertex_index + 3;
187 triangles[triangle_index++] = vertex_index + 1;
188
189 uv[vertex_index] = new Vector3((1.0f * s) / sides, (1.0f * i) / NUM_BONES);
190 uv[vertex_index + 1] = new Vector3((1.0f + s) / sides, (1.0f * i) / NUM_BONES);
191 uv[vertex_index + 2] = new Vector3((1.0f * s) / sides, (1.0f + i) / NUM_BONES);
192 uv[vertex_index + 3] = new Vector3((1.0f + s) / sides, (1.0f + i) / NUM_BONES);
193
194 vertices_[vertex_index++] = new Vector3(0, 0, 0);
195 vertices_[vertex_index++] = new Vector3(0, 0, 0);
196 vertices_[vertex_index++] = new Vector3(0, 0, 0);
197 vertices_[vertex_index++] = new Vector3(0, 0, 0);
198 }
199 }
200 mesh_.vertices = vertices_;
201 mesh_.normals = normals_;
202 mesh_.uv = uv;
203 mesh_.triangles = triangles;
204 }
205
206 protected void InitCapsMesh() {
207 cap_mesh_ = new Mesh();
208 cap_mesh_.MarkDynamic();
209
210 cap_vertices_ = cap_mesh_.vertices;
211 int num_vertices = 2 * sides;
212 if (num_vertices != cap_vertices_.Length)
213 Array.Resize(ref cap_vertices_, num_vertices);
214
215 Vector2[] uv = cap_mesh_.uv;
216 if (uv.Length != num_vertices)
217 Array.Resize(ref uv, num_vertices);
218
219 int triangle_index = 0;
220 int[] triangles = cap_mesh_.triangles;
221 int num_triangles = 2 * 3 * (sides - 2);
222 if (num_triangles != triangles.Length)
223 Array.Resize(ref triangles, num_triangles);
224
225 for (int i = 0; i < sides; ++i) {
226 cap_vertices_[i] = new Vector3(0, 0, 0);
227 cap_vertices_[i + sides] = new Vector3(0, 0, 0);
228 uv[i] = 0.5f * joint_vertices_[i];
229 uv[i] += new Vector2(0.5f, 0.5f);
230 uv[i + sides] = 0.5f * joint_vertices_[i];
231 uv[i + sides] += new Vector2(0.5f, 0.5f);
232 }
233
234 for (int i = 0; i < sides - 2; ++i) {
235 triangles[triangle_index++] = 0;
236 triangles[triangle_index++] = i + 1;
237 triangles[triangle_index++] = i + 2;
238
239 triangles[triangle_index++] = sides;
240 triangles[triangle_index++] = sides + i + 2;
241 triangles[triangle_index++] = sides + i + 1;
242 }
243
244 cap_mesh_.vertices = cap_vertices_;
245 cap_mesh_.uv = uv;
246 cap_mesh_.triangles = triangles;
247 }
248 }
249
250}
Quaternion GetBoneRotation(int bone_type)
Definition: FingerModel.cs:140
Vector3 GetJointPosition(int joint)
Definition: FingerModel.cs:95
Vector3[] joint_vertices_
Definition: PolyFinger.cs:32
Vector3[] cap_vertices_
Definition: PolyFinger.cs:36
Quaternion GetJointRotation(int joint)
Definition: PolyFinger.cs:84
override void UpdateFinger()
Definition: PolyFinger.cs:49
override void InitFinger()
Definition: PolyFinger.cs:39