// File: /workspace/github_cpp_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rcx, %rbx
movsd %xmm0, 0x8(%rsp)
movq %rdx, %r14
movq %rsi, %r12
movq %rdi, %r13
movq 0xd0(%rsp), %r15
testq %r8, %r8
je 0x18bdf
movq %r8, %rax
leaq 0x18(%r12), %rsi
movq (%r13), %rdx
movq %r12, %rdi
movq %r15, %rcx
movq %r9, %r8
callq *%rax
testl %eax, %eax
je 0x18d0d
movq %r14, 0x10(%rsp)
testb $0x4, 0xa8(%r15)
jne 0x18bfe
movq (%r13), %rdi
movq (%rdi), %rax
movq %r15, %rsi
callq *0x2c8(%rax)
leaq 0x38(%r15), %rbp
leaq 0x60(%rsp), %r14
movq %r14, %rdi
movq %rbp, %rsi
callq 0x507e2
movq %r14, %rdi
movq %r14, %rsi
callq 0x50a5e
leaq 0xd6f84(%rip), %rax     # 0xefba8
movsd (%rax), %xmm1
movapd 0x91400(%rip), %xmm2    # 0xaa030
xorpd %xmm1, %xmm2
ucomisd %xmm2, %xmm0
jb 0x18c44
ucomisd %xmm0, %xmm1
jae 0x18d0d
testb $0x4, 0xa8(%r15)
jne 0x18c5e
movq (%r13), %rdi
movq (%rdi), %rax
movq %r15, %rsi
callq *0x2c8(%rax)
leaq 0x78(%rsp), %r14
movq %r14, %rdi
movq %rbp, %rsi
callq 0x4e832
leaq 0x18(%rsp), %rcx
movq %r12, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x1a262
testl %eax, %eax
je 0x18d0d
movsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x18d0d
ucomisd (%rbx), %xmm0
jae 0x18d0d
leaq 0x40(%rsp), %rbp
movq %rbp, %rdi
callq 0x4fd3c
movq (%r13), %rdi
movq (%rdi), %rax
leaq 0x20(%rsp), %rcx
movq %r12, %rsi
movq %r15, %rdx
callq *0x178(%rax)
testl %eax, %eax
je 0x18d0d
movsd 0x58(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x18d0d
ucomisd (%rbx), %xmm0
jae 0x18d0d
movq 0x10(%rsp), %r14
movl $0x3, (%r14)
movq %r15, 0x18(%r14)
leaq 0x20(%r14), %rdi
movq %rbp, %rsi
callq 0x500a6
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x38(%r14)
movsd %xmm0, (%rbx)
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop