// File: /workspace/github_cpp_makefile_star2_O3/tomfunkhouser[P]gaps/pkgs/R3Utils/R3SurfelViewer.cpp
// Function: gaps::R3SurfelViewer::PickImage(int, int, gaps::R3Point*)
R3SurfelImage *R3SurfelViewer::
PickImage(int x, int y, R3Point *picked_position) 
{
  // How close the cursor has to be to a point (in pixels)
  int pick_tolerance = 0.01 * Viewport().Width() + 1;

  // Clear window 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Set viewing transformation
  viewer.Camera().Load();

  // Set viewing extent
  EnableViewingExtent();

  // Set OpenGL stuff
  glLineWidth(pick_tolerance);    

  // Draw image viewpoints
  if (image_viewpoint_visibility) {
    glDisable(GL_LIGHTING);
    for (int i = 0; i < scene->NImages(); i++) {
      R3SurfelImage *image = scene->Image(i);
      unsigned char rgba[4];
      int image_index = i + 1;
      rgba[0] = (image_index >> 16) & 0xFF;
      rgba[1] = (image_index >> 8) & 0xFF;
      rgba[2] = image_index & 0xFF;
      rgba[3] = 0xFD;
      RNLoadRgba(rgba);
      image->Draw(0);
    }
  }

  // Reset OpenGL stuff
  glLineWidth(1);
  glFinish();

  // Reset viewing modes
  DisableViewingExtent();

  // Read color buffer at cursor position
  unsigned char rgba[4];
  glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
  if (rgba[3] == 0) return NULL;

  // Determine image index
  int r = rgba[0] & 0xFF;
  int g = rgba[1] & 0xFF;
  int b = rgba[2] & 0xFF;
  int a = rgba[3] & 0xFF;
  if (a != 0xFD) return NULL;
  int image_index = (r << 16) | (g << 8) | b;
  image_index--;

  // Determine image
  if (image_index < 0) return NULL;
  if (image_index >= scene->NImages()) return NULL;
  R3SurfelImage *picked_image = scene->Image(image_index);

  // Find hit position
  if (picked_position) {
    GLfloat depth;
    GLdouble p[3];
    GLint viewport[4];
    GLdouble modelview_matrix[16];
    GLdouble projection_matrix[16];
    glGetIntegerv(GL_VIEWPORT, viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
    glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
    glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
    gluUnProject(x, y, depth, modelview_matrix, projection_matrix, viewport, &(p[0]), &(p[1]), &(p[2]));
    R3Point position(p[0], p[1], p[2]);
    *picked_position = position;
  }

  // Return picked image
  return picked_image;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x188, %rsp            # imm = 0x188
movq %rcx, 0x10(%rsp)
movl %edx, %ebp
movl %esi, %r14d
movq %rdi, %r15
cvtsi2sdl 0x118(%rdi), %xmm0
mulsd 0x10525a(%rip), %xmm0   # 0x138028
addsd 0x105232(%rip), %xmm0   # 0x138008
movapd %xmm0, 0x20(%rsp)
movl $0x4100, %edi           # imm = 0x4100
callq 0x271f0
leaq 0x80(%r15), %rdi
xorl %esi, %esi
callq 0x7a9a0
movq (%r15), %rax
movq %r15, %rdi
callq *0x230(%rax)
cvttpd2dq 0x20(%rsp), %xmm0
cvtdq2ps %xmm0, %xmm0
callq 0x281a0
cmpl $0x0, 0x324(%r15)
je 0x32e91
movl $0xb50, %edi            # imm = 0xB50
callq 0x27200
movq 0x8(%r15), %rax
cmpl $0x0, 0x9c(%rax)
jle 0x32e91
movl $0x1, %ebx
leaq 0x60(%rsp), %r12
movq 0x90(%rax), %rax
movq -0x8(%rax,%rbx,8), %r13
movl %ebx, %eax
shrl $0x10, %eax
movb %al, 0x60(%rsp)
movb %bh, 0x61(%rsp)
movb %bl, 0x62(%rsp)
movb $-0x3, 0x63(%rsp)
movq %r12, %rdi
callq 0x27420
movq (%r13), %rax
movq %r13, %rdi
xorl %esi, %esi
movsd 0x105194(%rip), %xmm0   # 0x138008
callq *0xf0(%rax)
movq 0x8(%r15), %rax
movslq 0x9c(%rax), %rcx
leaq 0x1(%rbx), %rdx
cmpq %rcx, %rbx
movq %rdx, %rbx
jl 0x32e39
movss 0x1051a7(%rip), %xmm0   # 0x138040
callq 0x281a0
callq 0x28370
movq (%r15), %rax
movq %r15, %rdi
callq *0x238(%rax)
leaq 0xc(%rsp), %rbx
movq %rbx, (%rsp)
movl %r14d, %edi
movl %ebp, %esi
movl $0x1, %edx
movl $0x1, %ecx
movl $0x1908, %r8d           # imm = 0x1908
movl $0x1401, %r9d           # imm = 0x1401
callq 0x273d0
cmpb $-0x3, 0x3(%rbx)
jne 0x32f02
movzbl 0xc(%rsp), %ecx
shll $0x10, %ecx
movzwl 0xd(%rsp), %eax
rolw $0x8, %ax
movzwl %ax, %eax
orl %ecx, %eax
je 0x32f02
movq 0x8(%r15), %rcx
cmpl 0x9c(%rcx), %eax
jle 0x32f1a
xorl %r15d, %r15d
movq %r15, %rax
addq $0x188, %rsp            # imm = 0x188
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x90(%rcx), %rcx
movl %eax, %eax
movq -0x8(%rcx,%rax,8), %r15
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x32f05
leaq 0x30(%rsp), %rsi
movl $0xba2, %edi            # imm = 0xBA2
callq 0x278c0
leaq 0x60(%rsp), %r13
movl $0xba6, %edi            # imm = 0xBA6
movq %r13, %rsi
callq 0x27a90
leaq 0x100(%rsp), %r12
movl $0xba7, %edi            # imm = 0xBA7
movq %r12, %rsi
callq 0x27a90
leaq 0x1c(%rsp), %rbx
movq %rbx, (%rsp)
movl %r14d, %edi
movl %ebp, %esi
movl $0x1, %edx
movl $0x1, %ecx
movl $0x1902, %r8d           # imm = 0x1902
movl $0x1406, %r9d           # imm = 0x1406
callq 0x273d0
xorps %xmm0, %xmm0
cvtsi2sd %r14d, %xmm0
cvtsi2sd %ebp, %xmm1
cvtss2sd (%rbx), %xmm2
leaq 0x48(%rsp), %r8
leaq 0x50(%rsp), %r9
leaq 0x40(%rsp), %r14
movq %r13, %rdi
movq %r12, %rsi
leaq 0x30(%rsp), %rdx
movq %r14, %rcx
callq 0x28280
movsd (%r14), %xmm0
movsd 0x8(%r14), %xmm1
movsd 0x10(%r14), %xmm2
leaq 0xe8(%rsp), %r14
movq %r14, %rdi
callq 0xc3d32
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0xc409a
jmp 0x32f05