// File: /workspace/github_cpp_makefile_star2_O3/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 $0x158, %rsp            # imm = 0x158
movq %rsi, %r14
movq %rdi, %rbx
movq (%rdx), %rax
leaq 0x88(%rsp), %rdi
movq %rdx, %rsi
callq *0x88(%rax)
leaq 0x10702a(%rip), %rsi    # 0x1462b8
leaq 0x60(%rsp), %rdi
callq 0x7fed0
movq %r14, 0x28(%rsp)
leaq 0x8(%r14), %rsi
leaq 0xd8(%rsp), %rdi
callq 0x701de
movq %rbx, 0x20(%rsp)
xorl %r12d, %r12d
movb $0x1, %al
movl %eax, 0x8(%rsp)
leaq 0xc0(%rsp), %r15
leaq 0x88(%rsp), %rbp
leaq 0xd8(%rsp), %rbx
leaq 0xfedfd(%rip), %r14     # 0x13e0d8
leaq 0xfee06(%rip), %r13     # 0x13e0e8
movq %r15, %rdi
movq %rbp, %rsi
movl %r12d, %edx
callq 0x6cf5a
leaq 0x30(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x73dc2
movsd 0x40(%rsp), %xmm2
movsd (%r14), %xmm0
movapd %xmm0, %xmm1
xorpd 0x9b229(%rip), %xmm1    # 0xda540
ucomisd %xmm1, %xmm2
jb 0x3f39a
movsd 0x30(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3f33d
ucomisd %xmm0, %xmm2
jbe 0x3f351
movsd (%r13), %xmm2
movsd %xmm2, 0x78(%rsp)
jmp 0x3f351
movsd (%r13), %xmm2
xorpd 0x9b1f5(%rip), %xmm2    # 0xda540
movlpd %xmm2, 0x68(%rsp)
movsd 0x38(%rsp), %xmm2
ucomisd %xmm2, %xmm1
ja 0x3f374
ucomisd %xmm0, %xmm2
jbe 0x3f388
movsd (%r13), %xmm0
movsd %xmm0, 0x80(%rsp)
jmp 0x3f388
movsd (%r13), %xmm0
xorpd 0x9b1be(%rip), %xmm0    # 0xda540
movlpd %xmm0, 0x70(%rsp)
incl %r12d
cmpl $0x8, %r12d
jne 0x3f2e2
jmp 0x3f4bc
movq 0x28(%rsp), %rbp
movl 0xa0(%rbp), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
addl 0x98(%rbp), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, 0x8(%rsp)
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd 0x9ac50(%rip), %xmm0    # 0xda020
mulsd %xmm0, %xmm1
mulsd 0x30(%rsp), %xmm1
movsd %xmm1, 0x18(%rsp)
movsd 0x68(%rbp), %xmm0
movsd %xmm2, 0x10(%rsp)
callq 0x214c0
mulsd 0x10(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
divsd %xmm0, %xmm1
movl 0xa4(%rbp), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
addl 0x9c(%rbp), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x8(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
mulsd 0x9abdf(%rip), %xmm0    # 0xda020
mulsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x70(%rbp), %xmm0
callq 0x214c0
mulsd 0x58(%rsp), %xmm0
movsd 0x10(%rsp), %xmm2
divsd %xmm0, %xmm2
movsd 0x18(%rsp), %xmm1
subsd %xmm2, %xmm1
movq %r15, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x819be
leaq 0x60(%rsp), %rdi
movq %r15, %rsi
callq 0x805de
leal 0x1(%r12), %eax
movl $0x0, 0x8(%rsp)
cmpl $0x7, %r12d
movl %eax, %r12d
leaq 0x88(%rsp), %rbp
jne 0x3f2e2
jmp 0x3f4d9
testb $0x1, 0x8(%rsp)
je 0x3f4d9
leaq 0x106dee(%rip), %rsi    # 0x1462b8
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
callq 0x7fed0
jmp 0x3f54c
movq 0x28(%rsp), %rsi
movl 0x98(%rsi), %eax
movl 0x9c(%rsi), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %ecx, %xmm1
movl 0xa0(%rsi), %edx
leal -0x1(%rax,%rdx), %eax
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
movl 0xa4(%rsi), %eax
leal -0x1(%rcx,%rax), %eax
cvtsi2sd %eax, %xmm3
leaq 0x30(%rsp), %rdi
callq 0x7fff4
leaq 0x60(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x806be
movq 0x20(%rsp), %rbx
leaq 0x60(%rsp), %rsi
movq %rbx, %rdi
callq 0x7fed0
leaq 0x30(%rsp), %rdi
callq 0x8086c
leaq 0x60(%rsp), %rdi
callq 0x8086c
leaq 0x88(%rsp), %rdi
callq 0x6dafc
movq %rbx, %rax
addq $0x158, %rsp            # imm = 0x158
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3f592
movq %rax, %rbx
jmp 0x3f59f
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x8086c
jmp 0x3f595
jmp 0x3f592
jmp 0x3f592
movq %rax, %rbx
leaq 0x60(%rsp), %rdi
callq 0x8086c
leaq 0x88(%rsp), %rdi
callq 0x6dafc
movq %rbx, %rdi
callq 0x220c0