Beispiel #1
0
void statisticsAddFrame()
{
	if (g_StatisticsState == SHOULD_COLLECT)
	{
		g_StatisticsState = COLLECTING;
	}

	if (g_StatisticsState == COLLECTING)
	{
		const DepthMetaData* pDepthMD = getDepthMetaData();

		const XnDepthPixel* pDepth = pDepthMD->Data();

		for (XnUInt32 y = pDepthMD->YOffset(); y < pDepthMD->YRes() + pDepthMD->YOffset(); ++y)
		{
			XnPixelStatistics* pPixel = &g_PixelStatistics[y*pDepthMD->FullXRes() + pDepthMD->XOffset()];
			for (XnUInt32 x = pDepthMD->XOffset(); x < pDepthMD->XRes() + pDepthMD->XOffset(); ++x, ++pDepth, ++pPixel)
			{
				XnDepthPixel nDepth = *pDepth;

				if (nDepth > pPixel->nMax)
					pPixel->nMax = nDepth;

				if (nDepth < pPixel->nMin)
					pPixel->nMin = nDepth;

				pPixel->nSum += nDepth;
				pPixel->nSumSquare += (nDepth * nDepth);
				pPixel->nCount++;
				pPixel->dAverage = pPixel->nSum / pPixel->nCount;
				pPixel->dStdDev = sqrt( (1.0/pPixel->nCount) * (pPixel->nSumSquare) - (pPixel->dAverage * pPixel->dAverage) );
			}
		}
	}
}
Beispiel #2
0
void captureSingleFrame(int)
{
	int num = findUniqueFileName();

	XnChar csImageFileName[XN_FILE_MAX_PATH];
	XnChar csDepthFileName[XN_FILE_MAX_PATH];
	XnChar csIRFileName[XN_FILE_MAX_PATH];
	getImageFileName(num, csImageFileName);
	getDepthFileName(num, csDepthFileName);
	getIRFileName(num, csIRFileName);

	const ImageMetaData* pImageMD = getImageMetaData();
	if (pImageMD != NULL)
	{
		xnOSSaveFile(csImageFileName, pImageMD->Data(), pImageMD->DataSize());
	}

	const IRMetaData* pIRMD = getIRMetaData();
	if (pIRMD != NULL)
	{
		xnOSSaveFile(csIRFileName, pIRMD->Data(), pIRMD->DataSize());
	}

	const DepthMetaData* pDepthMD = getDepthMetaData();
	if (pDepthMD != NULL)
	{
		xnOSSaveFile(csDepthFileName, pDepthMD->Data(), pDepthMD->DataSize());
	}
	
	g_Capture.nCapturedFrameUniqueID = num + 1;

// 	displayMessage("Frames saved with ID %d", num);
	printf("Frames saved with ID %d\n", num);
}
Beispiel #3
0
// --------------------------------
// Code
// --------------------------------
void statisticsInit()
{
	g_PixelStatistics = NULL;
	g_StatisticsState = NOT_COLLECTING;

	const DepthMetaData* pDepthMD = getDepthMetaData();
	if (pDepthMD != NULL)
	{
		g_PixelStatistics = new XnPixelStatistics[pDepthMD->FullXRes() * pDepthMD->FullYRes()];
	}
}
Beispiel #4
0
void getStatisticsMessage(char* csMessage)
{
	switch (g_StatisticsState)
	{
	case NOT_COLLECTING:
	case SHOULD_COLLECT:
		csMessage[0] = 0;
		break;
	case COLLECTING:
	case COLLECTION_ENDED:
		const DepthMetaData* pDepthMD = getDepthMetaData();
		sprintf(csMessage, "Collected Statistics for %u frames", g_PixelStatistics[pDepthMD->YOffset()*pDepthMD->FullXRes() + pDepthMD->XOffset()].nCount);
		break;
	}
}
Beispiel #5
0
void statisticsStart(int)
{
	const DepthMetaData* pDepthMD = getDepthMetaData();

	if (pDepthMD == NULL)
	{
		displayMessage("Can't collect statistics: Depth is turned off!");
		return;
	}

	int nCount = pDepthMD->FullXRes() * pDepthMD->FullYRes();

	XnDepthPixel nMaxDepth = getDepthGenerator()->GetDeviceMaxDepth();

	XnPixelStatistics* pPixel = g_PixelStatistics;
	for (int i = 0; i < nCount; ++i, ++pPixel)
	{
		xnOSMemSet(pPixel, 0, sizeof(XnPixelStatistics));
		pPixel->nMin = nMaxDepth;
	}

	g_StatisticsState = SHOULD_COLLECT;
}
Beispiel #6
0
void drawDepth(IntRect* pLocation, IntPair* pPointer)
{
	if (g_DrawConfig.Streams.Depth.Coloring != DEPTH_OFF)
	{
		if (!isDepthOn())
		{
			drawClosedStream(pLocation, "Depth");
			return;
		}

		const DepthMetaData* pDepthMD = getDepthMetaData();
		const XnDepthPixel* pDepth = pDepthMD->Data();
		XN_ASSERT(pDepth);
		
		if (pDepthMD->FrameID() == 0)
		{
			return;
		}

		if (g_DrawConfig.Streams.Depth.Coloring == STANDARD_DEVIATION)
		{
			XnPixelStatistics* pStatistics = g_PixelStatistics;

			for (XnUInt16 nY = pDepthMD->YOffset(); nY < pDepthMD->YRes() + pDepthMD->YOffset(); nY++)
			{
				XnUInt8* pTexture = TextureMapGetLine(&g_texDepth, nY) + pDepthMD->XOffset()*4;
				for (XnUInt16 nX = 0; nX < pDepthMD->XRes(); nX++, pTexture+=4, pStatistics++)
				{
					pTexture[0] = pTexture[1] = XN_MIN((int)pStatistics->dStdDev, 255);
					pTexture[2] = 0;
					pTexture[3] = g_DrawConfig.Streams.Depth.fTransparency*255;
				}
			}
		}
		else
		{
			// copy depth into texture-map
			for (XnUInt16 nY = pDepthMD->YOffset(); nY < pDepthMD->YRes() + pDepthMD->YOffset(); nY++)
			{
				XnUInt8* pTexture = TextureMapGetLine(&g_texDepth, nY) + pDepthMD->XOffset()*4;
				for (XnUInt16 nX = 0; nX < pDepthMD->XRes(); nX++, pDepth++, pTexture+=4)
				{
					XnUInt8 nRed = 0;
					XnUInt8 nGreen = 0;
					XnUInt8 nBlue = 0;
					XnUInt8 nAlpha = g_DrawConfig.Streams.Depth.fTransparency*255;

					XnUInt16 nColIndex;

					switch (g_DrawConfig.Streams.Depth.Coloring)
					{
					case LINEAR_HISTOGRAM:
						nRed = nGreen = g_pDepthHist[*pDepth]*255;
						break;
					case PSYCHEDELIC_SHADES:
						nAlpha *= (((XnFloat)(*pDepth % 10) / 20) + 0.5);
					case PSYCHEDELIC:

						switch ((*pDepth/10) % 10)
						{
						case 0:
							nRed = 255;
							break;
						case 1:
							nGreen = 255;
							break;
						case 2:
							nBlue = 255;
							break;
						case 3:
							nRed = 255;
							nGreen = 255;
							break;
						case 4:
							nGreen = 255;
							nBlue = 255;
							break;
						case 5:
							nRed = 255;
							nBlue = 255;
							break;
						case 6:
							nRed = 255;
							nGreen = 255;
							nBlue = 255;
							break;
						case 7:
							nRed = 127;
							nBlue = 255;
							break;
						case 8:
							nRed = 255;
							nBlue = 127;
							break;
						case 9:
							nRed = 127;
							nGreen = 255;
							break;
						}
						break;
					case RAINBOW:
						nColIndex = (XnUInt16)((*pDepth / (g_nMaxDepth / 256.)));
						nRed = PalletIntsR[nColIndex];
						nGreen = PalletIntsG[nColIndex];
						nBlue = PalletIntsB[nColIndex];
						break;
					case CYCLIC_RAINBOW:
						nColIndex = (*pDepth % 256);
						nRed = PalletIntsR[nColIndex];
						nGreen = PalletIntsG[nColIndex];
						nBlue = PalletIntsB[nColIndex];
						break;
					case CYCLIC_RAINBOW_HISTOGRAM:
						float fHist = g_pDepthHist[*pDepth];
						nColIndex = (*pDepth % 256);
						nRed = PalletIntsR[nColIndex]   * fHist;
						nGreen = PalletIntsG[nColIndex] * fHist;
						nBlue = PalletIntsB[nColIndex]  * fHist;
						break;
					}

					pTexture[0] = nRed;
					pTexture[1] = nGreen;
					pTexture[2] = nBlue;

					if (*pDepth == 0)
						pTexture[3] = 0;
					else
						pTexture[3] = nAlpha;
				}
			}
		} // not STANDRARD_DEVIATION

		if (pPointer != NULL)
		{
			TextureMapDrawCursor(&g_texDepth, *pPointer);
		}

		TextureMapUpdate(&g_texDepth);
		TextureMapDraw(&g_texDepth, pLocation);
	}
}
Beispiel #7
0
void drawColorImage(IntRect* pLocation, IntPair* pPointer, int pointerRed, int pointerGreen, int pointerBlue)
{
	if (g_DrawConfig.Streams.bBackground)
		TextureMapDraw(&g_texBackground, pLocation);

	if (g_DrawConfig.Streams.Image.Coloring == IMAGE_OFF)
		return;

	if (!isImageOn() && !isIROn())
	{
		drawClosedStream(pLocation, "Image");
		return;
	}

	const MapMetaData* pImageMD;
	const XnUInt8* pImage = NULL;

	if (isImageOn())
	{
		pImageMD = getImageMetaData();
		pImage = getImageMetaData()->Data();
	}
	else if (isIROn())
	{
		pImageMD = getIRMetaData();
		pImage = (const XnUInt8*)getIRMetaData()->Data();
	}
	else
		return;

	if (pImageMD->FrameID() == 0)
	{
		return;
	}

	const DepthMetaData* pDepthMetaData = getDepthMetaData();

	double grayscale16Factor = 1.0;
	if (pImageMD->PixelFormat() == XN_PIXEL_FORMAT_GRAYSCALE_16_BIT)
	{
		int nPixelsCount = pImageMD->XRes()*pImageMD->YRes();
		XnUInt16* pPixel = (XnUInt16*)pImage;
		for (int i = 0; i < nPixelsCount; ++i,++pPixel)
		{
			if (*pPixel > g_nMaxGrayscale16Value)
				g_nMaxGrayscale16Value = *pPixel;
		}

		if (g_nMaxGrayscale16Value > 0)
		{
			grayscale16Factor = 255.0 / g_nMaxGrayscale16Value;
		}
	}

	for (XnUInt16 nY = pImageMD->YOffset(); nY < pImageMD->YRes() + pImageMD->YOffset(); nY++)
	{
		XnUInt8* pTexture = TextureMapGetLine(&g_texImage, nY) + pImageMD->XOffset()*4;

		if (pImageMD->PixelFormat() == XN_PIXEL_FORMAT_YUV422)
		{
			YUV422ToRGB888(pImage, pTexture, pImageMD->XRes()*2, g_texImage.Size.X*g_texImage.nBytesPerPixel);
			pImage += pImageMD->XRes()*2;
		}
		else
		{
			for (XnUInt16 nX = 0; nX < pImageMD->XRes(); nX++, pTexture+=4)
			{
				XnInt32 nDepthIndex = 0;

				if (pDepthMetaData != NULL)
				{
					XnDouble dRealX = (nX + pImageMD->XOffset()) / (XnDouble)pImageMD->FullXRes();
					XnDouble dRealY = nY / (XnDouble)pImageMD->FullYRes();

					XnUInt32 nDepthX = dRealX * pDepthMetaData->FullXRes() - pDepthMetaData->XOffset();
					XnUInt32 nDepthY = dRealY * pDepthMetaData->FullYRes() - pDepthMetaData->YOffset();

					if (nDepthX >= pDepthMetaData->XRes() || nDepthY >= pDepthMetaData->YRes())
					{
						nDepthIndex = -1;
					}
					else
					{
						nDepthIndex = nDepthY*pDepthMetaData->XRes() + nDepthX;
					}
				}

				switch (pImageMD->PixelFormat())
				{
				case XN_PIXEL_FORMAT_RGB24:
					pTexture[0] = pImage[0];
					pTexture[1] = pImage[1];
					pTexture[2] = pImage[2];
					pImage+=3; 
					break;
				case XN_PIXEL_FORMAT_GRAYSCALE_8_BIT:
					pTexture[0] = pTexture[1] = pTexture[2] = *pImage;
					pImage+=1; 
					break;
				case XN_PIXEL_FORMAT_GRAYSCALE_16_BIT:
					XnUInt16* p16 = (XnUInt16*)pImage;
					XnUInt8 textureValue = 0;
					textureValue = (XnUInt8)((*p16) * grayscale16Factor);
					pTexture[0] = pTexture[1] = pTexture[2] = textureValue;
					pImage+=2; 
					break;
				}

				// decide if pixel should be lit or not
				if (g_DrawConfig.Streams.Image.Coloring == DEPTH_MASKED_IMAGE &&
					(pDepthMetaData == NULL || nDepthIndex == -1 || pDepthMetaData->Data()[nDepthIndex] == 0))
				{
					pTexture[3] = 0;
				}
				else
				{
					pTexture[3] = 255;
				}
			}
		}
	}

	if (pPointer != NULL)
	{
		TextureMapDrawCursor(&g_texImage, *pPointer, pointerRed, pointerGreen, pointerBlue);
	}

	TextureMapUpdate(&g_texImage);
	TextureMapDraw(&g_texImage, pLocation);
}
Beispiel #8
0
void drawFrame()
{
	// calculate locations
	g_DrawConfig.DepthLocation.uBottom = 0;
	g_DrawConfig.DepthLocation.uTop = WIN_SIZE_Y - 1;
	g_DrawConfig.DepthLocation.uLeft = 0;
	g_DrawConfig.DepthLocation.uRight = WIN_SIZE_X - 1;

	g_DrawConfig.ImageLocation.uBottom = 0;
	g_DrawConfig.ImageLocation.uTop = WIN_SIZE_Y - 1;
	g_DrawConfig.ImageLocation.uLeft = 0;
	g_DrawConfig.ImageLocation.uRight = WIN_SIZE_X - 1;

	if (g_DrawConfig.Streams.ScreenArrangement == SIDE_BY_SIDE)
	{
		g_DrawConfig.DepthLocation.uTop = WIN_SIZE_Y / 2 - 1;
		g_DrawConfig.DepthLocation.uRight = WIN_SIZE_X / 2 - 1;
		g_DrawConfig.ImageLocation.uTop = WIN_SIZE_Y / 2 - 1;
		g_DrawConfig.ImageLocation.uLeft = WIN_SIZE_X / 2;
	}

	// Texture map init
	const DepthMetaData* pDepthMD = getDepthMetaData();
	if (isDepthOn())
	{
		g_nMaxDepth = getDepthGenerator()->GetDeviceMaxDepth();
		TextureMapInit(&g_texDepth, pDepthMD->FullXRes(), pDepthMD->FullYRes(), 4, pDepthMD->XRes(), pDepthMD->YRes());
		fixLocation(&g_DrawConfig.DepthLocation, pDepthMD->FullXRes(), pDepthMD->FullYRes());
	}

	const MapMetaData* pImageMD = NULL;

	if (isImageOn())
	{
		pImageMD = getImageMetaData();
	}
	else if (isIROn())
	{
		pImageMD = getIRMetaData();
	}

	if (pImageMD != NULL)
	{
		TextureMapInit(&g_texImage, pImageMD->FullXRes(), pImageMD->FullYRes(), 4, pImageMD->XRes(), pImageMD->YRes());
		fixLocation(&g_DrawConfig.ImageLocation, pImageMD->FullXRes(), pImageMD->FullYRes());
	}

	// check if pointer is over a map
	bool bOverDepth = (pDepthMD != NULL) && isPointInRect(g_DrawUserInput.Cursor, &g_DrawConfig.DepthLocation);
	bool bOverImage = (pImageMD != NULL) && isPointInRect(g_DrawUserInput.Cursor, &g_DrawConfig.ImageLocation);
	bool bDrawDepthPointer = false;
	bool bDrawImagePointer = false;
	int imagePointerRed = 255;
	int imagePointerGreen = 0;
	int imagePointerBlue = 0;

	IntPair pointerInDepth;
	IntPair pointerInImage;

	if (bOverImage)
	{
		pointerInImage.X = (double)(g_DrawUserInput.Cursor.X - g_DrawConfig.ImageLocation.uLeft) / (g_DrawConfig.ImageLocation.uRight - g_DrawConfig.ImageLocation.uLeft + 1) * pImageMD->FullXRes();
		pointerInImage.Y = (double)(g_DrawUserInput.Cursor.Y - g_DrawConfig.ImageLocation.uBottom) / (g_DrawConfig.ImageLocation.uTop - g_DrawConfig.ImageLocation.uBottom + 1) * pImageMD->FullYRes();
		bDrawImagePointer = true;
	}

	if (bOverDepth)
	{
		pointerInDepth.X = (double)(g_DrawUserInput.Cursor.X - g_DrawConfig.DepthLocation.uLeft) / (g_DrawConfig.DepthLocation.uRight - g_DrawConfig.DepthLocation.uLeft + 1) * pDepthMD->FullXRes();
		pointerInDepth.Y = (double)(g_DrawUserInput.Cursor.Y - g_DrawConfig.DepthLocation.uBottom) / (g_DrawConfig.DepthLocation.uTop - g_DrawConfig.DepthLocation.uBottom + 1) * pDepthMD->FullYRes();

		// make sure we're in cropped area
		if (pointerInDepth.X >= pDepthMD->XOffset() && pointerInDepth.X < (pDepthMD->XOffset() + pDepthMD->XRes()) &&
			pointerInDepth.Y >= pDepthMD->YOffset() && pointerInDepth.Y < (pDepthMD->YOffset() + pDepthMD->YRes()))
		{
			bDrawDepthPointer = true;
			if (!bOverImage && g_DrawConfig.bShowPointer)
			{
				// try to translate depth pixel to image
				if (getImageCoordinatesForDepthPixel(pointerInDepth.X, pointerInDepth.Y, pointerInImage.X, pointerInImage.Y))
				{
					bDrawImagePointer = true;
					imagePointerRed = 0;
					imagePointerGreen = 0;
					imagePointerBlue = 255;
				}
			}
		}
	}

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	// Setup the opengl env for fixed location view
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0,WIN_SIZE_X,WIN_SIZE_Y,0,-1.0,1.0);
	glDisable(GL_DEPTH_TEST); 

	if (g_DrawConfig.Streams.Depth.Coloring == CYCLIC_RAINBOW_HISTOGRAM || g_DrawConfig.Streams.Depth.Coloring == LINEAR_HISTOGRAM || g_DrawConfig.bShowPointer)
		calculateHistogram();

	drawColorImage(&g_DrawConfig.ImageLocation, bDrawImagePointer ? &pointerInImage : NULL, imagePointerRed, imagePointerGreen, imagePointerBlue);

	drawDepth(&g_DrawConfig.DepthLocation, bDrawDepthPointer ? &pointerInDepth : NULL);

	printStatisticsInfo();
	printRecordingInfo();

	if (g_DrawConfig.bShowPointer)
		drawPointerMode(bDrawDepthPointer ? &pointerInDepth : NULL);

	drawUserInput(!bOverDepth && !bOverImage);

	drawUserMessage();
	drawPlaybackSpeed();

	if (g_DrawConfig.strErrorState != NULL)
		drawErrorState();

	if (g_DrawConfig.bHelp)
		drawHelpScreen();

	glutSwapBuffers();
}
Beispiel #9
0
void drawPointerMode(IntPair* pPointer)
{
	char buf[512] = "";
	int nCharWidth = glutBitmapWidth(GLUT_BITMAP_HELVETICA_18, '0');
	int nPointerValue = 0;

	XnDouble dTimestampDivider = 1E6;

	const DepthMetaData* pDepthMD = getDepthMetaData();

	if (pDepthMD != NULL)
	{
		// Print the scale black background
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		glBegin(GL_QUADS);
		glColor4f(0, 0, 0, 0.7);
		glVertex2i(0, WIN_SIZE_Y); // lower left
		glVertex2i(WIN_SIZE_X, WIN_SIZE_Y);
		glVertex2i(WIN_SIZE_X, WIN_SIZE_Y - 135);
		glVertex2i(0, WIN_SIZE_Y - 135);
		glEnd();

		glDisable(GL_BLEND);

		// set a large point size (for the scale)
		glPointSize(15);

		// Print the scale data
		glBegin(GL_POINTS);
		for (int i = 0; i < pDepthMD->ZRes(); i+=1)
		{
			float fNewColor = g_pDepthHist[i];
			if ((fNewColor > 0.004) && (fNewColor < 0.996))
			{
				glColor3f(fNewColor, fNewColor, 0);
				glVertex3f(((i/10)*2), WIN_SIZE_Y - 23, 1);
			}
		}
		glEnd();

		// Print the pointer scale data
		if (pPointer != NULL)
		{
			// make sure pointer in on a depth pixel (take in mind cropping might be in place)
			IntPair pointerInDepth = *pPointer;
			pointerInDepth.X -= pDepthMD->XOffset();
			pointerInDepth.Y -= pDepthMD->YOffset();

			if (pointerInDepth.X < (int)pDepthMD->XRes() && pointerInDepth.Y < (int)pDepthMD->YRes())
			{
				nPointerValue = (*pDepthMD)(pointerInDepth.X, pointerInDepth.Y);

				glBegin(GL_POINTS);
				glColor3f(1,0,0);
				glVertex3f(10 + ((nPointerValue/10)*2), WIN_SIZE_Y - 70, 1);
				glEnd();
			}
		}

		// Print the scale texts
		for (int i = 0; i < pDepthMD->ZRes()/10; i+=25)
		{
			int xPos = i*2 + 10;

			// draw a small line in this position
			glBegin(GL_LINES);
			glColor3f(0, 1, 0);
			glVertex2i(xPos, WIN_SIZE_Y - 54);
			glVertex2i(xPos, WIN_SIZE_Y - 62);
			glEnd();

			// place a label under, and in the middle of, that line.
			int chars = sprintf(buf, "%d", i);
			glColor3f(1,0,0);
			glRasterPos2i(xPos - chars*nCharWidth/2, WIN_SIZE_Y - 40);
			glPrintString(GLUT_BITMAP_HELVETICA_18,buf);
		}

		sprintf(buf, "%s - Frame %4u, Timestamp %.3f", getDepthGenerator()->GetInfo().GetInstanceName(), pDepthMD->FrameID(), (double)pDepthMD->Timestamp()/dTimestampDivider);
	}

	const ImageMetaData* pImageMD = getImageMetaData();
	if (pImageMD != NULL)
	{
		if (buf[0] != '\0')
			sprintf(buf + strlen(buf), " | ");

		sprintf(buf + strlen(buf), "%s - Frame %4u, Timestamp %.3f", getImageGenerator()->GetInfo().GetInstanceName(), pImageMD->FrameID(), (double)pImageMD->Timestamp()/dTimestampDivider);
	}

	const IRMetaData* pIRMD = getIRMetaData();
	if (pIRMD != NULL)
	{
		if (buf[0] != '\0')
			sprintf(buf + strlen(buf), " | ");

		sprintf(buf + strlen(buf), "%s - Frame %4u, Timestamp %.3f", getIRGenerator()->GetInfo().GetInstanceName(), pIRMD->FrameID(), (double)pIRMD->Timestamp()/dTimestampDivider);
	}

	const AudioMetaData* pAudioMD = getAudioMetaData();
	if (pAudioMD != NULL)
	{
		if (buf[0] != '\0')
			sprintf(buf + strlen(buf), " | ");

		sprintf(buf + strlen(buf), "%s - Timestamp %.3f", getAudioGenerator()->GetInfo().GetInstanceName(), (double)pAudioMD->Timestamp()/dTimestampDivider);
	}

	int nYLocation = WIN_SIZE_Y - 88;
	glColor3f(1,0,0);
	glRasterPos2i(10,nYLocation);
	glPrintString(GLUT_BITMAP_HELVETICA_18, buf);
	nYLocation -= 26;

	if (pPointer != NULL && isStatisticsActive())
	{
		XnPixelStatistics* pStatistics = &g_PixelStatistics[pPointer->Y * pDepthMD->XRes() + pPointer->X];
		sprintf(buf, "Collected: %3u, Min: %4u Max: %4u Avg: %6.2f StdDev: %6.2f", 
			pStatistics->nCount, pStatistics->nMin, pStatistics->nMax, pStatistics->dAverage, pStatistics->dStdDev);
		glRasterPos2i(10,nYLocation);
		glPrintString(GLUT_BITMAP_HELVETICA_18, buf);
		nYLocation -= 26;
	}

	if (pPointer != NULL)
	{
		// Print the pointer text
		XnUInt64 nCutOffMin = 0;
		XnUInt64 nCutOffMax = (pDepthMD != NULL) ? g_nMaxDepth : 0;

		XnChar sPointerValue[100];
		if (nPointerValue != g_nMaxDepth)
		{
			sprintf(sPointerValue, "%.1f", (float)nPointerValue/10);
		}
		else
		{
			sprintf(sPointerValue, "-");
		}

		sprintf(buf, "Pointer Value: %s (X:%d Y:%d) Cutoff: %llu-%llu.", 
			sPointerValue, pPointer->X, pPointer->Y, nCutOffMin, nCutOffMax);

		glRasterPos2i(10,nYLocation);
		glPrintString(GLUT_BITMAP_HELVETICA_18, buf);
		nYLocation -= 26;
	}
}