3 using System.Collections.Generic;
13 private float _epsilon = 0.01f;
15 private float _maxDistance = 1.5f;
16 private float _scale = 0.8f;
18 private List<int>[] _vertexIdentities;
19 private List<Vector3>[] _vertexOffsets;
27 private List<int>[] _lEyeF2v;
28 private Vector3[] _lEyeF2world;
29 private Vector3[] _lEyeFCP =
new Vector3[] {
30 new Vector3(0.167f, 1.993f, 0.680f),
31 new Vector3(0.241f, 2.049f, 0.704f),
32 new Vector3(0.304f, 2.039f, 0.701f),
33 new Vector3(0.394f, 2.006f, 0.638f),
34 new Vector3(0.328f, 1.967f, 0.684f),
35 new Vector3(0.233f, 1.983f, 0.680f)
38 get {
return _lEyeF2world; }
43 private List<int>[] _lEyebrow2v;
44 private Vector3[] _lEyebrow2world;
45 private Vector3[] _lEyebrowCP =
new Vector3[] {
46 new Vector3(0.152f, 2.111f, 0.834f),
47 new Vector3(0.184f, 2.202f, 0.832f),
48 new Vector3(0.298f, 2.234f, 0.776f),
49 new Vector3(0.389f, 2.240f, 0.699f),
50 new Vector3(0.464f, 2.184f, 0.601f),
51 new Vector3(0.438f, 2.121f, 0.668f),
52 new Vector3(0.438f, 2.121f, 0.668f),
53 new Vector3(0.354f, 2.162f, 0.745f),
54 new Vector3(0.271f, 2.147f, 0.796f),
57 get {
return _lEyebrow2world; }
62 private List<int>[] _rEyeF2v;
63 private Vector3[] _rEyeF2world;
64 private Vector3[] _rEyeFCP =
new Vector3[] {
65 new Vector3(-0.167f, 1.993f, 0.680f),
66 new Vector3(-0.241f, 2.049f, 0.704f),
67 new Vector3(-0.304f, 2.039f, 0.701f),
68 new Vector3(-0.394f, 2.006f, 0.638f),
69 new Vector3(-0.328f, 1.967f, 0.684f),
70 new Vector3(-0.233f, 1.983f, 0.689f)
73 get {
return _rEyeF2world; }
78 private List<int>[] _rEyebrow2v;
79 private Vector3[] _rEyebrow2world;
80 private Vector3[] _rEyebrowCP =
new Vector3[] {
81 new Vector3(-0.152f, 2.111f, 0.834f),
82 new Vector3(-0.184f, 2.202f, 0.832f),
83 new Vector3(-0.298f, 2.234f, 0.776f),
84 new Vector3(-0.389f, 2.240f, 0.699f),
85 new Vector3(-0.464f, 2.184f, 0.601f),
86 new Vector3(-0.438f, 2.121f, 0.668f),
87 new Vector3(-0.438f, 2.121f, 0.668f),
88 new Vector3(-0.354f, 2.162f, 0.745f),
89 new Vector3(-0.271f, 2.147f, 0.796f),
92 get {
return _rEyebrow2world; }
98 private List<int>[] _eyeS2v;
99 private Vector3[] _eyeS2world;
100 private Vector3[] _eyeSCP =
new Vector3[] {
101 new Vector3(0.241f, 2.049f, 0.704f),
102 new Vector3(0.286f, 1.968f, 0.693f),
103 new Vector3(0.394f, 2.006f, 0.638f)
106 get {
return _eyeS2world; }
112 private List<int>[] _mouthF2v;
113 private Vector3[] _mouthF2world;
114 private Vector3[] _mouthFCP =
new Vector3[] {
116 new Vector3(0.052f, 1.508f, 0.943f),
118 new Vector3(0.245f, 1.426f, 0.763f),
119 new Vector3(0.145f, 1.494f, 0.901f),
120 new Vector3(0.068f, 1.356f, 0.901f),
123 new Vector3(-0.068f, 1.356f, 0.901f),
124 new Vector3(-0.145f, 1.494f, 0.901f),
125 new Vector3(-0.245f, 1.426f, 0.763f),
127 new Vector3(-0.052f, 1.508f, 0.943f)
130 get {
return _mouthF2world; }
136 private List<int>[] _mouthS2v;
137 private Vector3[] _mouthS2world;
138 private Vector3[] _mouthSCP =
new Vector3[] {
139 new Vector3(0.245f, 1.426f, 0.763f),
140 new Vector3(0.068f, 1.356f, 0.901f),
141 new Vector3(0.000f, 1.490f, 0.949f)
144 get {
return _mouthS2world; }
150 private List<int>[] _contourF2v;
151 private Vector3[] _contourF2world;
152 private Vector3[] _contourFCP =
new Vector3[] {
153 new Vector3(0.000f, 2.944f, -0.038f),
154 new Vector3(0.406f, 2.837f, -0.082f),
155 new Vector3(0.618f, 2.290f, 0.075f),
156 new Vector3(0.542f, 1.742f, 0.256f),
157 new Vector3(0.368f, 1.253f, 0.457f),
158 new Vector3(0.000f, 1.084f, 0.855f),
159 new Vector3(-0.368f, 1.253f, 0.457f),
160 new Vector3(-0.542f, 1.742f, 0.256f),
161 new Vector3(-0.618f, 2.290f, 0.075f),
162 new Vector3(-0.406f, 2.837f, -0.082f)
165 get {
return _contourF2world; }
171 private List<int>[] _contourS2v;
172 private Vector3[] _contourS2world;
173 private Vector3[] _contourSCP =
new Vector3[] {
174 new Vector3(0.000f, 1.084f, 0.855f),
175 new Vector3(0.000f, 1.745f, 1.083f),
176 new Vector3(0.000f, 2.382f, 0.815f),
177 new Vector3(0.000f, 2.944f, -0.038f),
178 new Vector3(0.000f, 2.499f, -0.841f),
179 new Vector3(0.000f, 1.587f, -0.799f)
182 get {
return _contourS2world; }
185 private bool _enableRotation;
187 set { _enableRotation = value; }
188 get {
return _enableRotation; }
190 private float _sensitivity;
191 private Vector3 _mouseReference;
192 private Vector3 _mouseOffset;
193 private Vector3 _rotation;
194 private bool _isRotating;
203 _mesh = GetComponent<MeshFilter>().mesh;
205 Vector3[] vertices = _mesh.vertices;
212 _vertexOffsets =
new List<Vector3>[vertices.Length];
215 _vertexIdentities =
new List<int>[vertices.Length];
216 for (
int i = 0; i < vertices.Length; i++) {
217 for (
int j = 0; j < vertices.Length; j++) {
219 if (vertices [i].x == vertices [j].x
220 && vertices [i].y == vertices [j].y
221 && vertices [i].z == vertices [j].z) {
223 if (_vertexIdentities [i] == null) {
224 _vertexIdentities [i] =
new List<int> ();
226 _vertexIdentities [i].Add (j);
231 FindControlPoints (_lEyeFCP, out _lEyeF2v, out _lEyeF2world);
232 FindControlPoints (_rEyeFCP, out _rEyeF2v, out _rEyeF2world);
234 FindControlPoints (_lEyebrowCP, out _lEyebrow2v, out _lEyebrow2world);
235 FindControlPoints (_rEyebrowCP, out _rEyebrow2v, out _rEyebrow2world);
237 FindControlPoints (_mouthFCP, out _mouthF2v, out _mouthF2world);
238 FindControlPoints (_contourFCP, out _contourF2v, out _contourF2world);
245 FindControlPoints (_lEyebrowCP, out _lEyebrow2v, out _lEyebrow2world);
246 FindControlPoints (_rEyebrowCP, out _rEyebrow2v, out _rEyebrow2world);
247 FindControlPoints (_mouthSCP, out _mouthS2v, out _mouthS2world);
248 FindControlPoints (_eyeSCP, out _eyeS2v, out _eyeS2world);
249 FindControlPoints (_contourSCP, out _contourS2v, out _contourS2world);
254 _rotation = Vector3.zero;
263 if(_enableRotation && Input.GetMouseButtonDown(0)) {
267 _mouseReference = Input.mousePosition;
270 if(Input.GetMouseButtonUp(0))
276 _mouseOffset = (Input.mousePosition - _mouseReference);
278 _rotation.y = -(_mouseOffset.x) * _sensitivity;
279 _rotation.x = -(_mouseOffset.y) * _sensitivity;
282 transform.eulerAngles += _rotation;
284 _mouseReference = Input.mousePosition;
298 public Vector3[]
CalculateOffset(Vector3[] startPoints, Vector3[] endPoints,
bool side =
false) {
302 Vector3[] offsets =
new Vector3[startPoints.Length];
303 for (
int i = 0; i < startPoints.Length; i++) {
305 Vector3 startM = transform.InverseTransformPoint(startPoints[i]);
306 Vector3 endM = transform.InverseTransformPoint(endPoints[i]);
307 offsets[i] = endM - startM;
310 if(side) RotateToFront ();
325 DeformModel(offsets, _contourF2v,
new List<int>() { 4, 5, 6 } );
338 DeformModel(offsets, _lEyeF2v);
351 DeformModel(offsets, _rEyeF2v);
364 DeformModel(offsets, _lEyebrow2v);
377 DeformModel(offsets, _rEyebrow2v);
390 DeformModel(offsets, _mouthF2v);
403 private void DeformModel(Vector3[] offsets, List<int>[] idxCP) {
404 DeformModel(offsets, idxCP,
new List<int>());
417 private void DeformModel(Vector3[] offsets, List<int>[] idxCP, List<int> ignore) {
418 for(
int i = 0; i < offsets.Length; i++) {
420 if(ignore.IndexOf(i) != -1)
continue;
422 MoveVertex (idxCP [i], offsets[i]);
434 Vector3[] vertices = _mesh.vertices;
435 Vector2[] uvs = _mesh.uv;
437 for(
int i = 0; i < vertices.Length; i++) {
438 List<Vector3> offsets = _vertexOffsets[i];
441 Vector3 origin = transform.TransformPoint(vertices[i]);
442 Vector3 direction =
new Vector3(vertices[i].x, 0.0f, vertices[i].z);
443 direction.Normalize();
446 Ray r =
new Ray(origin, direction);
448 if (Physics.Raycast (r, out hit))
449 uvs[i] = hit.textureCoord;
451 if(offsets == null)
continue;
453 Vector3 sum = Vector3.zero;
455 foreach(Vector3 offset
in offsets) {
456 sum += offset * 2.0f;
460 vertices[i] += sum / offsets.Count;
463 _mesh.vertices = vertices;
476 void MoveVertex(List<int> vertexIndices, Vector3 transpose) {
479 for (
int i = 0; i < vertexIndices.Count; i++) {
480 if(_vertexOffsets[vertexIndices[i]] == null)
481 _vertexOffsets[vertexIndices[i]] =
new List<Vector3>();
483 _vertexOffsets[vertexIndices[i]].Add (transpose);
486 int controlPointIndex = vertexIndices [0];
488 List<int> neighbours = GetNeighbors (controlPointIndex);
490 List<int> ignore =
new List<int> (neighbours);
491 ignore.AddRange (vertexIndices);
494 for (
int i = 0; i < neighbours.Count; i++) {
495 int neighbourIndex = neighbours[i];
498 ignore.AddRange (_vertexIdentities[neighbourIndex]);
500 float distance = Vector3.Distance (_mesh.vertices[neighbourIndex], _mesh.vertices[controlPointIndex]);
504 if(distance > _maxDistance)
continue;
506 float distProb = Gauss(0);
509 MoveVertexRec(controlPointIndex, neighbourIndex, transpose * distProb, ref ignore);
524 void MoveVertexRec(
int controlPointIndex,
int currentVertexIndex, Vector3 transpose, ref List<int> ignore) {
527 for (
int i = 0; i < _vertexIdentities[currentVertexIndex].Count; i++) {
528 if(_vertexOffsets[_vertexIdentities[currentVertexIndex][i]] == null)
529 _vertexOffsets[_vertexIdentities[currentVertexIndex][i]] =
new List<Vector3>();
531 _vertexOffsets[_vertexIdentities[currentVertexIndex][i]].Add (transpose);
533 List<int> neighbours = GetNeighbors (currentVertexIndex);
534 List<int> oldIgnore =
new List<int> (ignore);
535 ignore.AddRange(neighbours);
538 for (
int i = 0; i < neighbours.Count; i++) {
539 int neighborIndex = neighbours[i];
541 if(oldIgnore.IndexOf(neighborIndex) != -1)
continue;
544 ignore.AddRange (_vertexIdentities[neighborIndex]);
546 float distance = Vector3.Distance (_mesh.vertices[neighborIndex], _mesh.vertices[controlPointIndex]);
550 if(distance > _maxDistance)
continue;
552 float distProb = Gauss(distance * _scale);
555 MoveVertexRec(controlPointIndex, neighborIndex, transpose * distProb, ref ignore);
570 void FindControlPoints(Vector3[] cp, out List<int>[] cp2v, out Vector3[] cp2world) {
571 cp2v =
new List<int>[cp.Length];
572 cp2world =
new Vector3[cp.Length];
573 Vector3[] vertices = _mesh.vertices;
577 for (
int i = 0; i < vertices.Length; i++) {
579 for (
int j = 0; j < cp.Length; j++) {
581 if(_epsilon > Mathf.Abs(vertices[i].x - cp[j].x)
582 && _epsilon > Mathf.Abs(vertices[i].y - cp[j].y)
583 && _epsilon > Mathf.Abs(vertices[i].z - cp[j].z)) {
587 if(cp2v[j] == null) {
588 cp2v[j] =
new List<int>();
591 cp2world[j] = transform.TransformPoint(vertices[i]);
600 if (found < cp.Length) {
601 throw new MissingComponentException (
"Could not find all control points (" + found +
"/" + cp.Length +
")");
616 float a = 1.0f / (sigma * Mathf.Sqrt (2.0f * Mathf.PI));
617 return a * Mathf.Exp ( - Mathf.Pow(x, 2.0f) / (2.0f * Mathf.Pow(sigma, 2.0f)) );
632 List<int> GetNeighbors(
int index) {
633 int[] triangles = _mesh.triangles;
635 List<int> verts =
new List<int>();
636 for(
int i = 0; i < triangles.Length / 3; i++){
639 for(
int j = 0; j < 3; j++){
640 int cur = triangles[i * 3 + j];
641 if(cur == index) found =
true;
645 for(
int j = 0; j < 3 ; j++){
646 int cur = triangles[i * 3 + j];
647 if(verts.IndexOf(cur) == -1 && cur != index){
660 transform.Rotate (Vector3.up * 90.0f);
665 void RotateToFront() {
666 transform.Rotate (Vector3.up * -90.0f);
void DeformMouth(Vector3[] offsets)
Deforms the mouth.
ControlPoints script on mesh.
void DeformREye(Vector3[] offsets)
Deforms the right eye.
void DeformLEyeBrow(Vector3[] offsets)
Deforms the left eyebrow.
void ApplyDeformation()
Applies the average of the calculated weighted offsets to every vertex in the mesh.
void DeformLEye(Vector3[] offsets)
Deforms the left eye.
void DeformContour(Vector3[] offsets)
Deforms the face contour.
void DeformREyeBrow(Vector3[] offsets)
Deforms the right eyebrow.
Vector3[] CalculateOffset(Vector3[] startPoints, Vector3[] endPoints, bool side=false)
Calculates the offset of two contours in world coordinates.
void RotateToProfile()
Rotates the mesh by 90 degrees around the y axis.