// File: tomfunkhouser[P]gaps/pkgs/R3Graphics/R3SceneNode.cpp
// Function: gaps::R3SceneNode::FindClosest(gaps::R3Point const&, gaps::R3SceneNode**, gaps::R3Material**, gaps::R3Shape**, gaps::R3Point*, gaps::R3Vector*, double*, double, double) const
RNBoolean R3SceneNode::
FindClosest(const R3Point& point,
  R3SceneNode **hit_node, R3Material **hit_material, R3Shape **hit_shape,
  R3Point *hit_point, R3Vector *hit_normal, RNLength *hit_d,
  RNLength min_d, RNLength max_d) const
{
  // Temporary variables
  RNBoolean found = FALSE;
  RNScalar d;

  // Check if bounding box is within max_d
  RNScalar bbox_d = R3Distance(point, BBox());
  if (bbox_d > max_d) return FALSE;

  // Apply inverse transformation to point
  R3Point node_point = point;
  node_point.InverseTransform(transformation);

  // Apply inverse transform to min_d and max_d
  RNScalar scale = transformation.ScaleFactor();
  if (RNIsZero(scale)) return FALSE;
  if (min_d < RN_INFINITY) min_d /= scale;
  if (max_d < RN_INFINITY) max_d /= scale;

  // Find closest element 
  for (int i = 0; i < elements.NEntries(); i++) {
    R3SceneElement *element = elements.Kth(i);
    if (element->FindClosest(node_point, hit_shape, hit_point, hit_normal, &d, min_d, max_d)) {
      if ((d >= min_d) && (d <= max_d)) {
        if (hit_node) *hit_node = (R3SceneNode *) this;
        if (hit_material) *hit_material = element->Material();
        if (hit_d) *hit_d = d;
        found = TRUE;
        max_d = d;
      }
    }
  }

  // Find closest reference 
  for (int i = 0; i < references.NEntries(); i++) {
    R3SceneReference *reference = references.Kth(i);
    R3Scene *referenced_scene = reference->ReferencedScene();
    if (referenced_scene) {
      if (referenced_scene->FindClosest(node_point, hit_node, hit_material, hit_shape, hit_point, hit_normal, &d, min_d, max_d)) {
        if ((d >= min_d) && (d <= max_d)) {
          if (hit_d) *hit_d = d;
          found = TRUE;
          max_d = d;
        }
      }
    }
  }

  // Find closest node
  for (int i = 0; i < children.NEntries(); i++) {
    R3SceneNode *child = children.Kth(i);
    if (child->FindClosest(node_point, hit_node, hit_material, hit_shape, hit_point, hit_normal, &d, min_d, max_d)) {
      if ((d >= min_d) && (d <= max_d)) {
        if (hit_d) *hit_d = d;
        found = TRUE;
        max_d = d;
      }
    }
  }

  // Transform hit into parent's coordinate system
  if (found) {
    if (hit_point) hit_point->Transform(transformation);
    if (hit_normal) hit_normal->Transform(transformation);
    if (hit_normal) hit_normal->Normalize();
    if (hit_d) *hit_d *= scale;
  }

  // Return if found a point
  return found;
}

// Assembly:
subq $0xe8, %rsp
movq 0xf8(%rsp), %rax
movq 0xf0(%rsp), %rax
movq %rdi, 0xd8(%rsp)
movq %rsi, 0xd0(%rsp)
movq %rdx, 0xc8(%rsp)
movq %rcx, 0xc0(%rsp)
movq %r8, 0xb8(%rsp)
movq %r9, 0xb0(%rsp)
movsd %xmm0, 0xa8(%rsp)
movsd %xmm1, 0xa0(%rsp)
movq 0xd8(%rsp), %rdi
movq %rdi, 0x20(%rsp)
movl $0x0, 0x9c(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x28(%rsp)
callq 0x56d40
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0x77e60
movsd %xmm0, 0x88(%rsp)
movsd 0x88(%rsp), %xmm0
ucomisd 0xa0(%rsp), %xmm0
jbe 0x564bd
movl $0x0, 0xe4(%rsp)
jmp 0x569c9
movq 0xd0(%rsp), %rsi
leaq 0x70(%rsp), %rdi
callq 0xcc8b0
movq 0x20(%rsp), %rsi
addq $0x58, %rsi
leaq 0x70(%rsp), %rdi
callq 0xcd510
movq 0x20(%rsp), %rdi
addq $0x58, %rdi
callq 0xc1ca0
movsd %xmm0, 0x68(%rsp)
movsd 0x68(%rsp), %xmm0
leaq 0x19fda5(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x48790
cmpl $0x0, %eax
je 0x56521
movl $0x0, 0xe4(%rsp)
jmp 0x569c9
movsd 0xa8(%rsp), %xmm1
leaq 0x19fd87(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x56557
movsd 0x68(%rsp), %xmm1
movsd 0xa8(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0xa0(%rsp), %xmm1
leaq 0x19fd51(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x5658d
movsd 0x68(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
movl $0x0, 0x64(%rsp)
movq 0x20(%rsp), %rdi
movl 0x64(%rsp), %eax
movl %eax, 0x1c(%rsp)
addq $0x30, %rdi
callq 0x2b8b0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x566d9
movq 0x20(%rsp), %rdi
addq $0x30, %rdi
movl 0x64(%rsp), %esi
callq 0x2bd50
movq %rax, 0x58(%rsp)
movq 0x58(%rsp), %rdi
movq 0xb8(%rsp), %rdx
movq 0xb0(%rsp), %rcx
movq 0xf0(%rsp), %r8
movsd 0xa8(%rsp), %xmm0
movsd 0xa0(%rsp), %xmm1
leaq 0x70(%rsp), %rsi
leaq 0x90(%rsp), %r9
callq 0x59550
cmpl $0x0, %eax
je 0x566c7
movsd 0x90(%rsp), %xmm0
ucomisd 0xa8(%rsp), %xmm0
jb 0x566c5
movsd 0x90(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x566c5
cmpq $0x0, 0xc8(%rsp)
je 0x56665
movq 0x20(%rsp), %rcx
movq 0xc8(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0xc0(%rsp)
je 0x56688
movq 0x58(%rsp), %rdi
callq 0x48b50
movq %rax, %rcx
movq 0xc0(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0xf8(%rsp)
je 0x566a8
movsd 0x90(%rsp), %xmm0
movq 0xf8(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0x9c(%rsp)
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x566c7
jmp 0x566c9
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0x56595
movl $0x0, 0x54(%rsp)
movq 0x20(%rsp), %rdi
movl 0x54(%rsp), %eax
movl %eax, 0x18(%rsp)
addq $0x40, %rdi
callq 0x2b8b0
movl %eax, %ecx
movl 0x18(%rsp), %eax
cmpl %ecx, %eax
jge 0x56815
movq 0x20(%rsp), %rdi
addq $0x40, %rdi
movl 0x54(%rsp), %esi
callq 0x2bd30
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
callq 0x2bb90
movq %rax, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
je 0x56803
movq 0x40(%rsp), %rdi
movq 0xc8(%rsp), %rdx
movq 0xc0(%rsp), %rcx
movq 0xb8(%rsp), %r8
movq 0xb0(%rsp), %r9
movq 0xf0(%rsp), %r10
movsd 0xa8(%rsp), %xmm0
movsd 0xa0(%rsp), %xmm1
leaq 0x70(%rsp), %rsi
leaq 0x90(%rsp), %rax
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x2dd00
cmpl $0x0, %eax
je 0x56801
movsd 0x90(%rsp), %xmm0
ucomisd 0xa8(%rsp), %xmm0
jb 0x567ff
movsd 0x90(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x567ff
cmpq $0x0, 0xf8(%rsp)
je 0x567e2
movsd 0x90(%rsp), %xmm0
movq 0xf8(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0x9c(%rsp)
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x56801
jmp 0x56803
jmp 0x56805
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0x566e1
movl $0x0, 0x3c(%rsp)
movq 0x20(%rsp), %rdi
movl 0x3c(%rsp), %eax
movl %eax, 0x14(%rsp)
addq $0x20, %rdi
callq 0x2b8b0
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jge 0x56934
movq 0x20(%rsp), %rdi
addq $0x20, %rdi
movl 0x3c(%rsp), %esi
callq 0x2bd10
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
movq 0xc8(%rsp), %rdx
movq 0xc0(%rsp), %rcx
movq 0xb8(%rsp), %r8
movq 0xb0(%rsp), %r9
movq 0xf0(%rsp), %r10
movsd 0xa8(%rsp), %xmm0
movsd 0xa0(%rsp), %xmm1
leaq 0x70(%rsp), %rsi
leaq 0x90(%rsp), %rax
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x56400
cmpl $0x0, %eax
je 0x56922
movsd 0x90(%rsp), %xmm0
ucomisd 0xa8(%rsp), %xmm0
jb 0x56920
movsd 0x90(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x56920
cmpq $0x0, 0xf8(%rsp)
je 0x56903
movsd 0x90(%rsp), %xmm0
movq 0xf8(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0x9c(%rsp)
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x56922
jmp 0x56924
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x5681d
cmpl $0x0, 0x9c(%rsp)
je 0x569bb
cmpq $0x0, 0xb0(%rsp)
je 0x5695f
movq 0x20(%rsp), %rsi
movq 0xb0(%rsp), %rdi
addq $0x58, %rsi
callq 0xcd4e0
cmpq $0x0, 0xf0(%rsp)
je 0x56980
movq 0x20(%rsp), %rsi
movq 0xf0(%rsp), %rdi
addq $0x58, %rsi
callq 0xceb30
cmpq $0x0, 0xf0(%rsp)
je 0x56998
movq 0xf0(%rsp), %rdi
callq 0xce130
cmpq $0x0, 0xf8(%rsp)
je 0x569b9
movsd 0x68(%rsp), %xmm0
movq 0xf8(%rsp), %rax
mulsd (%rax), %xmm0
movsd %xmm0, (%rax)
jmp 0x569bb
movl 0x9c(%rsp), %eax
movl %eax, 0xe4(%rsp)
movl 0xe4(%rsp), %eax
addq $0xe8, %rsp
retq
nopl (%rax,%rax)