// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Ray const&, gaps::R3Box const&, gaps::R3Point*, gaps::R3Vector*, double*)
RNClassID R3Intersects(const R3Ray& ray, const R3Box& box, 
    R3Point *hit_point1, R3Vector *hit_normal1, RNScalar *hit_t1)
{
    // Check box 
    if (box.IsEmpty()) {
        // Box is empty
        return RN_NULL_CLASS_ID;
    }
    else {
        R3Point point1;
        RNScalar tval1;

        // Check if ray start is inside box
        RNBoolean start_inside = R3Contains(box, ray.Start());
        if (start_inside) {
	  if (hit_point1) *hit_point1 = ray.Start();
	  if (hit_normal1) *hit_normal1 = -ray.Vector();
  	  if (hit_t1) *hit_t1 = 0;
          return R3_SPAN_CLASS_ID;
        }

	// Find parametric distance to front plane in each dimension
	for (RNDimension dim = RN_X; dim <= RN_Z; dim++) {
	    if (RNIsPositive(ray.Vector()[dim])) {
                RNCoord box_coord = (start_inside) ? box.Max()[dim] : box.Min()[dim];
		RNScalar delta = box_coord - ray.Start()[dim];
		if (delta < 0.0) continue;
		tval1 = delta / ray.Vector()[dim];
	    }
	    else if (RNIsNegative(ray.Vector()[dim])) {
                RNCoord box_coord = (start_inside) ? box.Min()[dim] : box.Max()[dim];
		RNScalar delta = box_coord - ray.Start()[dim];
		if (delta > 0.0) continue;
		tval1 = delta / ray.Vector()[dim];
	    }
	    else {
		continue;
	    }
	    
	    // Compute intersection point on plane
	    RNDimension dim1 = (dim + 1) % 3;
	    RNDimension dim2 = (dim + 2) % 3;
	    point1[dim] = ray.Start()[dim] + ray.Vector()[dim] * tval1;
	    point1[dim1] = ray.Start()[dim1] + ray.Vector()[dim1] * tval1;
	    point1[dim2] = ray.Start()[dim2] + ray.Vector()[dim2] * tval1;
	    
	    // Check if intersection point on plane is inside box
	    if ((RNIsLessOrEqual(point1[dim1], box.Max()[dim1])) &&
		(RNIsGreaterOrEqual(point1[dim1], box.Min()[dim1])) &&
		(RNIsLessOrEqual(point1[dim2], box.Max()[dim2])) &&
		(RNIsGreaterOrEqual(point1[dim2], box.Min()[dim2]))) {
		// Found first intersection point 
  	        if (hit_t1) *hit_t1 = tval1;
	        if (hit_point1) *hit_point1 = point1;
	        if (hit_normal1) {
	    	    if (RNIsNegative(ray.Vector()[dim])) *hit_normal1 = R3xyz_triad.Axis(dim);
		    else *hit_normal1 = -(R3xyz_triad.Axis(dim));
	        }
		return R3_SPAN_CLASS_ID;
	    }
	}

	// Return no intersection 
	return RN_NULL_CLASS_ID;
    }
}

