// File: 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:
subq $0x348, %rsp            # imm = 0x348
movq %rdi, 0x198(%rsp)
movq %rdi, %rax
movq %rax, 0x1a0(%rsp)
movq %rdi, 0x340(%rsp)
movq %rsi, 0x338(%rsp)
movq %rdx, 0x330(%rsp)
movq 0x338(%rsp), %rax
movq %rax, 0x1a8(%rsp)
movl $0x0, 0x32c(%rsp)
movq 0x330(%rsp), %rsi
movq (%rsi), %rax
movq 0x88(%rax), %rax
leaq 0x2f0(%rsp), %rdi
callq *%rax
leaq 0x1a3588(%rip), %rsi    # 0x1ff7c8
leaq 0x2c8(%rsp), %rdi
callq 0xe05f0
jmp 0x5c24f
movq 0x1a8(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x190(%rsp)
jmp 0x5c266
movq 0x190(%rsp), %rdi
callq 0x5d410
movq %rax, 0x188(%rsp)
jmp 0x5c27d
movq 0x188(%rsp), %rsi
leaq 0x238(%rsp), %rdi
callq 0xc2c20
jmp 0x5c294
movl $0x0, 0x234(%rsp)
cmpl $0x7, 0x234(%rsp)
jg 0x5c8ba
movl 0x234(%rsp), %edx
leaq 0x200(%rsp), %rdi
leaq 0x2f0(%rsp), %rsi
callq 0xb7840
jmp 0x5c2cb
leaq 0x218(%rsp), %rdi
leaq 0x238(%rsp), %rsi
leaq 0x200(%rsp), %rdx
callq 0xc9810
jmp 0x5c2ea
leaq 0x218(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0x180(%rsp)
jmp 0x5c302
movsd 0x180(%rsp), %xmm0
leaq 0x199f96(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x49e70
movl %eax, 0x17c(%rsp)
jmp 0x5c324
movl 0x17c(%rsp), %eax
cmpl $0x0, %eax
je 0x5c623
leaq 0x218(%rsp), %rdi
callq 0x2b820
movsd %xmm0, 0x170(%rsp)
jmp 0x5c34c
movsd 0x170(%rsp), %xmm0
leaq 0x199f4c(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x4e240
movl %eax, 0x16c(%rsp)
jmp 0x5c36e
movl 0x16c(%rsp), %eax
cmpl $0x0, %eax
je 0x5c41b
leaq 0x199f33(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
movaps 0x133930(%rip), %xmm1   # 0x18fcc0
pxor %xmm1, %xmm0
movsd %xmm0, 0x158(%rsp)
leaq 0x2c8(%rsp), %rdi
xorl %esi, %esi
callq 0x5d420
movq %rax, 0x160(%rsp)
jmp 0x5c3b6
movq 0x160(%rsp), %rdi
xorl %esi, %esi
callq 0x5d460
movq %rax, 0x150(%rsp)
jmp 0x5c3cf
movq 0x150(%rsp), %rax
movsd 0x158(%rsp), %xmm0
movsd %xmm0, (%rax)
jmp 0x5c4c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2c0(%rsp)
movl %eax, 0x2bc(%rsp)
jmp 0x5ca6f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2c0(%rsp)
movl %eax, 0x2bc(%rsp)
jmp 0x5ca62
leaq 0x218(%rsp), %rdi
callq 0x2b820
movsd %xmm0, 0x148(%rsp)
jmp 0x5c433
movsd 0x148(%rsp), %xmm0
leaq 0x199e65(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x4a000
movl %eax, 0x144(%rsp)
jmp 0x5c455
movl 0x144(%rsp), %eax
cmpl $0x0, %eax
je 0x5c4bf
leaq 0x199e50(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
movsd %xmm0, 0x130(%rsp)
leaq 0x2c8(%rsp), %rdi
movl $0x1, %esi
callq 0x5d420
movq %rax, 0x138(%rsp)
jmp 0x5c491
movq 0x138(%rsp), %rdi
xorl %esi, %esi
callq 0x5d460
movq %rax, 0x128(%rsp)
jmp 0x5c4aa
movq 0x128(%rsp), %rax
movsd 0x130(%rsp), %xmm0
movsd %xmm0, (%rax)
jmp 0x5c4c1
leaq 0x218(%rsp), %rdi
callq 0x2b830
movsd %xmm0, 0x120(%rsp)
jmp 0x5c4d9
movsd 0x120(%rsp), %xmm0
leaq 0x199dbf(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x4e240
movl %eax, 0x11c(%rsp)
jmp 0x5c4fb
movl 0x11c(%rsp), %eax
cmpl $0x0, %eax
je 0x5c575
leaq 0x199daa(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
movaps 0x1337a7(%rip), %xmm1   # 0x18fcc0
pxor %xmm1, %xmm0
movsd %xmm0, 0x108(%rsp)
leaq 0x2c8(%rsp), %rdi
xorl %esi, %esi
callq 0x5d420
movq %rax, 0x110(%rsp)
jmp 0x5c53f
movq 0x110(%rsp), %rdi
movl $0x1, %esi
callq 0x5d460
movq %rax, 0x100(%rsp)
jmp 0x5c55b
movq 0x100(%rsp), %rax
movsd 0x108(%rsp), %xmm0
movsd %xmm0, (%rax)
jmp 0x5c61e
leaq 0x218(%rsp), %rdi
callq 0x2b830
movsd %xmm0, 0xf8(%rsp)
jmp 0x5c58d
movsd 0xf8(%rsp), %xmm0
leaq 0x199d0b(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x4a000
movl %eax, 0xf4(%rsp)
jmp 0x5c5af
movl 0xf4(%rsp), %eax
cmpl $0x0, %eax
je 0x5c61c
leaq 0x199cf6(%rip), %rax    # 0x1f62b8
movsd (%rax), %xmm0
movsd %xmm0, 0xe0(%rsp)
leaq 0x2c8(%rsp), %rdi
movl $0x1, %esi
callq 0x5d420
movq %rax, 0xe8(%rsp)
jmp 0x5c5eb
movq 0xe8(%rsp), %rdi
movl $0x1, %esi
callq 0x5d460
movq %rax, 0xd8(%rsp)
jmp 0x5c607
movq 0xd8(%rsp), %rax
movsd 0xe0(%rsp), %xmm0
movsd %xmm0, (%rax)
jmp 0x5c61e
jmp 0x5c8a2
movq 0x1a8(%rsp), %rdi
addq $0x98, %rdi
callq 0x5d3b0
movl %eax, 0xd4(%rsp)
jmp 0x5c640
movq 0x1a8(%rsp), %rdi
movl 0xd4(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0xc8(%rsp)
addq $0x98, %rdi
callq 0x2be50
movl %eax, 0xd0(%rsp)
jmp 0x5c671
movl 0xd0(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x13199c(%rip), %xmm1   # 0x18e020
mulsd %xmm1, %xmm0
movsd %xmm0, 0xb8(%rsp)
leaq 0x218(%rsp), %rdi
callq 0x2b820
movsd %xmm0, 0xc0(%rsp)
jmp 0x5c6a9
movsd 0xc0(%rsp), %xmm1
movsd 0xb8(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
leaq 0x218(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0xb0(%rsp)
jmp 0x5c6e0
movq 0x1a8(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0xa0(%rsp)
jmp 0x5c6f7
movq 0xa0(%rsp), %rdi
callq 0x2b940
movsd %xmm0, 0x98(%rsp)
jmp 0x5c70f
movsd 0x98(%rsp), %xmm0
callq 0x22520
movsd 0xb0(%rsp), %xmm2
movsd 0xa8(%rsp), %xmm1
movq 0x1a8(%rsp), %rdi
movaps %xmm0, %xmm3
movsd 0xc8(%rsp), %xmm0
mulsd %xmm3, %xmm2
divsd %xmm2, %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x1f8(%rsp)
addq $0x98, %rdi
callq 0x5d3e0
movl %eax, 0x94(%rsp)
jmp 0x5c76d
movq 0x1a8(%rsp), %rdi
movl 0x94(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x88(%rsp)
addq $0x98, %rdi
callq 0x2be60
movl %eax, 0x90(%rsp)
jmp 0x5c79e
movl 0x90(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x13186f(%rip), %xmm1   # 0x18e020
mulsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
leaq 0x218(%rsp), %rdi
callq 0x2b830
movsd %xmm0, 0x80(%rsp)
jmp 0x5c7d3
movsd 0x80(%rsp), %xmm1
movsd 0x78(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x68(%rsp)
leaq 0x218(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0x70(%rsp)
jmp 0x5c801
movq 0x1a8(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x60(%rsp)
jmp 0x5c815
movq 0x60(%rsp), %rdi
callq 0x2b950
movsd %xmm0, 0x58(%rsp)
jmp 0x5c827
movsd 0x58(%rsp), %xmm0
callq 0x22520
movsd 0x70(%rsp), %xmm2
movsd 0x68(%rsp), %xmm1
movaps %xmm0, %xmm3
movsd 0x88(%rsp), %xmm0
mulsd %xmm3, %xmm2
divsd %xmm2, %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x1f0(%rsp)
movsd 0x1f8(%rsp), %xmm0
movsd 0x1f0(%rsp), %xmm1
leaq 0x1e0(%rsp), %rdi
callq 0xe3d80
jmp 0x5c880
leaq 0x2c8(%rsp), %rdi
leaq 0x1e0(%rsp), %rsi
callq 0xe1680
jmp 0x5c897
movl $0x1, 0x32c(%rsp)
jmp 0x5c8a4
movl 0x234(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x234(%rsp)
jmp 0x5c29f
cmpl $0x0, 0x32c(%rsp)
jne 0x5c8ea
movq 0x198(%rsp), %rdi
leaq 0x1a2ef5(%rip), %rsi    # 0x1ff7c8
callq 0xe05f0
jmp 0x5c8da
movl $0x1, 0x1dc(%rsp)
jmp 0x5ca38
movq 0x1a8(%rsp), %rdi
callq 0x2b6d0
movq %rax, 0x50(%rsp)
jmp 0x5c8fe
movq 0x50(%rsp), %rdi
callq 0x5d480
movl %eax, 0x4c(%rsp)
jmp 0x5c90e
movq 0x1a8(%rsp), %rdi
movl 0x4c(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x38(%rsp)
callq 0x2b6d0
movq %rax, 0x40(%rsp)
jmp 0x5c930
movq 0x40(%rsp), %rdi
callq 0x5d490
movl %eax, 0x34(%rsp)
jmp 0x5c940
movq 0x1a8(%rsp), %rdi
movl 0x34(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x20(%rsp)
callq 0x2b6d0
movq %rax, 0x28(%rsp)
jmp 0x5c962
movq 0x28(%rsp), %rdi
callq 0x5d4a0
movl %eax, 0x1c(%rsp)
jmp 0x5c972
movq 0x1a8(%rsp), %rdi
movl 0x1c(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x2b6d0
movq %rax, 0x10(%rsp)
jmp 0x5c994
movq 0x10(%rsp), %rdi
callq 0x5d4c0
movl %eax, 0x4(%rsp)
jmp 0x5c9a4
movsd 0x8(%rsp), %xmm2
movsd 0x20(%rsp), %xmm1
movsd 0x38(%rsp), %xmm0
movl 0x4(%rsp), %eax
cvtsi2sd %eax, %xmm3
leaq 0x1b0(%rsp), %rdi
callq 0xe0820
jmp 0x5c9cd
leaq 0x2c8(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0xe1a00
jmp 0x5c9e4
movq 0x198(%rsp), %rdi
leaq 0x2c8(%rsp), %rsi
callq 0xe05f0
jmp 0x5c9fb
movl $0x1, 0x1dc(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x5d4e0
jmp 0x5ca38
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2c0(%rsp)
movl %eax, 0x2bc(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x5d4e0
jmp 0x5ca62
leaq 0x2c8(%rsp), %rdi
callq 0x5d4e0
leaq 0x2f0(%rsp), %rdi
callq 0x2c1a0
movq 0x1a0(%rsp), %rax
addq $0x348, %rsp            # imm = 0x348
retq
leaq 0x2c8(%rsp), %rdi
callq 0x5d4e0
leaq 0x2f0(%rsp), %rdi
callq 0x2c1a0
movq 0x2c0(%rsp), %rdi
callq 0x23290
nopl (%rax)