프로젝트

일반

사용자정보

통계
| 개정판:

t1 / TFDContents / Assets / KinectScripts / KinectInterop.cs @ 3

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

1
using UnityEngine;
2
//using Windows.Kinect;
3

    
4
using System.Collections;
5
using System.Collections.Generic;
6
using System.Runtime.CompilerServices;
7
using System.Runtime.InteropServices;
8
using System;
9
using System.IO;
10
using System.Text;
11
#if !UNITY_WSA
12
using ICSharpCode.SharpZipLib.Zip;
13
#endif
14
//using OpenCvSharp;
15
using UnityEngine.SceneManagement;
16

    
17

    
18
/// <summary>
19
/// KinectInterop is a class containing utility and interop functions, that call the proper sensor interface.
20
/// </summary>
21
public class KinectInterop
22
{
23
	// order of depth sensor interfaces
24
//	public static Type[] SensorInterfaceOrder = new Type[] { 
25
//		typeof(Kinect2Interface), typeof(Kinect1Interface), typeof(OpenNI2Interface)
26
//	};
27
	public static DepthSensorInterface[] SensorInterfaceOrder = new DepthSensorInterface[] { 
28
#if UNITY_WSA_10_0 && NETFX_CORE
29
		new Kinect2UwpInterface()
30
#else
31
		new Kinect2Interface(), new Kinect1Interface()/**, new OpenNI2Interface()*/
32
#endif
33
	};
34

    
35
	// graphics shader level
36
	private static int graphicsShaderLevel = 0;
37

    
38
	
39
	/// <summary>
40
	/// Constants used by this class and other K2-components
41
	/// </summary>
42
	public static class Constants
43
	{
44
		public const int MaxBodyCount = 6;
45
		public const int MaxJointCount = 25;
46

    
47
		public const float MinTimeBetweenSameGestures = 0.0f;
48
		public const float PoseCompleteDuration = 1.0f;
49
		public const float ClickMaxDistance = 0.05f;
50
		public const float ClickStayDuration = 2.0f;
51
	}
52

    
53
	// Types of depth sensor platforms
54
	public enum DepthSensorPlatform : int
55
	{
56
		None = 0,
57
		KinectSDKv1 = 1,
58
		KinectSDKv2 = 2,
59
		OpenNIv2 = 3,
60
		RealSense = 4,
61
		KinectUWPv2 = 5,
62

    
63
		DummyK1 = 101,
64
		DummyK2 = 102
65
	}
66
	
67
	// Data structures for interfacing C# with the native wrappers
68

    
69
    [Flags]
70
    public enum FrameSource : uint
71
    {
72
		TypeNone = 0x0,
73
        TypeColor = 0x1,
74
        TypeInfrared = 0x2,
75
        TypeDepth = 0x8,
76
        TypeBodyIndex = 0x10,
77
        TypeBody = 0x20,
78
        TypeAudio = 0x40
79
    }
80
	
81
    public enum JointType : int
82
    {
83
		SpineBase = 0,
84
		SpineMid = 1,
85
        Neck = 2,
86
        Head = 3,
87
        ShoulderLeft = 4,
88
        ElbowLeft = 5,
89
        WristLeft = 6,
90
        HandLeft = 7,
91
        ShoulderRight = 8,
92
        ElbowRight = 9,
93
        WristRight = 10,
94
        HandRight = 11,
95
        HipLeft = 12,
96
        KneeLeft = 13,
97
        AnkleLeft = 14,
98
        FootLeft = 15,
99
        HipRight = 16,
100
        KneeRight = 17,
101
        AnkleRight = 18,
102
        FootRight = 19,
103
        SpineShoulder = 20,
104
        HandTipLeft = 21,
105
        ThumbLeft = 22,
106
        HandTipRight = 23,
107
        ThumbRight = 24
108
		//Count = 25
109
    }
110

    
111
    public static readonly Vector3[] JointBaseDir =
112
    {
113
        Vector3.zero,
114
        Vector3.up,
115
        Vector3.up,
116
        Vector3.up,
117
        Vector3.left,
118
        Vector3.left,
119
        Vector3.left,
120
        Vector3.left,
121
        Vector3.right,
122
        Vector3.right,
123
        Vector3.right,
124
        Vector3.right,
125
        Vector3.down,
126
        Vector3.down,
127
        Vector3.down,
128
        Vector3.forward,
129
        Vector3.down,
130
        Vector3.down,
131
        Vector3.down,
132
        Vector3.forward,
133
        Vector3.up,
134
        Vector3.left,
135
        Vector3.forward,
136
        Vector3.right,
137
        Vector3.forward
138
    };
139

    
140
    public enum TrackingState
141
    {
142
        NotTracked = 0,
143
        Inferred = 1,
144
        Tracked = 2
145
    }
146

    
147
	public enum HandState
148
    {
149
        Unknown = 0,
150
        NotTracked = 1,
151
        Open = 2,
152
        Closed = 3,
153
        Lasso = 4
154
    }
155
	
156
	public enum TrackingConfidence
157
    {
158
        Low = 0,
159
        High = 1
160
    }
161

    
162
//    [Flags]
163
//    public enum ClippedEdges
164
//    {
165
//        None = 0,
166
//        Right = 1,
167
//        Left = 2,
168
//        Top = 4,
169
//        Bottom = 8
170
//    }
171

    
172
	public enum FaceShapeAnimations : int
173
	{
174
		JawOpen                                  =0,
175
		LipPucker                                =1,
176
		JawSlideRight                            =2,
177
		LipStretcherRight                        =3,
178
		LipStretcherLeft                         =4,
179
		LipCornerPullerLeft                      =5,
180
		LipCornerPullerRight                     =6,
181
		LipCornerDepressorLeft                   =7,
182
		LipCornerDepressorRight                  =8,
183
		LeftcheekPuff                            =9,
184
		RightcheekPuff                           =10,
185
		LefteyeClosed                            =11,
186
		RighteyeClosed                           =12,
187
		RighteyebrowLowerer                      =13,
188
		LefteyebrowLowerer                       =14,
189
		LowerlipDepressorLeft                    =15,
190
		LowerlipDepressorRight                   =16,
191
	}
192
	
193
	public enum FaceShapeDeformations : int
194
	{
195
		PCA01                                    =0,
196
		PCA02                                    =1,
197
		PCA03                                    =2,
198
		PCA04                                    =3,
199
		PCA05                                    =4,
200
		PCA06                                    =5,
201
		PCA07                                    =6,
202
		PCA08                                    =7,
203
		PCA09                                    =8,
204
		PCA10                                    =9,
205
		Chin03                                   =10,
206
		Forehead00                               =11,
207
		Cheeks02                                 =12,
208
		Cheeks01                                 =13,
209
		MouthBag01                               =14,
210
		MouthBag02                               =15,
211
		Eyes02                                   =16,
212
		MouthBag03                               =17,
213
		Forehead04                               =18,
214
		Nose00                                   =19,
215
		Nose01                                   =20,
216
		Nose02                                   =21,
217
		MouthBag06                               =22,
218
		MouthBag05                               =23,
219
		Cheeks00                                 =24,
220
		Mask03                                   =25,
221
		Eyes03                                   =26,
222
		Nose03                                   =27,
223
		Eyes08                                   =28,
224
		MouthBag07                               =29,
225
		Eyes00                                   =30,
226
		Nose04                                   =31,
227
		Mask04                                   =32,
228
		Chin04                                   =33,
229
		Forehead05                               =34,
230
		Eyes06                                   =35,
231
		Eyes11                                   =36,
232
		Nose05                                   =37,
233
		Mouth07                                  =38,
234
		Cheeks08                                 =39,
235
		Eyes09                                   =40,
236
		Mask10                                   =41,
237
		Mouth09                                  =42,
238
		Nose07                                   =43,
239
		Nose08                                   =44,
240
		Cheeks07                                 =45,
241
		Mask07                                   =46,
242
		MouthBag09                               =47,
243
		Nose06                                   =48,
244
		Chin02                                   =49,
245
		Eyes07                                   =50,
246
		Cheeks10                                 =51,
247
		Rim20                                    =52,
248
		Mask22                                   =53,
249
		MouthBag15                               =54,
250
		Chin01                                   =55,
251
		Cheeks04                                 =56,
252
		Eyes17                                   =57,
253
		Cheeks13                                 =58,
254
		Mouth02                                  =59,
255
		MouthBag12                               =60,
256
		Mask19                                   =61,
257
		Mask20                                   =62,
258
		Forehead06                               =63,
259
		Mouth13                                  =64,
260
		Mask25                                   =65,
261
		Chin05                                   =66,
262
		Cheeks20                                 =67,
263
		Nose09                                   =68,
264
		Nose10                                   =69,
265
		MouthBag27                               =70,
266
		Mouth11                                  =71,
267
		Cheeks14                                 =72,
268
		Eyes16                                   =73,
269
		Mask29                                   =74,
270
		Nose15                                   =75,
271
		Cheeks11                                 =76,
272
		Mouth16                                  =77,
273
		Eyes19                                   =78,
274
		Mouth17                                  =79,
275
		MouthBag36                               =80,
276
		Mouth15                                  =81,
277
		Cheeks25                                 =82,
278
		Cheeks16                                 =83,
279
		Cheeks18                                 =84,
280
		Rim07                                    =85,
281
		Nose13                                   =86,
282
		Mouth18                                  =87,
283
		Cheeks19                                 =88,
284
		Rim21                                    =89,
285
		Mouth22                                  =90,
286
		Nose18                                   =91,
287
		Nose16                                   =92,
288
		Rim22                                    =93,
289
	}
290
	
291

    
292
	/// <summary>
293
	/// Container for the sensor data, including color, depth, ir and body frames.
294
	/// </summary>
295
	public class SensorData
296
	{
297
		public DepthSensorInterface sensorInterface;
298
		public DepthSensorPlatform sensorIntPlatform;
299

    
300
		public int bodyCount;
301
		public int jointCount;
302

    
303
		public float depthCameraOffset;
304
		public float depthCameraFOV;
305
		public float colorCameraFOV;
306
		public float faceOverlayOffset;
307

    
308
		public int colorImageWidth;
309
		public int colorImageHeight;
310

    
311
		public byte[] colorImage;
312
		public long lastColorFrameTime = 0;
313

    
314
		public int depthImageWidth;
315
		public int depthImageHeight;
316

    
317
		public ushort[] depthImage;
318
		public long lastDepthFrameTime = 0;
319

    
320
		public ushort[] infraredImage;
321
		public long lastInfraredFrameTime = 0;
322

    
323
		public byte[] bodyIndexImage;
324
		public long lastBodyIndexFrameTime = 0;
325

    
326
		public byte selectedBodyIndex = 255;
327

    
328
		public bool hintHeightAngle = false;
329
		public Quaternion sensorRotDetected = Quaternion.identity;
330
		public float sensorHgtDetected = 0f;
331
		
332
		public RenderTexture bodyIndexTexture;
333
		public Material bodyIndexMaterial;
334
		public ComputeBuffer bodyIndexBuffer;
335

    
336
		public float[] bodyIndexBufferData = null;
337
		public bool bodyIndexBufferReady = false;
338
		public object bodyIndexBufferLock = new object();
339

    
340
		public RenderTexture depthImageTexture;
341
		public Material depthImageMaterial;
342
		public ComputeBuffer depthImageBuffer;
343
		public ComputeBuffer depthHistBuffer;
344

    
345
		public float[] depthImageBufferData = null;
346
		public int[] depthHistBufferData = null;
347
		public float[] equalHistBufferData = null;
348
		public int depthHistTotalPoints = 0;
349
		public int firstUserIndex = -1;
350

    
351
		public bool depthImageBufferReady = false;
352
		public object depthImageBufferLock = new object();
353
		public bool depthCoordsBufferReady = false;
354
		public object depthCoordsBufferLock = new object();
355
		public bool newDepthImage = false;
356
		
357
		public Texture2D colorImageTexture;
358

    
359
		public bool colorImageBufferReady = false;
360
		public object colorImageBufferLock = new object();
361
		public bool newColorImage = false;
362

    
363
		public RenderTexture depth2ColorTexture;
364
		public Material depth2ColorMaterial;
365
		public ComputeBuffer depth2ColorBuffer;
366
		public Vector2[] depth2ColorCoords;
367

    
368
		public Vector3[] depth2SpaceCoords;
369
		public bool spaceCoordsBufferReady = false;
370
		public object spaceCoordsBufferLock = new object();
371

    
372
        public bool backgroundRemovalInited = false;
373
        public bool backgroundRemovalHiRes = false;
374
		public bool invertAlphaColorMask = false;
375

    
376
		public RenderTexture color2DepthTexture;
377
		public Material color2DepthMaterial;
378
		public ComputeBuffer color2DepthBuffer;
379
		public Vector2[] color2DepthCoords;
380
		
381
		public RenderTexture alphaBodyTexture;
382
		public Material alphaBodyMaterial;
383
		public Material erodeBodyMaterial, dilateBodyMaterial, blurBodyMaterial;
384

    
385
		public int erodeIterations;
386
		public int dilateIterations;
387

    
388
		public RenderTexture colorBackgroundTexture;
389
		public Material colorBackgroundMaterial;
390

    
391
		public bool newInfraredImage = false;
392

    
393
		public bool bodyFrameReady = false;
394
		public object bodyFrameLock = new object();
395
		public bool newBodyFrame = false;
396
		
397
		public bool isPlayModeEnabled;
398
		public string playModeData;
399
		public string playModeHandData;
400
	}
401

    
402
	/// <summary>
403
	/// Parameters used for smoothing of the body-joint positions between frames.
404
	/// </summary>
405
	public struct SmoothParameters
406
	{
407
		public float smoothing;
408
		public float correction;
409
		public float prediction;
410
		public float jitterRadius;
411
		public float maxDeviationRadius;
412
	}
413

    
414
	/// <summary>
415
	/// Container for the body-joint data.
416
	/// </summary>
417
	public struct JointData
418
    {
419
		// parameters filled in by the sensor interface
420
		//public JointType jointType;
421
    	public TrackingState trackingState;
422
    	public Vector3 kinectPos;
423
    	public Vector3 position;
424
		public Quaternion orientation;  // deprecated
425

    
426
		public Vector3 posPrev;
427
		public Vector3 posRel;
428
		public Vector3 posVel;
429

    
430
		// KM calculated parameters
431
		public Vector3 direction;
432
		public Quaternion normalRotation;
433
		public Quaternion mirroredRotation;
434
		
435
		// Constraint parameters
436
		public float lastAngle;
437
    }
438

    
439
	/// <summary>
440
	/// Container for the body data.
441
	/// </summary>
442
	public struct BodyData
443
    {
444
		// parameters filled in by the sensor interface
445
        public Int64 liTrackingID;
446
        public Vector3 position;
447
		public Quaternion orientation;  // deprecated
448

    
449
		public JointData[] joint;
450

    
451
		// KM calculated parameters
452
		public Quaternion normalRotation;
453
		public Quaternion mirroredRotation;
454
		
455
		public Vector3 hipsDirection;
456
		public Vector3 shouldersDirection;
457
		public float bodyTurnAngle;
458
		//public float bodyFullAngle;
459
		public bool isTurnedAround;
460
		public float turnAroundFactor;
461

    
462
		public Quaternion leftHandOrientation;
463
		public Quaternion rightHandOrientation;
464

    
465
		public Quaternion headOrientation;
466

    
467
//		public Vector3 leftArmDirection;
468
//		public Vector3 leftThumbForward;
469
//		public Vector3 leftThumbDirection;
470
//		//public float leftThumbAngle;
471
//
472
//		public Vector3 rightArmDirection;
473
//		public Vector3 rightThumbForward;
474
//		public Vector3 rightThumbDirection;
475
//		//public float rightThumbAngle;
476

    
477
		//public Vector3 leftLegDirection;
478
		//public Vector3 leftFootDirection;
479
		//public Vector3 rightLegDirection;
480
		//public Vector3 rightFootDirection;
481

    
482
		public HandState leftHandState;
483
		public TrackingConfidence leftHandConfidence;
484
		public HandState rightHandState;
485
		public TrackingConfidence rightHandConfidence;
486
		
487
        public uint dwClippedEdges;
488
        public short bIsTracked;
489
		public short bIsRestricted;
490
    }
491

    
492
	/// <summary>
493
	/// Container for the body frame data.
494
	/// </summary>
495
    public struct BodyFrameData
496
    {
497
        public Int64 liRelativeTime, liPreviousTime;
498
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.Struct)]
499
        public BodyData[] bodyData;
