// File: /workspace/github_cpp_makefile_star2_O3/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rcx, %r14
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbp
leaq 0x28(%rsp), %rbx
movq %rbx, %rdi
callq 0x3c530
leaq 0x20(%r12), %r13
leaq 0x20(%rsp), %rcx
movq %rbp, 0x10(%rsp)
movq %rbp, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x449ef
movl %eax, %ebp
testl %eax, %eax
je 0x44ce2
cmpl $0x4, %ebp
je 0x44bd6
cmpl $0x1, %ebp
jne 0x44c8a
leaq 0x28(%rsp), %rsi
movq %r12, %rdi
callq 0x4732f
testl %eax, %eax
je 0x44caa
testq %r15, %r15
je 0x44bb8
leaq 0x28(%rsp), %rsi
movq %r15, %rdi
callq 0x3c89a
movl $0x1, %ebp
testq %r14, %r14
je 0x44ce2
movsd 0x20(%rsp), %xmm0
movsd %xmm0, (%r14)
jmp 0x44ce2
movq %r15, 0x18(%rsp)
movq %r14, 0x8(%rsp)
leaq 0x40(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x3b8f6
movq 0x18(%r12), %r15
movl $0x1, %r14d
leaq 0xa8(%rsp), %rbx
movq %r15, %rdx
movq (%r12,%r14,8), %r15
leaq 0x90(%rsp), %rbp
movq %rbp, %rdi
movq %r15, %rsi
callq 0x3c78e
movq %rbx, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbp, %rcx
callq 0x3b198
leaq 0x40(%rsp), %rdi
movq %rbx, %rsi
callq 0x3bef4
movl %eax, %ebp
testl %eax, %eax
je 0x44ce2
cmpl $0x1, %ebp
je 0x44cae
incq %r14
cmpq $0x4, %r14
jne 0x44c02
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x44c66
leaq 0x40(%rsp), %rsi
callq 0x3c89a
movl $0x4, %ebp
movq 0x8(%rsp), %rbx
testq %rbx, %rbx
je 0x44ce2
leaq 0x40(%rsp), %rsi
movq 0x10(%rsp), %rdi
callq 0x3bc5c
movsd %xmm0, (%rbx)
jmp 0x44ce2
leaq 0x64366(%rip), %rdi     # 0xa8ff7
xorl %ebp, %ebp
xorl %eax, %eax
callq 0x718f6
leaq 0x64340(%rip), %rdi     # 0xa8fe1
xorl %eax, %eax
callq 0x718f6
jmp 0x44ce2
xorl %ebp, %ebp
jmp 0x44ce2
movq 0x18(%rsp), %rdi
testq %rdi, %rdi
je 0x44cc2
leaq 0x40(%rsp), %rsi
callq 0x3c89a
cmpq $0x0, 0x8(%rsp)
je 0x44ce2
leaq 0x40(%rsp), %rsi
movq 0x10(%rsp), %rdi
callq 0x3bc5c
movq 0x8(%rsp), %rax
movsd %xmm0, (%rax)
movl %ebp, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq