// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Line const&, gaps::R3Box const&, gaps::R3Point*)
RNClassID R3Intersects(const R3Line& line, const R3Box& box, 
    R3Point *hit_point)
{
    RNClassID id = RN_NULL_CLASS_ID;
    R3Point point1;
    RNScalar tval1;

    // Check if box contains point on line
    if (R3Contains(box, line.Point())) {
	if (hit_point) *hit_point = line.Point();
	return R3_SPAN_CLASS_ID;
    }
    else {
	// Find parametric distance to front plane in each dimension
	for (RNDimension dim = RN_X; dim <= RN_Z; dim++) {
	    if (RNIsPositive(line.Vector()[dim])) {
		RNScalar delta = box.Min()[dim] - line.Point()[dim];
		tval1 = delta / line.Vector()[dim];
	    }
	    else if (RNIsNegative(line.Vector()[dim])) {
		RNScalar delta = box.Max()[dim] - line.Point()[dim];
		tval1 = delta / line.Vector()[dim];
	    }
	    else {
		continue;
	    }
	    
	    // Compute intersection point on plane
	    RNDimension dim1 = (dim + 1) % 3;
	    RNDimension dim2 = (dim + 2) % 3;
	    point1[dim] = (line.Vector()[dim] > 0.0) ? box.Min()[dim] : box.Max()[dim];
	    assert(RNIsEqual(point1[dim], line.Point()[dim] + line.Vector()[dim] * tval1));
	    point1[dim1] = line.Point()[dim1] + line.Vector()[dim1] * tval1;
	    point1[dim2] = line.Point()[dim2] + line.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 
		id = R3_SPAN_CLASS_ID;
		break;
	    }
	}

	// Fill in results
	if (id != RN_NULL_CLASS_ID) {
	    if (hit_point) *hit_point = point1;
	}
	
	// Return intersection 
	return id;
    }
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movq %rsi, 0xd0(%rsp)
movq %rdx, 0xc8(%rsp)
movl $0x0, 0xc4(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x6eb40
movq 0xd0(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq 0x78(%rsp), %rdi
movq %rax, %rsi
callq 0x83a20
cmpl $0x0, %eax
je 0x79eab
cmpq $0x0, 0xc8(%rsp)
je 0x79e9b
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq %rax, %rsi
movq 0xc8(%rsp), %rdi
callq 0x6f1e0
movl $0x4, 0xe4(%rsp)
jmp 0x7a3e6
movl $0x0, 0x9c(%rsp)
cmpl $0x2, 0x9c(%rsp)
jg 0x7a3ac
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x3a4b0
leaq 0xfe5f9(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x79f93
movq 0xd0(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x68(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x68(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x90(%rsp)
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x3a4b0
movaps %xmm0, %xmm1
movsd 0x70(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x7a066
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x3a4b0
leaq 0xfe52a(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7a05f
movq 0xd0(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x58(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x58(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0x88(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x3a4b0
movaps %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x7a064
jmp 0x7a396
jmp 0x7a066
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0x84(%rsp)
movl 0x9c(%rsp), %eax
addl $0x2, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, 0x80(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x3a4b0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x7a0e1
movq 0xd0(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x50(%rsp)
jmp 0x7a103
movq 0xd0(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0x9c(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movl 0x9c(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd 0x20(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x28(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x3a4b0
movsd 0x28(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
movl 0x84(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd 0x30(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0xd8(%rsp), %rdi
callq 0x3c0d0
movq %rax, %rdi
movl 0x80(%rsp), %esi
callq 0x13af0
movsd %xmm0, 0x38(%rsp)
movq 0xd8(%rsp), %rdi
callq 0x3c0f0
movq %rax, %rdi
movl 0x80(%rsp), %esi
callq 0x3a4b0
movsd 0x38(%rsp), %xmm1
movsd 0xa0(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x40(%rsp)
movl 0x80(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd 0x40(%rsp), %xmm0
movsd %xmm0, (%rax)
movl 0x84(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x48(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x48(%rsp), %xmm0
leaq 0xfe277(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b50
cmpl $0x0, %eax
je 0x7a394
movl 0x84(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0x84(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
leaq 0xfe21b(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b80
cmpl $0x0, %eax
je 0x7a394
movl 0x80(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x45060
movq %rax, %rdi
movl 0x80(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x10(%rsp), %xmm0
leaq 0xfe1bf(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b50
cmpl $0x0, %eax
je 0x7a394
movl 0x80(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x36be0
movsd (%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x81b40
movq %rax, %rdi
movl 0x80(%rsp), %esi
callq 0x13af0
movaps %xmm0, %xmm1
movsd 0x8(%rsp), %xmm0
leaq 0xfe167(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm2
callq 0x81b80
cmpl $0x0, %eax
je 0x7a394
movl $0x4, 0xc4(%rsp)
jmp 0x7a3ac
jmp 0x7a396
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x79eb6
cmpl $0x0, 0xc4(%rsp)
je 0x7a3d8
cmpq $0x0, 0xc8(%rsp)
je 0x7a3d6
movq 0xc8(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x6f1e0
jmp 0x7a3d8
movl 0xc4(%rsp), %eax
movl %eax, 0xe4(%rsp)
movl 0xe4(%rsp), %eax
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)