Source

kinect-viewer / KVTriStripRenderer.m

Full commit
/*
 * 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 "KVTriStripRenderer.h"
#import "types.h"
#import "utility.h"

@implementation KVTriStripRenderer

- (void) drawInCurrentOpenGLContext: (const linear_depth_t *)zs
                             colors: (const colors_t *)colors {
  // Theory: each horizontal raster row of the image is converted to a
  // triangle strip, using the simplest possible method:
  //
  // 0 2 4 6
  // |/|/|/
  // 1 3 5   ...and so on.
  
  // Avoid message send for a large performance win.
  BOOL textured = self.textured;
  BOOL lit = self.lit;
  const projective_transform_t xform = self.colorTransform;

  KVAbstractRendererProjector projector =
      (KVAbstractRendererProjector) [self methodForSelector: @selector(projectInto:x:y:z:)];

  vec3f_t baseColor = [self colorAsRGBVector];
  glColor3fv(&baseColor.x);
  
  for (int y = 0; y < 480; y++) {
    for (int x = 0; x < 640; x++) {
      GLfloat d = zs->z[y][x];
      projector(self, @selector(projectInto:x:y:z:), &vertices[y][x], x, y, d);
    }
  }
  
  if (lit) {
    // The right and bottom edges won't have correct normals.
    // So be it.
    for (int y = 0; y < 479; y++) {
      for (int x = 0; x < 639; x++) {
        normals[y][x] = compute_normal(vertices[y][x], vertices[y + 1][x], vertices[y + 1][x + 1]);
      }
    }
  }
  
  for (int y = 0; y < 479; y++) {
    glBegin(GL_TRIANGLE_STRIP);
    
    // Whether we have called glBegin
    BOOL inStrip = YES;
    // Z of last point rendered, for slope test.
    GLfloat lastDepth = vertices[y][0].z;
    
    for (int x = 0; x < 640; x++) {
      
      for (int step = 0; step < 2; step++) {
        GLfloat d = vertices[y + step][x].z;
        GLfloat deltaZ = fabsf(d - lastDepth);
        lastDepth = d;
        
        if (d == 0.F || deltaZ > 0.05F * d) {
          // Hole in the data or depth discontinuity.
          if (inStrip) {
            glEnd();
            inStrip = NO;
          }
          // Break out of step loop to ensure that we always start
          // each vertical edge at the *top*.  Otherwise the winding
          // gets hosed.  This may cause us to skip a single vertex.
          break;
        } else {
          // Valid data.
          if (!inStrip) {
            glBegin(GL_TRIANGLE_STRIP);
            inStrip = YES;
          }
        }
        
        if (lit) {
          glNormal3fv(&normals[y + step][x].x);
        }

        if (textured) {
          int colorX = (int) (x * xform.scale.x + xform.offset.x);
          int colorY = (int) ((y + step) * xform.scale.y + xform.offset.y);
          const rgb_t *pixelColor = &colors->pixels[colorY][colorX];
          
          glColor3ubv(&pixelColor->r);
        } else if (!lit) {
          vec3f_t falseColor = vector_scale(baseColor, 1.F - d/10.F);
          glColor3fv(&falseColor.x);
        }
        glVertex3fv(&vertices[y + step][x].x);
      }
    }
    if (inStrip) glEnd();
  }
}

@end