Source

kinect-viewer / KVRenderer.m

Full commit
Cliff Biffle 0351b52 









Cliff Biffle abc6bdc 
Cliff Biffle d0f32bb 
Cliff Biffle 0351b52 







Cliff Biffle 0ea4300 
Cliff Biffle d0f32bb 
Cliff Biffle 0351b52 






Cliff Biffle 0ea4300 
Cliff Biffle d0f32bb 
Cliff Biffle 0351b52 


Cliff Biffle abc6bdc 
Cliff Biffle 0351b52 






Cliff Biffle d0f32bb 


















Cliff Biffle 0351b52 



Cliff Biffle 0ea4300 




Cliff Biffle 0351b52 

























Cliff Biffle e529285 
Cliff Biffle 0351b52 


Cliff Biffle 0ea4300 



Cliff Biffle 9aeccac 
Cliff Biffle 0351b52 

















Cliff Biffle abc6bdc 
Cliff Biffle 0351b52 





Cliff Biffle 9a7e575 



Cliff Biffle abc6bdc 
Cliff Biffle 0351b52 
Cliff Biffle abc6bdc 


Cliff Biffle 0351b52 



Cliff Biffle d0f32bb 




























Cliff Biffle 0351b52 
/*
 * Copyright 2010 Cliff L. Biffle.  All Rights Reserved.
 * Use of this source code is governed by the Apache License 2.0,
 * which can be found in the LICENSE file.
 */

#import "KVRenderer.h"
#import "utility.h"

@interface KVRenderer ()
- (void) buildPointField;
- (GLuint) loadShaderOfType: (GLenum) type fromFiles: (NSArray *) names;

@property(assign, nonatomic) double rayCastingTotal;
@property(assign, nonatomic) NSUInteger rayCastingCount;

@property(assign, nonatomic) double vertexPlacementTotal;
@property(assign, nonatomic) NSUInteger vertexPlacementCount;

@property GLuint depthTexture;
@property GLuint colorTexture;
@property GLuint program;

- (void) renderAsPointsWithOptions: (NSDictionary *) options;
@end

@implementation KVRenderer

@synthesize rayCastingCount, rayCastingTotal, vertexPlacementCount, vertexPlacementTotal;
@synthesize depthTexture, colorTexture;
@synthesize program;

- init {
  if ((self = [super init])) {
    [self buildPointField];
  }
  return self;
}

#pragma mark --- Implementation of KVSpaceModel

- (void) initGL {
  GLint vertexShader = [self loadShaderOfType: GL_VERTEX_SHADER
                                    fromFiles: [NSArray arrayWithObject: @"main"]];
  
  GLint fragmentShader = [self loadShaderOfType: GL_FRAGMENT_SHADER
                                      fromFiles: [NSArray arrayWithObjects: @"lighting", @"main", nil]];
  
  program = glCreateProgram();
  glAttachShader(program, vertexShader);
  glAttachShader(program, fragmentShader);
  glLinkProgram(program);
  glUseProgram(program);
  
  GLint depthUniform = glGetUniformLocation(program, "depthTex");
  glUniform1i(depthUniform, 0);
  
  GLint colorUniform = glGetUniformLocation(program, "colorTex");
  glUniform1i(colorUniform, 1);
  
  
  glGenTextures(1, &depthTexture);
  glBindTexture(GL_TEXTURE_2D, depthTexture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

  glGenTextures(1, &colorTexture);
  glBindTexture(GL_TEXTURE_2D, colorTexture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}

- (void) setDepthSamples: (NSData *)data {
  NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
  
  const uint16_t *sample = [data bytes];
  memcpy(&depthImage, sample, sizeof depthImage);
  
  NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
  rayCastingCount++;
  rayCastingTotal += end - start;
  
  if ((rayCastingCount & 0xF) == 0) {
    NSLog(@"Raycasting: latest %.03fµs mean %.03fµs",
          (end - start) * 1000000.,
          (rayCastingTotal / rayCastingCount) * 1000000.);
  }
}

- (void) setColorSamples: (NSData *)data {
  memcpy(&colorImage, [data bytes], sizeof colorImage);
}

- (void) drawInCurrentOpenGLContextWithOptions: (NSDictionary *) options {
  NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, depthTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE16, 640, 480, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, &depthImage);
  
  glActiveTexture(GL_TEXTURE1);
  glBindTexture(GL_TEXTURE_2D, colorTexture);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, &colorImage);
  
  [self renderAsPointsWithOptions: options];
  
  NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
  vertexPlacementCount++;
  vertexPlacementTotal += end - start;
  
  if ((vertexPlacementCount & 0xF) == 0) {
    NSLog(@"Vertex placement: latest %.03fµs mean %.03fµs",
          (end - start) * 1000000.,
          (vertexPlacementTotal / vertexPlacementCount) * 1000000.);
  }
  
}

#pragma mark --- Internals

- (void) renderAsPointsWithOptions: (NSDictionary *) options {
  glColor3f(1, 1, 1);
  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(2, GL_FLOAT, 0, &points);

  glDrawArrays(GL_POINTS, 0, 640 * 480);
  
  glDisableClientState(GL_VERTEX_ARRAY);
}

// We pre-fill the X and Y components with distance from the top-left
// corner of the image.  These values never make it to the rasterizer:
// they are merely input to the vertex shader that performs perspective
// correction.
- (void) buildPointField {
  for (int y = 0; y < 480; y++) {
    for (int x = 0; x < 640; x++) {
      points[y][x].x = (x / 640.f);
      points[y][x].y = (y / 480.f);
    }
  }
}

- (GLuint) loadShaderOfType: (GLenum) type fromFiles: (NSArray *) names {
  NSString *extension;
  if (type == GL_VERTEX_SHADER) {
    extension = @"vs";
  } else if (type == GL_FRAGMENT_SHADER) {
    extension = @"fs";
  } else if (type == GL_GEOMETRY_SHADER_EXT) {
    extension = @"gs";
  } else {
    @throw [NSException exceptionWithName: @"KVContractError" reason: @"Bad value for shader type" userInfo: nil];
  }
  
  const char *sources[[names count]];
  GLint lengths[[names count]];
  int i = 0;
  for (NSString *name in names) {
    NSData *source = [NSData dataWithContentsOfFile: [[NSBundle mainBundle] pathForResource: name ofType: extension]];
    sources[i] = [source bytes];
    lengths[i] = (GLint) [source length];
    i++;
  }
  
  GLuint shader = glCreateShader(type);
  glShaderSource(shader, i, &sources[0], &lengths[0]);
  glCompileShader(shader);
  
  return shader;
}

@end