// File: tomfunkhouser[P]gaps/apps/gapsview/gapsview.cpp
// Function: Pick(double, double, gaps::R3Point*, int*, int*, int*)
static int
Pick(double x, double y, R3Point *hit_position = NULL,
  int *hit_model_index = NULL, int *hit_element_type = NULL, int *hit_element_index = NULL)
{
  // Initialize result
  if (hit_position) *hit_position = R3unknown_point;
  if (hit_model_index) *hit_model_index = -1;
  if (hit_element_type) *hit_element_type = -1;
  if (hit_element_index) *hit_element_index = -1;

  // Clear window 
  glClearColor(0, 0, 0, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

  // Draw everything
  int pick_tolerance = 10;
  glDisable(GL_LIGHTING);
  glDisable(GL_MULTISAMPLE);
  glPointSize(2 * pick_tolerance);    
  glLineWidth(2 * pick_tolerance);    
  DrawData(PICK_COLOR_SCHEME);
  glEnable(GL_MULTISAMPLE);
  glPointSize(1);
  glLineWidth(1);
  glFinish();

  // 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 0;
  int r = rgba[0] & 0xFF;
  int g = rgba[1] & 0xFF;
  int b = rgba[2] & 0xFF;
  int a = rgba[3] & 0xFF;
  if (a == 0) return 0;
  if (a == 0xFF) return 0;

  // Get model index
  int model_index = (a >> 4) & 0x0F;
  if (model_index == 0) return 0;
  model_index -= 1;

  // Get element type
  int element_type = a & 0x0F;
  if (element_type == 0) return 0;
  element_type -= 1;

  // Get element index
  int element_index = (r) | (g << 8) | (b << 16);
  if (element_index < 1) return 0;
  element_index -= 1;

  // Return hit info
  if (hit_model_index) *hit_model_index = model_index;
  if (hit_element_type) *hit_element_type = element_type;
  if (hit_element_index) *hit_element_index = element_index;

  // Return hit position
  if (hit_position) {
    // Find hit 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]);
    *hit_position = position;
  }
  
  // Return success
  return 1;
}

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movsd %xmm0, 0x198(%rsp)
movsd %xmm1, 0x190(%rsp)
movq %rdi, 0x188(%rsp)
movq %rsi, 0x180(%rsp)
movq %rdx, 0x178(%rsp)
movq %rcx, 0x170(%rsp)
cmpq $0x0, 0x188(%rsp)
je 0x365a8
movq 0x188(%rsp), %rdi
leaq 0x6ccdd5(%rip), %rsi    # 0x703378
callq 0x180420
cmpq $0x0, 0x180(%rsp)
je 0x365c1
movq 0x180(%rsp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
cmpq $0x0, 0x178(%rsp)
je 0x365da
movq 0x178(%rsp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
cmpq $0x0, 0x170(%rsp)
je 0x365f3
movq 0x170(%rsp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
xorps %xmm2, %xmm2
movss 0x22fb16(%rip), %xmm3   # 0x266114
movaps %xmm2, %xmm0
movaps %xmm2, %xmm1
callq 0x29250
movl $0x4100, %edi           # imm = 0x4100
callq 0x29a70
movq 0x2c8696(%rip), %rdi    # 0x2fecb0
callq 0x38d50
movq %rax, %rdi
xorl %esi, %esi
callq 0xeed00
movl $0xa, 0x16c(%rsp)
movl $0xb50, %edi            # imm = 0xB50
callq 0x2a130
movl $0x809d, %edi           # imm = 0x809D
callq 0x2a130
movl 0x16c(%rsp), %eax
shll %eax
cvtsi2ss %eax, %xmm0
callq 0x29700
movl 0x16c(%rsp), %eax
shll %eax
cvtsi2ss %eax, %xmm0
callq 0x29310
movl $0x5, %edi
callq 0x30d70
movl $0x809d, %edi           # imm = 0x809D
callq 0x29a50
movss 0x22fa8c(%rip), %xmm0   # 0x266114
callq 0x29700
movss 0x22fa7f(%rip), %xmm0   # 0x266114
callq 0x29310
callq 0x29fc0
cvttsd2si 0x198(%rsp), %edi
cvttsd2si 0x190(%rsp), %esi
leaq 0x168(%rsp), %rax
movl $0x1, %ecx
movl $0x1908, %r8d           # imm = 0x1908
movl $0x1401, %r9d           # imm = 0x1401
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x29bb0
movzbl 0x16b(%rsp), %eax
cmpl $0x0, %eax
jne 0x366f2
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
movzbl 0x168(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x164(%rsp)
movzbl 0x169(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x160(%rsp)
movzbl 0x16a(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x15c(%rsp)
movzbl 0x16b(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x158(%rsp)
cmpl $0x0, 0x158(%rsp)
jne 0x3675c
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
cmpl $0xff, 0x158(%rsp)
jne 0x36779
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
movl 0x158(%rsp), %eax
sarl $0x4, %eax
andl $0xf, %eax
movl %eax, 0x154(%rsp)
cmpl $0x0, 0x154(%rsp)
jne 0x367a7
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
movl 0x154(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x154(%rsp)
movl 0x158(%rsp), %eax
andl $0xf, %eax
movl %eax, 0x150(%rsp)
cmpl $0x0, 0x150(%rsp)
jne 0x367e3
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
movl 0x150(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x150(%rsp)
movl 0x164(%rsp), %eax
movl 0x160(%rsp), %ecx
shll $0x8, %ecx
orl %ecx, %eax
movl 0x15c(%rsp), %ecx
shll $0x10, %ecx
orl %ecx, %eax
movl %eax, 0x14c(%rsp)
cmpl $0x1, 0x14c(%rsp)
jge 0x36834
movl $0x0, 0x1a4(%rsp)
jmp 0x369ac
movl 0x14c(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x14c(%rsp)
cmpq $0x0, 0x180(%rsp)
je 0x36861
movl 0x154(%rsp), %ecx
movq 0x180(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x178(%rsp)
je 0x3687d
movl 0x150(%rsp), %ecx
movq 0x178(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x170(%rsp)
je 0x36899
movl 0x14c(%rsp), %ecx
movq 0x170(%rsp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x188(%rsp)
je 0x369a1
leaq 0x120(%rsp), %rsi
movl $0xba2, %edi            # imm = 0xBA2
callq 0x29f50
leaq 0xa0(%rsp), %rsi
movl $0xba6, %edi            # imm = 0xBA6
callq 0x29060
leaq 0x20(%rsp), %rsi
movl $0xba7, %edi            # imm = 0xBA7
callq 0x29060
cvttsd2si 0x198(%rsp), %edi
cvttsd2si 0x190(%rsp), %esi
movl $0x1, %ecx
movl $0x1902, %r8d           # imm = 0x1902
movl $0x1406, %r9d           # imm = 0x1406
leaq 0x148(%rsp), %rax
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x29bb0
movsd 0x198(%rsp), %xmm0
movsd 0x190(%rsp), %xmm1
movss 0x148(%rsp), %xmm2
cvtss2sd %xmm2, %xmm2
leaq 0xa0(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x120(%rsp), %rdx
leaq 0x130(%rsp), %rcx
leaq 0x130(%rsp), %r8
addq $0x8, %r8
leaq 0x130(%rsp), %r9
addq $0x10, %r9
callq 0x29ad0
movsd 0x130(%rsp), %xmm0
movsd 0x138(%rsp), %xmm1
movsd 0x140(%rsp), %xmm2
leaq 0x8(%rsp), %rdi
callq 0x17fd90
movq 0x188(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x180420
movl $0x1, 0x1a4(%rsp)
movl 0x1a4(%rsp), %eax
addq $0x1a8, %rsp            # imm = 0x1A8
retq
nopl (%rax,%rax)