// File: tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: InterpolateCameraTrajectory(double)
static int
InterpolateCameraTrajectory(RNLength trajectory_step = 0.1)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Set some camera parameters based on first camera
  RNLength xf = cameras.Head()->XFOV();
  RNLength yf = cameras.Head()->YFOV();
  RNLength neardist = cameras.Head()->Near();
  RNLength fardist = cameras.Head()->Far();
  
  // Create spline data
  int nkeypoints = cameras.NEntries();
  R3Point *viewpoint_keypoints =  new R3Point [ nkeypoints ];
  R3Point *towards_keypoints =  new R3Point [ nkeypoints ];
  R3Point *up_keypoints =  new R3Point [ nkeypoints ];
  RNScalar *parameters = new RNScalar [ nkeypoints ];
  for (int i = 0; i < cameras.NEntries(); i++) {
    R3Camera *camera = cameras.Kth(i);
    viewpoint_keypoints[i] = camera->Origin();
    towards_keypoints[i] = camera->Towards().Point();
    up_keypoints[i] = camera->Up().Point();
    if (i == 0) parameters[i] = 0;
    else parameters[i] = parameters[i-1] + R3Distance(viewpoint_keypoints[i], viewpoint_keypoints[i-1]) + R3InteriorAngle(towards_keypoints[i].Vector(), towards_keypoints[i-1].Vector());
  }

  // Create splines
  R3CatmullRomSpline viewpoint_spline(viewpoint_keypoints, parameters, nkeypoints);
  R3CatmullRomSpline towards_spline(towards_keypoints, parameters, nkeypoints);
  R3CatmullRomSpline up_spline(up_keypoints, parameters, nkeypoints);

  // Delete cameras
  for (int i = 0; i < cameras.NEntries(); i++) delete cameras[i];
  cameras.Empty();
  
  // Resample splines
  for (RNScalar u = viewpoint_spline.StartParameter(); u <= viewpoint_spline.EndParameter(); u += trajectory_step) {
    R3Point viewpoint = viewpoint_spline.PointPosition(u);
    R3Point towards = towards_spline.PointPosition(u);
    R3Point up = up_spline.PointPosition(u);
    Camera *camera = new Camera(viewpoint, towards.Vector(), up.Vector(), xf, yf, neardist, fardist);
    char name[1024];
    sprintf(name, "T%f", u);
    camera->name = RNStrdup(name);
    cameras.Insert(camera);
  }

  // Delete spline data
  delete [] viewpoint_keypoints;
  delete [] towards_keypoints;
  delete [] up_keypoints;
  delete [] parameters;

  // Print statistics
  if (print_verbose) {
    printf("Interpolated camera trajectory ...\n");
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Cameras = %d\n", cameras.NEntries());
    fflush(stdout);
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x7e8, %rsp            # imm = 0x7E8
movsd %xmm0, 0x7e0(%rsp)
leaq 0x7d0(%rsp), %rdi
callq 0x11bad0
leaq 0x7d0(%rsp), %rdi
callq 0x321a0
leaq 0x201d8f(%rip), %rdi    # 0x22fb80
callq 0x36bf0
movq %rax, %rdi
callq 0x36c00
movsd %xmm0, 0x7c8(%rsp)
leaq 0x201d72(%rip), %rdi    # 0x22fb80
callq 0x36bf0
movq %rax, %rdi
callq 0x36c10
movsd %xmm0, 0x7c0(%rsp)
leaq 0x201d55(%rip), %rdi    # 0x22fb80
callq 0x36bf0
movq %rax, %rdi
callq 0x36c20
movsd %xmm0, 0x7b8(%rsp)
leaq 0x201d38(%rip), %rdi    # 0x22fb80
callq 0x36bf0
movq %rax, %rdi
callq 0x36c30
movsd %xmm0, 0x7b0(%rsp)
leaq 0x201d1b(%rip), %rdi    # 0x22fb80
callq 0x32280
movl %eax, 0x7ac(%rsp)
movslq 0x7ac(%rsp), %rax
movq %rax, 0x110(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x108(%rsp)
callq 0x23040
movq %rax, %rcx
movq 0x110(%rsp), %rax
movq %rcx, 0x118(%rsp)
cmpq $0x0, %rax
je 0x2df25
movq 0x118(%rsp), %rax
movq 0x110(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0xf8(%rsp)
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rdi
movq %rdi, 0xf0(%rsp)
callq 0xd9f30
jmp 0x2df04
movq 0xf8(%rsp), %rcx
movq 0xf0(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0x100(%rsp)
jne 0x2deed
movq 0x118(%rsp), %rax
movq %rax, 0x7a0(%rsp)
movslq 0x7ac(%rsp), %rax
movq %rax, 0xe0(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0xd8(%rsp)
callq 0x23040
movq %rax, %rcx
movq 0xe0(%rsp), %rax
movq %rcx, 0xe8(%rsp)
cmpq $0x0, %rax
je 0x2dfe9
movq 0xe8(%rsp), %rax
movq 0xe0(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0xc8(%rsp)
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
callq 0xd9f30
jmp 0x2dfc8
movq 0xc8(%rsp), %rcx
movq 0xc0(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0xd0(%rsp)
jne 0x2dfb1
movq 0xe8(%rsp), %rax
movq %rax, 0x788(%rsp)
movslq 0x7ac(%rsp), %rax
movq %rax, 0xb0(%rsp)
movl $0x18, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0xa8(%rsp)
callq 0x23040
movq %rax, %rcx
movq 0xb0(%rsp), %rax
movq %rcx, 0xb8(%rsp)
cmpq $0x0, %rax
je 0x2e0ad
movq 0xb8(%rsp), %rax
movq 0xb0(%rsp), %rcx
imulq $0x18, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x98(%rsp)
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rdi
movq %rdi, 0x90(%rsp)
callq 0xd9f30
jmp 0x2e08c
movq 0x98(%rsp), %rcx
movq 0x90(%rsp), %rax
addq $0x18, %rax
cmpq %rcx, %rax
movq %rax, 0xa0(%rsp)
jne 0x2e075
movq 0xb8(%rsp), %rax
movq %rax, 0x780(%rsp)
movslq 0x7ac(%rsp), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x23040
movq %rax, 0x778(%rsp)
movl $0x0, 0x774(%rsp)
movl 0x774(%rsp), %eax
movl %eax, 0x8c(%rsp)
leaq 0x201a72(%rip), %rdi    # 0x22fb80
callq 0x32280
movl %eax, %ecx
movl 0x8c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2e3ba
movl 0x774(%rsp), %esi
leaq 0x201a4e(%rip), %rdi    # 0x22fb80
callq 0x36c40
movq %rax, 0x768(%rsp)
movq 0x768(%rsp), %rdi
callq 0x332f0
movq %rax, %rsi
movq 0x7a0(%rsp), %rdi
movslq 0x774(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0xda5d0
movq 0x768(%rsp), %rsi
leaq 0x738(%rsp), %rdi
callq 0x34a10
leaq 0x750(%rsp), %rdi
leaq 0x738(%rsp), %rsi
callq 0xdb2c0
movq 0x788(%rsp), %rdi
movslq 0x774(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
leaq 0x750(%rsp), %rsi
callq 0xda5d0
movq 0x768(%rsp), %rdi
callq 0x34a60
movq %rax, %rsi
leaq 0x720(%rsp), %rdi
callq 0xdb2c0
movq 0x780(%rsp), %rdi
movslq 0x774(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
leaq 0x720(%rsp), %rsi
callq 0xda5d0
cmpl $0x0, 0x774(%rsp)
jne 0x2e2af
movq 0x778(%rsp), %rax
movslq 0x774(%rsp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0x2e3a2
movq 0x108(%rsp), %rsi
movq 0x118(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
callq 0x24430
jmp 0x2e869
movq 0xd8(%rsp), %rsi
movq 0xe8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
callq 0x24430
jmp 0x2e869
movq 0xa8(%rsp), %rsi
movq 0xb8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
callq 0x24430
jmp 0x2e869
movq 0x778(%rsp), %rax
movl 0x774(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, 0x78(%rsp)
movq 0x7a0(%rsp), %rdi
movslq 0x774(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
movq 0x7a0(%rsp), %rsi
movl 0x774(%rsp), %eax
subl $0x1, %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rsi
callq 0x81750
movaps %xmm0, %xmm1
movsd 0x78(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movq 0x788(%rsp), %rsi
movslq 0x774(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x708(%rsp), %rdi
callq 0x36c60
movq 0x788(%rsp), %rsi
movl 0x774(%rsp), %eax
subl $0x1, %eax
cltq
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x6f0(%rsp), %rdi
callq 0x36c60
leaq 0x708(%rsp), %rdi
leaq 0x6f0(%rsp), %rsi
callq 0x86dd0
movaps %xmm0, %xmm1
movsd 0x80(%rsp), %xmm0
addsd %xmm1, %xmm0
movq 0x778(%rsp), %rax
movslq 0x774(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
jmp 0x2e3a4
movl 0x774(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x774(%rsp)
jmp 0x2e0f9
movq 0x7a0(%rsp), %rsi
movq 0x778(%rsp), %rdx
movl 0x7ac(%rsp), %ecx
leaq 0x688(%rsp), %rdi
movsd 0x18cc4f(%rip), %xmm0   # 0x1bb030
movsd %xmm0, 0x70(%rsp)
callq 0x87990
movsd 0x70(%rsp), %xmm0
movq 0x788(%rsp), %rsi
movq 0x778(%rsp), %rdx
movl 0x7ac(%rsp), %ecx
leaq 0x620(%rsp), %rdi
callq 0x87990
jmp 0x2e418
movq 0x780(%rsp), %rsi
movq 0x778(%rsp), %rdx
movl 0x7ac(%rsp), %ecx
leaq 0x5b8(%rsp), %rdi
movsd 0x18cbf1(%rip), %xmm0   # 0x1bb030
callq 0x87990
jmp 0x2e446
movl $0x0, 0x5b4(%rsp)
movl 0x5b4(%rsp), %eax
movl %eax, 0x6c(%rsp)
leaq 0x20171d(%rip), %rdi    # 0x22fb80
callq 0x32280
movl %eax, %ecx
movl 0x6c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2e51c
movl 0x5b4(%rsp), %esi
leaq 0x2016fc(%rip), %rdi    # 0x22fb80
callq 0x36ca0
movq %rax, 0x60(%rsp)
jmp 0x2e490
movq 0x60(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x58(%rsp)
cmpq $0x0, %rax
je 0x2e4bc
movq 0x58(%rsp), %rdi
callq 0x33970
movq 0x58(%rsp), %rdi
movl $0x98, %esi
callq 0x239d0
jmp 0x2e4be
movl 0x5b4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5b4(%rsp)
jmp 0x2e451
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
jmp 0x2e85c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
jmp 0x2e84f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
jmp 0x2e842
leaq 0x20165d(%rip), %rdi    # 0x22fb80
xorl %esi, %esi
callq 0x11caf0
jmp 0x2e52c
leaq 0x688(%rsp), %rdi
callq 0x89580
movsd %xmm0, 0x50(%rsp)
jmp 0x2e541
movsd 0x50(%rsp), %xmm0
movsd %xmm0, 0x5a8(%rsp)
movsd 0x5a8(%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
leaq 0x688(%rsp), %rdi
callq 0x89590
movsd %xmm0, 0x48(%rsp)
jmp 0x2e574
movsd 0x48(%rsp), %xmm0
movsd 0x40(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jb 0x2e727
movsd 0x5a8(%rsp), %xmm0
leaq 0x590(%rsp), %rdi
leaq 0x688(%rsp), %rsi
callq 0x87e50
jmp 0x2e5aa
movsd 0x5a8(%rsp), %xmm0
leaq 0x578(%rsp), %rdi
leaq 0x620(%rsp), %rsi
callq 0x87e50
jmp 0x2e5ca
movsd 0x5a8(%rsp), %xmm0
leaq 0x560(%rsp), %rdi
leaq 0x5b8(%rsp), %rsi
callq 0x87e50
jmp 0x2e5ea
movl $0x98, %edi
callq 0x239b0
movq %rax, 0x38(%rsp)
jmp 0x2e5fb
leaq 0x540(%rsp), %rdi
leaq 0x578(%rsp), %rsi
callq 0x36c60
jmp 0x2e612
leaq 0x528(%rsp), %rdi
leaq 0x560(%rsp), %rsi
callq 0x36c60
jmp 0x2e629
movq 0x38(%rsp), %rdi
movsd 0x7c8(%rsp), %xmm0
movsd 0x7c0(%rsp), %xmm1
movsd 0x7b8(%rsp), %xmm2
movsd 0x7b0(%rsp), %xmm3
leaq 0x590(%rsp), %rsi
leaq 0x540(%rsp), %rdx
leaq 0x528(%rsp), %rcx
callq 0x322d0
jmp 0x2e671
movq 0x38(%rsp), %rax
movq %rax, 0x558(%rsp)
movsd 0x5a8(%rsp), %xmm0
leaq 0x18d176(%rip), %rsi    # 0x1bb804
leaq 0x120(%rsp), %rdi
movq %rdi, 0x28(%rsp)
movb $0x1, %al
callq 0x23150
movq 0x28(%rsp), %rdi
callq 0x120750
movq %rax, 0x30(%rsp)
jmp 0x2e6b3
movq 0x30(%rsp), %rcx
movq 0x558(%rsp), %rax
movq %rcx, 0x90(%rax)
movq 0x558(%rsp), %rsi
leaq 0x2014aa(%rip), %rdi    # 0x22fb80
callq 0x32370
jmp 0x2e6dd
jmp 0x2e6df
movsd 0x7e0(%rsp), %xmm0
addsd 0x5a8(%rsp), %xmm0
movsd %xmm0, 0x5a8(%rsp)
jmp 0x2e550
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x798(%rsp)
movl %eax, 0x794(%rsp)
movl $0x98, %esi
callq 0x239d0
jmp 0x2e842
movq 0x7a0(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x2e744
movq 0x20(%rsp), %rdi
callq 0x23d70
movq 0x788(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x2e761
movq 0x18(%rsp), %rdi
callq 0x23d70
movq 0x780(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x2e77e
movq 0x10(%rsp), %rdi
callq 0x23d70
movq 0x778(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x2e79b
movq 0x8(%rsp), %rdi
callq 0x23d70
cmpl $0x0, 0x201412(%rip)    # 0x22fbb4
je 0x2e80e
leaq 0x18d05d(%rip), %rdi    # 0x1bb808
xorl %eax, %eax
callq 0x23090
jmp 0x2e7b4
leaq 0x7d0(%rsp), %rdi
callq 0x11bb90
movsd %xmm0, (%rsp)
jmp 0x2e7c8
movsd (%rsp), %xmm0
leaq 0x18cc66(%rip), %rdi    # 0x1bb43a
movb $0x1, %al
callq 0x23090
jmp 0x2e7dd
leaq 0x20139c(%rip), %rdi    # 0x22fb80
callq 0x32280
movl %eax, %esi
leaq 0x18cd0d(%rip), %rdi    # 0x1bb4ff
xorl %eax, %eax
callq 0x23090
jmp 0x2e7fb
movq 0x1fa78e(%rip), %rax    # 0x228f90
movq (%rax), %rdi
callq 0x23bc0
jmp 0x2e80c
jmp 0x2e80e
leaq 0x5b8(%rsp), %rdi
callq 0x879f0
leaq 0x620(%rsp), %rdi
callq 0x879f0
leaq 0x688(%rsp), %rdi
callq 0x879f0
movl $0x1, %eax
addq $0x7e8, %rsp            # imm = 0x7E8
retq
leaq 0x5b8(%rsp), %rdi
callq 0x879f0
leaq 0x620(%rsp), %rdi
callq 0x879f0
leaq 0x688(%rsp), %rdi
callq 0x879f0
movq 0x798(%rsp), %rdi
callq 0x24250
nopw %cs:(%rax,%rax)