// File: tomfunkhouser[P]gaps/pkgs/R2Shapes/R2Isect.cpp
// Function: gaps::R2Intersects(gaps::R2Ray const&, gaps::R2Box const&, gaps::R2Point*, gaps::R2Vector*, double*)
RNClassID R2Intersects(const R2Ray& ray, const R2Box& box, 
    R2Point *hit_point1, R2Vector *hit_normal1, RNScalar *hit_t1)
{
    RNClassID id = RN_NULL_CLASS_ID;
    R2Point point1;
    RNScalar tval1;

    // Check box 
    if (box.IsEmpty()) {
        // Box is empty
        return RN_NULL_CLASS_ID;
    }
    else if (R2Contains(box, ray.Start())) {
        // Box contains ray start point
	if (hit_point1) *hit_point1 = ray.Start();
	if (hit_normal1) *hit_normal1 = ray.Vector();
	if (hit_t1) *hit_t1 = 0.0;
	return R2_SPAN_CLASS_ID;
    }
    else {
	// Find parametric distance to front plane in each dimension
	for (RNDimension dim = RN_X; dim <= RN_Y; dim++) {
	    if (RNIsPositive(ray.Vector()[dim])) {
		RNScalar delta = box.Min()[dim] - ray.Start()[dim];
		if (delta < 0.0) continue;
		tval1 = delta / ray.Vector()[dim];
	    }
	    else if (RNIsNegative(ray.Vector()[dim])) {
		RNScalar delta = box.Max()[dim] - ray.Start()[dim];
		if (delta > 0.0) continue;
		tval1 = delta / ray.Vector()[dim];
	    }
	    else {
		continue;
	    }
	    
	    // Compute intersection point on plane
	    RNDimension dim1 = 1 - dim;
	    point1[dim] = (ray.Vector()[dim] > 0.0) ? box.Min()[dim] : box.Max()[dim];
	    point1[dim1] = ray.Start()[dim1] + ray.Vector()[dim1] * tval1;
	    // assert(RNIsEqual(point1[dim], ray.Start()[dim] + ray.Vector()[dim] * tval1));
	    
	    // Check if intersection point on plane is inside box
	    if ((RNIsLessOrEqual(point1[dim1], box.Max()[dim1])) &&
		(RNIsGreaterOrEqual(point1[dim1], box.Min()[dim1]))) {
		// Found first intersection point 
		id = R2_SPAN_CLASS_ID;
                if (hit_t1) *hit_t1 = tval1;
                if (hit_point1) *hit_point1 = point1;
                if (hit_normal1) {
	            *hit_normal1 = R2zero_vector;
		    if (RNIsNegative(ray.Vector()[dim])) *hit_normal1 = (*hit_normal1)[dim] = 1.0;
		    else (*hit_normal1)[dim] = -1.0;
	        }
		break;
	    }
	}

	// Return intersection 
	return id;
    }
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xc8(%rsp)
movq %rsi, 0xc0(%rsp)
movq %rdx, 0xb8(%rsp)
movq %rcx, 0xb0(%rsp)
movq %r8, 0xa8(%rsp)
movl $0x0, 0xa4(%rsp)
leaq 0x90(%rsp), %rdi
callq 0xc3130
movq 0xc0(%rsp), %rdi
callq 0xa36c0
cmpl $0x0, %eax
je 0xa4519
movl $0x0, 0xd4(%rsp)
jmp 0xa4a80
movq 0xc0(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa3560
movq 0x50(%rsp), %rdi
movq %rax, %rsi
callq 0xa2600
cmpl $0x0, %eax
je 0xa45bf
cmpq $0x0, 0xb8(%rsp)
je 0xa456d
movq 0xc8(%rsp), %rdi
callq 0xa3560
movq %rax, %rsi
movq 0xb8(%rsp), %rdi
callq 0xc33e0
cmpq $0x0, 0xb0(%rsp)
je 0xa4595
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rsi
movq 0xb0(%rsp), %rdi
callq 0xc4350
cmpq $0x0, 0xa8(%rsp)
je 0xa45af
movq 0xa8(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x4, 0xd4(%rsp)
jmp 0xa4a80
movl $0x0, 0x84(%rsp)
cmpl $0x1, 0x84(%rsp)
jg 0xa4a72
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
leaq 0xd3ee5(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0xa46b1
movq 0xc0(%rsp), %rdi
callq 0xa3520
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movsd %xmm0, 0x48(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa3560
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movaps %xmm0, %xmm1
movsd 0x48(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
xorps %xmm0, %xmm0
ucomisd 0x78(%rsp), %xmm0
jbe 0xa466e
jmp 0xa4a5c
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
movaps %xmm0, %xmm1
movsd 0x40(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
jmp 0xa4792
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
leaq 0xd3e0c(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0xa478b
movq 0xc0(%rsp), %rdi
callq 0xa3570
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movsd %xmm0, 0x38(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa3560
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movaps %xmm0, %xmm1
movsd 0x38(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xa474b
jmp 0xa4a5c
movsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
movaps %xmm0, %xmm1
movsd 0x30(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
jmp 0xa4790
jmp 0xa4a5c
jmp 0xa4792
movl $0x1, %eax
subl 0x84(%rsp), %eax
movl %eax, 0x6c(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0xa47eb
movq 0xc0(%rsp), %rdi
callq 0xa3520
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movsd %xmm0, 0x28(%rsp)
jmp 0xa480d
movq 0xc0(%rsp), %rdi
callq 0xa3570
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0xa5bf0
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movl 0x84(%rsp), %esi
leaq 0x90(%rsp), %rdi
callq 0xa5b60
movsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0xc8(%rsp), %rdi
callq 0xa3560
movq %rax, %rdi
movl 0x6c(%rsp), %esi
callq 0xa5bf0
movsd %xmm0, 0x10(%rsp)
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x6c(%rsp), %esi
callq 0x86bd0
movsd 0x10(%rsp), %xmm1
movsd 0x88(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movl 0x6c(%rsp), %esi
leaq 0x90(%rsp), %rdi
callq 0xa5b60
movsd 0x18(%rsp), %xmm0
movsd %xmm0, (%rax)
movl 0x6c(%rsp), %esi
leaq 0x90(%rsp), %rdi
callq 0xa5b60
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0xc0(%rsp), %rdi
callq 0xa3570
movq %rax, %rdi
movl 0x6c(%rsp), %esi
callq 0xa5bf0
movaps %xmm0, %xmm1
movsd 0x20(%rsp), %xmm0
leaq 0xd3bf5(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b50
cmpl $0x0, %eax
je 0xa4a5a
movl 0x6c(%rsp), %esi
leaq 0x90(%rsp), %rdi
callq 0xa5b60
movsd (%rax), %xmm0
movsd %xmm0, (%rsp)
movq 0xc0(%rsp), %rdi
callq 0xa3520
movq %rax, %rdi
movl 0x6c(%rsp), %esi
callq 0xa5bf0
movaps %xmm0, %xmm1
movsd (%rsp), %xmm0
leaq 0xd3ba1(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b80
cmpl $0x0, %eax
je 0xa4a5a
movl $0x4, 0xa4(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0xa497c
movsd 0x88(%rsp), %xmm0
movq 0xa8(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0xb8(%rsp)
je 0xa499c
movq 0xb8(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0xc33e0
cmpq $0x0, 0xb0(%rsp)
je 0xa4a58
movq 0xb0(%rsp), %rdi
leaq 0x4d64de(%rip), %rsi    # 0x57ae98
callq 0xc4350
movq 0xc8(%rsp), %rdi
callq 0xa35c0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x86bd0
leaq 0xd3afe(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0xa4a36
movq 0xb0(%rsp), %rdi
movl 0x84(%rsp), %esi
callq 0xa5c10
movsd 0x8e5fc(%rip), %xmm0    # 0x133008
movsd %xmm0, (%rax)
leaq 0x58(%rsp), %rdi
movsd 0x8e5eb(%rip), %xmm0    # 0x133008
callq 0xc3c90
movq 0xb0(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0xc4350
jmp 0xa4a56
movq 0xb0(%rsp), %rdi
movl 0x84(%rsp), %esi
callq 0xa5c10
movsd 0x8e5c6(%rip), %xmm0    # 0x133018
movsd %xmm0, (%rax)
jmp 0xa4a58
jmp 0xa4a72
jmp 0xa4a5c
movl 0x84(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x84(%rsp)
jmp 0xa45ca
movl 0xa4(%rsp), %eax
movl %eax, 0xd4(%rsp)
movl 0xd4(%rsp), %eax
addq $0xd8, %rsp
retq
nop