Commits

Cliff Biffle  committed c3113b9

Added double-buffering for both depth and color data. It turns out that depth and color are mutually asynchronous and arrive at slightly different frequencies, which complicates this code a bit (must manage two separate buffer states).

  • Participants
  • Parent commits a2f6df4

Comments (0)

Files changed (2)

File KVDoubleBufferDepthMap.h

 @interface KVDoubleBufferDepthMap : NSObject <KVDepthMap> {
  @private
   GLfloat linearizationTable[2048];
-  linear_depth_t zs;
-  colors_t colors;
+  
+  linear_depth_t zs[2];
+  colors_t colors[2];
 }
 
 @end

File KVDoubleBufferDepthMap.m

 #import "KVRenderer.h"
 
 @interface KVDoubleBufferDepthMap ()
+
+@property(assign, nonatomic) unsigned int backColorBuffer;
+@property(assign, nonatomic) unsigned int backDepthBuffer;
+
+@property(readonly) unsigned int frontColorBuffer;
+@property(readonly) unsigned int frontDepthBuffer;
+
+@property(assign, nonatomic) unsigned int lastColorBufferRendered;
+@property(assign, nonatomic) unsigned int lastDepthBufferRendered;
+
+- (void) flipBuffers;
+
 - (void) buildLinearizationTable;
 @end
 
 @implementation KVDoubleBufferDepthMap
 
+# pragma mark --- Initialization and properties
+
 - init {
   if ((self = [super init])) {
     [self buildLinearizationTable];
   return self;
 }
 
+@synthesize backColorBuffer;
+
+- (unsigned int) frontColorBuffer {
+  return backColorBuffer ^ 1;
+}
+
+@synthesize backDepthBuffer;
+
+- (unsigned int) frontDepthBuffer {
+  return backDepthBuffer ^ 1;
+}
+
+@synthesize lastDepthBufferRendered, lastColorBufferRendered;
+
 #pragma mark --- KVDepthMap implementation
 
 - (void) updateDepth: (const depth_t *)rawDepthSamples {
-  linear_depth_t *out = &zs;  // Avoid ivar indirection during loop.
+  unsigned int buffer = self.backDepthBuffer;
+  linear_depth_t *out = &zs[buffer];  // Avoid ivar indirection during loop.
   
   for (int y = 0; y < 480; y++) {
     for (int x = 0; x < 640; x++) {
       out->z[y][x] = linearizationTable[rawDepthSamples->samples[y][x]];
     }
   }
+  
+  self.lastDepthBufferRendered = buffer;
 }
 
 - (void) updateColor: (const colors_t *)pixels {
-  memcpy(&colors, pixels, sizeof(colors_t));
+  unsigned int buffer = self.backColorBuffer;
+  
+  memcpy(&colors[buffer], pixels, sizeof(colors_t));
+  
+  self.lastColorBufferRendered = buffer;
 }
 
 - (void) drawInCurrentOpenGLContextWithRenderer: (id <KVRenderer>) renderer {
   NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
-  [renderer drawInCurrentOpenGLContext: &zs colors: &colors];
+  [renderer drawInCurrentOpenGLContext: &zs[self.frontDepthBuffer] colors: &colors[self.frontColorBuffer]];
+  [self flipBuffers];
   NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
-  
-  NSLog(@"Render (%@, lights=%d, texture=%d) took %.03fµs",
-        [[renderer class] description],
-        renderer.lit,
-        renderer.textured,
-        (end - start) * 1000000.);
+
+  if (0) {
+    NSLog(@"Render (%@, lights=%d, texture=%d) took %.03fµs",
+          [[renderer class] description],
+          renderer.lit,
+          renderer.textured,
+          (end - start) * 1000000.);
+  }
 }
 
 #pragma mark --- Internals
 
+- (void) flipBuffers {
+  if (self.lastColorBufferRendered == self.backColorBuffer) {
+    self.backColorBuffer = self.frontColorBuffer;
+  }
+  if (self.lastDepthBufferRendered == self.backDepthBuffer) {
+    self.backDepthBuffer = self.frontDepthBuffer;
+  }
+}
+
 // The Kinect produces 11-bit depth samples.  Z-resolution decreases
 // with distance, following a curve that looks suspiciously like the
 // one used for perspective projection.  The ROS folks at CCNY derived