// File: 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:
subq $0x1d8, %rsp            # imm = 0x1D8
movq %rdi, 0x1c8(%rsp)
movl %esi, 0x1c4(%rsp)
movl %edx, 0x1c0(%rsp)
movq %rcx, 0x1b8(%rsp)
movq 0x1c8(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x3df40
movq %rax, %rdi
callq 0x3df10
cvtsi2sd %eax, %xmm0
movsd 0x2067ed(%rip), %xmm1   # 0x241028
mulsd %xmm1, %xmm0
movsd 0x2067c9(%rip), %xmm1   # 0x241010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x1b4(%rsp)
movl $0x4100, %edi           # imm = 0x4100
callq 0x28230
movq 0x20(%rsp), %rdi
addq $0x78, %rdi
callq 0x2f6d0
movq %rax, %rdi
xorl %esi, %esi
callq 0xd1a70
movq 0x20(%rsp), %rdi
movq (%rdi), %rax
callq *0x230(%rax)
cvtsi2ssl 0x1b4(%rsp), %xmm0
callq 0x29370
movq 0x20(%rsp), %rax
cmpl $0x0, 0x324(%rax)
je 0x3a9b8
movl $0xb50, %edi            # imm = 0xB50
callq 0x28240
movl $0x0, 0x1b0(%rsp)
movq 0x20(%rsp), %rax
movl 0x1b0(%rsp), %ecx
movl %ecx, 0x1c(%rsp)
movq 0x8(%rax), %rdi
callq 0x2f000
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x3a9b6
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rdi
movl 0x1b0(%rsp), %esi
callq 0x2f840
movq %rax, 0x1a8(%rsp)
movl 0x1b0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a0(%rsp)
movl 0x1a0(%rsp), %eax
sarl $0x10, %eax
andl $0xff, %eax
movb %al, 0x1a4(%rsp)
movl 0x1a0(%rsp), %eax
sarl $0x8, %eax
andl $0xff, %eax
movb %al, 0x1a5(%rsp)
movl 0x1a0(%rsp), %eax
andl $0xff, %eax
movb %al, 0x1a6(%rsp)
movb $-0x3, 0x1a7(%rsp)
leaq 0x1a4(%rsp), %rdi
callq 0x3ed90
movq 0x1a8(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x198(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x2f310
movq 0x10(%rsp), %rdi
movq 0x198(%rsp), %rsi
movq (%rdi), %rax
movsd 0x206676(%rip), %xmm0   # 0x241010
callq *0xf0(%rax)
movl 0x1b0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1b0(%rsp)
jmp 0x3a8bb
jmp 0x3a9b8
movss 0x20706c(%rip), %xmm0   # 0x241a2c
callq 0x29370
callq 0x29580
movq 0x20(%rsp), %rdi
movq (%rdi), %rax
callq *0x238(%rax)
movl 0x1c4(%rsp), %edi
movl 0x1c0(%rsp), %esi
leaq 0x194(%rsp), %rax
movl $0x1, %ecx
movl $0x1908, %r8d           # imm = 0x1908
movl $0x1401, %r9d           # imm = 0x1401
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x28450
movzbl 0x197(%rsp), %eax
cmpl $0x0, %eax
jne 0x3aa28
movq $0x0, 0x1d0(%rsp)
jmp 0x3ac4b
movzbl 0x194(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x190(%rsp)
movzbl 0x195(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x18c(%rsp)
movzbl 0x196(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x188(%rsp)
movzbl 0x197(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x184(%rsp)
cmpl $0xfd, 0x184(%rsp)
je 0x3aa96
movq $0x0, 0x1d0(%rsp)
jmp 0x3ac4b
movl 0x190(%rsp), %eax
shll $0x10, %eax
movl 0x18c(%rsp), %ecx
shll $0x8, %ecx
orl %ecx, %eax
orl 0x188(%rsp), %eax
movl %eax, 0x180(%rsp)
movl 0x180(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x180(%rsp)
cmpl $0x0, 0x180(%rsp)
jge 0x3aae6
movq $0x0, 0x1d0(%rsp)
jmp 0x3ac4b
movq 0x20(%rsp), %rax
movl 0x180(%rsp), %ecx
movl %ecx, 0xc(%rsp)
movq 0x8(%rax), %rdi
callq 0x2f000
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jl 0x3ab1a
movq $0x0, 0x1d0(%rsp)
jmp 0x3ac4b
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rdi
movl 0x180(%rsp), %esi
callq 0x2f840
movq %rax, 0x178(%rsp)
cmpq $0x0, 0x1b8(%rsp)
je 0x3ac3b
leaq 0x140(%rsp), %rsi
movl $0xba2, %edi            # imm = 0xBA2
callq 0x289d0
leaq 0xc0(%rsp), %rsi
movl $0xba6, %edi            # imm = 0xBA6
callq 0x28bf0
leaq 0x40(%rsp), %rsi
movl $0xba7, %edi            # imm = 0xBA7
callq 0x28bf0
movl 0x1c4(%rsp), %edi
movl 0x1c0(%rsp), %esi
movl $0x1, %ecx
movl $0x1902, %r8d           # imm = 0x1902
movl $0x1406, %r9d           # imm = 0x1406
leaq 0x174(%rsp), %rax
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x28450
cvtsi2sdl 0x1c4(%rsp), %xmm0
cvtsi2sdl 0x1c0(%rsp), %xmm1
movss 0x174(%rsp), %xmm2
cvtss2sd %xmm2, %xmm2
leaq 0xc0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x140(%rsp), %rdx
leaq 0x150(%rsp), %rcx
leaq 0x150(%rsp), %r8
addq $0x8, %r8
leaq 0x150(%rsp), %r9
addq $0x10, %r9
callq 0x29460
movsd 0x150(%rsp), %xmm0
movsd 0x158(%rsp), %xmm1
movsd 0x160(%rsp), %xmm2
leaq 0x28(%rsp), %rdi
callq 0x1622c0
movq 0x1b8(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x162950
movq 0x178(%rsp), %rax
movq %rax, 0x1d0(%rsp)
movq 0x1d0(%rsp), %rax
addq $0x1d8, %rsp            # imm = 0x1D8
retq
nopl (%rax,%rax)