// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Isect.cpp
// Function: gaps::R3Intersects(gaps::R3Span const&, gaps::R3Triangle const&, gaps::R3Point*, double*)
RNClassID R3Intersects(const R3Span& span, const R3Triangle& triangle, 
    R3Point *hit_point1, RNScalar *hit_t1)
{
    // Find intersection of span and plane
    R3Point p;
    RNScalar t;
    switch (R3Intersects(span, triangle.Plane(), &p, &t)) {
    case RN_NULL_CLASS_ID:
	// Span does not intersect triangle plane
	return RN_NULL_CLASS_ID;
	
    case R3_POINT_CLASS_ID:
	// Span intersects triangle plane in a single point
	// Check whether triangle contains intersection point
	if (!R3Contains(triangle, p)) return RN_NULL_CLASS_ID;
	if (hit_point1) *hit_point1 = p;
	if (hit_t1) *hit_t1 = t;
	return R3_POINT_CLASS_ID;

    case R3_SPAN_CLASS_ID: 
	// Span lies in triangle plane 
	{
	    // Clip span to all edges of triangle
	    R3Span s(span);
	    const R3Point *p1 = &(triangle.Vertex(2)->Position());
	    for (int i = 0; i < 3; i++) {
		// Get kth point
		const R3Point *p2 = &(triangle.Vertex(i)->Position());
		
		// Construct edge plane (containing edge and normal to triangle)
		R3Plane edge_plane(*p2, triangle.Normal(), *p2 - *p1);
		
		// Clip span to edge plane
		RNClassID s_type = s.Clip(edge_plane);
		if (s_type == RN_NULL_CLASS_ID) {
		    return RN_NULL_CLASS_ID;
		}
		else if (s_type == R3_POINT_CLASS_ID) {
		    if (hit_point1) *hit_point1 = s.Start();
		    if (hit_t1) *hit_t1 = span.T(s.Start());
		    return R3_POINT_CLASS_ID;
		}
		
		// Remember previous point
		p1 = p2;
	    }
	    
	    // Span intersects triangle in span
	    if (hit_point1) *hit_point1 = s.Start();
	    if (hit_t1) *hit_t1 = span.T(s.Start());
	    // if (hit_point2) *hit_point2 = s.End();
	    // if (hit_t2) *hit_t2 = span.T(s.End());
	    return R3_SPAN_CLASS_ID;
        }
	break;

    default:
	RNAbort("Invalid intersection result");
	break;
    }

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

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x118(%rsp)
movq %rsi, 0x110(%rsp)
movq %rdx, 0x108(%rsp)
movq %rcx, 0x100(%rsp)
leaq 0xe8(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x6eb40
movq 0x118(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x110(%rsp), %rdi
callq 0x81b30
movq 0x28(%rsp), %rdi
movq 0x30(%rsp), %rdx
movq %rax, %rsi
leaq 0xe0(%rsp), %rcx
callq 0x7e560
movl %eax, %ecx
movl %ecx, 0x38(%rsp)
testl %eax, %eax
je 0x7eb76
jmp 0x7eb59
movl 0x38(%rsp), %eax
subl $0x1, %eax
je 0x7eb86
jmp 0x7eb64
movl 0x38(%rsp), %eax
subl $0x4, %eax
je 0x7ec00
jmp 0x7edff
movl $0x0, 0x124(%rsp)
jmp 0x7ee26
movq 0x110(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x836e0
cmpl $0x0, %eax
jne 0x7ebb0
movl $0x0, 0x124(%rsp)
jmp 0x7ee26
cmpq $0x0, 0x108(%rsp)
je 0x7ebd0
movq 0x108(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x6f1e0
cmpq $0x0, 0x100(%rsp)
je 0x7ebf0
movsd 0xe0(%rsp), %xmm0
movq 0x100(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0x124(%rsp)
jmp 0x7ee26
movq 0x118(%rsp), %rsi
leaq 0x90(%rsp), %rdi
callq 0x6d450
movq 0x110(%rsp), %rdi
movl $0x2, %esi
callq 0x81eb0
movq %rax, %rdi
callq 0x78950
movq %rax, 0x88(%rsp)
movl $0x0, 0x84(%rsp)
cmpl $0x3, 0x84(%rsp)
jge 0x7ed8c
movq 0x110(%rsp), %rdi
movl 0x84(%rsp), %esi
callq 0x81eb0
movq %rax, %rdi
callq 0x78950
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x110(%rsp), %rdi
callq 0x78960
movq %rax, 0x20(%rsp)
movq 0x78(%rsp), %rsi
movq 0x88(%rsp), %rdx
leaq 0x40(%rsp), %rdi
callq 0x6eeb0
movq 0x18(%rsp), %rsi
movq 0x20(%rsp), %rdx
leaq 0x58(%rsp), %rdi
leaq 0x40(%rsp), %rcx
callq 0x6c4c0
leaq 0x90(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x6dd30
movl %eax, 0x3c(%rsp)
cmpl $0x0, 0x3c(%rsp)
jne 0x7ecea
movl $0x0, 0x124(%rsp)
jmp 0x7ee26
cmpl $0x1, 0x3c(%rsp)
jne 0x7ed67
cmpq $0x0, 0x108(%rsp)
je 0x7ed19
leaq 0x90(%rsp), %rdi
callq 0x39250
movq %rax, %rsi
movq 0x108(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0x100(%rsp)
je 0x7ed57
movq 0x118(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x39250
movq 0x10(%rsp), %rdi
movq %rax, %rsi
callq 0x6d920
movq 0x100(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x1, 0x124(%rsp)
jmp 0x7ee26
jmp 0x7ed69
movq 0x78(%rsp), %rax
movq %rax, 0x88(%rsp)
movl 0x84(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x84(%rsp)
jmp 0x7ec42
cmpq $0x0, 0x108(%rsp)
je 0x7edb4
leaq 0x90(%rsp), %rdi
callq 0x39250
movq %rax, %rsi
movq 0x108(%rsp), %rdi
callq 0x6f1e0
cmpq $0x0, 0x100(%rsp)
je 0x7edf2
movq 0x118(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x39250
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x6d920
movq 0x100(%rsp), %rax
movsd %xmm0, (%rax)
movl $0x4, 0x124(%rsp)
jmp 0x7ee26
leaq 0xb6b99(%rip), %rdi     # 0x13599f
movb $0x0, %al
callq 0xd4e20
leaq 0xb6b75(%rip), %rdi     # 0x135989
movb $0x0, %al
callq 0xd4e20
movl $0x0, 0x124(%rsp)
movl 0x124(%rsp), %eax
addq $0x128, %rsp            # imm = 0x128
retq
nopw %cs:(%rax,%rax)