// Update the user histogram map
	void UpdateUserHistogramImage(UserMapType userMapType)
	{
		int numOfPoints = 0;
		Array.Clear(usersHistogramMap, 0, usersHistogramMap.Length);
		
		// Calculate cumulative histogram for depth
		for (int i = 0; i < usersMapSize; i++)
		{
			// Only calculate for depth that contains users
			if (sensorData.bodyIndexImage[i] != 255)
			{
				ushort depth = sensorData.depthImage[i];
				if(depth > 5000)
					depth = 5000;

				usersHistogramMap[depth]++;
				numOfPoints++;
			}
		}
		
		if (numOfPoints > 0)
		{
			for (int i = 1; i < usersHistogramMap.Length; i++)
			{   
				usersHistogramMap[i] += usersHistogramMap[i - 1];
			}
			
			for (int i = 0; i < usersHistogramMap.Length; i++)
			{
				usersHistogramMap[i] = 1.0f - (usersHistogramMap[i] / numOfPoints);
			}
		}

		//List<int> alTrackedIndexes = new List<int>(dictUserIdToIndex.Values);
		byte btSelBI = sensorData.selectedBodyIndex;
		Color32 clrClear = Color.clear;

		// convert the body indices to string
		string sTrackedIndices = string.Empty;
		foreach(int bodyIndex in dictUserIdToIndex.Values)
		{
			sTrackedIndices += (char)(0x30 + bodyIndex);
		}
		
		// Create the actual users texture based on label map and depth histogram
		for (int i = 0; i < usersMapSize; i++)
		{
			ushort userMap = sensorData.bodyIndexImage[i];
			ushort userDepth = sensorData.depthImage[i];

			if(userDepth > 5000)
				userDepth = 5000;
			
			ushort nowUserPixel = userMap != 255 ? (ushort)((userMap << 13) | userDepth) : userDepth;
			ushort wasUserPixel = usersPrevState[i];
			
			// draw only the changed pixels
			if(nowUserPixel != wasUserPixel)
			{
				usersPrevState[i] = nowUserPixel;

				bool bUserTracked = btSelBI != 255 ? btSelBI == (byte)userMap : 
					//(bLimitedUsers ? alTrackedIndexes.Contains(userMap): userMap != 255);
					(bLimitedUsers ? sTrackedIndices.IndexOf((char)(0x30 + userMap)) >= 0 : userMap != 255);

				if(!bUserTracked)
				{
					usersHistogramImage[i] = clrClear;
				}
				else
				{
					if(userMapType == UserMapType.CutOutTexture && sensorData.colorImage != null)
					{
						Vector2 vColorPos = Vector2.zero;

						if(sensorData.depth2ColorCoords != null)
						{
							vColorPos = sensorData.depth2ColorCoords[i];
						}
						else
						{
							Vector2 vDepthPos = Vector2.zero;
							vDepthPos.x = i % sensorData.depthImageWidth;
							vDepthPos.y = i / sensorData.depthImageWidth;

							vColorPos = KinectInterop.MapDepthPointToColorCoords(sensorData, vDepthPos, userDepth);
						}

						if(!float.IsInfinity(vColorPos.x) && !float.IsInfinity(vColorPos.y))
						{
							int cx = (int)vColorPos.x;
							int cy = (int)vColorPos.y;
							int colorIndex = cx + cy * sensorData.colorImageWidth;

							if(colorIndex >= 0 && colorIndex < usersClrSize)
							{
								int ci = colorIndex << 2;
								Color32 colorPixel = new Color32(sensorData.colorImage[ci], sensorData.colorImage[ci + 1], sensorData.colorImage[ci + 2], 255);
								
								usersHistogramImage[i] = colorPixel;
							}
						}
					}
					else
					{
						// Create a blending color based on the depth histogram
						float histDepth = usersHistogramMap[userDepth];
						Color c = new Color(histDepth, histDepth, histDepth, 0.9f);
						
						switch(userMap % 4)
						{
						case 0:
							usersHistogramImage[i] = Color.red * c;
							break;
						case 1:
							usersHistogramImage[i] = Color.green * c;
							break;
						case 2:
							usersHistogramImage[i] = Color.blue * c;
							break;
						case 3:
							usersHistogramImage[i] = Color.magenta * c;
							break;
						}
					}
				}
				
			}
		}
		
	}
	// Update the user histogram
	void UpdateUserMap(UserMapType userMapType)
    {
		if(sensorData != null && sensorData.sensorInterface != null && 
		   !sensorData.sensorInterface.IsBackgroundRemovalActive())
		{
			if(!KinectInterop.IsDirectX11Available())
			{
				if(userMapType != UserMapType.RawUserDepth)
				{
					UpdateUserHistogramImage(userMapType);
					usersLblTex.SetPixels32(usersHistogramImage);
				}
			}
			else
			{
				if(userMapType == UserMapType.CutOutTexture)
				{
					if(!sensorData.color2DepthTexture && sensorData.depth2ColorTexture && 
					   KinectInterop.RenderDepth2ColorTex(sensorData))
					{
						KinectInterop.RenderTex2Tex2D(sensorData.depth2ColorTexture, ref usersLblTex);
					}
					else if(!sensorData.color2DepthTexture)
					{
						KinectInterop.RenderTex2Tex2D(sensorData.bodyIndexTexture, ref usersLblTex);
					}
				}
				else if(userMapType == UserMapType.BodyTexture && sensorData.bodyIndexTexture)
				{
					KinectInterop.RenderTex2Tex2D(sensorData.bodyIndexTexture, ref usersLblTex);
				}
				else if(userMapType == UserMapType.UserTexture && sensorData.depthImageTexture)
				{
					KinectInterop.RenderTex2Tex2D(sensorData.depthImageTexture, ref usersLblTex);
				}
			}
			
			if(userMapType != UserMapType.RawUserDepth)
			{
				// draw skeleton lines
				if(displaySkeletonLines)
				{
					for(int i = 0; i < alUserIds.Count; i++)
					{
						Int64 liUserId = alUserIds[i];
						int index = dictUserIdToIndex[liUserId];
						
						if(index >= 0 && index < sensorData.bodyCount)
						{
							DrawSkeleton(usersLblTex, ref bodyFrame.bodyData[index]);
						}
					}
				}
				
				usersLblTex.Apply();
			}
		}
    }