// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Span const&, gaps::R3Plane const&, gaps::R3Point*, double*)
RNClassID R3Intersects(const R3Span& span, const R3Plane& plane, 
    R3Point *hit_point, RNScalar *hit_t)
{
#if FALSE
    // Intersect plane with span's ray
    // Doesn't get backfacing planes ???
    RNScalar s;
    switch (R3Intersects(plane, span.Ray(), hit_point, &s)) {
    case RN_NULL_CLASS_ID:
	// Span and plane do not intersect
	return RN_NULL_CLASS_ID;

    case R3_RAY_CLASS_ID:
	// Plane contains span
	return R3_SPAN_CLASS_ID;

    case R3_POINT_CLASS_ID: 
	// Check if intersection point is on span
	if (RNIsGreater(s, span.Length())) {
	    // Span's ray intersects plane beyond span endpoint
	    return RN_NULL_CLASS_ID;
	}
	else {
	    // Span and plane intersect at point
	    if (hit_t) *hit_t = s;
	    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;
#else
    // Compute signed distances from plane to span endpoints
    RNScalar d1 = R3SignedDistance(plane, span.Start());
    RNScalar d2 = R3SignedDistance(plane, span.End());

    // Compute intersection relationship based on endpoint distances
    if (RNIsPositive(d1)) {
        if (RNIsPositive(d2)) {
	    // Span lies above plane
	    return RN_NULL_CLASS_ID;
	}
	else if (d2 >= 0.0) {
	    // Span abuts plane at end point
	    if (hit_point) *hit_point = span.End();
	    if (hit_t) *hit_t = span.Length();
	    return R3_POINT_CLASS_ID;
	}
	else {
	    // Span crosses plane
	    RNScalar t = span.Length() * d1 / (d1 - d2);
	    if (hit_point) *hit_point = span.Point(t);
	    if (hit_t) *hit_t = t;
	    return R3_POINT_CLASS_ID;
	}
    }
    else if (RNIsNegative(d1)) {
        if (RNIsNegative(d2)) {
	    // Span lies below plane
	    return RN_NULL_CLASS_ID;
	}
	else if (d2 <= 0.0) {
	    // Span abuts plane at end point
	    if (hit_point) *hit_point = span.End();
	    if (hit_t) *hit_t = span.Length();
	    return R3_POINT_CLASS_ID;
	}
	else {
	    // Span crosses plane
	    RNScalar t = span.Length() * d1 / (d1 - d2);
	    if (hit_point) *hit_point = span.Point(t);
	    if (hit_t) *hit_t = t;
	    return R3_POINT_CLASS_ID;
	}
    }
    else {
        if (RNIsPositive(d2)) {	  
	    if (d1 >= 0.0) {
		// Span abuts plane at start point
	        if (hit_point) *hit_point = span.Start();
		if (hit_t) *hit_t = 0.0;
		return R3_POINT_CLASS_ID;
	    }
	    else {
	        // Span crosses plane
	        RNScalar t = span.Length() * d1 / (d1 - d2);
		if (hit_point) *hit_point = span.Point(t);
		if (hit_t) *hit_t = t;
		return R3_POINT_CLASS_ID;
	    }
	}
	else if (RNIsNegative(d2)) {	  
	    if (d1 <= 0.0) {
		// Span abuts plane at start point
	        if (hit_point) *hit_point = span.Start();
		if (hit_t) *hit_t = 0.0;
		return R3_POINT_CLASS_ID;
	    }
	    else {
	        // Span crosses plane
	        RNScalar t = span.Length() * d1 / (d1 - d2);
		if (hit_point) *hit_point = span.Point(t);
		if (hit_t) *hit_t = t;
		return R3_POINT_CLASS_ID;
	    }
	}
	else {
	    // Span lies on plane
	    return R3_SPAN_CLASS_ID;
	}
    }
#endif
}

// Assembly:
subq $0xc8, %rsp
movq %rdi, 0xb8(%rsp)
movq %rsi, 0xb0(%rsp)
movq %rdx, 0xa8(%rsp)
movq %rcx, 0xa0(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, (%rsp)
movq 0xb8(%rsp), %rdi
callq 0x39250
movq (%rsp), %rdi
movq %rax, %rsi
callq 0x86f90
movsd %xmm0, 0x98(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0xb8(%rsp), %rdi
callq 0x39260
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x86f90
movsd %xmm0, 0x90(%rsp)
movsd 0x98(%rsp), %xmm0
leaq 0xf9eeb(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x7e740
movsd 0x90(%rsp), %xmm0
leaq 0xf9ec9(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x7e635
movl $0x0, 0xc4(%rsp)
jmp 0x7eac6
movsd 0x90(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x7e6a3
cmpq $0x0, 0xa8(%rsp)
je 0x7e66f
movq 0xb8(%rsp), %rdi
callq 0x39260
movq %rax, %rsi
movq 0xa8(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e693
movq 0xb8(%rsp), %rdi
callq 0x37a50
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movq 0xb8(%rsp), %rdi
callq 0x37a50
mulsd 0x98(%rsp), %xmm0
movsd 0x98(%rsp), %xmm1
subsd 0x90(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x7e710
movq 0xb8(%rsp), %rsi
movsd 0x88(%rsp), %xmm0
leaq 0x70(%rsp), %rdi
callq 0x6d710
movq 0xa8(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e730
movsd 0x88(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movsd 0x98(%rsp), %xmm0
leaq 0xf9d90(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7e88e
movsd 0x90(%rsp), %xmm0
leaq 0xf9d6e(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7e790
movl $0x0, 0xc4(%rsp)
jmp 0x7eac6
xorps %xmm0, %xmm0
ucomisd 0x90(%rsp), %xmm0
jb 0x7e7fa
cmpq $0x0, 0xa8(%rsp)
je 0x7e7c6
movq 0xb8(%rsp), %rdi
callq 0x39260
movq %rax, %rsi
movq 0xa8(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e7ea
movq 0xb8(%rsp), %rdi
callq 0x37a50
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movq 0xb8(%rsp), %rdi
callq 0x37a50
mulsd 0x98(%rsp), %xmm0
movsd 0x98(%rsp), %xmm1
subsd 0x90(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x68(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x7e861
movq 0xb8(%rsp), %rsi
movsd 0x68(%rsp), %xmm0
leaq 0x50(%rsp), %rdi
callq 0x6d710
movq 0xa8(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e87e
movsd 0x68(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movsd 0x90(%rsp), %xmm0
leaq 0xf9c42(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x36d50
cmpl $0x0, %eax
je 0x7e9a8
movsd 0x98(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x7e914
cmpq $0x0, 0xa8(%rsp)
je 0x7e8ea
movq 0xb8(%rsp), %rdi
callq 0x39250
movq %rax, %rsi
movq 0xa8(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e904
movq 0xa0(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movq 0xb8(%rsp), %rdi
callq 0x37a50
mulsd 0x98(%rsp), %xmm0
movsd 0x98(%rsp), %xmm1
subsd 0x90(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x7e97b
movq 0xb8(%rsp), %rsi
movsd 0x48(%rsp), %xmm0
leaq 0x30(%rsp), %rdi
callq 0x6d710
movq 0xa8(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7e998
movsd 0x48(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movsd 0x90(%rsp), %xmm0
leaq 0xf9b28(%rip), %rax     # 0x1784e0
movsd (%rax), %xmm1
callq 0x38fd0
cmpl $0x0, %eax
je 0x7eabb
xorps %xmm0, %xmm0
ucomisd 0x98(%rsp), %xmm0
jb 0x7ea2a
cmpq $0x0, 0xa8(%rsp)
je 0x7ea00
movq 0xb8(%rsp), %rdi
callq 0x39250
movq %rax, %rsi
movq 0xa8(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7ea1a
movq 0xa0(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movq 0xb8(%rsp), %rdi
callq 0x37a50
mulsd 0x98(%rsp), %xmm0
movsd 0x98(%rsp), %xmm1
subsd 0x90(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x28(%rsp)
cmpq $0x0, 0xa8(%rsp)
je 0x7ea91
movq 0xb8(%rsp), %rsi
movsd 0x28(%rsp), %xmm0
leaq 0x10(%rsp), %rdi
callq 0x6d710
movq 0xa8(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0xa0(%rsp)
je 0x7eaae
movsd 0x28(%rsp), %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0xc4(%rsp)
jmp 0x7eac6
movl $0x4, 0xc4(%rsp)
movl 0xc4(%rsp), %eax
addq $0xc8, %rsp
retq
nopw %cs:(%rax,%rax)