500
        //public UnityEngine.Vector4 floorClipPlane;
501
		public bool bTurnAnalisys;
502
		
503
		public BodyFrameData(int bodyCount, int jointCount)
504
		{
505
			liRelativeTime = liPreviousTime = 0;
506
			//floorClipPlane = UnityEngine.Vector4.zero;
507
			bTurnAnalisys = false;
508

    
509
			bodyData = new BodyData[bodyCount];
510

    
511
			for(int i = 0; i < bodyCount; i++)
512
			{
513
				bodyData[i].joint = new JointData[jointCount];
514

    
515
				bodyData[i].leftHandOrientation = Quaternion.identity;
516
				bodyData[i].rightHandOrientation = Quaternion.identity;
517
				bodyData[i].headOrientation = Quaternion.identity;
518
			}
519
		}
520
    }
521
	
522

    
523
	// initializes the available sensor interfaces
524
	public static List<DepthSensorInterface> InitSensorInterfaces(bool bOnceRestarted, ref bool bNeedRestart)
525
	{
526
		List<DepthSensorInterface> listInterfaces = new List<DepthSensorInterface>();
527

    
528
		//var typeInterface = typeof(DepthSensorInterface);
529

    
530
		for(int pass = 0; pass <= 1; pass++)
531
		{
532
			bool bCopyLibs = (pass != 0);
533

    
534
			//foreach(Type type in SensorInterfaceOrder)
535
			for(int i = 0; i < SensorInterfaceOrder.Length; i++)
536
			{
537
				DepthSensorInterface sensorInt = SensorInterfaceOrder[i];
538

    
539
				//if(typeInterface.IsAssignableFrom(type) && type != typeInterface)
540
				if(sensorInt != null)
541
				{
542
					//DepthSensorInterface sensorInt = null;
543
					
544
					try 
545
					{
546
						//sensorInt = (DepthSensorInterface)Activator.CreateInstance(type);
547
						
548
						bool bIntNeedRestart = false;
549
						if(sensorInt.InitSensorInterface(bCopyLibs, ref bIntNeedRestart))
550
						{
551
							bNeedRestart |= bIntNeedRestart;
552
						}
553
						else
554
						{
555
							sensorInt.FreeSensorInterface(bCopyLibs);
556
							sensorInt = null;
557

    
558
							continue;
559
						}
560
						
561
						if(!bNeedRestart && !sensorInt.IsSensorAvailable())
562
						{
563
							sensorInt.FreeSensorInterface(false);
564
							sensorInt = null;
565
						}
566
					}
567
					catch (Exception /**ex*/) 
568
					{
569
						//Debug.Log(ex);
570
						
571
						if(sensorInt != null)
572
						{
573
							try 
574
							{
575
								sensorInt.FreeSensorInterface(bCopyLibs);
576
							}
577
							catch (Exception) 
578
							{
579
								// do nothing
580
							}
581
							finally
582
							{
583
								sensorInt = null;
584
							}
585
						}
586
					}
587
					
588
					if(sensorInt != null)
589
					{
590
						listInterfaces.Add(sensorInt);
591
					}
592
				}
593
			}
594

    
595
			if(listInterfaces.Count > 0)
596
			{
597
				// we found working interface(s), don't go any further
598
				break;
599
			}
600

    
601
			if(bOnceRestarted)
602
			{
603
				// we have restarted once, don't do it again
604
				break;
605
			}
606
		}
607

    
608
		return listInterfaces;
609
	}
610

    
611
	// opens the default sensor and needed readers
612
	public static SensorData OpenDefaultSensor(List<DepthSensorInterface> listInterfaces, FrameSource dwFlags, float sensorAngle, bool bUseMultiSource,  
613
		KinectManager.UserMapType userMapType, BackgroundRemovalManager brManager)
614
	{
615
		SensorData sensorData = null;
616
		if(listInterfaces == null)
617
			return sensorData;
618

    
619
		foreach(DepthSensorInterface sensorInt in listInterfaces)
620
		{
621
			try 
622
			{
623
				if(sensorData == null)
624
				{
625
					sensorData = sensorInt.OpenDefaultSensor(dwFlags, sensorAngle, bUseMultiSource);
626

    
627
					if(sensorData != null)
628
					{
629
						sensorData.sensorInterface = sensorInt;
630
						sensorData.sensorIntPlatform = sensorInt.GetSensorPlatform();
631
						Debug.Log("Interface used: " + sensorInt.GetType().Name);
632

    
633
						Debug.Log("Shader level: " + SystemInfo.graphicsShaderLevel);
634
						if(sensorData.bodyIndexImage != null && IsDirectX11Available())
635
						{
636
							Shader bodyIndexShader = Shader.Find("Kinect/BodyShader");
637

    
638
							if(bodyIndexShader != null)
639
							{
640
                                if(sensorData.bodyIndexTexture == null || sensorData.bodyIndexTexture.width != sensorData.depthImageWidth || sensorData.bodyIndexTexture.height != sensorData.depthImageHeight)
641
                                {
642
                                    sensorData.bodyIndexTexture = new RenderTexture(sensorData.depthImageWidth, sensorData.depthImageHeight, 0);
643
                                    sensorData.bodyIndexTexture.wrapMode = TextureWrapMode.Clamp;
644
                                    sensorData.bodyIndexTexture.filterMode = FilterMode.Point;
645
                                    //Debug.Log(sensorData.bodyIndexTexture.format);
646
                                }
647

    
648
                                sensorData.bodyIndexMaterial = new Material(bodyIndexShader);
649
								
650
								sensorData.bodyIndexMaterial.SetFloat("_TexResX", (float)sensorData.depthImageWidth);
651
								sensorData.bodyIndexMaterial.SetFloat("_TexResY", (float)sensorData.depthImageHeight);
652
								
653
								sensorData.bodyIndexBuffer = new ComputeBuffer(sensorData.bodyIndexImage.Length, sizeof(float));
654
								sensorData.bodyIndexMaterial.SetBuffer("_BodyIndexBuffer", sensorData.bodyIndexBuffer);
655
							}
656
						}
657
						
658
						if(sensorData.depthImage != null && IsDirectX11Available() &&
659
						    userMapType == KinectManager.UserMapType.UserTexture)
660
						{
661
							Shader depthImageShader = Shader.Find("Kinect/DepthShader");
662

    
663
							if(depthImageShader != null)
664
							{
665
                                if (sensorData.depthImageTexture == null || sensorData.depthImageTexture.width != sensorData.depthImageWidth || sensorData.depthImageTexture.height != sensorData.depthImageHeight)
666
                                {
667
                                    sensorData.depthImageTexture = new RenderTexture(sensorData.depthImageWidth, sensorData.depthImageHeight, 0);
668
                                    sensorData.depthImageTexture.wrapMode = TextureWrapMode.Clamp;
669
                                    sensorData.depthImageTexture.filterMode = FilterMode.Point;
670
                                }
671

    
672
                                sensorData.depthImageMaterial = new Material(depthImageShader);
673
								
674
								sensorData.depthImageMaterial.SetTexture("_MainTex", sensorData.bodyIndexTexture);
675
								
676
								sensorData.depthImageMaterial.SetFloat("_TexResX", (float)sensorData.depthImageWidth);
677
								sensorData.depthImageMaterial.SetFloat("_TexResY", (float)sensorData.depthImageHeight);
678
								
679
								sensorData.depthImageBuffer = new ComputeBuffer(sensorData.depthImage.Length, sizeof(float));
680
								sensorData.depthImageMaterial.SetBuffer("_DepthBuffer", sensorData.depthImageBuffer);
681
								
682
								sensorData.depthHistBuffer = new ComputeBuffer(5001, sizeof(float));
683
								sensorData.depthImageMaterial.SetBuffer("_HistBuffer", sensorData.depthHistBuffer);
684

    
685
								// use body index buffer to overcome the linear color correction
686
								sensorData.depthImageMaterial.SetBuffer("_BodyIndexBuffer", sensorData.bodyIndexBuffer);
687
							}
688
						}
689

    
690
						if(sensorData.colorImage != null)
691
						{
692
                            if (sensorData.colorImageTexture == null || sensorData.colorImageTexture.width != sensorData.colorImageWidth || sensorData.colorImageTexture.height != sensorData.colorImageHeight)
693
                            {
694
                                sensorData.colorImageTexture = new Texture2D(sensorData.colorImageWidth, sensorData.colorImageHeight, TextureFormat.RGBA32, false);
695
                            }
696
                        }
697
						
698
						// check if background removal requires cut-out image
699
						bool bBrRequiresCutOut = brManager && (!brManager.colorCameraResolution || !sensorInt.IsBRHiResSupported());
700
						
701
						if(sensorData.bodyIndexImage != null && sensorData.colorImage != null && IsDirectX11Available() &&
702
						   (userMapType == KinectManager.UserMapType.CutOutTexture || bBrRequiresCutOut))
703
						{
704
							Shader depth2ColorShader = Shader.Find("Kinect/Depth2ColorShader");
705

    
706
							if(depth2ColorShader != null)
707
							{
708
                                if (sensorData.depth2ColorTexture == null || sensorData.depth2ColorTexture.width != sensorData.depthImageWidth || sensorData.depth2ColorTexture.height != sensorData.depthImageHeight)
709
                                {
710
                                    sensorData.depth2ColorTexture = new RenderTexture(sensorData.depthImageWidth, sensorData.depthImageHeight, 0);
711
                                    sensorData.depth2ColorTexture.wrapMode = TextureWrapMode.Clamp;
712
                                    sensorData.depth2ColorTexture.filterMode = FilterMode.Point;
713
                                }
714

    
715
                                sensorData.depth2ColorMaterial = new Material(depth2ColorShader);
716
								
717
								sensorData.depth2ColorMaterial.SetFloat("_ColorResX", (float)sensorData.colorImageWidth);
718
								sensorData.depth2ColorMaterial.SetFloat("_ColorResY", (float)sensorData.colorImageHeight);
719
								sensorData.depth2ColorMaterial.SetFloat("_DepthResX", (float)sensorData.depthImageWidth);
720
								sensorData.depth2ColorMaterial.SetFloat("_DepthResY", (float)sensorData.depthImageHeight);
721
								
722
								sensorData.depth2ColorBuffer = new ComputeBuffer(sensorData.depthImage.Length, sizeof(float) * 2);
723
								sensorData.depth2ColorMaterial.SetBuffer("_ColorCoords", sensorData.depth2ColorBuffer);
724

    
725
								sensorData.depth2ColorCoords = new Vector2[sensorData.depthImage.Length];
726
							}
727
						}
728

    
729
//						if(sensorData.bodyIndexImage != null && sensorData.colorImage != null && IsDirectX11Available() &&
730
//						   (userMapType == KinectManager.UserMapType.CutOutTexture || bBrRequiresCutOut))
731
//						{
732
//							sensorData.depth2ColorCoords = new Vector2[sensorData.depthImage.Length];
733
//						}
734
						
735
					}
736
				}
737
				else
738
				{
739
					sensorInt.FreeSensorInterface(false);
740
				}
741
			}
742
			catch (Exception ex) 
743
			{
744
				Debug.LogError("Initialization of the sensor failed.");
745
				Debug.LogError(ex.ToString());
746

    
747
				try 
748
				{
749
					sensorInt.FreeSensorInterface(false);
750
				} 
751
				catch (Exception) 
752
				{
753
					// do nothing
754
				}
755
			}
756
		}
757

    
758
		return sensorData;
759
	}
760

    
761
	// closes opened readers and closes the sensor
762
	public static void CloseSensor(SensorData sensorData)
763
	{
764
		FinishBackgroundRemoval(sensorData);
765
		//FinishColorBackground(sensorData);
766

    
767
		if(sensorData != null && sensorData.sensorInterface != null)
768
		{
769
			sensorData.sensorInterface.CloseSensor(sensorData);
770
		}
771
		
772
		if(sensorData.bodyIndexBuffer != null)
773
		{
774
			sensorData.bodyIndexBuffer.Release();
775
			sensorData.bodyIndexBuffer = null;
776
		}
777
		
778
		if(sensorData.depthImageBuffer != null)
779
		{
780
			sensorData.depthImageBuffer.Release();
781
			sensorData.depthImageBuffer = null;
782
		}
783

    
784
		if(sensorData.depthHistBuffer != null)
785
		{
786
			sensorData.depthHistBuffer.Release();
787
			sensorData.depthHistBuffer = null;
788
		}
789
		
790
		if(sensorData.depth2ColorBuffer != null)
791
		{
792
			sensorData.depth2ColorBuffer.Release();
793
			sensorData.depth2ColorBuffer = null;
794
		}
795

    
796
        //if (sensorData.depth2ColorTexture != null)
797
        //{
798
        //    sensorData.depth2ColorTexture.Release();
799
        //    sensorData.depth2ColorTexture = null;
800
        //}
801

    
802
        //sensorData.depth2ColorMaterial = null;
803
        //sensorData.depth2ColorCoords = null;
804
    }
805

    
806
    // invoked periodically to update sensor data, if needed
807
    public static bool UpdateSensorData(SensorData sensorData)
808
	{
809
		bool bResult = false;
810

    
811
		if(sensorData.sensorInterface != null)
812
		{
813
			bResult = sensorData.sensorInterface.UpdateSensorData(sensorData);
814
		}
815

    
816
		return bResult;
817
	}
818
	
819
	// returns the mirror joint of the given joint
820
	public static JointType GetMirrorJoint(JointType joint)
821
	{
822
		switch(joint)
823
		{
824
			case JointType.ShoulderLeft:
825
				return JointType.ShoulderRight;
826
	        case JointType.ElbowLeft:
827
				return JointType.ElbowRight;
828
	        case JointType.WristLeft:
829
				return JointType.WristRight;
830
	        case JointType.HandLeft:
831
				return JointType.HandRight;
832
					
833
	        case JointType.ShoulderRight:
834
				return JointType.ShoulderLeft;
835
	        case JointType.ElbowRight:
836
				return JointType.ElbowLeft;
837
	        case JointType.WristRight:
838
				return JointType.WristLeft;
839
	        case JointType.HandRight:
840
				return JointType.HandLeft;
841
					
842
	        case JointType.HipLeft:
843
				return JointType.HipRight;
844
	        case JointType.KneeLeft:
845
				return JointType.KneeRight;
846
	        case JointType.AnkleLeft:
847
				return JointType.AnkleRight;
848
	        case JointType.FootLeft:
849
				return JointType.FootRight;
850
					
851
	        case JointType.HipRight:
852
				return JointType.HipLeft;
853
	        case JointType.KneeRight:
854
				return JointType.KneeLeft;
855
	        case JointType.AnkleRight:
856
				return JointType.AnkleLeft;
857
	        case JointType.FootRight:
858
				return JointType.FootLeft;
859
					
860
	        case JointType.HandTipLeft:
861
				return JointType.HandTipRight;
862
	        case JointType.ThumbLeft:
863
				return JointType.ThumbRight;
864
			
865
	        case JointType.HandTipRight:
866
				return JointType.HandTipLeft;
867
	        case JointType.ThumbRight:
868
				return JointType.ThumbLeft;
869
		}
870
	
871
		return joint;
872
	}
873

    
874
	// gets new multi source frame
875
	public static bool GetMultiSourceFrame(SensorData sensorData)
876
	{
877
		bool bResult = false;
878

    
879
		if(sensorData.sensorInterface != null)
880
		{
881
			bResult = sensorData.sensorInterface.GetMultiSourceFrame(sensorData);
882
		}
883

    
884
		return bResult;
885
	}
886

    
887
	// frees last multi source frame
888
	public static void FreeMultiSourceFrame(SensorData sensorData)
889
	{
890
		if(sensorData.sensorInterface != null)
891
		{
892
			sensorData.sensorInterface.FreeMultiSourceFrame(sensorData);
893
		}
894
	}
895

    
896
	// gets matrix values as csv line
897
	public static string GetMatrixAsCsv(ref Matrix4x4 mat, char delimiter)
898
	{
899
		// create the output string
900
		StringBuilder sbBuf = new StringBuilder();
901
		//const char delimiter = ',';
902

    
903
		sbBuf.Append("km").Append(delimiter);
904

    
905
		for(int i = 0; i < 4; i++)
906
		{
907
			Vector4 vRow = mat.GetRow(i);
908

    
909
			sbBuf.AppendFormat("{0:F3}", vRow.x).Append(delimiter);
910
			sbBuf.AppendFormat("{0:F3}", vRow.y).Append(delimiter);
911
			sbBuf.AppendFormat("{0:F3}", vRow.z).Append(delimiter);
912
			sbBuf.AppendFormat("{0:F3}", vRow.w).Append(delimiter);
913
		}
914

    
915
		// remove the last delimiter
916
		if(sbBuf.Length > 0 && sbBuf[sbBuf.Length - 1] == delimiter)
917
		{
918
			sbBuf.Remove(sbBuf.Length - 1, 1);
919
		}
920

    
921
		return sbBuf.ToString();
922
	}
923

    
924
	// sets matrix values from a csv line
925
	public static bool SetMatrixFromCsv(string sCsvLine, ref Matrix4x4 mat)
926
	{
927
		if(sCsvLine.Length == 0)
928
			return false;
929

    
930
		// split the csv line in parts
931
		char[] delimiters = { ',' };
932
		string[] alCsvParts = sCsvLine.Split(delimiters);
933

    
934
		if(alCsvParts.Length < 17)
935
			return false;
936
		if(alCsvParts[0] != "km")
937
			return false;
938

    
939
		int iIndex = 1;
940
		for(int i = 0; i < 4; i++)
941
		{
942
			float x = 0f, y = 0f, z = 0f, w = 0f;
943

    
944
			float.TryParse(alCsvParts[iIndex], out x);
945
			float.TryParse(alCsvParts[iIndex + 1], out y);
946
			float.TryParse(alCsvParts[iIndex + 2], out z);
947
			float.TryParse(alCsvParts[iIndex + 3], out w);
948
			iIndex += 4;
949

    
950
			Vector4 vRow = new Vector4(x, y, z, w);
951
			mat.SetRow(i, vRow);
952
		}
953
	
954
		return true;
955
	}
956

    
957
	// converts current hand data to a single csv line. returns empty string if there is no new data
958
	public static string GetHandsDataAsCsv(SensorData sensorData, ref BodyFrameData bodyFrame, ref long liRelTime, char delimiter)
959
	{
960
		// check for invalid sensor data and if the frame is still the same
961
		if(sensorData == null)
962
			return string.Empty;
963
//		if(bodyFrame.liRelativeTime == liRelTime)
964
//			return string.Empty;
965

    
966
		// create the output string
967
		StringBuilder sbBuf = new StringBuilder();
968
		//const char delimiter = ',';
969

    
970
		sbBuf.Append("kh").Append(delimiter);
971
		sbBuf.Append(bodyFrame.liRelativeTime).Append(delimiter);
972
		sbBuf.Append(sensorData.bodyCount).Append(delimiter);
973

    
974
		// add information for all bodies
975
		for(int i = 0; i < sensorData.bodyCount; i++)
976
		{
977
			sbBuf.Append(bodyFrame.bodyData[i].bIsTracked).Append(delimiter);
978

    
979
			if(bodyFrame.bodyData[i].bIsTracked != 0)
980
			{
981
				// add information for the tracked body - body-id and hand states
982
				sbBuf.Append(bodyFrame.bodyData[i].liTrackingID).Append(delimiter);
983

    
984
				sbBuf.AppendFormat("{0}", (int)bodyFrame.bodyData[i].leftHandState).Append(delimiter);
985
				sbBuf.AppendFormat("{0}", (int)bodyFrame.bodyData[i].leftHandConfidence).Append(delimiter);
986

    
987
				sbBuf.AppendFormat("{0}", (int)bodyFrame.bodyData[i].rightHandState).Append(delimiter);
988
				sbBuf.AppendFormat("{0}", (int)bodyFrame.bodyData[i].rightHandConfidence).Append(delimiter);
989
			}
990
		}
991

    
992
		// remove the last delimiter
993
		if(sbBuf.Length > 0 && sbBuf[sbBuf.Length - 1] == delimiter)
994
		{
995
			sbBuf.Remove(sbBuf.Length - 1, 1);
996
		}
997

    
998
		return sbBuf.ToString();
999
	}
1000

    
1001
	// sets current hand data from the given csv line. returns true on success, false otherwise
1002
	public static bool SetHandsDataFromCsv(string sCsvLine, SensorData sensorData, ref BodyFrameData bodyFrame)
1003
	{
1004
		// check for invalid sensor data and for same frame time
1005
		if(sensorData == null)
1006
			return false;
1007
		if(sCsvLine.Length == 0)
1008
			return false;
1009

    
1010
		// split the csv line in parts
1011
		char[] delimiters = { ',' };
1012
		string[] alCsvParts = sCsvLine.Split(delimiters);
1013

    
1014
		if(alCsvParts.Length < 3)
1015
			return false;
1016

    
1017
		// check the id & body count
1018
		int bodyCount = 0;
1019
		int.TryParse(alCsvParts[2], out bodyCount);
1020

    
1021
		long liRelTime = 0;
1022
		long.TryParse(alCsvParts[1], out liRelTime);
1023

    
1024
		if(alCsvParts[0] != "kh" || bodyCount == 0 || liRelTime == 0)
1025
			return false;
1026

    
1027
		// check rel time
1028
		if(bodyFrame.liRelativeTime > liRelTime)
1029
			return false;
1030

    
1031
		int iIndex = 3;
1032
		for(int i = 0; i < bodyCount; i++)
1033
		{
1034
			if(alCsvParts.Length < (iIndex + 1))
1035
				return false;
1036

    
1037
			// update the tracked-flag and body id
1038
			short bIsTracked = 0;
1039
			long liTrackingID = 0;
1040

    
1041
			short.TryParse(alCsvParts[iIndex], out bIsTracked);
1042
			iIndex++;
1043

    
1044
			if(bIsTracked != 0 && alCsvParts.Length >= (iIndex + 5))
1045
			{
1046
				long.TryParse(alCsvParts[iIndex], out liTrackingID);
1047
				iIndex++;
1048

    
1049
				int lhState = 0, lhConf = 0, rhState = 0, rhConf = 0;
1050

    
1051
				int.TryParse(alCsvParts[iIndex++], out lhState);
1052
				int.TryParse(alCsvParts[iIndex++], out lhConf);
1053

    
1054
				int.TryParse(alCsvParts[iIndex++], out rhState);
1055
				int.TryParse(alCsvParts[iIndex++], out rhConf);
1056

    
1057
				if(i < sensorData.bodyCount && bodyFrame.bodyData[i].bIsTracked != 0 && 
1058
					bodyFrame.bodyData[i].liTrackingID == liTrackingID)
1059
				{
1060
					bodyFrame.bodyData[i].leftHandState = (HandState)lhState;
1061
					bodyFrame.bodyData[i].leftHandConfidence = (TrackingConfidence)lhConf;
1062

    
1063
					bodyFrame.bodyData[i].rightHandState = (HandState)rhState;
1064
					bodyFrame.bodyData[i].rightHandConfidence = (TrackingConfidence)rhConf;
1065
				}
1066
			}
1067
		}
1068

    
1069
		return true;
1070
	}
1071

    
1072
	// converts current body frame to a single csv line. returns empty string if there is no new data
1073
	public static string GetBodyFrameAsCsv(SensorData sensorData, ref BodyFrameData bodyFrame, ref long liRelTime, ref float fUnityTime, char delimiter)
1074
	{
1075
		// check for invalid sensor data and if the frame is still the same
1076
		if(sensorData == null)
1077
			return string.Empty;
1078
		if(bodyFrame.liRelativeTime == liRelTime)
1079
			return string.Empty;
1080

    
1081
		// create the output string
1082
		StringBuilder sbBuf = new StringBuilder();
1083
		//const char delimiter = ',';
1084

    
1085
		sbBuf.Append("kb").Append(delimiter);
1086
		sbBuf.Append(bodyFrame.liRelativeTime).Append(delimiter);
1087

    
1088
		liRelTime = bodyFrame.liRelativeTime;
1089
		fUnityTime = Time.time;
1090

    
1091
		sbBuf.Append(sensorData.bodyCount).Append(delimiter);
1092
		sbBuf.Append(sensorData.jointCount).Append(delimiter);
1093

    
1094
		// add information for all bodies
1095
		for(int i = 0; i < sensorData.bodyCount; i++)
1096
		{
1097
			sbBuf.Append(bodyFrame.bodyData[i].bIsTracked).Append(delimiter);
1098

    
1099
			if(bodyFrame.bodyData[i].bIsTracked != 0)
1100
			{
1101
				// add information for the tracked body - body-id and joints
1102
				sbBuf.Append(bodyFrame.bodyData[i].liTrackingID).Append(delimiter);
1103

    
1104
				for(int j = 0; j < sensorData.jointCount; j++)
1105
				{
1106
					KinectInterop.JointData jointData = bodyFrame.bodyData[i].joint[j];
1107

    
1108
					sbBuf.Append((int)jointData.trackingState).Append(delimiter);
1109

    
1110
					if(jointData.trackingState != TrackingState.NotTracked)
1111
					{
1112
						sbBuf.AppendFormat("{0:F3}", jointData.kinectPos.x).Append(delimiter);
1113
						sbBuf.AppendFormat("{0:F3}", jointData.kinectPos.y).Append(delimiter);
1114
						sbBuf.AppendFormat("{0:F3}", jointData.kinectPos.z).Append(delimiter);
1115
					}
1116
				}
1117
			}
1118
		}
1119

    
1120
		// remove the last delimiter
1121
		if(sbBuf.Length > 0 && sbBuf[sbBuf.Length - 1] == delimiter)
1122
		{
1123
			sbBuf.Remove(sbBuf.Length - 1, 1);
1124
		}
1125

    
1126
		return sbBuf.ToString();
1127
	}
1128

    
1129
	// sets current body frame from the given csv line. returns true on success, false otherwise
1130
	public static bool SetBodyFrameFromCsv(string sCsvLine, SensorData sensorData, ref BodyFrameData bodyFrame, ref Matrix4x4 kinectToWorld)
1131
	{
1132
		// check for invalid sensor data and for same frame time
1133
		if(sensorData == null)
1134
			return false;
1135
		if(sCsvLine.Length == 0)
1136
			return false;
1137

    
1138
		// split the csv line in parts
1139
		char[] delimiters = { ',' };
1140
		string[] alCsvParts = sCsvLine.Split(delimiters);
1141

    
1142
		if(alCsvParts.Length < 4)
1143
			return false;
1144

    
1145
		//// wait for buffer release
1146
		//while(sensorData.bodyFrameReady)
1147
		//{
1148
		//	Sleep(1);
1149
		//}
1150

    
1151
		// check the id, body count & joint count
1152
		int bodyCount = 0, jointCount = 0;
1153
		int.TryParse(alCsvParts[2], out bodyCount);
1154
		int.TryParse(alCsvParts[3], out jointCount);
1155

    
1156
		long liRelTime = 0;
1157
		long.TryParse(alCsvParts[1], out liRelTime);
1158

    
1159
		if(alCsvParts[0] != "kb" || bodyCount == 0 || jointCount == 0 || liRelTime == 0)
1160
			return false;
1161
		//		if(bodyCount != sensorData.bodyCount || jointCount != sensorData.jointCount)
1162
		//			return false;
1163

    
1164
		if (bodyCount != sensorData.bodyCount) 
1165
		{
1166
			// set the other bodies as not tracked
1167
			for (int i = bodyCount; i < sensorData.bodyCount; i++) 
1168
			{
1169
				bodyFrame.bodyData[i].bIsTracked = 0;
1170
			}
1171
		}
1172

    
1173
		// update body frame data
1174
		bodyFrame.liPreviousTime = bodyFrame.liRelativeTime;
1175
		bodyFrame.liRelativeTime = liRelTime;
1176

    
1177
		int iIndex = 4;
1178
		for(int i = 0; i < bodyCount; i++)
1179
		{
1180
			if(alCsvParts.Length < (iIndex + 1))
1181
				return false;
1182

    
1183
			// update the tracked-flag and body id
1184
			short bIsTracked = 0;
1185
			long liTrackingID = 0;
1186

    
1187
			short.TryParse(alCsvParts[iIndex], out bIsTracked);
1188
			iIndex++;
1189

    
1190
			if(bIsTracked != 0 && alCsvParts.Length >= (iIndex + 1))
1191
			{
1192
				long.TryParse(alCsvParts[iIndex], out liTrackingID);
1193
				iIndex++;
1194

    
1195
				if(liTrackingID == 0)
1196
				{
1197
					bIsTracked = 0;
1198
				}
1199
			}
1200

    
1201
			bodyFrame.bodyData[i].bIsTracked = bIsTracked;
1202
			bodyFrame.bodyData[i].liTrackingID = liTrackingID;
1203

    
1204
			if(bIsTracked != 0)
1205
			{
1206
				if (jointCount != sensorData.jointCount) 
1207
				{
1208
					// set the other joints as not tracked
1209
					for (int j = jointCount; j < sensorData.jointCount; j++) 
1210
					{
1211
						bodyFrame.bodyData [i].joint [j].trackingState = TrackingState.NotTracked;
1212
					}
1213
				}
1214

    
1215
				// update joints' data
1216
				for(int j = 0; j < jointCount; j++)
1217
				{
1218
					KinectInterop.JointData jointData = bodyFrame.bodyData[i].joint[j];
1219
					int iTrackingState = 0;
1220

    
1221
					if(alCsvParts.Length >= (iIndex + 1))
1222
					{
1223
						int.TryParse(alCsvParts[iIndex], out iTrackingState);
1224
						iIndex++;
1225

    
1226
						jointData.trackingState = (KinectInterop.TrackingState)iTrackingState;
1227

    
1228
						if(iTrackingState != (int)TrackingState.NotTracked && alCsvParts.Length >= (iIndex + 3))
1229
						{
1230
							float x = 0f, y = 0f, z = 0f;
1231

    
1232
							float.TryParse(alCsvParts[iIndex], out x);
1233
							float.TryParse(alCsvParts[iIndex + 1], out y);
1234
							float.TryParse(alCsvParts[iIndex + 2], out z);
1235
							iIndex += 3;
1236

    
1237
							jointData.kinectPos = new Vector3(x, y, z);
1238
						}
1239
						else
1240
						{
1241
							jointData.kinectPos = Vector3.zero;
1242
						}
1243

    
1244
						jointData.position = kinectToWorld.MultiplyPoint3x4(jointData.kinectPos);
1245
						jointData.orientation = Quaternion.identity;
1246

    
1247
						if(j == 0)
1248
						{
1249
							// set body position
1250
							bodyFrame.bodyData[i].position = jointData.position;
1251
							bodyFrame.bodyData[i].orientation = jointData.orientation;
1252
						}
1253
					}
1254

    
1255
					bodyFrame.bodyData[i].joint[j] = jointData;
1256
				}
1257
			}
1258
		}
1259

    
1260
		// calculate bone directions
1261
		CalcBodyFrameBoneDirs(sensorData, ref bodyFrame);
1262

    
1263
		// frame is ready
1264
		lock(sensorData.bodyFrameLock)
1265
		{
1266
			sensorData.bodyFrameReady = true;
1267
		}
1268

    
1269
		return true;
1270
	}
1271

    
1272
	// Polls for new skeleton data
1273
	public static bool PollBodyFrame(SensorData sensorData, ref BodyFrameData bodyFrame, ref Matrix4x4 kinectToWorld, bool bIgnoreJointZ)
1274
	{
1275
		bool bNewFrame = false;
1276

    
1277
		if(sensorData.sensorInterface != null)
1278
		{
1279
			//// wait for buffer release
1280
			//while(sensorData.bodyFrameReady)
1281
			//{
1282
			//	Sleep(1);
1283
			//}
1284
			
1285
			bNewFrame = sensorData.sensorInterface.PollBodyFrame(sensorData, ref bodyFrame, ref kinectToWorld, bIgnoreJointZ);
1286

    
1287
			if(bNewFrame)
1288
			{
1289
				if(bodyFrame.bTurnAnalisys && bodyFrame.liPreviousTime > 0)
1290
				{
1291
					CalcBodyFrameJointVels(sensorData, ref bodyFrame);
1292
				}
1293

    
1294
				CalcBodyFrameBoneDirs(sensorData, ref bodyFrame);
1295
				
1296
				// frame is ready
1297
				lock(sensorData.bodyFrameLock)
1298
				{
1299
					sensorData.bodyFrameReady = true;
1300
				}
1301
			}
1302
		}
1303
		
1304
		return bNewFrame;
1305
	}
1306

    
1307
	// calculates joint velocities in a body frame
1308
	private static void CalcBodyFrameJointVels(SensorData sensorData, ref BodyFrameData bodyFrame)
1309
	{
1310
		// calculate the inter-frame time
1311
		float frameTime = (float)(bodyFrame.liRelativeTime - bodyFrame.liPreviousTime) / 100000000000f;
1312

    
1313
		for(int i = 0; i < sensorData.bodyCount; i++)
1314
		{
1315
			if(bodyFrame.bodyData[i].bIsTracked != 0)
1316
			{
1317
				for(int j = 0; j < sensorData.jointCount; j++)
1318
				{
1319
					KinectInterop.JointData jointData = bodyFrame.bodyData[i].joint[j];
1320

    
1321
					int p = (int)sensorData.sensorInterface.GetParentJoint((KinectInterop.JointType)j);
1322
					Vector3 parentPos = bodyFrame.bodyData[i].joint[p].position;
1323

    
1324
					jointData.posRel = jointData.position - parentPos;
1325
					jointData.posVel = frameTime > 0f ? (jointData.position - jointData.posPrev) / frameTime : Vector3.zero;
1326
					jointData.posPrev = jointData.position;
1327

    
1328
					bodyFrame.bodyData[i].joint[j] = jointData;
1329
				}
1330
			}
1331
		}
1332

    
1333
	}
1334

    
1335
	// Calculates all valid bone directions in a body frame
1336
	private static void CalcBodyFrameBoneDirs(SensorData sensorData, ref BodyFrameData bodyFrame)
1337
	{
1338
		for(int i = 0; i < sensorData.bodyCount; i++)
1339
		{
1340
			if(bodyFrame.bodyData[i].bIsTracked != 0)
1341
			{
1342
				for(int j = 0; j < sensorData.jointCount; j++)
1343
				{
1344
					if(j == 0)
1345
					{
1346
						bodyFrame.bodyData[i].joint[j].direction = Vector3.zero;
1347
					}
1348
					else
1349
					{
1350
						int jParent = (int)sensorData.sensorInterface.GetParentJoint((KinectInterop.JointType)j);
1351
						
1352
						if(bodyFrame.bodyData[i].joint[j].trackingState != TrackingState.NotTracked && 
1353
						   bodyFrame.bodyData[i].joint[jParent].trackingState != TrackingState.NotTracked)
1354
						{
1355
							bodyFrame.bodyData[i].joint[j].direction = 
1356
								bodyFrame.bodyData[i].joint[j].position - bodyFrame.bodyData[i].joint[jParent].position;
1357
						}
1358
					}
1359
				}
1360
			}
1361
		}
1362

    
1363
	}
1364
	
1365
	// Recalculates bone directions for the given body
1366
	public static void RecalcBoneDirs(SensorData sensorData, ref BodyData bodyData)
1367
	{
1368
		for(int j = 0; j < bodyData.joint.Length; j++)
1369
		{
1370
			if(j == 0)
1371
			{
1372
				bodyData.joint[j].direction = Vector3.zero;
1373
			}
1374
			else
1375
			{
1376
				int jParent = (int)sensorData.sensorInterface.GetParentJoint((KinectInterop.JointType)j);
1377
				
1378
				if(bodyData.joint[j].trackingState != TrackingState.NotTracked && 
1379
				   bodyData.joint[jParent].trackingState != TrackingState.NotTracked)
1380
				{
1381
					bodyData.joint[j].direction = bodyData.joint[j].position - bodyData.joint[jParent].position;
1382
				}
1383
			}
1384
		}
1385
	}
1386
	
1387
	// Polls for new color frame data
1388
	public static bool PollColorFrame(SensorData sensorData)
1389
	{
1390
		bool bNewFrame = false;
1391

    
1392
		if(sensorData.sensorInterface != null && !sensorData.isPlayModeEnabled)
1393
		{
1394
			//// wait for buffer release
1395
			//while(sensorData.colorImageBufferReady)
1396
			//{
1397
			//	Sleep(1);
1398
			//}
1399
			
1400
			bNewFrame = sensorData.sensorInterface.PollColorFrame(sensorData);
1401

    
1402
			if(bNewFrame)
1403
			{
1404
				// buffer is ready
1405
				lock(sensorData.colorImageBufferLock)
1406
				{
1407
					sensorData.colorImageBufferReady = true;
1408
				}
1409
			}
1410
		}
1411

    
1412
		return bNewFrame;
1413
	}
1414

    
1415
	// Renders color texture
1416
	public static void RenderColorTexture(SensorData sensorData)
1417
	{
1418
		if(sensorData.colorImageBufferReady && sensorData.colorImageTexture)
1419
		{
1420
			sensorData.colorImageTexture.LoadRawTextureData(sensorData.colorImage);
1421
			sensorData.colorImageTexture.Apply();
1422
		
1423
			// buffer is released
1424
			lock(sensorData.colorImageBufferLock)
1425
			{
1426
				sensorData.colorImageBufferReady = false;
1427
			}
1428
		}
1429
	}
1430
	
1431
	// Polls for new depth frame data
1432
	public static bool PollDepthFrame(SensorData sensorData, KinectManager.UserMapType userMapType,
1433
	                                  bool bLimitedUsers, ICollection<int> alTrackedIndexes)
1434
	{
1435
		bool bNewFrame = false;
1436

    
1437
		if(sensorData.sensorInterface != null && !sensorData.isPlayModeEnabled)
1438
		{
1439
			//// wait for buffer releases
1440
			//while(sensorData.bodyIndexBufferReady || sensorData.depthImageBufferReady)
1441
			//{
1442
			//	Sleep(1);
1443
			//}
1444
			
1445
			bNewFrame = sensorData.sensorInterface.PollDepthFrame(sensorData);
1446

    
1447
			if(bNewFrame)
1448
			{
1449
				if(userMapType != KinectManager.UserMapType.RawUserDepth && sensorData.bodyIndexBuffer != null)
1450
				{
1451
					byte btSelBI = sensorData.selectedBodyIndex;
1452
					int iBodyIndexLength = sensorData.bodyIndexImage.Length;
1453

    
1454
					// convert the body indices to string
1455
					string sTrackedIndices = string.Empty;
1456

    
1457
					if (bLimitedUsers) 
1458
					{
1459
						foreach(int bodyIndex in alTrackedIndexes)
1460
						{
1461
							sTrackedIndices += (char)(0x30 + bodyIndex);
1462
						}
1463

    
1464
						//Debug.Log ("Tracked indices: " + sTrackedIndices);
1465
					}
1466

    
1467
					// create body index texture
1468
					if(sensorData.bodyIndexBufferData == null)
1469
					{
1470
						sensorData.bodyIndexBufferData = new float[iBodyIndexLength];
1471
					}
1472

    
1473
					for (int i = 0; i < iBodyIndexLength; i++)
1474
					{
1475
						byte btBufBI = sensorData.bodyIndexImage[i];
1476

    
1477
						bool bUserTracked = btSelBI != 255 ? btSelBI == btBufBI : 
1478
								//(bLimitedUsers ? alTrackedIndexes.Contains((int)btBufBI) : btBufBI != 255);
1479
								(bLimitedUsers ? sTrackedIndices.IndexOf((char)(0x30 + btBufBI)) >= 0 : btBufBI != 255);
1480

    
1481
						if(bUserTracked)
1482
						{
1483
							sensorData.bodyIndexBufferData[i] = (float)btBufBI;
1484
						}
1485
						else
1486
						{
1487
							sensorData.bodyIndexBufferData[i] = 255f;
1488
						}
1489
					}
1490

    
1491
					// buffer is ready
1492
					lock(sensorData.bodyIndexBufferLock)
1493
					{
1494
						sensorData.bodyIndexBufferReady = true;
1495
					}
1496
				}
1497
				
1498
				if(sensorData.depthImageBuffer != null && sensorData.depthHistBuffer != null &&
1499
				   userMapType == KinectManager.UserMapType.UserTexture)
1500
				{
1501
					// create depth texture
1502
					if(sensorData.depthImageBufferData == null)
1503
					{
1504
						sensorData.depthImageBufferData = new float[sensorData.depthImage.Length];
1505
						sensorData.depthHistBufferData = new int[5001];
1506
						sensorData.equalHistBufferData = new float[sensorData.depthHistBufferData.Length];
1507
					}
1508

    
1509
					Array.Clear(sensorData.depthHistBufferData, 0, sensorData.depthHistBufferData.Length);
1510
					Array.Clear(sensorData.equalHistBufferData, 0, sensorData.equalHistBufferData.Length);
1511
					sensorData.depthHistTotalPoints = 0;
1512

    
1513
					for (int i = 0; i < sensorData.depthImage.Length; i++)
1514
					{
1515
						int depth = sensorData.depthImage[i] < 5000 ? (int)sensorData.depthImage[i] : 5000;
1516
						sensorData.depthImageBufferData[i] = (float)depth;
1517

    
1518
						if(sensorData.bodyIndexImage[i] != 255)
1519
						{
1520
							sensorData.depthHistBufferData[depth]++;
1521
							sensorData.depthHistTotalPoints++;
1522
						}
1523
					}
1524

    
1525
					sensorData.equalHistBufferData[0] = (float)sensorData.depthHistBufferData[0];
1526
					for(int i = 1; i < sensorData.depthHistBufferData.Length; i++)
1527
					{
1528
						sensorData.equalHistBufferData[i] = sensorData.equalHistBufferData[i - 1] + (float)sensorData.depthHistBufferData[i];
1529
					}
1530

    
1531
					// buffer is ready
1532
					lock(sensorData.depthImageBufferLock)
1533
					{
1534
						sensorData.depthImageBufferReady = true;
1535
					}
1536
				}
1537

    
1538
				if(sensorData.color2DepthCoords != null)
1539
				{
1540
					//// wait for buffer release
1541
					//while(sensorData.depthCoordsBufferReady)
1542
					//{
1543
					//	Sleep(1);
1544
					//}
1545
					
1546
					if(!MapColorFrameToDepthCoords(sensorData, ref sensorData.color2DepthCoords))
1547
					{
1548
						sensorData.color2DepthCoords = null;
1549
					}
1550

    
1551
					// buffer is ready
1552
					lock(sensorData.depthCoordsBufferLock)
1553
					{
1554
						sensorData.depthCoordsBufferReady = (sensorData.color2DepthCoords != null);
1555
					}
1556
				}
1557
				else if(sensorData.depth2ColorCoords != null && (userMapType == KinectManager.UserMapType.CutOutTexture || 
1558
					    (sensorData.sensorInterface.IsBackgroundRemovalActive() && 
1559
						 sensorData.sensorInterface.GetSensorPlatform() != KinectInterop.DepthSensorPlatform.KinectSDKv1)))
1560
				{
1561
					//// wait for buffer release
1562
					//while(sensorData.depthCoordsBufferReady)
1563
					//{
1564
					//	Sleep(1);
1565
					//}
1566
					
1567
					if(!MapDepthFrameToColorCoords(sensorData, ref sensorData.depth2ColorCoords))
1568
					{
1569
						sensorData.depth2ColorCoords = null;
1570
					}
1571
					
1572
					// buffer is ready
1573
					lock(sensorData.depthCoordsBufferLock)
1574
					{
1575
						sensorData.depthCoordsBufferReady = (sensorData.depth2ColorCoords != null);
1576
					}
1577
				}
1578

    
1579
				if(sensorData.depth2SpaceCoords != null)
1580
				{
1581
					//// wait for buffer release
1582
					//while(sensorData.spaceCoordsBufferReady)
1583
					//{
1584
					//	Sleep(1);
1585
					//}
1586
					
1587
					if(!MapDepthFrameToSpaceCoords(sensorData, ref sensorData.depth2SpaceCoords))
1588
					{
1589
						sensorData.depth2SpaceCoords = null;
1590
					}
1591
					
1592
					// buffer is ready
1593
					lock(sensorData.spaceCoordsBufferLock)
1594
					{
1595
						sensorData.spaceCoordsBufferReady = (sensorData.depth2SpaceCoords != null);
1596
					}
1597
				}
1598

    
1599
			}
1600
		}
1601
		
1602
		return bNewFrame;
1603
	}
