프로젝트

일반

사용자정보

통계
| 개정판:

t1 / TFDContents / Assets / KinectDemos / FaceTrackingDemo / Scripts / ModelFaceController.cs @ 3

이력 | 보기 | 이력해설 | 다운로드 (15.2 KB)

1
using UnityEngine;
2
using System.Collections;
3
using System.Collections.Generic;
4

    
5
public class ModelFaceController : MonoBehaviour 
6
{
7
	public enum AxisEnum { X, Y, Z };
8
	
9
	[Tooltip("Transform of the joint, used to move and rotate the head.")]
10
	public Transform HeadTransform;
11

    
12
	[Tooltip("Whether the model's head is facing the player or not.")]
13
	public bool mirroredHeadMovement = true;
14

    
15
	[Tooltip("Camera used to estimate the overlay position of the head over the background.")]
16
	public Camera foregroundCamera;
17

    
18
	// for testing purposes
19
	//public Transform overlayObj;
20
	
21
	[Tooltip("Vertical offset of the model above the head position.")]
22
	public float verticalOffset = 0f;
23
	
24
	[Tooltip("Scale factor for the head model.")]
25
	[Range(0.1f, 2.0f)]
26
	public float modelScaleFactor = 1f;
27
	
28
	[Tooltip("Smooth factor used for head movement and head-joint rotations.")]
29
	public float smoothFactor = 10f;
30
	
31
	// Upper Lip Left
32
	[Tooltip("Left upper lip transform.")]
33
	public Transform UpperLipLeft;
34
	[Tooltip("Left upper lip axis of rotation.")]
35
	public AxisEnum UpperLipLeftAxis;
36
	[Tooltip("Maximum up-value for the left upper lip, down-value is the opposite one.")]
37
	public float UpperLipLeftUp;
38

    
39
	// Upper Lip Right
40
	[Tooltip("Right upper lip transform.")]
41
	public Transform UpperLipRight;
42
	[Tooltip("Right upper lip axis of rotation.")]
43
	public AxisEnum UpperLipRightAxis;
44
	[Tooltip("Maximum up-value for the right upper lip, down-value is the opposite one.")]
45
	public float UpperLipRightUp;
46

    
47
	// Jaw
48
	[Tooltip("Jaw (mouth) transform.")]
49
	public Transform Jaw;
50
	[Tooltip("Jaw axis of rotation.")]
51
	public AxisEnum JawAxis;
52
	[Tooltip("Maximum down-value for the jaw, up-value is the opposite one.")]
53
	public float JawDown;
54
	
55
	// Lip Left
56
	[Tooltip("Left lip transform.")]
57
	public Transform LipLeft;
58
	[Tooltip("Left lip axis of rotation.")]
59
	public AxisEnum LipLeftAxis;
60
	[Tooltip("Maximum stretched-value for the left lip, rounded-value is the opposite one.")]
61
	public float LipLeftStretched;
62

    
63
	// Lip Right
64
	[Tooltip("Right lip transform.")]
65
	public Transform LipRight;
66
	[Tooltip("Right lip axis of rotation.")]
67
	public AxisEnum LipRightAxis;
68
	[Tooltip("Maximum stretched-value for the right lip, rounded-value is the opposite one.")]
69
	public float LipRightStretched;
70

    
71
	// Eyebrow Left
72
	[Tooltip("Left eyebrow transform.")]
73
	public Transform EyebrowLeft;
74
	[Tooltip("Left eyebrow axis of rotation.")]
75
	public AxisEnum EyebrowLeftAxis;
76
	[Tooltip("Maximum lowered-value for the left eyebrow, raised-value is the opposite one.")]
77
	public float EyebrowLeftLowered;
78

    
79
	// Eyebrow Right
80
	[Tooltip("Right eyebrow transform.")]
81
	public Transform EyebrowRight;
82
	[Tooltip("Right eyebrow axis of rotation.")]
83
	public AxisEnum EyebrowRightAxis;
84
	[Tooltip("Maximum lowered-value for the right eyebrow, raised-value is the opposite one.")]
85
	public float EyebrowRightLowered;
86
	
87
	// Lip Corner Left
88
	[Tooltip("Left lip-corner transform.")]
89
	public Transform LipCornerLeft;
90
	[Tooltip("Left lip-corner axis of rotation.")]
91
	public AxisEnum LipCornerLeftAxis;
92
	[Tooltip("Maximum depressed-value for the left lip-corner, smile-value is the opposite one.")]
93
	public float LipCornerLeftDepressed;
94

    
95
	// Lip Corner Right
96
	[Tooltip("Right lip-corner transform.")]
97
	public Transform LipCornerRight;
98
	[Tooltip("Right lip-corner axis of rotation.")]
99
	public AxisEnum LipCornerRightAxis;
100
	[Tooltip("Maximum depressed-value for the right lip-corner, smile-value is the opposite one.")]
101
	public float LipCornerRightDepressed;
102

    
103
	// Upper Eyelid Left
104
	[Tooltip("Left upper eyelid transform.")]
105
	public Transform UpperEyelidLeft;
106
	[Tooltip("Left upper eyelid axis of rotation.")]
107
	public AxisEnum UpperEyelidLeftAxis;
108
	[Tooltip("Maximum lowered-value for the left upper eyelid, raised-value is the opposite one.")]
109
	public float UpperEyelidLeftLowered;
110

    
111
	// Upper Eyelid Right
112
	[Tooltip("Right upper eyelid transform.")]
113
	public Transform UpperEyelidRight;
114
	[Tooltip("Right upper eyelid axis of rotation.")]
115
	public AxisEnum UpperEyelidRightAxis;
116
	[Tooltip("Maximum lowered-value for the right upper eyelid, raised-value is the opposite one.")]
117
	public float UpperEyelidRightLowered;
118
	
119
	// Lower Eyelid Left
120
	[Tooltip("Left lower eyelid transform.")]
121
	public Transform LowerEyelidLeft;
122
	[Tooltip("Left lower eyelid axis of rotation.")]
123
	public AxisEnum LowerEyelidLeftAxis;
124
	[Tooltip("Maximum raised-value for the left lower eyelid, lowered-value is the opposite one.")]
125
	public float LowerEyelidLeftRaised;
126

    
127
	// Lower Eyelid Right
128
	[Tooltip("Right lower eyelid transform.")]
129
	public Transform LowerEyelidRight;
130
	[Tooltip("Right lower eyelid axis of rotation.")]
131
	public AxisEnum LowerEyelidRightAxis;
132
	[Tooltip("Maximum raised-value for the right lower eyelid, lowered-value is the opposite one.")]
133
	public float LowerEyelidRightRaised;
134
	
135
	
136
	private FacetrackingManager manager;
137
	private KinectInterop.DepthSensorPlatform platform;
138
	
139
	private Vector3 HeadInitialPosition;
140
	private Quaternion HeadInitialRotation;
141
	
142
	private float UpperLipLeftNeutral;
143
	private float UpperLipRightNeutral;
144
	private float JawNeutral;
145
	private float LipLeftNeutral;
146
	private float LipRightNeutral;
147
	private float EyebrowLeftNeutral;
148
	private float EyebrowRightNeutral;
149
	private float LipCornerLeftNeutral;
150
	private float LipCornerRightNeutral;
151
	private float UpperEyelidLeftNeutral;
152
	private float UpperEyelidRightNeutral;
153
	private float LowerEyelidLeftNeutral;
154
	private float LowerEyelidRightNeutral;
155

    
156
	
157
	void Start()
158
	{
159
		if(HeadTransform != null)
160
		{
161
			HeadInitialPosition = HeadTransform.position;
162
			//HeadInitialPosition.z = 0;
163
			HeadInitialRotation = HeadTransform.rotation;
164
		}
165
		
166
		UpperLipLeftNeutral = GetJointRotation(UpperLipLeft, UpperLipLeftAxis);
167
		UpperLipRightNeutral = GetJointRotation(UpperLipRight, UpperLipRightAxis);
168
		
169
		JawNeutral = GetJointRotation(Jaw, JawAxis);
170
		
171
		LipLeftNeutral = GetJointRotation(LipLeft, LipLeftAxis);
172
		LipRightNeutral = GetJointRotation(LipRight, LipRightAxis);
173
		
174
		EyebrowLeftNeutral = GetJointRotation(EyebrowLeft, EyebrowLeftAxis);
175
		EyebrowRightNeutral = GetJointRotation(EyebrowRight, EyebrowRightAxis);
176
		
177
		LipCornerLeftNeutral = GetJointRotation(LipCornerLeft, LipCornerLeftAxis);
178
		LipCornerRightNeutral = GetJointRotation(LipCornerRight, LipCornerRightAxis);
179
		
180
		UpperEyelidLeftNeutral = GetJointRotation(UpperEyelidLeft, UpperEyelidLeftAxis);
181
		UpperEyelidRightNeutral = GetJointRotation(UpperEyelidRight, UpperEyelidRightAxis);
182

    
183
		LowerEyelidLeftNeutral = GetJointRotation(LowerEyelidLeft, LowerEyelidLeftAxis);
184
		LowerEyelidRightNeutral = GetJointRotation(LowerEyelidRight, LowerEyelidRightAxis);
185

    
186
		KinectManager kinectManager = KinectManager.Instance;
187
		if(kinectManager && kinectManager.IsInitialized())
188
		{
189
			platform = kinectManager.GetSensorPlatform();
190
		}
191
	}
192
	
193
	void Update() 
194
	{
195
		// get the face-tracking manager instance
196
		if(manager == null)
197
		{
198
			manager = FacetrackingManager.Instance;
199
		}
200

    
201
		if(manager && manager.GetFaceTrackingID() != 0)
202
		{
203
			// set head position & rotation
204
			if(HeadTransform != null)
205
			{
206
				// head position
207
				Vector3 newPosition = manager.GetHeadPosition(mirroredHeadMovement);
208
				
209
				// head rotation
210
				Quaternion newRotation = HeadInitialRotation * manager.GetHeadRotation(mirroredHeadMovement);
211
				
212
				// rotational fix, provided by Richard Borys:
213
				// The added rotation fixes rotational error that occurs when person is not centered in the middle of the kinect
214
				Vector3 addedRotation = newPosition.z != 0f ? new Vector3(Mathf.Rad2Deg * (Mathf.Tan(newPosition.y) / newPosition.z),
215
				                                                          Mathf.Rad2Deg * (Mathf.Tan(newPosition.x) / newPosition.z), 0) : Vector3.zero;
216
				
217
				addedRotation.x = newRotation.eulerAngles.x + addedRotation.x;
218
				addedRotation.y = newRotation.eulerAngles.y + addedRotation.y;
219
				addedRotation.z = newRotation.eulerAngles.z + addedRotation.z;
220
				
221
				newRotation = Quaternion.Euler(addedRotation.x, addedRotation.y, addedRotation.z);
222
				// end of rotational fix
223
				
224
				if(smoothFactor != 0f)
225
					HeadTransform.rotation = Quaternion.Slerp(HeadTransform.rotation, newRotation, smoothFactor * Time.deltaTime);
226
				else
227
					HeadTransform.rotation = newRotation;
228

    
229
				// check for head pos overlay
230
				if(foregroundCamera)
231
				{
232
					// get the background rectangle (use the portrait background, if available)
233
					Rect backgroundRect = foregroundCamera.pixelRect;
234
					PortraitBackground portraitBack = PortraitBackground.Instance;
235
					
236
					if(portraitBack && portraitBack.enabled)
237
					{
238
						backgroundRect = portraitBack.GetBackgroundRect();
239
					}
240

    
241
					KinectManager kinectManager = KinectManager.Instance;
242

    
243
					if(kinectManager)
244
					{
245
						long userId = kinectManager.GetUserIdByIndex(manager.playerIndex);
246
						Vector3 posColorOverlay = kinectManager.GetJointPosColorOverlay(userId, (int)KinectInterop.JointType.Head, foregroundCamera, backgroundRect);
247
						
248
						if(posColorOverlay != Vector3.zero)
249
						{
250
							newPosition = posColorOverlay;
251

    
252
//							if(overlayObj)
253
//							{
254
//								overlayObj.position = newPosition;
255
//							}
256
						}
257
					}
258
				}
259
				else
260
				{
261
					// move around the initial position
262
					newPosition += HeadInitialPosition;
263
				}
264

    
265
				// vertical offet
266
				if(verticalOffset != 0f)
267
				{
268
					// add the vertical offset
269
					Vector3 dirHead = new Vector3(0, verticalOffset, 0);
270
					dirHead = HeadTransform.InverseTransformDirection(dirHead);
271
					newPosition += dirHead;
272
				}
273

    
274
				// set the position
275
				if(smoothFactor != 0f)
276
					HeadTransform.position = Vector3.Lerp(HeadTransform.position, newPosition, smoothFactor * Time.deltaTime);
277
				else
278
					HeadTransform.position = newPosition;
279

    
280
				// scale factor
281
				if(HeadTransform.localScale.x != modelScaleFactor)
282
				{
283
					HeadTransform.localScale = new Vector3(modelScaleFactor, modelScaleFactor, modelScaleFactor);
284
				}
285
			}
286
			
287
			// apply animation units
288

    
289
			// AU0 - Upper Lip Raiser
290
			// 0=neutral, covering teeth; 1=showing teeth fully; -1=maximal possible pushed down lip
291
			float fAU0 = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LipPucker);
292
			SetJointRotation(UpperLipLeft, UpperLipLeftAxis, fAU0, UpperLipLeftNeutral, UpperLipLeftUp);
293
			SetJointRotation(UpperLipRight, UpperLipRightAxis, fAU0, UpperLipRightNeutral, UpperLipRightUp);
294
			
295
			// AU1 - Jaw Lowerer
296
			// 0=closed; 1=fully open; -1= closed, like 0
297
			float fAU1 = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.JawOpen);
298
			SetJointRotation(Jaw, JawAxis, fAU1, JawNeutral, JawDown);
299
			
300
			// AU2 – Lip Stretcher
301
			// 0=neutral; 1=fully stretched (joker’s smile); -1=fully rounded (kissing mouth)
302
			float fAU2_left = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LipStretcherLeft);
303
			fAU2_left = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU2_left * 2 - 1) : fAU2_left;
304
			SetJointRotation(LipLeft, LipLeftAxis, fAU2_left, LipLeftNeutral, LipLeftStretched);
305

    
306
			float fAU2_right = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LipStretcherRight);
307
			fAU2_right = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU2_right * 2 - 1) : fAU2_right;
308
			SetJointRotation(LipRight, LipRightAxis, fAU2_right, LipRightNeutral, LipRightStretched);
309
			
310
			// AU3 – Brow Lowerer
311
			// 0=neutral; -1=raised almost all the way; +1=fully lowered (to the limit of the eyes)
312
			float fAU3_left = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LefteyebrowLowerer);
313
			fAU3_left = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU3_left * 2 - 1) : fAU3_left;
314
			SetJointRotation(EyebrowLeft, EyebrowLeftAxis, fAU3_left, EyebrowLeftNeutral, EyebrowLeftLowered);
315

    
316
			float fAU3_right = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.RighteyebrowLowerer);
317
			fAU3_right = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU3_right * 2 - 1) : fAU3_right;
318
			SetJointRotation(EyebrowRight, EyebrowRightAxis, fAU3_right, EyebrowRightNeutral, EyebrowRightLowered);
319
			
320
			// AU4 – Lip Corner Depressor
321
			// 0=neutral; -1=very happy smile; +1=very sad frown
322
			float fAU4_left = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LipCornerDepressorLeft);
323
			fAU4_left = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU4_left * 2) : fAU4_left;
324
			SetJointRotation(LipCornerLeft, LipCornerLeftAxis, fAU4_left, LipCornerLeftNeutral, LipCornerLeftDepressed);
325

    
326
			float fAU4_right = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LipCornerDepressorRight);
327
			fAU4_right = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU4_right * 2) : fAU4_right;
328
			SetJointRotation(LipCornerRight, LipCornerRightAxis, fAU4_right, LipCornerRightNeutral, LipCornerRightDepressed);
329

    
330
			// AU6, AU7 – Eyelid closed
331
			// 0=neutral; -1=raised; +1=fully lowered
332
			float fAU6_left = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.LefteyeClosed);
333
			fAU6_left = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU6_left * 2 - 1) : fAU6_left;
334
			SetJointRotation(UpperEyelidLeft, UpperEyelidLeftAxis, fAU6_left, UpperEyelidLeftNeutral, UpperEyelidLeftLowered);
335
			SetJointRotation(LowerEyelidLeft, LowerEyelidLeftAxis, fAU6_left, LowerEyelidLeftNeutral, LowerEyelidLeftRaised);
