// File: tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Viewer.cpp
// Function: gaps::R3Viewer::ViewportBCircle(gaps::R3Shape const&) const
const R2Circle R3Viewer::
ViewportBCircle(const R3Shape& shape) const 
{
    // Return bounding circle of shape projection on viewport
    R3Sphere bsphere(shape.BSphere());
    R3Point p = Camera().CoordSystem().InverseMatrix() * bsphere.Center();
    if (RNIsPositiveOrZero(p.Z())) return R2infinite_circle;

    // Compute sphere center projection
    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()));
    R2Point center(x, y);

    // Compute sphere radius projection
    RNScalar fov = (Camera().XFOV() > Camera().YFOV()) ? Camera().XFOV() : Camera().YFOV();
    RNScalar radius = 0.5 * viewport.Width() * bsphere.Radius() / -(p.Z() * fov);

    // Return bounding circle of projection
    return R2Circle(center, radius);
}

// Assembly:
subq $0x248, %rsp            # imm = 0x248
movq %rdi, 0x110(%rsp)
movq %rdi, %rax
movq %rax, 0x118(%rsp)
movq %rdi, 0x240(%rsp)
movq %rsi, 0x238(%rsp)
movq %rdx, 0x230(%rsp)
movq 0x238(%rsp), %rax
movq %rax, 0x120(%rsp)
movq 0x230(%rsp), %rsi
movq (%rsi), %rax
movq 0x90(%rax), %rax
leaq 0x208(%rsp), %rdi
callq *%rax
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x128(%rsp)
jmp 0x5cb05
movq 0x128(%rsp), %rdi
callq 0x5d410
movq %rax, 0x108(%rsp)
jmp 0x5cb1c
movq 0x108(%rsp), %rsi
leaq 0x170(%rsp), %rdi
callq 0xc2c20
jmp 0x5cb33
leaq 0x208(%rsp), %rdi
callq 0x4e950
movq %rax, 0x100(%rsp)
jmp 0x5cb4a
movq 0x100(%rsp), %rdx
leaq 0x1f0(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0xc9810
jmp 0x5cb69
leaq 0x1f0(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0xf8(%rsp)
jmp 0x5cb81
movsd 0xf8(%rsp), %xmm0
leaq 0x199717(%rip), %rax    # 0x1f62a8
movsd (%rax), %xmm1
callq 0x49e70
movl %eax, 0xf4(%rsp)
jmp 0x5cba3
movl 0xf4(%rsp), %eax
cmpl $0x0, %eax
je 0x5cbfb
movq 0x110(%rsp), %rdi
leaq 0x1a2872(%rip), %rsi    # 0x1ff430
callq 0xe00f0
jmp 0x5cbc5
movl $0x1, 0x160(%rsp)
jmp 0x5d00d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x168(%rsp)
movl %eax, 0x164(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x2ba70
jmp 0x5d02a
movq 0x120(%rsp), %rdi
addq $0x98, %rdi
callq 0x5d3b0
movl %eax, 0xf0(%rsp)
jmp 0x5cc18
movq 0x120(%rsp), %rdi
movl 0xf0(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0xe0(%rsp)
addq $0x98, %rdi
callq 0x2be50
movl %eax, 0xec(%rsp)
jmp 0x5cc49
movl 0xec(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1313c4(%rip), %xmm1   # 0x18e020
mulsd %xmm1, %xmm0
movsd %xmm0, 0xd0(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x2b820
movsd %xmm0, 0xd8(%rsp)
jmp 0x5cc81
movsd 0xd8(%rsp), %xmm1
movsd 0xd0(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0xc0(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0xc8(%rsp)
jmp 0x5ccb8
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0xb8(%rsp)
jmp 0x5cccf
movq 0xb8(%rsp), %rdi
callq 0x2b940
movsd %xmm0, 0xb0(%rsp)
jmp 0x5cce7
movsd 0xb0(%rsp), %xmm0
callq 0x22520
movsd 0xc8(%rsp), %xmm2
movsd 0xc0(%rsp), %xmm1
movq 0x120(%rsp), %rdi
movaps %xmm0, %xmm3
movsd 0xe0(%rsp), %xmm0
mulsd %xmm3, %xmm2
divsd %xmm2, %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x158(%rsp)
addq $0x98, %rdi
callq 0x5d3e0
movl %eax, 0xac(%rsp)
jmp 0x5cd45
movq 0x120(%rsp), %rdi
movl 0xac(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0xa0(%rsp)
addq $0x98, %rdi
callq 0x2be60
movl %eax, 0xa8(%rsp)
jmp 0x5cd76
movl 0xa8(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x131297(%rip), %xmm1   # 0x18e020
mulsd %xmm1, %xmm0
movsd %xmm0, 0x90(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x2b830
movsd %xmm0, 0x98(%rsp)
jmp 0x5cdae
movsd 0x98(%rsp), %xmm1
movsd 0x90(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0x88(%rsp)
jmp 0x5cde5
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x78(%rsp)
jmp 0x5cdf9
movq 0x78(%rsp), %rdi
callq 0x2b950
movsd %xmm0, 0x70(%rsp)
jmp 0x5ce0b
movsd 0x70(%rsp), %xmm0
callq 0x22520
movsd 0x88(%rsp), %xmm2
movsd 0x80(%rsp), %xmm1
movaps %xmm0, %xmm3
movsd 0xa0(%rsp), %xmm0
mulsd %xmm3, %xmm2
divsd %xmm2, %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, 0x150(%rsp)
movsd 0x158(%rsp), %xmm0
movsd 0x150(%rsp), %xmm1
leaq 0x140(%rsp), %rdi
callq 0xe3d80
jmp 0x5ce6a
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x68(%rsp)
jmp 0x5ce7e
movq 0x68(%rsp), %rdi
callq 0x2b940
movsd %xmm0, 0x60(%rsp)
jmp 0x5ce90
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x58(%rsp)
jmp 0x5cea4
movq 0x58(%rsp), %rdi
callq 0x2b950
movsd %xmm0, 0x50(%rsp)
jmp 0x5ceb6
movsd 0x60(%rsp), %xmm0
movsd 0x50(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x5cefc
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x48(%rsp)
jmp 0x5cedc
movq 0x48(%rsp), %rdi
callq 0x2b940
movsd %xmm0, 0x40(%rsp)
jmp 0x5ceee
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
jmp 0x5cf30
movq 0x120(%rsp), %rdi
callq 0x2b4d0
movq %rax, 0x30(%rsp)
jmp 0x5cf10
movq 0x30(%rsp), %rdi
callq 0x2b950
movsd %xmm0, 0x28(%rsp)
jmp 0x5cf22
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
jmp 0x5cf30
movq 0x120(%rsp), %rdi
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x138(%rsp)
addq $0x98, %rdi
callq 0x2be50
movl %eax, 0x24(%rsp)
jmp 0x5cf59
movl 0x24(%rsp), %eax
cvtsi2sd %eax, %xmm0
movsd 0x1310b7(%rip), %xmm1   # 0x18e020
mulsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x487f0
movsd %xmm0, 0x18(%rsp)
jmp 0x5cf88
movsd 0x18(%rsp), %xmm1
movsd 0x10(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x2b840
movsd %xmm0, 0x8(%rsp)
jmp 0x5cfb2
movq 0x110(%rsp), %rdi
movsd (%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
movsd 0x138(%rsp), %xmm2
mulsd %xmm2, %xmm1
movaps 0x132ce7(%rip), %xmm2   # 0x18fcc0
pxor %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x130(%rsp)
movsd 0x130(%rsp), %xmm0
leaq 0x140(%rsp), %rsi
callq 0xe0170
jmp 0x5d002
movl $0x1, 0x160(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x2ba70
movq 0x118(%rsp), %rax
addq $0x248, %rsp            # imm = 0x248
retq
movq 0x168(%rsp), %rdi
callq 0x23290
nopw (%rax,%rax)