// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3SurfelViewer.cpp
// Function: gaps::R3SurfelViewer::DrawVBO(int) const
void R3SurfelViewer::
DrawVBO(int color_scheme) const
{
#if (R3_SURFEL_VIEWER_DRAW_METHOD == R3_SURFEL_VIEWER_DRAW_WITH_VBO)
  // Update VBO
  ((R3SurfelViewer *) this)->UpdateVBO();

  // Check VBO
  if (vbo_nsurfels == 0) return;

  // Determine stride and point size
  int subsampling = 1;
  float pointSize = SurfelSize();
  if (color_scheme == R3_SURFEL_VIEWER_COLOR_BY_PICK_INDEX)
    pointSize = 0.01 * Viewport().Width() + 1;
  if (subsampling_multiplier_when_mouse_down > 1) {
    if (mouse_button[0] || mouse_button[1] || mouse_button[2]) {
      subsampling = subsampling_multiplier_when_mouse_down;
      pointSize *= sqrt(subsampling_multiplier_when_mouse_down);
      glPointSize(pointSize);
    }
  }

  // Assign shader and its variables
  if (shader_program > 0) {
    glUseProgram(shader_program);
    int pointSizeLocation = glGetUniformLocation(shader_program, "pointSize");
    glUniform1f(pointSizeLocation, pointSize);
  }

  // Enable position buffer
  if (vbo_position_buffer > 0) {
    glBindBuffer(GL_ARRAY_BUFFER, vbo_position_buffer);
    glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat) * subsampling, 0);
    glEnableClientState(GL_VERTEX_ARRAY);
  }

  // Enable color/normal buffers
  if (color_scheme == R3_SURFEL_VIEWER_COLOR_BY_PICK_INDEX) {
    // Enable color buffer to draw pick colors 
    if (vbo_color_buffer > 0) {
      // Set color pointer to second half of buffer where pick colors are
      void *pick_color_offset = (void *) (3 * vbo_nsurfels * sizeof(GLubyte));
      glBindBuffer(GL_ARRAY_BUFFER, vbo_color_buffer);
      glColorPointer(3, GL_UNSIGNED_BYTE, 3 * sizeof(GLubyte) * subsampling, pick_color_offset);
      glEnableClientState(GL_COLOR_ARRAY);
    }

    // Draw points with pick color
    glDrawArrays(GL_POINTS, 0, vbo_nsurfels);

    // Reset color pointer to start of buffer where regular colors are
    if (vbo_color_buffer > 0) {
      glBindBuffer(GL_ARRAY_BUFFER, vbo_color_buffer);
      glColorPointer(3, GL_UNSIGNED_BYTE,  3 * sizeof(GLubyte) * subsampling, 0);
    }
  }
  else if (color_scheme == R3_SURFEL_VIEWER_COLOR_BY_SHADING) {
    // Enable normal buffer
    if (vbo_normal_buffer > 0) {
      glBindBuffer(GL_ARRAY_BUFFER, vbo_normal_buffer);
      glNormalPointer(GL_FLOAT,  3 * sizeof(GLfloat) * subsampling, 0);
      glEnableClientState(GL_NORMAL_ARRAY);
    }

    // Draw points with shading
    glEnable(GL_LIGHTING);
    RNLoadRgb(0.8, 0.8, 0.8);
    glDrawArrays(GL_POINTS, 0, vbo_nsurfels);
    glDisable(GL_LIGHTING);
  }
  else {
    // Enable color buffer
    if (vbo_color_buffer > 0) {
      glBindBuffer(GL_ARRAY_BUFFER, vbo_color_buffer);
      glColorPointer(3, GL_UNSIGNED_BYTE, 3 * sizeof(GLubyte) * subsampling, 0);
      glEnableClientState(GL_COLOR_ARRAY);
    }

    // Draw points with color
    glDrawArrays(GL_POINTS, 0, vbo_nsurfels);
  }

  // Disable client state
  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  // Reset shader
  glUseProgram(0);
#endif
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movl %esi, 0x1c(%rsp)
movq 0x20(%rsp), %rdi
movq %rdi, (%rsp)
movq (%rdi), %rax
callq *0x380(%rax)
movq (%rsp), %rax
cmpl $0x0, 0x604(%rax)
jne 0x3c991
jmp 0x3ccf5
movq (%rsp), %rdi
movl $0x1, 0x18(%rsp)
callq 0x3e890
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x14(%rsp)
cmpl $0xe, 0x1c(%rsp)
jne 0x3c9ea
movq (%rsp), %rdi
callq 0x3df40
movq %rax, %rdi
callq 0x3df10
cvtsi2sd %eax, %xmm0
movsd 0x204658(%rip), %xmm1   # 0x241028
mulsd %xmm1, %xmm0
movsd 0x204634(%rip), %xmm1   # 0x241010
addsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x14(%rsp)
movq (%rsp), %rax
cmpl $0x1, 0x490(%rax)
jle 0x3ca5f
movq (%rsp), %rax
cmpl $0x0, 0x49c(%rax)
jne 0x3ca1e
movq (%rsp), %rax
cmpl $0x0, 0x4a0(%rax)
jne 0x3ca1e
movq (%rsp), %rax
cmpl $0x0, 0x4a4(%rax)
je 0x3ca5d
movq (%rsp), %rax
movl 0x490(%rax), %ecx
movl %ecx, 0x18(%rsp)
movl 0x490(%rax), %edi
callq 0x3f160
movaps %xmm0, %xmm1
movss 0x14(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x14(%rsp)
movss 0x14(%rsp), %xmm0
callq 0x280b0
jmp 0x3ca5f
movq (%rsp), %rax
cmpl $0x0, 0x608(%rax)
jbe 0x3cab9
movq (%rsp), %rcx
movq 0x286559(%rip), %rax    # 0x2c2fd0
movq (%rax), %rax
movl 0x608(%rcx), %edi
callq *%rax
movq (%rsp), %rcx
movq 0x28648b(%rip), %rax    # 0x2c2f18
movq (%rax), %rax
movl 0x608(%rcx), %edi
leaq 0x205073(%rip), %rsi    # 0x241b10
callq *%rax
movl %eax, 0x10(%rsp)
movq 0x2864de(%rip), %rax    # 0x2c2f88
movq (%rax), %rax
movl 0x10(%rsp), %edi
movss 0x14(%rsp), %xmm0
callq *%rax
movq (%rsp), %rax
cmpl $0x0, 0x5f8(%rax)
jbe 0x3cb09
movq (%rsp), %rcx
movq 0x2864cf(%rip), %rax    # 0x2c2fa0
movq (%rax), %rax
movl 0x5f8(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movslq 0x18(%rsp), %rax
imulq $0xc, %rax, %rax
movl %eax, %edx
movl $0x3, %edi
movl $0x1406, %esi           # imm = 0x1406
xorl %eax, %eax
movl %eax, %ecx
callq 0x28aa0
movl $0x8074, %edi           # imm = 0x8074
callq 0x28670
cmpl $0xe, 0x1c(%rsp)
jne 0x3cbd5
movq (%rsp), %rax
cmpl $0x0, 0x600(%rax)
jbe 0x3cb77
movq (%rsp), %rcx
imull $0x3, 0x604(%rcx), %eax
movl %eax, %eax
shlq $0x0, %rax
movq %rax, 0x8(%rsp)
movq 0x286462(%rip), %rax    # 0x2c2fa0
movq (%rax), %rax
movl 0x600(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movslq 0x18(%rsp), %rax
imulq $0x3, %rax, %rax
movl %eax, %edx
movq 0x8(%rsp), %rcx
movl $0x3, %edi
movl $0x1401, %esi           # imm = 0x1401
callq 0x28a70
movl $0x8076, %edi           # imm = 0x8076
callq 0x28670
movq (%rsp), %rax
movl 0x604(%rax), %edx
xorl %esi, %esi
movl %esi, %edi
callq 0x28070
movq (%rsp), %rax
cmpl $0x0, 0x600(%rax)
jbe 0x3cbd0
movq (%rsp), %rcx
movq 0x2863fe(%rip), %rax    # 0x2c2fa0
movq (%rax), %rax
movl 0x600(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movslq 0x18(%rsp), %rax
imulq $0x3, %rax, %rax
movl %eax, %edx
movl $0x3, %edi
movl $0x1401, %esi           # imm = 0x1401
xorl %eax, %eax
movl %eax, %ecx
callq 0x28a70
jmp 0x3cccc
cmpl $0x1, 0x1c(%rsp)
jne 0x3cc67
movq (%rsp), %rax
cmpl $0x0, 0x5fc(%rax)
jbe 0x3cc2b
movq (%rsp), %rcx
movq 0x2863a8(%rip), %rax    # 0x2c2fa0
movq (%rax), %rax
movl 0x5fc(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movslq 0x18(%rsp), %rax
imulq $0xc, %rax, %rax
movl %eax, %esi
movl $0x1406, %edi           # imm = 0x1406
xorl %eax, %eax
movl %eax, %edx
callq 0x29250
movl $0x8075, %edi           # imm = 0x8075
callq 0x28670
movl $0xb50, %edi            # imm = 0xB50
callq 0x28960
movsd 0x204923(%rip), %xmm2   # 0x241560
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x2f2e0
movq (%rsp), %rax
movl 0x604(%rax), %edx
xorl %esi, %esi
movl %esi, %edi
callq 0x28070
movl $0xb50, %edi            # imm = 0xB50
callq 0x28240
jmp 0x3ccca
movq (%rsp), %rax
cmpl $0x0, 0x600(%rax)
jbe 0x3ccb7
movq (%rsp), %rcx
movq 0x286321(%rip), %rax    # 0x2c2fa0
movq (%rax), %rax
movl 0x600(%rcx), %esi
movl $0x8892, %edi           # imm = 0x8892
callq *%rax
movslq 0x18(%rsp), %rax
imulq $0x3, %rax, %rax
movl %eax, %edx
movl $0x3, %edi
movl $0x1401, %esi           # imm = 0x1401
xorl %eax, %eax
movl %eax, %ecx
callq 0x28a70
movl $0x8076, %edi           # imm = 0x8076
callq 0x28670
movq (%rsp), %rax
movl 0x604(%rax), %edx
xorl %esi, %esi
movl %esi, %edi
callq 0x28070
jmp 0x3cccc
movl $0x8074, %edi           # imm = 0x8074
callq 0x285f0
movl $0x8075, %edi           # imm = 0x8075
callq 0x285f0
movl $0x8076, %edi           # imm = 0x8076
callq 0x285f0
xorl %edi, %edi
movq 0x2862dd(%rip), %rax    # 0x2c2fd0
callq *(%rax)
addq $0x28, %rsp
retq
nopw (%rax,%rax)