336

    
337
			float fAU6_right = manager.GetAnimUnit(KinectInterop.FaceShapeAnimations.RighteyeClosed);
338
			fAU6_right = (platform == KinectInterop.DepthSensorPlatform.KinectSDKv2) ? (fAU6_right * 2 - 1) : fAU6_right;
339
			SetJointRotation(UpperEyelidRight, UpperEyelidRightAxis, fAU6_right, UpperEyelidRightNeutral, UpperEyelidRightLowered);
340
			SetJointRotation(LowerEyelidRight, LowerEyelidRightAxis, fAU6_right, LowerEyelidRightNeutral, LowerEyelidRightRaised);
341
		}
342
		else
343
		{
344
			// hide the model behind the camera
345
			if(HeadTransform && HeadTransform.position.z >= 0f)
346
			{
347
				HeadTransform.position = new Vector3(0f, 0f, -10f);
348
			}
349
		}
350
	}
351
	
352
	private float GetJointRotation(Transform joint, AxisEnum axis)
353
	{
354
		float fJointRot = 0.0f;
355
		
356
		if(joint == null)
357
			return fJointRot;
358
		
359
		Vector3 jointRot = joint.localRotation.eulerAngles;
360
		
361
		switch(axis)
362
		{
363
			case AxisEnum.X:
364
				fJointRot = jointRot.x;
365
				break;
366
			
367
			case AxisEnum.Y:
368
				fJointRot = jointRot.y;
369
				break;
370
			
371
			case AxisEnum.Z:
372
				fJointRot = jointRot.z;
373
				break;
374
		}
375
		
376
		return fJointRot;
377
	}
378
	
379
	private void SetJointRotation(Transform joint, AxisEnum axis, float fAU, float fMin, float fMax)
380
	{
381
		if(joint == null)
382
			return;
383
		
384
//		float fSign = 1.0f;
385
//		if(fMax < fMin)
386
//			fSign = -1.0f;
387
		
388
		// [-1, +1] -> [0, 1]
389
		//fAUnorm = (fAU + 1f) / 2f;
390
		float fValue = fMin + (fMax - fMin) * fAU;
391
		
392
		Vector3 jointRot = joint.localRotation.eulerAngles;
393
		
394
		switch(axis)
395
		{
396
			case AxisEnum.X:
397
				jointRot.x = fValue;
398
				break;
399
			
400
			case AxisEnum.Y:
401
				jointRot.y = fValue;
402
				break;
403
			
404
			case AxisEnum.Z:
405
				jointRot.z = fValue;
406
				break;
407
		}
408

    
409
		if(smoothFactor != 0f)
410
			joint.localRotation = Quaternion.Slerp(joint.localRotation, Quaternion.Euler(jointRot), smoothFactor * Time.deltaTime);
411
		else
412
			joint.localRotation = Quaternion.Euler(jointRot);
413
	}
414
	
415
	
416
}