// Assembly:
subq $0x148, %rsp            # imm = 0x148
movq %rdi, 0x138(%rsp)
movq %rsi, 0x130(%rsp)
movq %rdx, 0x128(%rsp)
movq %rcx, 0x120(%rsp)
movq %r8, 0x118(%rsp)
movq 0x130(%rsp), %rdi
callq 0x44d80
cmpl $0x0, %eax
je 0x7b481
movl $0x0, 0x144(%rsp)
jmp 0x7bc01
leaq 0x100(%rsp), %rdi
callq 0x6eb40
movq 0x130(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq 0x88(%rsp), %rdi
movq %rax, %rsi
callq 0x83a20
movl %eax, 0xf4(%rsp)
cmpl $0x0, 0xf4(%rsp)
je 0x7b55f
cmpq $0x0, 0x128(%rsp)
je 0x7b4f8
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rsi
movq 0x128(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0x120(%rsp)
je 0x7b535
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rsi
leaq 0xd8(%rsp), %rdi
callq 0x70fa0
movq 0x120(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
callq 0x70970
cmpq $0x0, 0x118(%rsp)
je 0x7b54f
movq 0x118(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x4, 0x144(%rsp)
jmp 0x7bc01
movl $0x0, 0xd4(%rsp)
cmpl $0x2, 0xd4(%rsp)
jg 0x7bbf6
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
leaq 0xfcf45(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x7b6af
cmpl $0x0, 0xf4(%rsp)
je 0x7b5de
movq 0x130(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x80(%rsp)
jmp 0x7b603
movq 0x130(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
movsd 0xc8(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x78(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0xc0(%rsp)
xorps %xmm0, %xmm0
ucomisd 0xc0(%rsp), %xmm0
jbe 0x7b669
jmp 0x7bbe0
movsd 0xc0(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
movaps %xmm0, %xmm1
movsd 0x70(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xf8(%rsp)
jmp 0x7b7e5
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
leaq 0xfce0e(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7b7de
cmpl $0x0, 0xf4(%rsp)
je 0x7b712
movq 0x130(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x68(%rsp)
jmp 0x7b734
movq 0x130(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x68(%rsp)
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0xb8(%rsp)
movsd 0xb8(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0xb0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x7b79b
jmp 0x7bbe0
movsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
movaps %xmm0, %xmm1
movsd 0x58(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xf8(%rsp)
jmp 0x7b7e3
jmp 0x7bbe0
jmp 0x7b7e5
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0xac(%rsp)
movl 0xd4(%rsp), %eax
addl $0x2, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0xa8(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x20(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
movsd 0x20(%rsp), %xmm1
movsd 0xf8(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
movl 0xd4(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd 0x28(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x30(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x3a4b0
movsd 0x30(%rsp), %xmm1
movsd 0xf8(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x38(%rsp)
movl 0xac(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd 0x38(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x138(%rsp), %rdi
callq 0x3c0c0
movq %rax, %rdi
movl 0xa8(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x40(%rsp)
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xa8(%rsp), %esi
callq 0x3a4b0
movsd 0x40(%rsp), %xmm1
movsd 0xf8(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0xa8(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd 0x48(%rsp), %xmm0
movsd %xmm0, (%rax)
movl 0xac(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x50(%rsp)
movq 0x130(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x50(%rsp), %xmm0
leaq 0xfcb14(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b50
cmpl $0x0, %eax
je 0x7bbde
movl 0xac(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq 0x130(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0xac(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
leaq 0xfcab8(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b80
cmpl $0x0, %eax
je 0x7bbde
movl 0xa8(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x130(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0xa8(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x10(%rsp), %xmm0
leaq 0xfca5c(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b50
cmpl $0x0, %eax
je 0x7bbde
movl 0xa8(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x130(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0xa8(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
leaq 0xfca00(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b80
cmpl $0x0, %eax
je 0x7bbde
cmpq $0x0, 0x118(%rsp)
je 0x7bb12
movsd 0xf8(%rsp), %xmm0
movq 0x118(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x128(%rsp)
je 0x7bb32
movq 0x128(%rsp), %rdi
leaq 0x100(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0x120(%rsp)
je 0x7bbd1
movq 0x138(%rsp), %rdi
callq 0x3c0e0
movq %rax, %rdi
movl 0xd4(%rsp), %esi
callq 0x3a4b0
leaq 0xfc97c(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7bb97
movl 0xd4(%rsp), %esi
leaq 0xfcf88(%rip), %rdi     # 0x178b08
callq 0x3c2c0
movq %rax, %rsi
movq 0x120(%rsp), %rdi
callq 0x70970
jmp 0x7bbcf
movl 0xd4(%rsp), %esi
leaq 0xfcf63(%rip), %rdi     # 0x178b08
callq 0x3c2c0
movq %rax, %rsi
leaq 0x90(%rsp), %rdi
callq 0x70fa0
movq 0x120(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x70970
jmp 0x7bbd1
movl $0x4, 0x144(%rsp)
jmp 0x7bc01
jmp 0x7bbe0
movl 0xd4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xd4(%rsp)
jmp 0x7b56a
movl $0x0, 0x144(%rsp)
movl 0x144(%rsp), %eax
addq $0x148, %rsp            # imm = 0x148
retq