1604

    
1605
	// Renders body-index texture
1606
	public static void RenderBodyIndexTexture(SensorData sensorData, KinectManager.UserMapType userMapType)
1607
	{
1608
		// check if buffer is ready
1609
		if(sensorData.bodyIndexBufferReady)
1610
		{
1611
			sensorData.bodyIndexBuffer.SetData(sensorData.bodyIndexBufferData);
1612
			Graphics.Blit(null, sensorData.bodyIndexTexture, sensorData.bodyIndexMaterial);
1613

    
1614
			if(userMapType != KinectManager.UserMapType.UserTexture || !sensorData.depthImageBufferReady)
1615
			{
1616
				// buffer is released
1617
				lock(sensorData.bodyIndexBufferLock)
1618
				{
1619
					sensorData.bodyIndexBufferReady = false;
1620
				}
1621
			}
1622
		}
1623
	}
1624

    
1625
	// Renders depth image texture
1626
	public static void RenderDepthImageTexture(SensorData sensorData)
1627
	{
1628
		if(sensorData.depthImageBufferReady)
1629
		{
1630
			sensorData.depthImageMaterial.SetFloat("_TotalPoints", (float)sensorData.depthHistTotalPoints);
1631
			sensorData.depthImageMaterial.SetInt("_FirstUserIndex", sensorData.firstUserIndex);
1632
			sensorData.depthImageBuffer.SetData(sensorData.depthImageBufferData);
1633
			sensorData.depthHistBuffer.SetData(sensorData.equalHistBufferData);
1634
			
1635
			Graphics.Blit(sensorData.bodyIndexTexture, sensorData.depthImageTexture, sensorData.depthImageMaterial);
1636
			
1637
			// release the buffers for the next poll
1638
			lock(sensorData.depthImageBufferLock)
1639
			{
1640
				sensorData.depthImageBufferReady = false;
1641
			}
1642

    
1643
			lock(sensorData.bodyIndexBufferLock)
1644
			{
1645
				sensorData.bodyIndexBufferReady = false;
1646
			}
1647
		}
1648
	}
1649

    
1650
	// renders depth2color texture
1651
	public static bool RenderDepth2ColorTex(SensorData sensorData)
1652
	{
1653
		if(sensorData.depth2ColorMaterial != null && sensorData.depth2ColorCoords != null && sensorData.depthCoordsBufferReady)
1654
		{
1655
			sensorData.depth2ColorBuffer.SetData(sensorData.depth2ColorCoords);
1656
			
1657
			sensorData.depth2ColorMaterial.SetTexture("_BodyTex", sensorData.bodyIndexTexture);
1658
			sensorData.depth2ColorMaterial.SetTexture("_ColorTex", sensorData.colorImageTexture);
1659
			
1660
			Graphics.Blit(null, sensorData.depth2ColorTexture, sensorData.depth2ColorMaterial);
1661
			
1662
			// buffer is released
1663
			lock(sensorData.depthCoordsBufferLock)
1664
			{
1665
				sensorData.depthCoordsBufferReady = false;
1666
			}
1667

    
1668
			return true;
1669
		}
1670

    
1671
		return false;
1672
	}
1673

    
1674
	// Polls for new infrared frame data
1675
	public static bool PollInfraredFrame(SensorData sensorData)
1676
	{
1677
		bool bNewFrame = false;
1678

    
1679
		if(sensorData.sensorInterface != null && !sensorData.isPlayModeEnabled)
1680
		{
1681
			bNewFrame = sensorData.sensorInterface.PollInfraredFrame(sensorData);
1682
		}
1683

    
1684
		return bNewFrame;
1685
	}
1686

    
1687
	// returns depth frame coordinates for the given 3d Kinect-space point
1688
	public static Vector2 MapSpacePointToDepthCoords(SensorData sensorData, Vector3 kinectPos)
1689
	{
1690
		Vector2 vPoint = Vector2.zero;
1691

    
1692
		if(sensorData.sensorInterface != null)
1693
		{
1694
			vPoint = sensorData.sensorInterface.MapSpacePointToDepthCoords(sensorData, kinectPos);
1695
		}
1696

    
1697
		return vPoint;
1698
	}
1699

    
1700
	// returns 3d coordinates for the given depth-map point
1701
	public static Vector3 MapDepthPointToSpaceCoords(SensorData sensorData, Vector2 depthPos, ushort depthVal)
1702
	{
1703
		Vector3 vPoint = Vector3.zero;
1704

    
1705
		if (sensorData.depth2SpaceCoords != null) 
1706
		{
1707
			int pIndex = (int)depthPos.y * sensorData.depthImageWidth + (int)depthPos.x;
1708
			if (pIndex >= 0 && pIndex < sensorData.depth2SpaceCoords.Length)
1709
				return sensorData.depth2SpaceCoords[pIndex];
1710
		}
1711

    
1712
		if(sensorData.sensorInterface != null)
1713
		{
1714
			vPoint = sensorData.sensorInterface.MapDepthPointToSpaceCoords(sensorData, depthPos, depthVal);
1715
		}
1716

    
1717
		return vPoint;
1718
	}
1719

    
1720
	// estimates space coordinates for the current depth frame
1721
	public static bool MapDepthFrameToSpaceCoords(SensorData sensorData, ref Vector3[] vSpaceCoords)
1722
	{
1723
		bool bResult = false;
1724
		
1725
		if(sensorData.sensorInterface != null)
1726
		{
1727
			bResult = sensorData.sensorInterface.MapDepthFrameToSpaceCoords(sensorData, ref vSpaceCoords);
1728
		}
1729
		
1730
		return bResult;
1731
	}
1732
	
1733
	// returns color-map coordinates for the given depth point
1734
	public static Vector2 MapDepthPointToColorCoords(SensorData sensorData, Vector2 depthPos, ushort depthVal)
1735
	{
1736
		Vector2 vPoint = Vector2.zero;
1737

    
1738
		if (sensorData.depth2ColorCoords != null) 
1739
		{
1740
			int pIndex = (int)depthPos.y * sensorData.depthImageWidth + (int)depthPos.x;
1741
			if (pIndex >= 0 && pIndex < sensorData.depth2ColorCoords.Length)
1742
				return sensorData.depth2ColorCoords[pIndex];
1743
		}
1744

    
1745
		if(sensorData.sensorInterface != null)
1746
		{
1747
			vPoint = sensorData.sensorInterface.MapDepthPointToColorCoords(sensorData, depthPos, depthVal);
1748
		}
1749

    
1750
		return vPoint;
1751
	}
1752

    
1753
	// estimates color-map coordinates for the current depth frame
1754
	public static bool MapDepthFrameToColorCoords(SensorData sensorData, ref Vector2[] vColorCoords)
1755
	{
1756
		bool bResult = false;
1757
		
1758
		if(sensorData.sensorInterface != null)
1759
		{
1760
			bResult = sensorData.sensorInterface.MapDepthFrameToColorCoords(sensorData, ref vColorCoords);
1761
		}
1762
		
1763
		return bResult;
1764
	}
1765
	
1766
	// estimates depth-map coordinates for the current color frame
1767
	public static bool MapColorFrameToDepthCoords(SensorData sensorData, ref Vector2[] vDepthCoords)
1768
	{
1769
		bool bResult = false;
1770
		
1771
		if(sensorData.sensorInterface != null)
1772
		{
1773
			bResult = sensorData.sensorInterface.MapColorFrameToDepthCoords(sensorData, ref vDepthCoords);
1774
		}
1775
		
1776
		return bResult;
1777
	}
1778

    
1779
	// estimates depth-map coordinates for the given color coords
1780
	public static Vector2 MapColorPointToDepthCoords(SensorData sensorData, Vector2 colorPos, bool bReadDepthCoordsIfNeeded)
1781
	{
1782
		Vector2 vPoint = Vector2.zero;
1783

    
1784
		if(sensorData.sensorInterface != null && !float.IsInfinity(colorPos.x) && !float.IsInfinity(colorPos.y))
1785
		{
1786
			int cIndex = (int)colorPos.y * sensorData.colorImageWidth + (int)colorPos.x;
1787

    
1788
			if(sensorData.color2DepthCoords != null)
1789
			{
1790
				if (cIndex >= 0 && cIndex < sensorData.color2DepthCoords.Length) 
1791
				{
1792
					vPoint = sensorData.color2DepthCoords[cIndex];
1793
				}
1794
			}
1795
			else if(bReadDepthCoordsIfNeeded)
1796
			{
1797
				Vector2[] vDepthCoords = new Vector2[sensorData.colorImageWidth * sensorData.colorImageHeight];
1798

    
1799
				if(MapColorFrameToDepthCoords(sensorData, ref vDepthCoords))
1800
				{
1801
					if (cIndex >= 0 && cIndex < vDepthCoords.Length) 
1802
					{
1803
						vPoint = vDepthCoords[cIndex];
1804
					}
1805
				}
1806

    
1807
				vDepthCoords = null;
1808
			}
1809
		}
1810
		
1811
		return vPoint;
1812
	}
1813

    
1814
	// draws a rectangle on texture-2d
1815
	public static void DrawRect(Texture2D a_Texture, Rect a_rect, Color a_Color)
1816
	{
1817
		Vector2 pt1, pt2;
1818

    
1819
		// bottom
1820
		pt1.x = a_rect.x; pt1.y = a_rect.y;
1821
		pt2.x = a_rect.x + a_rect.width - 1; pt2.y = pt1.y;
1822
		DrawLine(a_Texture, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y, a_Color);
1823

    
1824
		// right
1825
		pt1.x = pt2.x; pt1.y = pt2.y;
1826
		pt2.x = pt1.x; pt2.y = a_rect.y + a_rect.height - 1;
1827
		DrawLine(a_Texture, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y, a_Color);
1828

    
1829
		// top
1830
		pt1.x = pt2.x; pt1.y = pt2.y;
1831
		pt2.x = a_rect.x; pt2.y = pt1.y;
1832
		DrawLine(a_Texture, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y, a_Color);
1833

    
1834
		// left
1835
		pt1.x = pt2.x; pt1.y = pt2.y;
1836
		pt2.x = pt1.x; pt2.y = a_rect.y;
1837
		DrawLine(a_Texture, (int)pt1.x, (int)pt1.y, (int)pt2.x, (int)pt2.y, a_Color);
1838
	}
1839

    
1840
	// draws a line on texture-2d
1841
	public static void DrawLine(Texture2D a_Texture, int x1, int y1, int x2, int y2, Color a_Color)
