// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3MeshSearchTree.cpp
// Function: gaps::R3MeshSearchTree::FindIntersection(gaps::R3Ray const&, gaps::R3MeshIntersection&, double, double&, int (*)(gaps::R3Point const&, gaps::R3Vector const&, gaps::R3Mesh*, gaps::R3MeshFace*, void*), void*, gaps::R3MeshFace*) const
void R3MeshSearchTree::
FindIntersection(const R3Ray& ray, R3MeshIntersection& closest, 
  RNScalar min_t, RNScalar& max_t, 
  int (*IsCompatible)(const R3Point&, const R3Vector&, R3Mesh *, R3MeshFace *, void *), void *compatible_data,
  R3MeshFace *face) const
{
  // Check compatibility 
  if (IsCompatible) {
    if (!(*IsCompatible)(ray.Start(), ray.Vector(), mesh, face, compatible_data)) return;
  }


  // Check face
  R3Vector normal = mesh->FaceNormal(face);
  if (RNIsZero(normal.Dot(normal))) return;

  // Check intersection with plane (this is redundant, but allows checking min_t and max_t)
  RNScalar plane_t;
  R3Plane plane = mesh->FacePlane(face);
  if (!R3Intersects(ray, plane, NULL, &plane_t)) return;
  if (plane_t >= max_t) return;
  if (plane_t < min_t) return;
  
  // Check intersection with face
  R3MeshIntersection face_intersection;
  if (!mesh->Intersection(ray, face, &face_intersection)) return;
  if (face_intersection.t >= max_t) return;
  if (face_intersection.t < min_t) return;

  // Update closest intersection
  closest.type = R3_MESH_FACE_TYPE;
  closest.face = face;
  closest.point = face_intersection.point;
  closest.t = face_intersection.t;
  max_t = face_intersection.t;
}

// Assembly:
subq $0xd8, %rsp
movq 0xe0(%rsp), %rax
movq %rdi, 0xd0(%rsp)
movq %rsi, 0xc8(%rsp)
movq %rdx, 0xc0(%rsp)
movsd %xmm0, 0xb8(%rsp)
movq %rcx, 0xb0(%rsp)
movq %r8, 0xa8(%rsp)
movq %r9, 0xa0(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x2079f
movq 0xa8(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x21ab0
movq %rax, 0x8(%rsp)
movq 0xc8(%rsp), %rdi
callq 0x21ac0
movq 0x18(%rsp), %rcx
movq 0x8(%rsp), %rdi
movq %rax, %rsi
movq 0x10(%rsp), %rax
movq (%rcx), %rdx
movq 0xe0(%rsp), %rcx
movq 0xa0(%rsp), %r8
callq *%rax
cmpl $0x0, %eax
jne 0x2079d
jmp 0x20939
jmp 0x2079f
movq 0x18(%rsp), %rax
movq (%rax), %rdi
movq 0xe0(%rsp), %rsi
callq 0x17fd0
movq %rax, %rsi
leaq 0x88(%rsp), %rdi
callq 0x940b0
leaq 0x88(%rsp), %rsi
movq %rsi, %rdi
callq 0x94680
leaq 0x165d15(%rip), %rax    # 0x1864f0
movsd (%rax), %xmm1
callq 0x1b080
cmpl $0x0, %eax
je 0x207ee
jmp 0x20939
movq 0x18(%rsp), %rax
movq (%rax), %rdi
movq 0xe0(%rsp), %rsi
callq 0x18070
movq %rax, %rsi
leaq 0x60(%rsp), %rdi
callq 0x90530
movq 0xc8(%rsp), %rdi
leaq 0x60(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
leaq 0x80(%rsp), %rcx
callq 0x23c50
cmpl $0x0, %eax
jne 0x20838
jmp 0x20939
movsd 0x80(%rsp), %xmm0
movq 0xb0(%rsp), %rax
ucomisd (%rax), %xmm0
jb 0x20854
jmp 0x20939
movsd 0x80(%rsp), %xmm1
movsd 0xb8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x20871
jmp 0x20939
leaq 0x20(%rsp), %rdi
callq 0x17ed0
movq 0x18(%rsp), %rax
movq (%rax), %rdi
movq 0xc8(%rsp), %rsi
movq 0xe0(%rsp), %rdx
movq (%rdi), %rax
leaq 0x20(%rsp), %rcx
callq *0x178(%rax)
cmpl $0x0, %eax
jne 0x208ab
jmp 0x20939
movsd 0x58(%rsp), %xmm0
movq 0xb0(%rsp), %rax
ucomisd (%rax), %xmm0
jb 0x208c1
jmp 0x20939
movsd 0x58(%rsp), %xmm1
movsd 0xb8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x208d8
jmp 0x20939
movq 0xc0(%rsp), %rax
movl $0x3, (%rax)
movq 0xe0(%rsp), %rcx
movq 0xc0(%rsp), %rax
movq %rcx, 0x18(%rax)
leaq 0x20(%rsp), %rsi
addq $0x20, %rsi
movq 0xc0(%rsp), %rdi
addq $0x20, %rdi
callq 0x935a0
movsd 0x58(%rsp), %xmm0
movq 0xc0(%rsp), %rax
movsd %xmm0, 0x38(%rax)
movsd 0x58(%rsp), %xmm0
movq 0xb0(%rsp), %rax
movsd %xmm0, (%rax)
addq $0xd8, %rsp
retq
nopw %cs:(%rax,%rax)