// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Graphics/R3SceneNode.cpp
// Function: gaps::R3SceneNode::Intersects(gaps::R3Ray const&, gaps::R3SceneNode**, gaps::R3Material**, gaps::R3Shape**, gaps::R3Point*, gaps::R3Vector*, double*, double, double) const
RNBoolean R3SceneNode::
Intersects(const R3Ray& ray,
  R3SceneNode **hit_node, R3Material **hit_material, R3Shape **hit_shape,
  R3Point *hit_point, R3Vector *hit_normal, RNScalar *hit_t,
  RNScalar min_t, RNScalar max_t) const
{
  // Temporary variables
  R3SceneNode *closest_node = NULL;
  R3Point closest_point = R3zero_point;
  RNScalar closest_t = max_t;
  RNScalar bbox_t;
  R3SceneNode *node;
  R3Material *material;
  R3Shape *shape;
  R3Point point;
  R3Vector normal;
  RNScalar t;

  // Check if ray intersects bounding box
  if (!R3Intersects(ray, BBox(), NULL, NULL, &bbox_t)) return FALSE;
  if (RNIsGreater(bbox_t, max_t)) return FALSE;

  // Apply inverse transformation to ray
  R3Ray node_ray = ray;
  node_ray.InverseTransform(transformation);

  // Apply inverse transform to min_t and closest_t
  RNScalar scale = 1.0;
  R3Vector v(ray.Vector());
  v.InverseTransform(transformation);
  RNScalar length = v.Length();
  if (RNIsNegativeOrZero(length)) return FALSE;
  if (RNIsNotEqual(length, 1.0)) {
    scale = length;
    min_t *= scale;
    closest_t *= scale;
  }

  // Find closest element intersection
  for (int i = 0; i < elements.NEntries(); i++) {
    R3SceneElement *element = elements.Kth(i);
    if (element->Intersects(node_ray, &shape, &point, &normal, &t, min_t, closest_t)) {
      if ((t >= min_t) && (t <= closest_t)) {
        if (hit_node) *hit_node = (R3SceneNode *) this;
        if (hit_material) *hit_material = element->Material();
        if (hit_shape) *hit_shape = shape; 
        if (hit_normal) *hit_normal = normal; 
        closest_node = (R3SceneNode *) this;
        closest_point = point;
        closest_t = t;
      }
    }
  }

  // Find closest reference intersection
  for (int i = 0; i < references.NEntries(); i++) {
    R3SceneReference *reference = references.Kth(i);
    R3Scene *referenced_scene = reference->ReferencedScene();
    if (referenced_scene) {
      if (referenced_scene->Intersects(node_ray, &node, &material, &shape, &point, &normal, &t, min_t, closest_t)) {
        if ((t >= min_t) && (t <= closest_t)) {
          if (hit_node) *hit_node = node;
          if (hit_material) *hit_material = material;
          if (hit_shape) *hit_shape = shape; 
          if (hit_normal) *hit_normal = normal; 
          closest_node = (R3SceneNode *) this;
          closest_point = point;
          closest_t = t;
        }
      }
    }
  }

  // Find closest node intersection
  for (int i = 0; i < children.NEntries(); i++) {
    R3SceneNode *child = children.Kth(i);
    if (child->Intersects(node_ray, &node, &material, &shape, &point, &normal, &t, min_t, closest_t)) {
      if ((t >= min_t) && (t <= closest_t)) {
        if (hit_node) *hit_node = node;
        if (hit_material) *hit_material = material;
        if (hit_shape) *hit_shape = shape; 
        if (hit_normal) *hit_normal = normal; 
        closest_node = node;
        closest_point = point;
        closest_t = t;
      }
    }
  }

  // Check if found hit
  if (!closest_node) return FALSE;

  // Transform hit point into parent's coordinate system
  if (hit_t || hit_point) {
    closest_point.Transform(transformation); 
    if (hit_point) *hit_point = closest_point;
    if (hit_t) *hit_t = closest_t / scale; 
  }

  // Transform hit normal into parent's coordinate system
  if (hit_normal) {
    hit_normal->Transform(transformation); 
    hit_normal->Normalize();
  }

  // Return success
  return TRUE;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x108, %rsp            # imm = 0x108
movsd %xmm1, (%rsp)
movsd %xmm0, 0x8(%rsp)
movq %r9, %r12
movq %r8, %rbp
movq %rcx, 0x40(%rsp)
movq %rdx, %r15
movq %rsi, %rbx
movq %rdi, %r13
leaq 0xfe1c1(%rip), %rsi     # 0x136db0
leaq 0x78(%rsp), %rdi
callq 0x6b884
leaq 0x90(%rsp), %rdi
callq 0x6b872
leaq 0xd8(%rsp), %rdi
callq 0x6c032
movq %r13, %rdi
callq 0x386ba
xorl %r14d, %r14d
leaq 0x70(%rsp), %r8
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x42e21
testl %eax, %eax
je 0x390d3
movq %r15, 0x48(%rsp)
movsd 0x70(%rsp), %xmm0
leaq 0xf64ac(%rip), %r15     # 0x12f0f8
movsd (%rsp), %xmm1
subsd %xmm1, %xmm0
ucomisd (%r15), %xmm0
ja 0x390d3
movq %r12, 0x68(%rsp)
leaq 0xa8(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6b480
leaq 0x58(%r13), %r12
movq %r14, %rdi
movq %r12, %rsi
callq 0x6b540
addq $0x18, %rbx
leaq 0xf0(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x6c044
movq %r14, %rdi
movq %r12, 0x60(%rsp)
movq %r12, %rsi
callq 0x6c8f2
movq %r14, %rdi
callq 0x6c13a
movapd %xmm0, %xmm3
movsd (%r15), %xmm0
ucomisd %xmm3, %xmm0
jae 0x390d0
movsd 0x8c7ff(%rip), %xmm1    # 0xc54d0
addsd %xmm3, %xmm1
movapd 0x8c853(%rip), %xmm2    # 0xc5530
xorpd %xmm0, %xmm2
cmpnltpd %xmm1, %xmm0
cmpnltpd %xmm2, %xmm1
andpd %xmm0, %xmm1
movd %xmm1, %eax
movl %eax, 0x5c(%rsp)
testb $0x1, %al
movq %rbp, 0x38(%rsp)
movsd %xmm3, 0x30(%rsp)
jne 0x38d1b
movsd 0x8(%rsp), %xmm0
mulsd %xmm3, %xmm0
movsd (%rsp), %xmm1
mulsd %xmm3, %xmm1
jmp 0x38d26
movsd 0x8(%rsp), %xmm0
movsd (%rsp), %xmm1
xorl %r14d, %r14d
leaq 0x18(%rsp), %r15
leaq 0x90(%rsp), %r12
leaq 0xd8(%rsp), %rbx
movq $0x0, 0x20(%rsp)
movsd %xmm0, 0x8(%rsp)
movslq 0x3c(%r13), %rax
cmpq %rax, %r14
jge 0x38e26
movq 0x30(%r13), %rax
movq (%rax,%r14,8), %rbp
movq %rbp, %rdi
leaq 0xa8(%rsp), %rsi
movq %r15, %rdx
movq %r12, %rcx
movq %rbx, %r8
leaq 0x10(%rsp), %r9
movsd %xmm1, (%rsp)
callq 0x398fa
testl %eax, %eax
je 0x38e13
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x38e19
movsd (%rsp), %xmm2
ucomisd %xmm1, %xmm2
movapd %xmm2, %xmm1
jb 0x38e1e
movq 0x48(%rsp), %rax
testq %rax, %rax
je 0x38dbb
movq %r13, (%rax)
movq 0x40(%rsp), %rcx
testq %rcx, %rcx
je 0x38dcc
movq 0x8(%rbp), %rax
movq %rax, (%rcx)
movq 0x38(%rsp), %rcx
testq %rcx, %rcx
je 0x38dde
movq 0x18(%rsp), %rax
movq %rax, (%rcx)
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x38df3
movq %rbx, %rsi
callq 0x6c5a4
leaq 0x78(%rsp), %rdi
movq %r12, %rsi
callq 0x6bb5e
movsd 0x10(%rsp), %xmm1
movq %r13, 0x20(%rsp)
movsd 0x8(%rsp), %xmm0
jmp 0x38e1e
movsd 0x8(%rsp), %xmm0
movsd (%rsp), %xmm1
incq %r14
jmp 0x38d4d
xorl %r14d, %r14d
leaq 0xa8(%rsp), %rbp
movq 0x38(%rsp), %r15
movq 0x40(%rsp), %r12
movslq 0x4c(%r13), %rax
cmpq %rax, %r14
jge 0x38f2c
movq 0x40(%r13), %rax
movq (%rax,%r14,8), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x38f24
movq %rbp, %rsi
leaq 0x28(%rsp), %rdx
leaq 0x50(%rsp), %rcx
leaq 0x18(%rsp), %r8
leaq 0x90(%rsp), %r9
movsd %xmm1, (%rsp)
leaq 0x10(%rsp), %rax
pushq %rax
pushq %rbx
callq 0x27fd2
popq %rcx
popq %rdx
testl %eax, %eax
je 0x38f19
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x38f1f
movsd (%rsp), %xmm2
ucomisd %xmm1, %xmm2
movapd %xmm2, %xmm1
jb 0x38f24
movq 0x48(%rsp), %rcx
testq %rcx, %rcx
je 0x38ec4
movq 0x28(%rsp), %rax
movq %rax, (%rcx)
testq %r12, %r12
je 0x38ed2
movq 0x50(%rsp), %rax
movq %rax, (%r12)
testq %r15, %r15
je 0x38edf
movq 0x18(%rsp), %rax
movq %rax, (%r15)
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x38ef4
movq %rbx, %rsi
callq 0x6c5a4
leaq 0x78(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x6bb5e
movsd 0x10(%rsp), %xmm1
movq %r13, 0x20(%rsp)
movsd 0x8(%rsp), %xmm0
jmp 0x38f24
movsd 0x8(%rsp), %xmm0
movsd (%rsp), %xmm1
incq %r14
jmp 0x38e3b
xorl %r15d, %r15d
leaq 0x50(%rsp), %r12
leaq 0x18(%rsp), %rbp
leaq 0x90(%rsp), %r14
movslq 0x2c(%r13), %rax
cmpq %rax, %r15
movsd %xmm1, (%rsp)
jge 0x3902f
movq 0x20(%r13), %rax
movq (%rax,%r15,8), %rdi
leaq 0xa8(%rsp), %rsi
leaq 0x28(%rsp), %rdx
movq %r12, %rcx
movq %rbp, %r8
movq %r14, %r9
leaq 0x10(%rsp), %rax
pushq %rax
pushq %rbx
callq 0x38bb8
popq %rcx
popq %rdx
testl %eax, %eax
je 0x3901c
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x39022
movsd (%rsp), %xmm2
ucomisd %xmm1, %xmm2
movapd %xmm2, %xmm1
jb 0x39027
movq 0x48(%rsp), %rcx
testq %rcx, %rcx
je 0x38fbe
movq 0x28(%rsp), %rax
movq %rax, (%rcx)
movq 0x40(%rsp), %rcx
testq %rcx, %rcx
je 0x38fd0
movq 0x50(%rsp), %rax
movq %rax, (%rcx)
movq 0x38(%rsp), %rcx
testq %rcx, %rcx
je 0x38fe2
movq 0x18(%rsp), %rax
movq %rax, (%rcx)
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x38ff7
movq %rbx, %rsi
callq 0x6c5a4
movq 0x28(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x78(%rsp), %rdi
movq %r14, %rsi
callq 0x6bb5e
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
jmp 0x39027
movsd 0x8(%rsp), %xmm0
movsd (%rsp), %xmm1
incq %r15
jmp 0x38f41
testb $0x1, 0x5c(%rsp)
jne 0x39043
movq 0x68(%rsp), %rbx
movsd 0x30(%rsp), %xmm0
jmp 0x39050
movsd 0x8bfcd(%rip), %xmm0    # 0xc5018
movq 0x68(%rsp), %rbx
movq 0x148(%rsp), %r14
cmpq $0x0, 0x20(%rsp)
je 0x390d0
movq %rbx, %rax
orq %r14, %rax
je 0x390a8
movsd %xmm0, 0x30(%rsp)
leaq 0x78(%rsp), %rdi
movq 0x60(%rsp), %rsi
callq 0x6beba
testq %rbx, %rbx
je 0x3908f
leaq 0x78(%rsp), %rsi
movq %rbx, %rdi
callq 0x6bb5e
testq %r14, %r14
movsd 0x30(%rsp), %xmm0
movsd (%rsp), %xmm1
je 0x390a8
divsd %xmm0, %xmm1
movsd %xmm1, (%r14)
pushq $0x1
popq %r14
movq 0x140(%rsp), %rbx
testq %rbx, %rbx
je 0x390d3
movq %rbx, %rdi
movq 0x60(%rsp), %rsi
callq 0x6c8e0
movq %rbx, %rdi
callq 0x6c336
jmp 0x390d3
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq