// File: /workspace/github_cpp_makefile_star2_O1/tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Viewer.cpp
// Function: gaps::R3Viewer::ViewportBBox(gaps::R3Shape const&) const
const R2Box R3Viewer::
ViewportBBox(const R3Shape& shape) const 
{
    // ??? THIS FUNCTION DOES NOT HANDLE SOME INVISIBLE SHAPES PROPERLY ???
    // ??? IT RETURNS FULL SCREEN BOXES FOR INVISIBLE DIAGONAL BOXES    ???
    // ??? THAT SPAN VIEW ORIGIN IN EVERY DIMENSION                     ???

    // Compute bounding box of shape projection on viewport
    RNBoolean infront = FALSE;
    R3Box shape_box(shape.BBox());
    R2Box projection_box(R2null_box);
    R4Matrix m(Camera().CoordSystem().InverseMatrix());
    for (RNOctant octant = RN_NNN_OCTANT; octant <= RN_PPP_OCTANT; octant++) {
        // Transform corner into canonical coordinate system
        R3Point p = m * shape_box.Corner(octant);

	// Union point's projection into projection box
	if (RNIsPositiveOrZero(p.Z())) {
	    // Point is behind viewer - union extrema into projection box
	    if (RNIsNegative(p.X())) projection_box[RN_LO][RN_X] = -RN_INFINITY;
	    else if (RNIsPositive(p.X())) projection_box[RN_HI][RN_X] = RN_INFINITY;
	    if (RNIsNegative(p.Y())) projection_box[RN_LO][RN_Y] = -RN_INFINITY;
	    else if (RNIsPositive(p.Y())) projection_box[RN_HI][RN_Y] = RN_INFINITY;
	}
	else {
	    // Point is in front of viewer - Union projection point into projection box
	    RNCoord x = viewport.XCenter() + 0.5 * viewport.Width() * p.X() / -(p.Z() * tan(Camera().XFOV()));
	    RNCoord y = viewport.YCenter() + 0.5 * viewport.Height() * p.Y() / -(p.Z() * tan(Camera().YFOV()));
	    projection_box.Union(R2Point(x, y));
	    infront = TRUE;
	}
    }

    // Check if some part of shape box is in front of viewer
    if (!infront) return R2null_box;

    // Intersect projection box with viewport box
    R2Box viewport_box(Viewport().XMin(), Viewport().YMin(), Viewport().XMax(), Viewport().YMax());
    projection_box.Intersect(viewport_box);

    // Return projection box
    return projection_box;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x148, %rsp            # imm = 0x148
movq %rsi, %r14
movq %rdi, %rbx
movq (%rdx), %rax
leaq 0x78(%rsp), %rdi
movq %rdx, %rsi
callq *0x88(%rax)
leaq 0x108b7d(%rip), %rsi    # 0x1482b8
leaq 0x50(%rsp), %rdi
callq 0x80fa0
leaq 0x8(%r14), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x7101a
movq %rbx, 0x18(%rsp)
xorl %r13d, %r13d
leaq 0xb0(%rsp), %r15
leaq 0xc8(%rsp), %rbp
leaq 0x100963(%rip), %r12    # 0x1400d8
xorl %ebx, %ebx
movq %r15, %rdi
leaq 0x78(%rsp), %rsi
movl %ebx, %edx
callq 0x6dd7a
leaq 0x20(%rsp), %rdi
movq %rbp, %rsi
movq %r15, %rdx
callq 0x74cb2
movsd 0x30(%rsp), %xmm2
movsd (%r12), %xmm0
movapd %xmm0, %xmm1
xorpd 0x9cd82(%rip), %xmm1    # 0xdc530
ucomisd %xmm1, %xmm2
jae 0x3f8bb
movl 0xa0(%r14), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
addl 0x98(%r14), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, 0x10(%rsp)
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd 0x9c835(%rip), %xmm0    # 0xdc020
mulsd %xmm0, %xmm1
mulsd 0x20(%rsp), %xmm1
movsd %xmm1, 0x8(%rsp)
movsd 0x68(%r14), %xmm0
movsd %xmm2, (%rsp)
callq 0x214c0
mulsd (%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movl 0xa4(%r14), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
addl 0x9c(%r14), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd 0x9c7c3(%rip), %xmm0    # 0xdc020
mulsd 0x28(%rsp), %xmm0
movsd %xmm0, (%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x70(%r14), %xmm0
callq 0x214c0
mulsd 0x48(%rsp), %xmm0
movsd (%rsp), %xmm2
divsd %xmm0, %xmm2
movsd 0x8(%rsp), %xmm1
subsd %xmm2, %xmm1
movq %r15, %rdi
movsd 0x10(%rsp), %xmm0
callq 0x82a96
leaq 0x50(%rsp), %rdi
movq %r15, %rsi
callq 0x816bc
movl $0x1, %r13d
jmp 0x3f937
movsd 0x20(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3f8e0
ucomisd %xmm0, %xmm2
jbe 0x3f8f9
leaq 0x100814(%rip), %rax    # 0x1400e8
movsd (%rax), %xmm2
movsd %xmm2, 0x68(%rsp)
jmp 0x3f8f9
leaq 0x100801(%rip), %rax    # 0x1400e8
movsd (%rax), %xmm2
xorpd 0x9cc3d(%rip), %xmm2    # 0xdc530
movlpd %xmm2, 0x58(%rsp)
movsd 0x28(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3f91e
ucomisd %xmm0, %xmm2
jbe 0x3f937
leaq 0x1007d6(%rip), %rax    # 0x1400e8
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
jmp 0x3f937
leaq 0x1007c3(%rip), %rax    # 0x1400e8
movsd (%rax), %xmm0
xorpd 0x9cbff(%rip), %xmm0    # 0xdc530
movlpd %xmm0, 0x60(%rsp)
incl %ebx
cmpl $0x8, %ebx
jne 0x3f777
testl %r13d, %r13d
je 0x3f9bb
movl 0x98(%r14), %eax
movl 0x9c(%r14), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %ecx, %xmm1
movl 0xa0(%r14), %edx
leal -0x1(%rax,%rdx), %eax
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
movl 0xa4(%r14), %eax
leal -0x1(%rcx,%rax), %eax
cvtsi2sd %eax, %xmm3
leaq 0x20(%rsp), %rdi
callq 0x810c4
movq 0x18(%rsp), %rbx
leaq 0x50(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x8179c
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x80fa0
leaq 0x20(%rsp), %rdi
callq 0x81944
jmp 0x3f9cf
leaq 0x1088f6(%rip), %rsi    # 0x1482b8
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x80fa0
leaq 0x50(%rsp), %rdi
callq 0x81944
leaq 0x78(%rsp), %rdi
callq 0x6e944
movq %rbx, %rax
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3fa12
movq %rax, %rbx
jmp 0x3fa1f
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x81944
jmp 0x3fa15
jmp 0x3fa12
jmp 0x3fa12
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x81944
leaq 0x78(%rsp), %rdi
callq 0x6e944
movq %rbx, %rdi
callq 0x220d0
nop