// File: /workspace/github_cpp_makefile_star2_O2/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 0xfc3c3(%rip), %rsi     # 0x1372d8
leaq 0x50(%rsp), %rdi
callq 0x75436
leaq 0x8(%r14), %rsi
leaq 0xc8(%rsp), %rdi
callq 0x66f88
movq %rbx, 0x18(%rsp)
xorl %ebp, %ebp
leaq 0xb0(%rsp), %r15
leaq 0xc8(%rsp), %rbx
pushq $0x2
popq %r13
xorl %r12d, %r12d
cmpl $0x8, %ebp
je 0x3b10f
movq %r15, %rdi
leaq 0x78(%rsp), %rsi
movl %ebp, %edx
callq 0x63f5a
leaq 0x20(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x6a307
movsd 0x30(%rsp), %xmm2
leaq 0xf4175(%rip), %rax     # 0x12f0f8
movsd (%rax), %xmm0
movapd %xmm0, %xmm1
xorpd 0x8a59d(%rip), %xmm1    # 0xc5530
ucomisd %xmm1, %xmm2
jae 0x3b08c
movl 0xa0(%r14), %ecx
movl %ecx, %eax
cltd
idivl %r13d
addl 0x98(%r14), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x10(%rsp)
cvtsi2sd %ecx, %xmm1
movsd 0x8a079(%rip), %xmm0    # 0xc5040
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), %ecx
movl %ecx, %eax
cltd
idivl %r13d
addl 0x9c(%r14), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
cvtsi2sd %ecx, %xmm0
mulsd 0x8a010(%rip), %xmm0    # 0xc5040
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 0x76d94
leaq 0x50(%rsp), %rdi
movq %r15, %rsi
callq 0x75a68
pushq $0x1
popq %r12
jmp 0x3b108
movsd 0x20(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3b0b1
ucomisd %xmm0, %xmm2
jbe 0x3b0ca
leaq 0xf4063(%rip), %rax     # 0x12f108
movsd (%rax), %xmm2
movsd %xmm2, 0x68(%rsp)
jmp 0x3b0ca
leaq 0xf4050(%rip), %rax     # 0x12f108
movsd (%rax), %xmm2
xorpd 0x8a46c(%rip), %xmm2    # 0xc5530
movlpd %xmm2, 0x58(%rsp)
movsd 0x28(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3b0ef
ucomisd %xmm0, %xmm2
jbe 0x3b108
leaq 0xf4025(%rip), %rax     # 0x12f108
movsd (%rax), %xmm0
movsd %xmm0, 0x70(%rsp)
jmp 0x3b108
leaq 0xf4012(%rip), %rax     # 0x12f108
movsd (%rax), %xmm0
xorpd 0x8a42e(%rip), %xmm0    # 0xc5530
movlpd %xmm0, 0x60(%rsp)
incl %ebp
jmp 0x3af4e
testl %r12d, %r12d
je 0x3b17f
movl 0x98(%r14), %eax
movl 0x9c(%r14), %ecx
cvtsi2sd %eax, %xmm0
cvtsi2sd %ecx, %xmm1
movl 0xa0(%r14), %edx
leal -0x1(%rax,%rdx), %eax
cvtsi2sd %eax, %xmm2
movl 0xa4(%r14), %eax
leal -0x1(%rcx,%rax), %eax
cvtsi2sd %eax, %xmm3
leaq 0x20(%rsp), %rdi
callq 0x7555a
movq 0x18(%rsp), %rbx
leaq 0x50(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x75b48
leaq 0x50(%rsp), %rsi
movq %rbx, %rdi
callq 0x75436
leaq 0x20(%rsp), %rdi
callq 0x75cce
jmp 0x3b193
leaq 0xfc152(%rip), %rsi     # 0x1372d8
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x75436
leaq 0x50(%rsp), %rdi
callq 0x75cce
leaq 0x78(%rsp), %rdi
callq 0x6499a
movq %rbx, %rax
addq $0x148, %rsp            # imm = 0x148
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3b1d6
movq %rax, %rbx
jmp 0x3b1e3
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x75cce
jmp 0x3b1d9
jmp 0x3b1d6
jmp 0x3b1d6
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x75cce
leaq 0x78(%rsp), %rdi
callq 0x6499a
movq %rbx, %rdi
callq 0x220e0
nop