void* KinectViewer::SynchedRenderer::depthReaderThreadMethod(void)
	{
	Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE);
	// Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS);
	
	/* Read depth frames: */
	while(true)
		{
		/* Read the next depth frame: */
		Kinect::FrameBuffer nextFrame=depthReader->readNextFrame();
		
		#if KINECT_USE_SHADERPROJECTOR
		
		/* Put the new depth frame into the queue: */
		{
		Threads::Mutex::Lock frameQueueLock(frameQueueMutex);
		while(numDepthFrames==numQueueSlots)
			depthFrameQueueFullCond.wait(frameQueueMutex);
		mostRecentDepthFrame=(mostRecentDepthFrame+1)%numQueueSlots;
		depthFrames[mostRecentDepthFrame]=nextFrame;
		if(++numDepthFrames==1)
			frameQueuesEmptyCond.broadcast();
		}
		
		if(nextFrame.timeStamp>=Math::Constants<double>::max)
			break;
		
		#else
		
		/* Process the next depth frame into a mesh: */
		Kinect::MeshBuffer nextMesh;
		projector->processDepthFrame(nextFrame,nextMesh);
		
		/* Put the new mesh into the queue: */
		{
		Threads::Mutex::Lock frameQueueLock(frameQueueMutex);
		while(numDepthFrames==numQueueSlots)
			depthFrameQueueFullCond.wait(frameQueueMutex);
		mostRecentDepthFrame=(mostRecentDepthFrame+1)%numQueueSlots;
		depthFrames[mostRecentDepthFrame]=nextMesh;
		if(++numDepthFrames==1)
			frameQueuesEmptyCond.broadcast();
		}
		
		if(nextMesh.timeStamp>=Math::Constants<double>::max)
			break;
		
		#endif
		}
	
	return 0;
	}
void* KinectPlayer::KinectStreamer::depthDecompressorThreadMethod(void)
	{
	Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE);
	// Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS);
	
	/* Read depth frames: */
	while(true)
		{
		/* Read the next depth frame: */
		Kinect::FrameBuffer nextFrame=depthDecompressor->readNextFrame();
		
		/* Put the new depth frame into the queue: */
		{
		Threads::MutexCond::Lock frameQueueLock(frameQueueCond);
		while(numDepthFrames==2)
			frameQueueCond.wait(frameQueueLock);
		mostRecentDepthFrame=1-mostRecentDepthFrame;
		depthFrames[mostRecentDepthFrame]=nextFrame;
		++numDepthFrames;
		if(numDepthFrames==1)
			frameQueueCond.broadcast();
		}
		
		if(nextFrame.timeStamp==Math::Constants<double>::max)
			break;
		}
	
	return 0;
	}
void* KinectViewer::SynchedRenderer::colorReaderThreadMethod(void)
	{
	Threads::Thread::setCancelState(Threads::Thread::CANCEL_ENABLE);
	// Threads::Thread::setCancelType(Threads::Thread::CANCEL_ASYNCHRONOUS);
	
	/* Read color frames: */
	while(true)
		{
		/* Read the next color frame: */
		Kinect::FrameBuffer nextFrame=colorReader->readNextFrame();
		
		/* Put the new color frame into the queue: */
		{
		Threads::Mutex::Lock frameQueueLock(frameQueueMutex);
		while(numColorFrames==numQueueSlots)
			colorFrameQueueFullCond.wait(frameQueueMutex);
		mostRecentColorFrame=(mostRecentColorFrame+1)%numQueueSlots;
		colorFrames[mostRecentColorFrame]=nextFrame;
		if(++numColorFrames==1)
			frameQueuesEmptyCond.broadcast();
		}
		
		if(nextFrame.timeStamp>=Math::Constants<double>::max)
			break;
		}
	
	return 0;
	}
void KinectViewer::SynchedRenderer::frame(double newTimeStamp)
	{
	timeStamp=newTimeStamp;
	
	/* Wait until the next frame is newer than the new time step: */
	bool newColor=false;
	Kinect::FrameBuffer currentColorFrame;
	bool newDepth=false;
	#if KINECT_USE_SHADERPROJECTOR
	Kinect::FrameBuffer currentDepthFrame;
	#else
	Kinect::MeshBuffer currentDepthFrame;
	#endif
	while(nextColorFrame.timeStamp<=timeStamp||nextDepthFrame.timeStamp<=timeStamp)
		{
		/* Check if both frame queues are empty: */
		Threads::Mutex::Lock frameQueueLock(frameQueueMutex);
		while(numColorFrames==0&&numDepthFrames==0)
			frameQueuesEmptyCond.wait(frameQueueMutex);
		
		/* Advance in the color frame queue: */
		while(numColorFrames>0&&nextColorFrame.timeStamp<=timeStamp)
			{
			newColor=true;
			currentColorFrame=nextColorFrame;
			nextColorFrame=colorFrames[(mostRecentColorFrame-numColorFrames+numQueueSlots+1)%numQueueSlots];
			if(--numColorFrames==numQueueSlots-1)
				colorFrameQueueFullCond.broadcast();
			}
		
		/* Advance in the depth frame queue: */
		while(numDepthFrames>0&&nextDepthFrame.timeStamp<=timeStamp)
			{
			newDepth=true;
			currentDepthFrame=nextDepthFrame;
			nextDepthFrame=depthFrames[(mostRecentDepthFrame-numDepthFrames+numQueueSlots+1)%numQueueSlots];
			if(--numDepthFrames==numQueueSlots-1)
				depthFrameQueueFullCond.broadcast();
			}
		}
	
	/* Update the projector: */
	if(newColor)
		projector->setColorFrame(currentColorFrame);
	if(newDepth)
		{
		#if KINECT_USE_SHADERPROJECTOR
		projector->setDepthFrame(currentDepthFrame);
		#else
		projector->setMesh(currentDepthFrame);
		#endif
		}
	projector->updateFrames();
	}
void KinectPlayer::KinectStreamer::updateFrames(double currentTimeStamp)
	{
	/* Wait until the next frame is newer than the new time step: */
	Kinect::FrameBuffer currentColorFrame;
	Kinect::FrameBuffer currentDepthFrame;
	while(nextColorFrame.timeStamp<=currentTimeStamp||nextDepthFrame.timeStamp<=currentTimeStamp)
		{
		if(nextColorFrame.timeStamp<=currentTimeStamp)
			{
			currentColorFrame=nextColorFrame;
			{
			Threads::MutexCond::Lock frameQueueLock(frameQueueCond);
			while(numColorFrames==0)
				frameQueueCond.wait(frameQueueLock);
			nextColorFrame=colorFrames[(mostRecentColorFrame-numColorFrames+3)%2];
			if(--numColorFrames==1)
				frameQueueCond.broadcast();
			}
			}
		if(nextDepthFrame.timeStamp<=currentTimeStamp)
			{
			currentDepthFrame=nextDepthFrame;
			{
			Threads::MutexCond::Lock frameQueueLock(frameQueueCond);
			while(numDepthFrames==0)
				frameQueueCond.wait(frameQueueLock);
			nextDepthFrame=depthFrames[(mostRecentDepthFrame-numDepthFrames+3)%2];
			if(--numDepthFrames==1)
				frameQueueCond.broadcast();
			}
			}
		}
	
	/* Update the projector: */
	if(currentColorFrame.timeStamp!=0.0)
		projector.setColorFrame(currentColorFrame);
	if(currentDepthFrame.timeStamp!=0.0)
		projector.setDepthFrame(currentDepthFrame);
	projector.updateFrames();
	}