// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %r8, %r14
movq %rcx, %r15
movq %rdx, %rbx
movq %rsi, %r12
movq %rdi, %r13
leaq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0x37b4a
leaq 0x8(%rsp), %rcx
andq $0x0, (%rcx)
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x3d0f9
movl %eax, %ebp
movl %eax, %eax
leaq 0x5c4d5(%rip), %rcx     # 0x99f18
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x10(%rsp), %rsi
movq %r12, %rdi
callq 0x377ac
movsd 0x8(%rsp), %xmm1
leaq 0x9d142(%rip), %rax     # 0xdaba8
movsd (%rax), %xmm2
xorpd 0x555be(%rip), %xmm2    # 0x93030
ucomisd %xmm1, %xmm2
ja 0x3db30
testq %r15, %r15
je 0x3da86
movsd %xmm1, (%r15)
testq %r14, %r14
je 0x3da90
movsd %xmm0, (%r14)
pushq $0x1
popq %rbp
testq %rbx, %rbx
je 0x3db32
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x37e36
jmp 0x3db32
leaq 0x5c4c7(%rip), %rdi     # 0x99f7c
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x680f0
leaq 0x5c4cc(%rip), %rdi     # 0x99f91
xorl %eax, %eax
callq 0x680f0
jmp 0x3db32
leaq 0x18(%r13), %rdi
leaq 0x18(%r12), %rsi
callq 0x40d74
testl %eax, %eax
je 0x3dae5
pushq $0x3
popq %rbp
jmp 0x3db32
movq %r12, %rdi
movq %r13, %rsi
callq 0x377ac
leaq 0x9d0b1(%rip), %rax     # 0xdaba8
movsd (%rax), %xmm1
movapd 0x5552d(%rip), %xmm2    # 0x93030
xorpd %xmm1, %xmm2
ucomisd %xmm0, %xmm2
ja 0x3db30
ucomisd %xmm2, %xmm0
pushq $0x4
popq %rbp
jb 0x3db32
ucomisd %xmm0, %xmm1
jb 0x3db32
testq %r15, %r15
je 0x3da86
movsd 0x8(%rsp), %xmm1
jmp 0x3da81
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq