// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3Frustum.cpp
// Function: gaps::R3Frustum::R3Frustum(gaps::R3Point const&, gaps::R3Vector const&, gaps::R3Vector const&, double, double, double, double)
R3Frustum::
R3Frustum(const R3Point& viewpoint, const R3Vector& towards, const R3Vector& up, 
  RNAngle xfov, RNAngle yfov, RNLength neardist, RNLength fardist)
  : cs(viewpoint, R3Triad(towards, up)),
    xfov(xfov),
    yfov(yfov),
    neardist(neardist),
    fardist(fardist)
{
  // Compute halfspaces
  for (int dir = 0; dir < 2; dir++) {
    for (int dim = 0; dim < 3; dim++) {
      R3Vector normal;
      switch (dim) {
      case RN_X:
        normal = cs.Axes().Axis(RN_X); 
        if (dir == RN_LO) normal.Rotate(cs.Axes().Axis(RN_Y), xfov);
        else normal.Rotate(cs.Axes().Axis(RN_Y), RN_PI - xfov);
        halfspaces[dir][dim] = R3Halfspace(cs.Origin(), normal);
        break;

      case RN_Y:
        normal = cs.Axes().Axis(RN_Y); 
        if (dir == RN_LO) normal.Rotate(cs.Axes().Axis(RN_X), -yfov);
        else normal.Rotate(cs.Axes().Axis(RN_X), yfov - RN_PI);
        halfspaces[dir][dim] = R3Halfspace(cs.Origin(), normal);
        break;

      case RN_Z:
        if (dir == RN_LO) {
          halfspaces[dir][dim] = R3Halfspace(cs.Origin() - cs.Axes().Axis(RN_Z) * neardist, -cs.Axes().Axis(RN_Z));
        }
        else {
          halfspaces[dir][dim] = R3Halfspace(cs.Origin() - cs.Axes().Axis(RN_Z) * fardist, cs.Axes().Axis(RN_Z));
        }
        break;

      default:
        RNAbort("Should never get here");
        break;
      }
    }
  }
}

// Assembly:
subq $0x2a8, %rsp            # imm = 0x2A8
movq %rdi, 0x2a0(%rsp)
movq %rsi, 0x298(%rsp)
movq %rdx, 0x290(%rsp)
movq %rcx, 0x288(%rsp)
movsd %xmm0, 0x280(%rsp)
movsd %xmm1, 0x278(%rsp)
movsd %xmm2, 0x270(%rsp)
movsd %xmm3, 0x268(%rsp)
movq 0x2a0(%rsp), %rdi
movq %rdi, 0xe0(%rsp)
callq 0xcc3d0
movq 0xe0(%rsp), %rax
leaq 0x12a319(%rip), %rcx    # 0x1efbd8
movq %rcx, (%rax)
addq $0x8, %rax
movq %rax, 0xe8(%rsp)
movq 0x298(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0x290(%rsp), %rsi
movq 0x288(%rsp), %rdx
leaq 0x220(%rsp), %rdi
callq 0xd5d60
jmp 0xc58fd
movq 0xf0(%rsp), %rsi
movq 0xe8(%rsp), %rdi
leaq 0x220(%rsp), %rdx
callq 0xd5570
jmp 0xc591c
movq 0xe0(%rsp), %rax
addq $0x68, %rax
movq %rax, %rcx
addq $0xc0, %rcx
movq %rcx, 0xd0(%rsp)
movq %rax, 0xd8(%rsp)
movq 0xd8(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
callq 0xf56d0
jmp 0xc5959
movq 0xd0(%rsp), %rcx
movq 0xc8(%rsp), %rax
addq $0x20, %rax
cmpq %rcx, %rax
movq %rax, 0xd8(%rsp)
jne 0xc5942
movq 0xe0(%rsp), %rax
movsd 0x280(%rsp), %xmm0
movsd %xmm0, 0x128(%rax)
movsd 0x278(%rsp), %xmm0
movsd %xmm0, 0x130(%rax)
movsd 0x270(%rsp), %xmm0
movsd %xmm0, 0x138(%rax)
movsd 0x268(%rsp), %xmm0
movsd %xmm0, 0x140(%rax)
movl $0x0, 0x210(%rsp)
cmpl $0x2, 0x210(%rsp)
jge 0xc5fe2
movl $0x0, 0x20c(%rsp)
cmpl $0x3, 0x20c(%rsp)
jge 0xc5fca
leaq 0x1f0(%rsp), %rdi
callq 0xf94a0
jmp 0xc5a07
movl 0x20c(%rsp), %eax
movl %eax, 0xc4(%rsp)
testl %eax, %eax
je 0xc5a68
jmp 0xc5a1b
movl 0xc4(%rsp), %eax
subl $0x1, %eax
je 0xc5bf8
jmp 0xc5a2d
movl 0xc4(%rsp), %eax
subl $0x2, %eax
je 0xc5d6c
jmp 0xc5fa0
movq 0xe0(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x218(%rsp)
movl %eax, 0x214(%rsp)
callq 0xcc400
jmp 0xc5fea
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0xb8(%rsp)
jmp 0xc5a83
movq 0xb8(%rsp), %rdi
xorl %esi, %esi
callq 0x32100
movq %rax, 0xb0(%rsp)
jmp 0xc5a9c
movq 0xb0(%rsp), %rsi
leaq 0x1f0(%rsp), %rdi
callq 0xfa170
jmp 0xc5ab3
cmpl $0x0, 0x210(%rsp)
jne 0xc5b16
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0xa8(%rsp)
jmp 0xc5ad8
movq 0xa8(%rsp), %rdi
movl $0x1, %esi
callq 0x32100
movq %rax, 0xa0(%rsp)
jmp 0xc5af4
movq 0xa0(%rsp), %rsi
movsd 0x280(%rsp), %xmm0
leaq 0x1f0(%rsp), %rdi
callq 0xfa1b0
jmp 0xc5b14
jmp 0xc5b7e
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x98(%rsp)
jmp 0xc5b31
movq 0x98(%rsp), %rdi
movl $0x1, %esi
callq 0x32100
movq %rax, 0x90(%rsp)
jmp 0xc5b4d
movq 0x90(%rsp), %rsi
leaq 0xe37a4(%rip), %rax     # 0x1a9300
movsd (%rax), %xmm0
movsd 0x280(%rsp), %xmm1
subsd %xmm1, %xmm0
leaq 0x1f0(%rsp), %rdi
callq 0xfa1b0
jmp 0xc5b7c
jmp 0xc5b7e
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x31e40
movq %rax, 0x88(%rsp)
jmp 0xc5b99
movq 0x88(%rsp), %rsi
leaq 0x1d0(%rsp), %rdi
leaq 0x1f0(%rsp), %rdx
callq 0xf57c0
jmp 0xc5bb8
movq 0xe0(%rsp), %rcx
movslq 0x210(%rsp), %rax
leaq (%rax,%rax,2), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x20c(%rsp), %rax
shlq $0x5, %rax
leaq 0x68(%rax,%rcx), %rdi
leaq 0x1d0(%rsp), %rsi
callq 0xc6f50
jmp 0xc5bf3
jmp 0xc5fb2
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x80(%rsp)
jmp 0xc5c13
movq 0x80(%rsp), %rdi
movl $0x1, %esi
callq 0x32100
movq %rax, 0x78(%rsp)
jmp 0xc5c2c
movq 0x78(%rsp), %rsi
leaq 0x1f0(%rsp), %rdi
callq 0xfa170
jmp 0xc5c40
cmpl $0x0, 0x210(%rsp)
jne 0xc5c9f
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x70(%rsp)
jmp 0xc5c62
movq 0x70(%rsp), %rdi
xorl %esi, %esi
callq 0x32100
movq %rax, 0x68(%rsp)
jmp 0xc5c75
movq 0x68(%rsp), %rsi
movaps 0xdee9f(%rip), %xmm1    # 0x1a4b20
movsd 0x278(%rsp), %xmm0
pxor %xmm1, %xmm0
leaq 0x1f0(%rsp), %rdi
callq 0xfa1b0
jmp 0xc5c9d
jmp 0xc5cf8
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x60(%rsp)
jmp 0xc5cb7
movq 0x60(%rsp), %rdi
xorl %esi, %esi
callq 0x32100
movq %rax, 0x58(%rsp)
jmp 0xc5cca
movq 0x58(%rsp), %rsi
movsd 0x278(%rsp), %xmm0
leaq 0xe3621(%rip), %rax     # 0x1a9300
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
leaq 0x1f0(%rsp), %rdi
callq 0xfa1b0
jmp 0xc5cf6
jmp 0xc5cf8
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x31e40
movq %rax, 0x50(%rsp)
jmp 0xc5d10
movq 0x50(%rsp), %rsi
leaq 0x1b0(%rsp), %rdi
leaq 0x1f0(%rsp), %rdx
callq 0xf57c0
jmp 0xc5d2c
movq 0xe0(%rsp), %rcx
movslq 0x210(%rsp), %rax
leaq (%rax,%rax,2), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x20c(%rsp), %rax
shlq $0x5, %rax
leaq 0x68(%rax,%rcx), %rdi
leaq 0x1b0(%rsp), %rsi
callq 0xc6f50
jmp 0xc5d67
jmp 0xc5fb2
cmpl $0x0, 0x210(%rsp)
jne 0xc5e9a
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x31e40
movq %rax, 0x48(%rsp)
jmp 0xc5d92
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x40(%rsp)
jmp 0xc5daa
movq 0x40(%rsp), %rdi
movl $0x2, %esi
callq 0x32100
movq %rax, 0x38(%rsp)
jmp 0xc5dc0
movq 0x38(%rsp), %rsi
movsd 0x270(%rsp), %xmm0
leaq 0x160(%rsp), %rdi
callq 0xfa380
jmp 0xc5ddd
movq 0x48(%rsp), %rsi
leaq 0x178(%rsp), %rdi
leaq 0x160(%rsp), %rdx
callq 0xf92b0
jmp 0xc5df9
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x30(%rsp)
jmp 0xc5e11
movq 0x30(%rsp), %rdi
movl $0x2, %esi
callq 0x32100
movq %rax, 0x28(%rsp)
jmp 0xc5e27
movq 0x28(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0xfa7a0
jmp 0xc5e3b
leaq 0x190(%rsp), %rdi
leaq 0x178(%rsp), %rsi
leaq 0x148(%rsp), %rdx
callq 0xf57c0
jmp 0xc5e5a
movq 0xe0(%rsp), %rcx
movslq 0x210(%rsp), %rax
leaq (%rax,%rax,2), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x20c(%rsp), %rax
shlq $0x5, %rax
leaq 0x68(%rax,%rcx), %rdi
leaq 0x190(%rsp), %rsi
callq 0xc6f50
jmp 0xc5e95
jmp 0xc5f9e
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x31e40
movq %rax, 0x20(%rsp)
jmp 0xc5eb2
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x18(%rsp)
jmp 0xc5eca
movq 0x18(%rsp), %rdi
movl $0x2, %esi
callq 0x32100
movq %rax, 0x10(%rsp)
jmp 0xc5ee0
movq 0x10(%rsp), %rsi
movsd 0x268(%rsp), %xmm0
leaq 0xf8(%rsp), %rdi
callq 0xfa380
jmp 0xc5efd
movq 0x20(%rsp), %rsi
leaq 0x110(%rsp), %rdi
leaq 0xf8(%rsp), %rdx
callq 0xf92b0
jmp 0xc5f19
movq 0xe0(%rsp), %rdi
addq $0x8, %rdi
callq 0x320f0
movq %rax, 0x8(%rsp)
jmp 0xc5f31
movq 0x8(%rsp), %rdi
movl $0x2, %esi
callq 0x32100
movq %rax, (%rsp)
jmp 0xc5f46
movq (%rsp), %rdx
leaq 0x128(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0xf57c0
jmp 0xc5f61
movq 0xe0(%rsp), %rcx
movslq 0x210(%rsp), %rax
leaq (%rax,%rax,2), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x20c(%rsp), %rax
shlq $0x5, %rax
leaq 0x68(%rax,%rcx), %rdi
leaq 0x128(%rsp), %rsi
callq 0xc6f50
jmp 0xc5f9c
jmp 0xc5f9e
jmp 0xc5fb2
leaq 0xdfd52(%rip), %rdi     # 0x1a5cf9
xorl %eax, %eax
callq 0x1463a0
jmp 0xc5fb0
jmp 0xc5fb2
jmp 0xc5fb4
movl 0x20c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20c(%rsp)
jmp 0xc59ea
jmp 0xc5fcc
movl 0x210(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x210(%rsp)
jmp 0xc59d1
addq $0x2a8, %rsp            # imm = 0x2A8
retq
movq 0x218(%rsp), %rdi
callq 0x13970
nopw (%rax,%rax)