1842
	{
1843
		int width = a_Texture.width;
1844
		int height = a_Texture.height;
1845
		
1846
		int dy = y2 - y1;
1847
		int dx = x2 - x1;
1848
		
1849
		int stepy = 1;
1850
		if (dy < 0) 
1851
		{
1852
			dy = -dy; 
1853
			stepy = -1;
1854
		}
1855
		
1856
		int stepx = 1;
1857
		if (dx < 0) 
1858
		{
1859
			dx = -dx; 
1860
			stepx = -1;
1861
		}
1862
		
1863
		dy <<= 1;
1864
		dx <<= 1;
1865
		
1866
		if(x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
1867
			for(int x = -1; x <= 1; x++)
1868
				for(int y = -1; y <= 1; y++)
1869
					a_Texture.SetPixel(x1 + x, y1 + y, a_Color);
1870
		
1871
		if (dx > dy) 
1872
		{
1873
			int fraction = dy - (dx >> 1);
1874
			
1875
			while (x1 != x2) 
1876
			{
1877
				if (fraction >= 0) 
1878
				{
1879
					y1 += stepy;
1880
					fraction -= dx;
1881
				}
1882
				
1883
				x1 += stepx;
1884
				fraction += dy;
1885
				
1886
				if(x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
1887
					for(int x = -1; x <= 1; x++)
1888
						for(int y = -1; y <= 1; y++)
1889
							a_Texture.SetPixel(x1 + x, y1 + y, a_Color);
1890
			}
1891
		}
1892
		else 
1893
		{
1894
			int fraction = dx - (dy >> 1);
1895
			
1896
			while (y1 != y2) 
1897
			{
1898
				if (fraction >= 0) 
1899
				{
1900
					x1 += stepx;
1901
					fraction -= dy;
1902
				}
1903
				
1904
				y1 += stepy;
1905
				fraction += dx;
1906
				
1907
				if(x1 >= 0 && x1 < width && y1 >= 0 && y1 < height)
1908
					for(int x = -1; x <= 1; x++)
1909
						for(int y = -1; y <= 1; y++)
1910
							a_Texture.SetPixel(x1 + x, y1 + y, a_Color);
1911
			}
1912
		}
1913
		
1914
	}
1915

    
1916
	// copy source file to the target
1917
	public static bool CopyFile(string sourceFilePath, string targetFilePath, ref bool bOneCopied, ref bool bAllCopied)
1918
	{
1919
#if !UNITY_WSA
1920
		FileInfo sourceFile = new FileInfo(sourceFilePath);
1921
		if(!sourceFile.Exists)
1922
		{
1923
			return false;
1924
		}
1925

    
1926
		FileInfo targetFile = new FileInfo(targetFilePath);
1927
		if(!targetFile.Directory.Exists)
1928
		{
1929
			targetFile.Directory.Create();
1930
		}
1931
		
1932
		if(!targetFile.Exists || targetFile.Length !=  sourceFile.Length)
1933
		{
1934
			Debug.Log("Copying " + sourceFile.Name + "...");
1935
			File.Copy(sourceFilePath, targetFilePath);
1936
			
1937
			bool bFileCopied = File.Exists(targetFilePath);
1938
			
1939
			bOneCopied = bOneCopied || bFileCopied;
1940
			bAllCopied = bAllCopied && bFileCopied;
1941
			
1942
			return bFileCopied;
1943
		}
1944
#endif
1945

    
1946
		return false;
1947
	}
1948
	
1949
	// Copy a resource file to the target
1950
	public static bool CopyResourceFile(string targetFilePath, string resFileName, ref bool bOneCopied, ref bool bAllCopied)
1951
	{
1952
#if !UNITY_WSA
1953
		TextAsset textRes = Resources.Load(resFileName, typeof(TextAsset)) as TextAsset;
1954
		if(textRes == null)
1955
		{
1956
			bOneCopied = false;
1957
			bAllCopied = false;
1958
			
1959
			return false;
1960
		}
1961
		
1962
		FileInfo targetFile = new FileInfo(targetFilePath);
1963
		if(!targetFile.Directory.Exists)
1964
		{
1965
			targetFile.Directory.Create();
1966
		}
1967
		
1968
		if(!targetFile.Exists || targetFile.Length !=  textRes.bytes.Length)
1969
		{
1970
			Debug.Log("Copying " + resFileName + "...");
1971

    
1972
			if(textRes != null)
1973
			{
1974
				using (FileStream fileStream = new FileStream (targetFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
1975
				{
1976
					fileStream.Write(textRes.bytes, 0, textRes.bytes.Length);
1977
				}
1978
				
1979
				bool bFileCopied = File.Exists(targetFilePath);
1980
				
1981
				bOneCopied = bOneCopied || bFileCopied;
1982
				bAllCopied = bAllCopied && bFileCopied;
1983
				
1984
				return bFileCopied;
1985
			}
1986
		}
1987
#endif
1988

    
1989
		return false;
1990
	}
1991

    
1992
	// Unzips resource file to the target path
1993
	public static bool UnzipResourceDirectory(string targetDirPath, string resZipFileName, string checkForDir)
1994
	{
1995
#if !UNITY_WSA
1996
		if(checkForDir != string.Empty && Directory.Exists(checkForDir))
1997
		{
1998
			return false;
1999
		}
2000

    
2001
		TextAsset textRes = Resources.Load(resZipFileName, typeof(TextAsset)) as TextAsset;
2002
		if(textRes == null || textRes.bytes.Length == 0)
2003
		{
2004
			return false;
2005
		}
2006

    
2007
		Debug.Log("Unzipping " + resZipFileName + "...");
2008

    
2009
		// get the resource steam
2010
		MemoryStream memStream = new MemoryStream(textRes.bytes);
2011

    
2012
		// fix invalid code page 437 error
2013
		ZipConstants.DefaultCodePage = 0;
2014

    
2015
		using(ZipInputStream s = new ZipInputStream(memStream))
2016
		{
2017
			ZipEntry theEntry;
2018
			while ((theEntry = s.GetNextEntry()) != null) 
2019
			{
2020
				//Debug.Log(theEntry.Name);
2021
				
2022
				string directoryName = targetDirPath + Path.GetDirectoryName(theEntry.Name);
2023
				string fileName = Path.GetFileName(theEntry.Name);
2024

    
2025
				if(!Directory.Exists(directoryName))
2026
				{
2027
					// create directory
2028
					Directory.CreateDirectory(directoryName);
2029
				}
2030

    
2031
				if (fileName != string.Empty && !fileName.EndsWith(".meta")) 
2032
				{
2033
					string targetFilePath = directoryName + "/" + fileName;
2034

    
2035
					using (FileStream streamWriter = File.Create(targetFilePath)) 
2036
					{
2037
						int size = 2048;
2038
						byte[] data = new byte[2048];
2039
						
2040
						while (true) 
2041
						{
2042
							size = s.Read(data, 0, data.Length);
2043
							
2044
							if (size > 0) 
2045
							{
2046
								streamWriter.Write(data, 0, size);
2047
							} 
2048
							else 
2049
							{
2050
								break;
2051
							}
2052
						}
2053
					}
2054
				}
2055
			}
2056
		}
2057

    
2058
		// close the resource stream
2059
		//memStream.Close();
2060
		memStream.Dispose();
2061

    
2062
		return true;
2063
#else
2064
		return false;
2065
#endif	
2066
	}
2067

    
2068
	// Unzips resource file to the target path
2069
	public static bool UnzipResourceFiles(Dictionary<string, string> dictFilesToUnzip, string resZipFileName, 
2070
	                                      ref bool bOneCopied, ref bool bAllCopied)
2071
	{
2072
#if !UNITY_WSA		
2073
		TextAsset textRes = Resources.Load(resZipFileName, typeof(TextAsset)) as TextAsset;
2074
		if(textRes == null || textRes.bytes.Length == 0)
2075
		{
2076
			bOneCopied = false;
2077
			bAllCopied = false;
2078

    
2079
			return false;
2080
		}
2081
		
2082
		//Debug.Log("Unzipping " + resZipFileName + "...");
2083
		
2084
		// get the resource steam
2085
		MemoryStream memStream = new MemoryStream(textRes.bytes);
2086
		
2087
		// fix invalid code page 437 error
2088
		ZipConstants.DefaultCodePage = 0;
2089
		
2090
		using(ZipInputStream s = new ZipInputStream(memStream))
2091
		{
2092
			ZipEntry theEntry;
2093
			while ((theEntry = s.GetNextEntry()) != null) 
2094
			{
2095
				//Debug.Log(theEntry.Name);
2096

    
2097
				if(dictFilesToUnzip.ContainsKey(theEntry.Name))
2098
			   	{
2099
					string targetFilePath = dictFilesToUnzip[theEntry.Name];
2100

    
2101
					string directoryName = Path.GetDirectoryName(targetFilePath);
2102
					string fileName = Path.GetFileName(theEntry.Name);
2103
					
2104
					if(!Directory.Exists(directoryName))
2105
					{
2106
						// create directory
2107
						Directory.CreateDirectory(directoryName);
2108
					}
2109

    
2110
					FileInfo targetFile = new FileInfo(targetFilePath);
2111
					bool bTargetFileNewOrUpdated = !targetFile.Exists || targetFile.Length !=  theEntry.Size;
2112
					
2113
					if (fileName != string.Empty && bTargetFileNewOrUpdated) 
2114
					{
2115
						using (FileStream streamWriter = File.Create(targetFilePath)) 
2116
						{
2117
							int size = 2048;
2118
							byte[] data = new byte[2048];
2119
							
2120
							while (true) 
2121
							{
2122
								size = s.Read(data, 0, data.Length);
2123
								
2124
								if (size > 0) 
2125
								{
2126
									streamWriter.Write(data, 0, size);
2127
								} 
2128
								else 
2129
								{
2130
									break;
2131
								}
2132
							}
2133
						}
2134
						
2135
						bool bFileCopied = File.Exists(targetFilePath);
2136
						
2137
						bOneCopied = bOneCopied || bFileCopied;
2138
						bAllCopied = bAllCopied && bFileCopied;
2139
					}
2140
				}
2141

    
2142
			}
2143
		}
2144
		
2145
		// close the resource stream
2146
		//memStream.Close();
2147
		memStream.Dispose();
2148
		
2149
		return true;
2150
#else
2151
		return false;
2152
#endif
2153
	}
2154
	
2155
	// returns the unzipped file size in bytes, or -1 if the entry is not found in the zip
2156
	public static long GetUnzippedEntrySize(string resZipFileName, string sEntryName)
2157
	{
2158
#if !UNITY_WSA
2159
		TextAsset textRes = Resources.Load(resZipFileName, typeof(TextAsset)) as TextAsset;
2160
		if(textRes == null || textRes.bytes.Length == 0)
2161
		{
2162
			return -1;
2163
		}
2164
		
2165
		// get the resource steam
2166
		MemoryStream memStream = new MemoryStream(textRes.bytes);
2167
		
2168
		// fix invalid code page 437 error
2169
		ZipConstants.DefaultCodePage = 0;
2170
		long entryFileSize = -1;
2171
		
2172
		using(ZipInputStream s = new ZipInputStream(memStream))
2173
		{
2174
			ZipEntry theEntry;
2175
			while ((theEntry = s.GetNextEntry()) != null) 
2176
			{
2177
				if(theEntry.Name == sEntryName)
2178
				{
2179
					entryFileSize = theEntry.Size;
2180
					break;
2181
				}
2182
				
2183
			}
2184
		}
2185
		
2186
		// close the resource stream
2187
		//memStream.Close();
2188
		memStream.Dispose();
2189
		
2190
		return entryFileSize;
2191
#else
2192
		return -1;
2193
#endif
2194
	}
2195
	
2196
	// returns true if the project is running on 64-bit architecture, false if 32-bit
2197
	public static bool Is64bitArchitecture()
2198
	{
2199
		int sizeOfPtr = Marshal.SizeOf(typeof(IntPtr));
2200
		return (sizeOfPtr > 4);
2201
	}
2202

    
2203
	// returns the target dll path for the current platform (x86 or x64)
2204
	public static string GetTargetDllPath(string sAppPath, bool bIs64bitApp)
2205
	{
2206
		string sTargetPath = sAppPath;
2207
//		string sPluginsPath = Application.dataPath + "/Plugins";
2208
//		
2209
//		if(Directory.Exists(sPluginsPath))
2210
//		{
2211
//			sTargetPath = sPluginsPath;
2212
//			
2213
//			//if(Application.isEditor)
2214
//			{
2215
//				string sPlatformPath = sPluginsPath + "/" + (!bIs64bitApp ? "x86" : "x86_64");
2216
//				
2217
//				if(Directory.Exists(sPlatformPath))
2218
//				{
2219
//					sTargetPath = sPlatformPath;
2220
//				}
2221
//			}
2222
//		}
2223
		
2224
		return sTargetPath;
2225
	}
2226

    
2227
	// cleans up objects and restarts the current level
2228
	public static void RestartLevel(GameObject parentObject, string callerName)
2229
	{
2230
		Debug.Log(callerName + " is restarting level...");
2231

    
2232
		// destroy parent object if any
2233
		if(parentObject)
2234
		{
2235
			GameObject.Destroy(parentObject);
2236
		}
2237

    
2238
		// clean up memory assets
2239
		Resources.UnloadUnusedAssets();
2240
		GC.Collect();
2241

    
2242
		//if(Application.HasProLicense() && Application.isEditor)
2243
		{
2244
#if UNITY_EDITOR
2245
			// refresh the assets database
2246
			UnityEditor.AssetDatabase.Refresh();
2247
#endif
2248
		}
2249
		
2250
		// reload the same level
2251
		SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
2252
		//SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
2253
	}
2254

    
2255
	// sets the graphics shader level
2256
	public static void SetGraphicsShaderLevel(int shaderLevel)
2257
	{
2258
		graphicsShaderLevel = shaderLevel;
2259
	}
2260

    
2261
	// checks if DirectX11/Direct3D-11 is turned on or not
2262
	public static bool IsDirectX11Available()
2263
	{
2264
		return (graphicsShaderLevel >= 50);
2265
	}
2266

    
2267
	// copies open-cv dlls to the root folder, if needed
2268
	public static bool IsOpenCvAvailable(ref bool bNeedRestart)
2269
	{
2270
		bNeedRestart = false;
2271

    
2272
		if(IsDirectX11Available())
2273
		{
2274
			// use shaders
2275
			return true;
2276
		}
2277

    
2278
//		bool bOneCopied = false, bAllCopied = true;
2279
//		string sTargetPath = GetTargetDllPath(".", Is64bitArchitecture()) + "/";
2280
//		//string sTargetPath = ".";
2281
//		
2282
//		if(!Is64bitArchitecture())
2283
//		{
2284
//			// 32 bit architecture
2285
//			sTargetPath = GetTargetDllPath(".", false) + "/";
2286
//			
2287
//			Dictionary<string, string> dictFilesToUnzip = new Dictionary<string, string>();
2288
//			dictFilesToUnzip["opencv_core2410.dll"] = sTargetPath + "opencv_core2410.dll";
2289
//			dictFilesToUnzip["opencv_imgproc2410.dll"] = sTargetPath + "opencv_imgproc2410.dll";
2290
//			dictFilesToUnzip["msvcp120.dll"] = sTargetPath + "msvcp120.dll";
2291
//			dictFilesToUnzip["msvcr120.dll"] = sTargetPath + "msvcr120.dll";
2292
//			
2293
//			UnzipResourceFiles(dictFilesToUnzip, "opencv.x86.zip", ref bOneCopied, ref bAllCopied);
2294
//		}
2295
//		else
2296
//		{
2297
//			// 64 bit architecture
2298
//			sTargetPath = GetTargetDllPath(".", true) + "/";
2299
//			
2300
//			Dictionary<string, string> dictFilesToUnzip = new Dictionary<string, string>();
2301
//			dictFilesToUnzip["opencv_core2410.dll"] = sTargetPath + "opencv_core2410.dll";
2302
//			dictFilesToUnzip["opencv_imgproc2410.dll"] = sTargetPath + "opencv_imgproc2410.dll";
2303
//			dictFilesToUnzip["msvcp120.dll"] = sTargetPath + "msvcp120.dll";
2304
//			dictFilesToUnzip["msvcr120.dll"] = sTargetPath + "msvcr120.dll";
2305
//			
2306
//			UnzipResourceFiles(dictFilesToUnzip, "opencv.x64.zip", ref bOneCopied, ref bAllCopied);
2307
//		}
2308
//
2309
//		bNeedRestart = (bOneCopied && bAllCopied);
2310
		
2311
		return true;
2312
	}
2313

    
2314
	// initializes background removal with shaders
2315
	public static bool InitBackgroundRemoval(SensorData sensorData, bool isHiResPrefered)
2316
	{
2317
		if(sensorData != null && sensorData.bodyIndexImage != null && sensorData.colorImage != null
2318
		   && IsDirectX11Available())
2319
		{
2320
			Shader erodeBodyShader = Shader.Find("Custom/Erode");
2321
			sensorData.erodeBodyMaterial = new Material(erodeBodyShader);
2322
			sensorData.erodeBodyMaterial.SetFloat("_TexResX", (float)sensorData.depthImageWidth);
2323
			sensorData.erodeBodyMaterial.SetFloat("_TexResY", (float)sensorData.depthImageHeight);
2324
			//sensorData.erodeBodyMaterial.SetTexture("_MainTex", sensorData.bodyIndexTexture);
2325
			
2326
			Shader dilateBodyShader = Shader.Find("Custom/Dilate");
2327
			sensorData.dilateBodyMaterial = new Material(dilateBodyShader);
2328
			sensorData.dilateBodyMaterial.SetFloat("_TexResX", (float)sensorData.depthImageWidth);
2329
			sensorData.dilateBodyMaterial.SetFloat("_TexResY", (float)sensorData.depthImageHeight);
2330
			//sensorData.dilateBodyMaterial.SetTexture("_MainTex", sensorData.bodyIndexTexture);
2331

    
2332
			Shader blurBodyShader = Shader.Find("Custom/BlurShader5");
2333
			sensorData.blurBodyMaterial = new Material(blurBodyShader);
2334
			//sensorData.blurBodyMaterial.SetFloat("_Amount", 1.5f);
2335
			//sensorData.blurBodyMaterial.SetFloat("_BlurSizeXY", 2f);
2336

    
2337
			if(isHiResPrefered)
2338
			{
2339
                if (sensorData.alphaBodyTexture == null || sensorData.alphaBodyTexture.width != sensorData.colorImageWidth || sensorData.alphaBodyTexture.height != sensorData.colorImageHeight)
2340
                {
2341
                    sensorData.alphaBodyTexture = new RenderTexture(sensorData.colorImageWidth, sensorData.colorImageHeight, 0);
2342
                    sensorData.alphaBodyTexture.wrapMode = TextureWrapMode.Clamp;
2343
                    sensorData.alphaBodyTexture.filterMode = FilterMode.Point;
2344
                }
2345

    
2346
                Shader alphaBodyShader = Shader.Find("Kinect/Color2BodyShader");
2347
				if(alphaBodyShader)
2348
				{
2349
					sensorData.alphaBodyMaterial = new Material(alphaBodyShader);
2350
					
2351
					sensorData.alphaBodyMaterial.SetFloat("_ColorResX", (float)sensorData.colorImageWidth);
2352
					sensorData.alphaBodyMaterial.SetFloat("_ColorResY", (float)sensorData.colorImageHeight);
2353
					sensorData.alphaBodyMaterial.SetFloat("_DepthResX", (float)sensorData.depthImageWidth);
2354
					sensorData.alphaBodyMaterial.SetFloat("_DepthResY", (float)sensorData.depthImageHeight);
2355
					
2356
					sensorData.color2DepthBuffer = new ComputeBuffer(sensorData.colorImageWidth * sensorData.colorImageHeight, sizeof(float) * 2);
2357
					sensorData.alphaBodyMaterial.SetBuffer("_DepthCoords", sensorData.color2DepthBuffer);
2358
				}
2359

    
2360
				Shader color2DepthShader = !sensorData.invertAlphaColorMask ? Shader.Find("Kinect/Color2DepthShader") : Shader.Find("Kinect/Color2DepthShaderInv");
2361
				if(color2DepthShader)
2362
				{
2363
                    if (sensorData.color2DepthTexture == null || sensorData.color2DepthTexture.width != sensorData.colorImageWidth || sensorData.color2DepthTexture.height != sensorData.colorImageHeight)
2364
                    {
2365
                        sensorData.color2DepthTexture = new RenderTexture(sensorData.colorImageWidth, sensorData.colorImageHeight, 0);
2366
                        sensorData.color2DepthTexture.wrapMode = TextureWrapMode.Clamp;
2367
                        sensorData.color2DepthTexture.filterMode = FilterMode.Point;
2368
                    }
2369

    
2370
                    sensorData.color2DepthMaterial = new Material(color2DepthShader);
2371
					
2372
//					sensorData.color2DepthMaterial.SetFloat("_ColorResX", (float)sensorData.colorImageWidth);
2373
//					sensorData.color2DepthMaterial.SetFloat("_ColorResY", (float)sensorData.colorImageHeight);
2374
//					sensorData.color2DepthMaterial.SetFloat("_DepthResX", (float)sensorData.depthImageWidth);
2375
//					sensorData.color2DepthMaterial.SetFloat("_DepthResY", (float)sensorData.depthImageHeight);
2376
//					
2377
//					sensorData.color2DepthBuffer = new ComputeBuffer(sensorData.colorImageWidth * sensorData.colorImageHeight, sizeof(float) * 2);
2378
//					sensorData.color2DepthMaterial.SetBuffer("_DepthCoords", sensorData.color2DepthBuffer);
2379
				}
2380
			}
2381
			else
2382
			{
2383
				sensorData.alphaBodyTexture = new RenderTexture(sensorData.depthImageWidth, sensorData.depthImageHeight, 0);
2384
				sensorData.alphaBodyTexture.wrapMode = TextureWrapMode.Clamp;
2385
				//sensorData.alphaBodyTexture.filterMode = FilterMode.Point;
2386
			}
2387
		}
2388

    
2389
		if(isHiResPrefered && sensorData != null && sensorData.bodyIndexImage != null && sensorData.colorImage != null)
2390
		{
2391
			sensorData.color2DepthCoords = new Vector2[sensorData.colorImageWidth * sensorData.colorImageHeight];
2392
		}
2393

    
2394
        sensorData.backgroundRemovalInited = true;
2395
        sensorData.backgroundRemovalHiRes = isHiResPrefered;
2396

    
2397
		return true;
2398
	}
2399

    
2400
	// releases background removal shader resources
2401
	public static void FinishBackgroundRemoval(SensorData sensorData)
2402
	{
2403
		if(sensorData == null)
2404
			return;
2405

    
2406
		if(sensorData.alphaBodyTexture != null)
2407
		{
2408
			sensorData.alphaBodyTexture.Release();
2409
			sensorData.alphaBodyTexture = null;
2410
		}
2411
		
2412
		sensorData.erodeBodyMaterial = null;
2413
		sensorData.dilateBodyMaterial = null;
2414
		sensorData.blurBodyMaterial = null;
2415

    
2416
		if(sensorData.color2DepthBuffer != null)
2417
		{
2418
			sensorData.color2DepthBuffer.Release();
2419
			sensorData.color2DepthBuffer = null;
2420
		}
2421

    
2422
		if(sensorData.color2DepthTexture != null)
2423
		{
2424
			sensorData.color2DepthTexture.Release();
2425
			sensorData.color2DepthTexture = null;
2426
		}
2427

    
2428
		sensorData.alphaBodyMaterial = null;
2429
		sensorData.color2DepthMaterial = null;
2430
		sensorData.color2DepthCoords = null;
2431

    
2432
        sensorData.backgroundRemovalInited = false;
2433
    }
2434

    
2435
	// computes current background removal texture
2436
	public static bool UpdateBackgroundRemoval(SensorData sensorData, bool isHiResPrefered, Color32 defaultColor, bool bAlphaTexOnly)
2437
	{
2438
		if(sensorData.color2DepthMaterial != null && sensorData.color2DepthCoords != null && sensorData.depthCoordsBufferReady)
2439
		{
2440
			if(sensorData.alphaBodyMaterial != null && sensorData.alphaBodyTexture)
2441
			{
2442
				sensorData.color2DepthBuffer.SetData(sensorData.color2DepthCoords);
2443
				
2444
				sensorData.alphaBodyMaterial.SetTexture("_BodyTex", sensorData.bodyIndexTexture);
2445
				Graphics.Blit(null, sensorData.alphaBodyTexture, sensorData.alphaBodyMaterial);
2446
				
2447
				if(sensorData.erodeBodyMaterial != null && sensorData.dilateBodyMaterial != null && sensorData.blurBodyMaterial)
2448
				{
2449
					ApplyErodeDilate(sensorData.alphaBodyTexture, sensorData.alphaBodyTexture, sensorData.erodeBodyMaterial, 
2450
 					                 sensorData.dilateBodyMaterial, sensorData.erodeIterations, sensorData.dilateIterations);
2451
					ApplyImageBlur(sensorData.alphaBodyTexture, sensorData.alphaBodyTexture, sensorData.blurBodyMaterial, 1, 0.6f);
2452
				}
2453
			}
2454

    
2455
			// blit the hi-res texture
2456
			if(!bAlphaTexOnly)
2457
			{
2458
				//sensorData.color2DepthBuffer.SetData(sensorData.color2DepthCoords);
2459
				
2460
				sensorData.color2DepthMaterial.SetTexture("_BodyTex", sensorData.alphaBodyTexture);
2461
				sensorData.color2DepthMaterial.SetTexture("_ColorTex", sensorData.colorImageTexture);
2462
				//sensorData.color2DepthMaterial.SetColor("_DefaultClr", defaultColor);
2463
				
2464
				Graphics.Blit(null, sensorData.color2DepthTexture, sensorData.color2DepthMaterial);
2465
			}
2466

    
2467
			// buffer is released
2468
			lock(sensorData.depthCoordsBufferLock)
2469
			{
2470
				sensorData.depthCoordsBufferReady = false;
2471
			}
2472
		}
2473
		else if(sensorData.depth2ColorMaterial != null && sensorData.depth2ColorCoords != null && sensorData.depthCoordsBufferReady)
2474
		{
2475
			if(sensorData.erodeBodyMaterial != null && sensorData.dilateBodyMaterial != null && sensorData.blurBodyMaterial)
2476
			{
2477
				ApplyErodeDilate(sensorData.bodyIndexTexture, sensorData.alphaBodyTexture, sensorData.erodeBodyMaterial, 
2478
				                 sensorData.dilateBodyMaterial, sensorData.erodeIterations, sensorData.dilateIterations);
2479
				ApplyImageBlur(sensorData.alphaBodyTexture, sensorData.alphaBodyTexture, sensorData.blurBodyMaterial, 0, 0.6f);
2480
			}
2481

    
2482
			// blit the lo-res texture
2483
			if(!bAlphaTexOnly)
2484
			{
2485
				sensorData.depth2ColorBuffer.SetData(sensorData.depth2ColorCoords);
2486
				
2487
				sensorData.depth2ColorMaterial.SetTexture("_BodyTex", sensorData.alphaBodyTexture);
2488
				sensorData.depth2ColorMaterial.SetTexture("_ColorTex", sensorData.colorImageTexture);
2489
				//sensorData.depth2ColorMaterial.SetColor("_DefaultClr", defaultColor);
2490
				
2491
				Graphics.Blit(null, sensorData.depth2ColorTexture, sensorData.depth2ColorMaterial);
2492
			}
2493

    
2494
			// buffer is released
2495
			lock(sensorData.depthCoordsBufferLock)
2496
			{
2497
				sensorData.depthCoordsBufferReady = false;
2498
			}
2499
		}
2500
		
2501
		return true;
2502
	}
2503

    
2504
	private static void ApplyErodeDilate(RenderTexture source, RenderTexture destination, Material erodeMaterial, 
2505
	                                     Material dilateMaterial, int erodeIterations, int dilateIterations)
2506
	{
2507
		if(!source || !destination || !erodeMaterial || !dilateMaterial)
2508
			return;
2509

    
2510
		RenderTexture[] tempTexture = new RenderTexture[2];
2511
		tempTexture[0] = RenderTexture.GetTemporary(source.width, source.height, 0);
2512
		tempTexture[1] = RenderTexture.GetTemporary(source.width, source.height, 0);
2513

    
2514
		Graphics.Blit(source, tempTexture[0]);
2515

    
2516
		for(int i = 0; i < erodeIterations; i++)
2517
		{
2518
			Graphics.Blit(tempTexture[i % 2], tempTexture[(i + 1) % 2], erodeMaterial);
2519
		}
2520

    
2521
		if((erodeIterations % 2) != 0)
2522
		{
2523
			Graphics.Blit(tempTexture[1], tempTexture[0]);
2524
		}
2525
		
2526
		for(int i = 0; i < dilateIterations; i++)
2527
		{
2528
			Graphics.Blit(tempTexture[i % 2], tempTexture[(i + 1) % 2], dilateMaterial);
2529
		}
2530

    
2531
		Graphics.Blit(tempTexture[dilateIterations % 2], destination);
2532

    
2533
		RenderTexture.ReleaseTemporary(tempTexture[0]);
2534
		RenderTexture.ReleaseTemporary(tempTexture[1]);
2535
	}
2536

    
2537
	private static void ApplyImageBlur(RenderTexture source, RenderTexture destination, Material blurMaterial, int blurIterations, float blurSpread)
2538
	{
2539
		if(!source || !destination || !blurMaterial)
2540
			return;
2541

    
2542
//		Graphics.Blit(source, destination, blurMaterial);
2543
//		return;
2544

    
2545
		int rtW = source.width / 4;
2546
		int rtH = source.height / 4;
2547
		RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH, 0);
2548

    
2549
		// Copy source to the 4x4 smaller texture.
2550
		Downsample4x(source, buffer, blurMaterial);
2551

    
2552
		// Blur the small texture
2553
		for(int i = 0; i < blurIterations; i++)
2554
		{
2555
			RenderTexture buffer2 = RenderTexture.GetTemporary(rtW, rtH, 0);
2556
			FourTapCone(buffer, buffer2, blurMaterial, i, blurSpread);
2557
			RenderTexture.ReleaseTemporary(buffer);
2558
			buffer = buffer2;
2559
		}
2560

    
2561
		Graphics.Blit(buffer, destination);
2562
		RenderTexture.ReleaseTemporary(buffer);
2563
	}
2564

    
2565
	// downsamples the texture to a quarter resolution.
2566
	private static void Downsample4x(RenderTexture source, RenderTexture dest, Material material)
2567
	{
2568
		float off = 1.0f;
2569

    
2570
		Graphics.BlitMultiTap (source, dest, material,
2571
			new Vector2(-off, -off),
2572
			new Vector2(-off,  off),
2573
			new Vector2( off,  off),
2574
			new Vector2( off, -off)
2575
		);
2576
	}
2577

    
2578
	// performs one blur iteration.
2579
	private static void FourTapCone (RenderTexture source, RenderTexture dest, Material material, int iteration, float blurSpread)
2580
	{
2581
		float off = 0.5f + iteration * blurSpread;
2582

    
2583
		Graphics.BlitMultiTap (source, dest, material,
2584
			new Vector2(-off, -off),
2585
			new Vector2(-off,  off),
2586
			new Vector2( off,  off),
2587
			new Vector2( off, -off)
2588
		);
2589
	}
2590

    
2591
	// returns the foregound frame rectangle, as to the required resolution
2592
	public static Rect GetForegroundFrameRect(SensorData sensorData, bool isHiResPrefered)
2593
	{
2594
		if(isHiResPrefered && sensorData != null && sensorData.sensorInterface != null)
2595
		{
2596
			if(sensorData.sensorInterface.IsBRHiResSupported() && sensorData.colorImage != null)
2597
			{
2598
				return new Rect(0f, 0f, sensorData.colorImageWidth, sensorData.colorImageHeight);
2599
			}
2600
		}
2601
		
2602
		return sensorData != null ? new Rect(0f, 0f, sensorData.depthImageWidth, sensorData.depthImageHeight) : new Rect();
2603
	}
2604

    
2605
	// returns the foregound frame length, as to the required resolution
2606
	public static int GetForegroundFrameLength(SensorData sensorData, bool isHiResPrefered)
2607
	{
2608
		if(isHiResPrefered && sensorData != null && sensorData.sensorInterface != null)
2609
		{
2610
			if(sensorData.sensorInterface.IsBRHiResSupported() && sensorData.colorImage != null)
2611
			{
2612
				return sensorData.colorImage.Length;
2613
			}
2614
		}
2615

    
2616
		return (sensorData != null && sensorData.bodyIndexImage != null) ? sensorData.bodyIndexImage.Length * 4 : 0;
2617
	}
2618
	
2619
	private static bool GetForegroundAlphaFrame(SensorData sensorData, bool bLimitedUsers, ICollection<int> alTrackedIndexes, ref byte[] fgAlphaFrame)
2620
	{
2621
		if(sensorData == null || sensorData.bodyIndexImage == null)
2622
			return false;
2623

    
2624
//		CvMat cvAlphaMap = new CvMat(sensorData.depthImageHeight, sensorData.depthImageWidth, MatrixType.U8C1);
2625
//
2626
//		System.IntPtr rawPtrAlpha;
2627
//		cvAlphaMap.GetRawData(out rawPtrAlpha);
2628
//
2629
//		if(sensorData.selectedBodyIndex != 255 || bLimitedUsers)
2630
//		{
2631
//			// copy body-index selectively
2632
//			byte btSelBI = sensorData.selectedBodyIndex;
2633
//			int iBodyIndexLength = sensorData.bodyIndexImage.Length;
2634
//
2635
//			for (int i = 0; i < iBodyIndexLength; i++)
2636
//			{
2637
//				byte btBufBI = sensorData.bodyIndexImage[i];
2638
//
2639
//				bool bUserTracked = btSelBI != 255 ? btSelBI == btBufBI : 
2640
//					(btBufBI != 255 ? alTrackedIndexes.Contains((int)btBufBI) : false);
2641
//
2642
//				if(bUserTracked)
2643
//				{
2644
//					cvAlphaMap.Set1D(i, btBufBI);
2645
//				}
2646
//				else
2647
//				{
2648
//					cvAlphaMap.Set1D(i, 255);
2649
//				}
2650
//			}
2651
//		}
2652
//		else
2653
//		{
2654
//			// copy the entire body-index buffer
2655
//			Marshal.Copy(sensorData.bodyIndexImage, 0, rawPtrAlpha, sensorData.bodyIndexImage.Length);
2656
//		}
2657
//
2658
//		// make the image b&w
2659
//		cvAlphaMap.Threshold(cvAlphaMap, 254, 255, ThresholdType.BinaryInv);
2660
//
2661
//		// apply erode, dilate and blur
2662
//		cvAlphaMap.Erode(cvAlphaMap);
2663
//		cvAlphaMap.Dilate(cvAlphaMap);
2664
//		cvAlphaMap.Smooth(cvAlphaMap, SmoothType.Blur, 5, 5);
2665
//		//cvAlphaMap.Smooth(cvAlphaMap, SmoothType.Median, 7);
2666
//
2667
//		// get the foreground image
2668
//		Marshal.Copy(rawPtrAlpha, fgAlphaFrame, 0, fgAlphaFrame.Length);
2669
//
2670
//		return true;
2671
		return false;
2672
	}
2673
	
2674
	// gets the updated foreground frame, as to the required resolution
2675
	public static bool PollForegroundFrame(SensorData sensorData, bool isHiResPrefered, Color32 defaultColor, bool bLimitedUsers, ICollection<int> alTrackedIndexes, ref byte[] fgImageFrame)
2676
	{
2677
//		if(IsDirectX11Available())
2678
//			return false;
2679
//
2680
//		if(sensorData.colorImage == null)
2681
//			return false;
2682
//
2683
//		// get the alpha frame
2684
//		byte[] fgAlphaFrame = new byte[sensorData.bodyIndexImage.Length];
2685
//		if(!GetForegroundAlphaFrame(sensorData, bLimitedUsers, alTrackedIndexes, ref fgAlphaFrame))
2686
//			return false;
2687
//		
2688
//		int alphaImageLength = fgAlphaFrame.Length;
2689
//		int colorImageLength = sensorData.colorImageWidth * sensorData.colorImageHeight;
2690
//		
2691
//		Array.Clear(fgImageFrame, 0, fgImageFrame.Length);
2692
//		
2693
//		// try to get the full color frame coordinates
2694
//		if(isHiResPrefered && sensorData.color2DepthCoords != null && sensorData.depthCoordsBufferReady)
2695
//		{
2696
//			for (int i = 0, fi = 0; i < colorImageLength; i++, fi += 4)
2697
//			{
2698
//				Vector2 vDepthPos = sensorData.color2DepthCoords[i];
2699
//
2700
//				if(!float.IsInfinity(vDepthPos.x) && !float.IsInfinity(vDepthPos.y))
2701
//				{
2702
//					int dx = Mathf.RoundToInt(vDepthPos.x);
2703
//					int dy = Mathf.RoundToInt(vDepthPos.y);
2704
//
2705
//					int di = dx + dy * sensorData.depthImageWidth;
2706
//
2707
//					if(di >= 0 && di < fgAlphaFrame.Length)
2708
//					{
2709
//						int ci = i << 2;
2710
//
2711
//						fgImageFrame[fi] = sensorData.colorImage[ci];
2712
//						fgImageFrame[fi + 1] = sensorData.colorImage[ci + 1];
2713
//						fgImageFrame[fi + 2] = sensorData.colorImage[ci + 2];
2714
//						fgImageFrame[fi + 3] = fgAlphaFrame[di];
2715
//					}
2716
//				}
2717
//				else
2718
//				{
2719
//					fgImageFrame[fi + 3] = 0;
2720
//				}
2721
//			}
2722
//			
2723
//			// buffer is released
2724
//			lock(sensorData.depthCoordsBufferLock)
2725
//			{
2726
//				sensorData.depthCoordsBufferReady = false;
2727
//			}
2728
//		}
2729
//		else
2730
//		{
2731
//			for (int i = 0, fi = 0; i < alphaImageLength; i++, fi += 4)
2732
//			{
2733
//				Vector2 vColorPos = Vector2.zero;
2734
//				
2735
//				if(sensorData.depth2ColorCoords != null && sensorData.depthCoordsBufferReady)
2736
//				{
2737
//					vColorPos = sensorData.depth2ColorCoords[i];
2738
//				}
2739
//				else
2740
//				{
2741
//					Vector2 vDepthPos = Vector2.zero;
2742
//					vDepthPos.x = i % sensorData.depthImageWidth;
2743
//					vDepthPos.y = i / sensorData.depthImageWidth;
2744
//					
2745
//					ushort userDepth = sensorData.depthImage[i];
2746
//					vColorPos = MapDepthPointToColorCoords(sensorData, vDepthPos, userDepth);
2747
//				}
2748
//				
2749
//				if(!float.IsInfinity(vColorPos.x) && !float.IsInfinity(vColorPos.y))
2750
//				{
2751
//					int cx = (int)vColorPos.x;
2752
//					int cy = (int)vColorPos.y;
2753
//					int colorIndex = cx + cy * sensorData.colorImageWidth;
2754
//					
2755
//					if(colorIndex >= 0 && colorIndex < colorImageLength)
2756
//					{
2757
//						int ci = colorIndex << 2;
2758
//						
2759
//						fgImageFrame[fi] = sensorData.colorImage[ci];
2760
//						fgImageFrame[fi + 1] = sensorData.colorImage[ci + 1];
2761
//						fgImageFrame[fi + 2] = sensorData.colorImage[ci + 2];
2762
//						fgImageFrame[fi + 3] = fgAlphaFrame[i];
2763
//					}
2764
//				}
2765
//				else
2766
//				{
2767
//					fgImageFrame[fi] = defaultColor.r;
2768
//					fgImageFrame[fi + 1] = defaultColor.g;
2769
//					fgImageFrame[fi + 2] = defaultColor.b;
2770
//					fgImageFrame[fi + 3] = fgAlphaFrame[i];
2771
//				}
2772
//			}
2773
//			
2774
//			// buffer is released
2775
//			lock(sensorData.depthCoordsBufferLock)
2776
//			{
2777
//				sensorData.depthCoordsBufferReady = false;
2778
//			}
2779
//		}
2780
//
2781
//		return true;
2782
		return false;
2783
	}
2784
	
2785
	// reads render texture contents into tex2d (it must have the same width and height).
2786
	public static bool RenderTex2Tex2D(RenderTexture rt, ref Texture2D tex) 
2787
	{
2788
		if(!rt || !tex || rt.width != tex.width || rt.height != tex.height)
2789
			return false;
2790
		
2791
		RenderTexture currentActiveRT = RenderTexture.active;
2792
		RenderTexture.active = rt;
2793
		
2794
		tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
2795
		tex.Apply();
2796
		
2797
		RenderTexture.active = currentActiveRT;
2798
		
2799
		return true;
2800
	}
2801

    
2802
	// reads render texture contents into tex2d (it must have the same width and height).
2803
	public static bool RenderTex2Tex2D(RenderTexture rt, int rtX, int rtY, int rtW, int rtH, ref Texture2D tex) 
2804
	{
2805
		if(!rt || !tex || rtW != tex.width || rtH != tex.height)
2806
			return false;
2807

    
2808
		RenderTexture currentActiveRT = RenderTexture.active;
2809
		RenderTexture.active = rt;
2810

    
2811
		tex.ReadPixels(new Rect(rtX, rtY, rtW, rtH), 0, 0);
2812
		tex.Apply();
2813

    
2814
		RenderTexture.active = currentActiveRT;
2815

    
2816
		return true;
2817
	}
2818

    
2819
	// copies source texture pixels into destination texture. Creates it, if needed.
2820
	public static bool CopyTex2D(Texture2D src, ref Texture2D dest)
2821
	{
2822
		if (src == null)
2823
			return false;
2824

    
2825
		if (dest == null) 
2826
		{
2827
			dest = new Texture2D(src.width, src.height, src.format, false);
2828
		}
2829

    
2830
		if (src.width != dest.width || src.height != dest.height)
2831
			return false;
2832

    
2833
		Color32[] pix = src.GetPixels32();
2834
		dest.SetPixels32(pix);
2835
		dest.Apply();
2836

    
2837
		return true;
2838
	}
2839

    
2840
	// DLL Imports for native library functions
2841
	[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
2842
	static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
2843
	
2844
	[DllImport("kernel32", SetLastError=true)]
2845
	static extern bool FreeLibrary(IntPtr hModule);
2846

    
2847
	// load the native dll to ensure the library is loaded
2848
	public static bool LoadNativeLib(string sLibName)
2849
	{
2850
		string sTargetPath = KinectInterop.GetTargetDllPath(".", Is64bitArchitecture());
2851
		string sFullLibPath = sTargetPath + "/" + sLibName;
2852

    
2853
		IntPtr hLibrary = LoadLibrary(sFullLibPath);
2854

    
2855
		return (hLibrary != IntPtr.Zero);
2856
	}
2857
	
2858
	// unloads and deletes native library
2859
	public static void DeleteNativeLib(string sLibName, bool bUnloadLib)
2860
	{
2861
		string sTargetPath = KinectInterop.GetTargetDllPath(".", Is64bitArchitecture());
2862
		string sFullLibPath = sTargetPath + "/" + sLibName;
2863
		
2864
		if(bUnloadLib)
2865
		{
2866
			IntPtr hLibrary = LoadLibrary(sFullLibPath);
2867
			
2868
			if(hLibrary != IntPtr.Zero)
2869
			{
2870
				FreeLibrary(hLibrary);
2871
				FreeLibrary(hLibrary);
2872
			}
2873
		}
2874
		
2875
		try 
2876
		{
2877
			// delete file
2878
			if(File.Exists(sFullLibPath))
2879
			{
2880
				File.Delete(sFullLibPath);
2881
			}
2882
		} 
2883
		catch (Exception) 
2884
		{
2885
			Debug.Log("Could not delete file: " + sFullLibPath);
2886
		}
2887
	}
2888

    
2889
	// universal windows platform specific functions
2890

    
2891
#if UNITY_WSA
2892
	[DllImport("kernelbase")]
2893
	public static extern void Sleep(int dwMilliseconds);
2894
#else
2895
	[DllImport("kernel32")]
2896
	public static extern void Sleep(int dwMilliseconds);
2897
#endif
2898

    
2899

    
2900
	public static bool IsFileExists(string sFilePath, long iFileSize)
2901
	{
2902
#if UNITY_WSA
2903
		return File.Exists(sFilePath);
2904
#else
2905
		System.IO.FileInfo targetFile = new System.IO.FileInfo(sFilePath);
2906
		return targetFile.Exists && targetFile.Length == iFileSize;
2907
#endif
2908
	}
2909

    
2910

    
2911
	public static string GetEnvironmentVariable(string sEnvVar)
2912
	{
2913
#if !UNITY_WSA
2914
		return System.Environment.GetEnvironmentVariable(sEnvVar);
2915
#else
2916
		return String.Empty;
2917
#endif
2918
	}
2919

    
2920
}