// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Ray const&, gaps::R3Ray const&, gaps::R3Point*, double*, double*)
RNClassID R3Intersects(const R3Ray& ray1, const R3Ray& ray2, 
    R3Point *hit_point, RNScalar *hit_t1, RNScalar *hit_t2)
{
    // Intersect ray1 with ray2's line
    R3Point point;
    RNScalar s1 = 0, s2 = 0;
    switch (R3Intersects(ray1, ray2.Line(), &point, &s1)) {
    case RN_NULL_CLASS_ID:
	// Rays do not intersect
	return RN_NULL_CLASS_ID;

    case R3_RAY_CLASS_ID:
	// Ray2's line contains ray1 -- check directions
	if (R3Contains(ray1.Vector(), ray2.Vector())) {
	    // Rays share same line in same direction
	    return R3_RAY_CLASS_ID;
	}
	else {
	    // Rays share same line, but in different directions
	    assert(R3Contains(ray1.Vector(), -(ray2.Vector())));

	    // Check intersection point
	    s2 = ray2.T(ray1.Start());
	    if (RNIsNegative(s2)) {
		// Rays share line, but intersection is behind endpoint of ray2
		return RN_NULL_CLASS_ID;
	    }
	    else if (RNIsZero(s2)) {
		// Rays share line and endpoint
		if (hit_t1) *hit_t1 = s1;
		if (hit_t2) *hit_t2 = s2;
		if (hit_point) *hit_point = point;
		return R3_POINT_CLASS_ID;
	    }
	    else {
		// Rays share line and intersect in span 
		return R3_SPAN_CLASS_ID;
	    }
	}

    case R3_POINT_CLASS_ID: 
	// Check if intersection point is on ray2
	s2 = ray2.T(point);
	if (RNIsNegative(s1)) {
	    // Line intersection is behind ray1
	    return RN_NULL_CLASS_ID;
	}
	else {
	    // Rays intersect at point
	    if (hit_t1) *hit_t1 = s1;
	    if (hit_t2) *hit_t2 = s2;
	    if (hit_point) *hit_point = point;
	    return R3_POINT_CLASS_ID;
	}
	break;

    default:
	RNAbort("Illegal intersection");
	break;
    }

    // Should never get here
    RNAbort("Should never get here");
    return RN_NULL_CLASS_ID;
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x78(%rsp)
movq %rsi, 0x70(%rsp)
movq %rdx, 0x68(%rsp)
movq %rcx, 0x60(%rsp)
movq %r8, 0x58(%rsp)
leaq 0x40(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x6eb40
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x70(%rsp), %rdi
callq 0x81c00
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rdx
movq %rax, %rsi
leaq 0x38(%rsp), %rcx
callq 0x81bc0
movl %eax, %ecx
movl %ecx, 0x2c(%rsp)
testl %eax, %eax
je 0x7aaa5
jmp 0x7aa88
movl 0x2c(%rsp), %eax
subl $0x1, %eax
je 0x7abc2
jmp 0x7aa97
movl 0x2c(%rsp), %eax
subl $0x3, %eax
je 0x7aab5
jmp 0x7ac51
movl $0x0, 0x84(%rsp)
jmp 0x7ac78
movq 0x78(%rsp), %rdi
callq 0x3c0e0
movq %rax, 0x10(%rsp)
movq 0x70(%rsp), %rdi
callq 0x3c0e0
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x820a0
cmpl $0x0, %eax
je 0x7aaf0
movl $0x3, 0x84(%rsp)
jmp 0x7ac78
movq 0x70(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x78(%rsp), %rdi
callq 0x3c0c0
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x6e550
movsd %xmm0, 0x30(%rsp)
movsd 0x30(%rsp), %xmm0
leaq 0xfd9bc(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7ab42
movl $0x0, 0x84(%rsp)
jmp 0x7ac78
movsd 0x30(%rsp), %xmm0
leaq 0xfd991(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36b80
cmpl $0x0, %eax
je 0x7abb2
cmpq $0x0, 0x60(%rsp)
je 0x7ab74
movsd 0x38(%rsp), %xmm0
movq 0x60(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x58(%rsp)
je 0x7ab8b
movsd 0x30(%rsp), %xmm0
movq 0x58(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x68(%rsp)
je 0x7aba2
movq 0x68(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x6f1e0
movl $0x1, 0x84(%rsp)
jmp 0x7ac78
movl $0x4, 0x84(%rsp)
jmp 0x7ac78
movq 0x70(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x6e550
movsd %xmm0, 0x30(%rsp)
movsd 0x38(%rsp), %xmm0
leaq 0xfd8fc(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7abff
movl $0x0, 0x84(%rsp)
jmp 0x7ac78
cmpq $0x0, 0x60(%rsp)
je 0x7ac16
movsd 0x38(%rsp), %xmm0
movq 0x60(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x58(%rsp)
je 0x7ac2d
movsd 0x30(%rsp), %xmm0
movq 0x58(%rsp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, 0x68(%rsp)
je 0x7ac44
movq 0x68(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x6f1e0
movl $0x1, 0x84(%rsp)
jmp 0x7ac78
leaq 0xbad1c(%rip), %rdi     # 0x135974
movb $0x0, %al
callq 0xd4e20
leaq 0xbad23(%rip), %rdi     # 0x135989
movb $0x0, %al
callq 0xd4e20
movl $0x0, 0x84(%rsp)
movl 0x84(%rsp), %eax
addq $0x88, %rsp
retq
nopw (%rax,%rax)