// File: tomfunkhouser[P]gaps/apps/scnview/scnview.cpp
// Function: Pick(gaps::R3Scene*, int, int, gaps::R3SceneNode**, gaps::R3Point*)
static int
Pick(R3Scene *scene, int x, int y,
  R3SceneNode **hit_node = NULL, R3Point *hit_position = NULL)
{
  // Clear window
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

  // Set OpenGL stuff
  int pick_tolerance = 10;
  glPointSize(pick_tolerance);
  glDisable(GL_LIGHTING);
  glDisable(GL_MULTISAMPLE);

  // Draw leaf nodes with color indicating node index
  for (int i = 0; i < scene->NNodes(); i++) {
    R3SceneNode *node = scene->Node(i);
    if (node->NChildren() > 0) continue;
    R3Affine parent_transformation = node->CumulativeParentTransformation();
    parent_transformation.Push();
    int index = i + 1;
    unsigned char rgba[4];
    rgba[0] = (index >> 16) & 0xFF;
    rgba[1] = (index >> 8) & 0xFF;
    rgba[2] = index & 0xFF;
    rgba[3] = 0xFF;
    RNLoadRgba(rgba);
    node->Draw(R3_SURFACES_DRAW_FLAG);
    parent_transformation.Pop();
  }

  // Reset OpenGL stuff
  glEnable(GL_MULTISAMPLE);
  glPointSize(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[0] == 0) && (rgba[1] == 0) && (rgba[2] == 0)) return 0;

  // Parse color value
  int r = rgba[0] & 0xFF;
  int g = rgba[1] & 0xFF;
  int b = rgba[2] & 0xFF;
  // int a = rgba[3] & 0xFF;
  int node_index = ((r << 16) | (g << 8) | b) - 1;
  if (node_index < 0) return 0;
  if (node_index >= scene->NNodes()) return 0;
 
  // Return hit node
  if (hit_node) {
   *hit_node = scene->Node(node_index);
  }

  // Return hit position
  if (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 $0x2e8, %rsp            # imm = 0x2E8
movq %rdi, 0x2d8(%rsp)
movl %esi, 0x2d4(%rsp)
movl %edx, 0x2d0(%rsp)
movq %rcx, 0x2c8(%rsp)
movq %r8, 0x2c0(%rsp)
xorps %xmm3, %xmm3
movaps %xmm3, %xmm0
movaps %xmm3, %xmm1
movaps %xmm3, %xmm2
callq 0x22fd0
movl $0x4100, %edi           # imm = 0x4100
callq 0x22220
movq 0x1d2f69(%rip), %rdi    # 0x1fbc28
callq 0x2b4d0
movq %rax, %rdi
xorl %esi, %esi
callq 0x5e9f0
movl $0xa, 0x2bc(%rsp)
cvtsi2ssl 0x2bc(%rsp), %xmm0
callq 0x220b0
movl $0xb50, %edi            # imm = 0xB50
callq 0x22230
movl $0x809d, %edi           # imm = 0x809D
callq 0x22230
movl $0x0, 0x2b8(%rsp)
movl 0x2b8(%rsp), %eax
movl %eax, 0x24(%rsp)
movq 0x2d8(%rsp), %rdi
callq 0x2bf50
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x28e67
movq 0x2d8(%rsp), %rdi
movl 0x2b8(%rsp), %esi
callq 0x2bf70
movq %rax, 0x2b0(%rsp)
movq 0x2b0(%rsp), %rdi
callq 0x2baf0
cmpl $0x0, %eax
jle 0x28d5f
jmp 0x28e2b
movq 0x2b0(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x572d0
movq 0x18(%rsp), %rdi
callq 0x66690
jmp 0x28d85
movl 0x2b8(%rsp), %eax
incl %eax
movl %eax, 0x190(%rsp)
movb 0x192(%rsp), %al
movb %al, 0x18c(%rsp)
movb 0x191(%rsp), %al
movb %al, 0x18d(%rsp)
movb 0x190(%rsp), %al
movb %al, 0x18e(%rsp)
movb $-0x1, 0x18f(%rsp)
leaq 0x18c(%rsp), %rdi
callq 0x2bfa0
jmp 0x28dd6
movq 0x2b0(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x180(%rsp), %rdi
movl $0x2, %esi
callq 0x2b520
jmp 0x28df7
movq 0x10(%rsp), %rdi
movq 0x180(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x58170
jmp 0x28e0f
leaq 0x1a0(%rsp), %rdi
callq 0x66700
jmp 0x28e1e
leaq 0x1a0(%rsp), %rdi
callq 0xc1b00
movl 0x2b8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2b8(%rsp)
jmp 0x28d06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0xc1b00
jmp 0x290e6
movl $0x809d, %edi           # imm = 0x809D
callq 0x22910
movss 0x16520f(%rip), %xmm0   # 0x18e088
callq 0x220b0
callq 0x23530
movl 0x2d4(%rsp), %edi
movl 0x2d0(%rsp), %esi
leaq 0x17c(%rsp), %rax
movl $0x1, %ecx
movl $0x1908, %r8d           # imm = 0x1908
movl $0x1401, %r9d           # imm = 0x1401
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x22430
movzbl 0x17c(%rsp), %eax
cmpl $0x0, %eax
jne 0x28eec
movzbl 0x17d(%rsp), %eax
cmpl $0x0, %eax
jne 0x28eec
movzbl 0x17e(%rsp), %eax
cmpl $0x0, %eax
jne 0x28eec
movl $0x0, 0x2e4(%rsp)
jmp 0x290d7
movzbl 0x17c(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x178(%rsp)
movzbl 0x17d(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x174(%rsp)
movzbl 0x17e(%rsp), %eax
andl $0xff, %eax
movl %eax, 0x170(%rsp)
movl 0x178(%rsp), %eax
shll $0x10, %eax
movl 0x174(%rsp), %ecx
shll $0x8, %ecx
orl %ecx, %eax
orl 0x170(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x16c(%rsp)
cmpl $0x0, 0x16c(%rsp)
jge 0x28f69
movl $0x0, 0x2e4(%rsp)
jmp 0x290d7
movl 0x16c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x2d8(%rsp), %rdi
callq 0x2bf50
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jl 0x28f9b
movl $0x0, 0x2e4(%rsp)
jmp 0x290d7
cmpq $0x0, 0x2c8(%rsp)
je 0x28fc8
movq 0x2d8(%rsp), %rdi
movl 0x16c(%rsp), %esi
callq 0x2bf70
movq %rax, %rcx
movq 0x2c8(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x2c0(%rsp)
je 0x290cc
leaq 0x140(%rsp), %rsi
movl $0xba2, %edi            # imm = 0xBA2
callq 0x22980
leaq 0xc0(%rsp), %rsi
movl $0xba6, %edi            # imm = 0xBA6
callq 0x22ba0
leaq 0x40(%rsp), %rsi
movl $0xba7, %edi            # imm = 0xBA7
callq 0x22ba0
movl 0x2d4(%rsp), %edi
movl 0x2d0(%rsp), %esi
movl $0x1, %ecx
movl $0x1902, %r8d           # imm = 0x1902
movl $0x1406, %r9d           # imm = 0x1406
leaq 0x168(%rsp), %rax
movl %ecx, %edx
movq %rax, (%rsp)
callq 0x22430
cvtsi2sdl 0x2d4(%rsp), %xmm0
cvtsi2sdl 0x2d0(%rsp), %xmm1
movss 0x168(%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 0x23410
movsd 0x150(%rsp), %xmm0
movsd 0x158(%rsp), %xmm1
movsd 0x160(%rsp), %xmm2
leaq 0x28(%rsp), %rdi
callq 0xcc870
movq 0x2c0(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0xccf00
movl $0x1, 0x2e4(%rsp)
movl 0x2e4(%rsp), %eax
addq $0x2e8, %rsp            # imm = 0x2E8
retq
movq 0x198(%rsp), %rdi
callq 0x23290
nopw %cs:(%rax,%rax)