// File: /workspace/github_cpp_makefile_star2_O1/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, 0x8(%rsp)
movsd %xmm0, 0x10(%rsp)
movq %r9, %r12
movq %r8, 0x48(%rsp)
movq %rcx, %rbp
movq %rdx, 0x40(%rsp)
movq %rsi, %rbx
movq %rdi, %r13
leaq 0x10ac04(%rip), %rsi    # 0x147d90
leaq 0x90(%rsp), %rdi
callq 0x762ca
leaq 0xa8(%rsp), %rdi
callq 0x762b8
leaq 0x70(%rsp), %rdi
callq 0x76d50
movsd 0x170(%r13), %xmm0
ucomisd 0xa09df(%rip), %xmm0    # 0xddba0
jne 0x3d1cd
jp 0x3d1cd
movq %r13, %rdi
callq 0x3c7ca
leaq 0x168(%r13), %rsi
xorl %r14d, %r14d
leaq 0x88(%rsp), %r8
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x4870a
testl %eax, %eax
je 0x3d686
movsd 0x88(%rsp), %xmm0
leaq 0x102ed5(%rip), %r15    # 0x1400d8
subsd 0x8(%rsp), %xmm0
ucomisd (%r15), %xmm0
ja 0x3d686
movq %r12, 0x68(%rsp)
leaq 0xc0(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x75ea2
leaq 0x58(%r13), %r12
movq %r14, %rdi
movq %r12, %rsi
callq 0x75f82
addq $0x18, %rbx
leaq 0xf0(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x76d62
movq %r14, %rdi
movq %r12, 0x60(%rsp)
movq %r12, %rsi
callq 0x77940
movq %r14, %rdi
callq 0x76e58
movsd (%r15), %xmm4
ucomisd %xmm0, %xmm4
jae 0x3d683
movsd 0x9f24f(%rip), %xmm1    # 0xdc4d0
addsd %xmm0, %xmm1
movapd 0x9f2a3(%rip), %xmm2    # 0xdc530
xorpd %xmm4, %xmm2
cmpnltpd %xmm1, %xmm4
cmpnltpd %xmm2, %xmm1
andpd %xmm4, %xmm1
movd %xmm1, %eax
testb $0x1, %al
jne 0x3d2c7
movapd %xmm0, %xmm3
movsd 0x10(%rsp), %xmm0
mulsd %xmm3, %xmm0
movsd 0x8(%rsp), %xmm1
mulsd %xmm3, %xmm1
movsd %xmm1, 0x8(%rsp)
jmp 0x3d2d5
movsd 0x9ed49(%rip), %xmm3    # 0xdc018
movsd 0x10(%rsp), %xmm0
movsd %xmm3, 0x58(%rsp)
movq %rbp, 0x38(%rsp)
cmpl $0x0, 0x3c(%r13)
movsd %xmm0, 0x10(%rsp)
jle 0x3d3df
xorl %r14d, %r14d
leaq 0xa8(%rsp), %r15
leaq 0x70(%rsp), %r12
leaq 0x18(%rsp), %rbp
movq $0x0, 0x20(%rsp)
movq 0x30(%r13), %rax
movq (%rax,%r14,8), %rbx
movq %rbx, %rdi
leaq 0xc0(%rsp), %rsi
leaq 0x28(%rsp), %rdx
movq %r15, %rcx
movq %r12, %r8
movq %rbp, %r9
movsd 0x8(%rsp), %xmm1
callq 0x3dedc
testl %eax, %eax
je 0x3d3c7
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x3d3cd
movsd 0x8(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jb 0x3d3cd
movq 0x40(%rsp), %rax
testq %rax, %rax
movq 0x48(%rsp), %rcx
je 0x3d373
movq %r13, (%rax)
movq 0x38(%rsp), %rdx
testq %rdx, %rdx
je 0x3d384
movq 0x8(%rbx), %rax
movq %rax, (%rdx)
testq %rcx, %rcx
je 0x3d391
movq 0x28(%rsp), %rax
movq %rax, (%rcx)
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x3d3a6
movq %r12, %rsi
callq 0x774fe
leaq 0x90(%rsp), %rdi
movq %r15, %rsi
callq 0x76628
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movq %r13, 0x20(%rsp)
movsd 0x10(%rsp), %xmm0
incq %r14
movslq 0x3c(%r13), %rax
cmpq %rax, %r14
jl 0x3d30f
jmp 0x3d3e8
movq $0x0, 0x20(%rsp)
cmpl $0x0, 0x4c(%r13)
jle 0x3d4f1
xorl %r14d, %r14d
leaq 0xa8(%rsp), %rbx
movq 0x38(%rsp), %r15
movq 0x40(%rsp), %r12
movq 0x140(%rsp), %rbp
movq 0x40(%r13), %rax
movq (%rax,%r14,8), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x3d4e1
leaq 0xc0(%rsp), %rsi
leaq 0x30(%rsp), %rdx
leaq 0x50(%rsp), %rcx
leaq 0x28(%rsp), %r8
movq %rbx, %r9
movsd 0x8(%rsp), %xmm1
leaq 0x18(%rsp), %rax
pushq %rax
leaq 0x78(%rsp), %rax
pushq %rax
callq 0x29142
addq $0x10, %rsp
testl %eax, %eax
je 0x3d4db
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x3d4e1
movsd 0x8(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jb 0x3d4e1
testq %r12, %r12
movq 0x48(%rsp), %rcx
je 0x3d48e
movq 0x30(%rsp), %rax
movq %rax, (%r12)
testq %r15, %r15
je 0x3d49b
movq 0x50(%rsp), %rax
movq %rax, (%r15)
testq %rcx, %rcx
je 0x3d4a8
movq 0x28(%rsp), %rax
movq %rax, (%rcx)
testq %rbp, %rbp
je 0x3d4ba
movq %rbp, %rdi
leaq 0x70(%rsp), %rsi
callq 0x774fe
leaq 0x90(%rsp), %rdi
movq %rbx, %rsi
callq 0x76628
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movq %r13, 0x20(%rsp)
movsd 0x10(%rsp), %xmm0
incq %r14
movslq 0x4c(%r13), %rax
cmpq %rax, %r14
jl 0x3d410
cmpl $0x0, 0x2c(%r13)
jle 0x3d5ff
xorl %ebx, %ebx
leaq 0x30(%rsp), %rbp
leaq 0x50(%rsp), %r14
leaq 0x28(%rsp), %r15
leaq 0xa8(%rsp), %r12
movq 0x20(%r13), %rax
movq (%rax,%rbx,8), %rdi
leaq 0xc0(%rsp), %rsi
movq %rbp, %rdx
movq %r14, %rcx
movq %r15, %r8
movq %r12, %r9
movsd 0x8(%rsp), %xmm1
leaq 0x18(%rsp), %rax
pushq %rax
leaq 0x78(%rsp), %rax
pushq %rax
callq 0x3d152
addq $0x10, %rsp
testl %eax, %eax
je 0x3d5e9
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
ucomisd %xmm0, %xmm1
jb 0x3d5ef
movsd 0x8(%rsp), %xmm2
ucomisd %xmm1, %xmm2
jb 0x3d5ef
movq 0x40(%rsp), %rdx
testq %rdx, %rdx
movq 0x48(%rsp), %rcx
je 0x3d58d
movq 0x30(%rsp), %rax
movq %rax, (%rdx)
movq 0x38(%rsp), %rdx
testq %rdx, %rdx
je 0x3d59f
movq 0x50(%rsp), %rax
movq %rax, (%rdx)
testq %rcx, %rcx
je 0x3d5ac
movq 0x28(%rsp), %rax
movq %rax, (%rcx)
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x3d5c3
leaq 0x70(%rsp), %rsi
callq 0x774fe
movq 0x30(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x90(%rsp), %rdi
movq %r12, %rsi
callq 0x76628
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
incq %rbx
movslq 0x2c(%r13), %rax
cmpq %rax, %rbx
jl 0x3d515
cmpq $0x0, 0x20(%rsp)
je 0x3d683
movq 0x148(%rsp), %rbx
movq 0x68(%rsp), %r14
movq %r14, %rax
orq %rbx, %rax
movq 0x60(%rsp), %r15
movq 0x140(%rsp), %r12
je 0x3d663
leaq 0x90(%rsp), %rdi
movq %r15, %rsi
callq 0x76bd6
testq %r14, %r14
je 0x3d64e
leaq 0x90(%rsp), %rsi
movq %r14, %rdi
callq 0x76628
testq %rbx, %rbx
je 0x3d663
movsd 0x8(%rsp), %xmm0
divsd 0x58(%rsp), %xmm0
movsd %xmm0, (%rbx)
movl $0x1, %r14d
testq %r12, %r12
je 0x3d686
movq %r12, %rdi
movq %r15, %rsi
callq 0x7792e
movq %r12, %rdi
callq 0x77074
jmp 0x3d686
xorl %r14d, %r14d
movl %r14d, %eax
addq $0x108, %rsp            # imm = 0x108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop