// File: tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: CreateLookAtCameras()
static void
CreateLookAtCameras(void)
{
  // Check points
  if (!points) return;

  // Start statistics
  RNTime start_time;
  start_time.Read();
  int camera_count = 0;

  // Determine camera parameters
  RNScalar neardist = 0.01;
  RNScalar fardist = 10.0;
  RNScalar aspect = (RNScalar) height / (RNScalar) width;
  RNScalar yfov = atan(aspect * tan(xfov));
  RNScalar downward_angle = RN_PI/3.0;
  RNScalar downward_angle_cosine = cos(downward_angle);

  // Consider every point in pointset
  for (int i = 0; i < points->NPoints(); i++) {
    R3Point lookat_position = points->PointPosition(i);
  
    // Sample angles rotated around gravity dimension
    int nangles = RN_TWO_PI / angle_sampling + 1;
    for (int j = 0; j < nangles; j++) {
      // Determine view direction
      RNAngle angle = j * (RN_TWO_PI / nangles);
      R3Vector towards = R3xyz_triad[(gravity_dimension+1)%3];
      towards.Rotate(gravity_dimension, angle);
      towards[gravity_dimension] = -downward_angle_cosine;
      towards.Normalize();

      // Determine viewpoint and other directions
      R3Point viewpoint = lookat_position - max_surface_distance * towards;
      R3Vector right = towards % R3xyz_triad[gravity_dimension];
      right.Normalize();
      R3Vector up = right % towards;
      up.Normalize();

      // Ensure lookat position is not occluded
      RNScalar hit_t = FLT_MAX;
      R3Ray ray(lookat_position, -towards);
      if (scene->Intersects(ray, NULL, NULL, NULL, NULL, NULL, &hit_t, 0.1, max_surface_distance)) {
        if (hit_t < min_surface_distance) continue;
        viewpoint = lookat_position - hit_t * towards;
      }

      // Create camera
      R3Camera camera(viewpoint, towards, up, xfov, yfov, neardist, fardist);

      // Compute score for camera
      camera.SetValue(SceneCoverageScore(camera, scene, NULL, TRUE));
      if (camera.Value() == 0) continue;
      if (camera.Value() < min_score) continue;

      // Insert camera
      char camera_name[1024];
      sprintf(camera_name, "%s#%d_%d", "LookAt", i, j);
      Camera *insertable_camera = new Camera(camera, camera_name);
      cameras.Insert(insertable_camera);
      camera_count++;
    }
  }

  // Print statistics
  if (print_verbose) {
    printf("Created lookat cameras ...\n");
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Points = %d\n", points->NPoints());
    printf("  # Cameras = %d\n", camera_count);
    fflush(stdout);
  }
}

// Assembly:
subq $0x658, %rsp            # imm = 0x658
cmpq $0x0, 0x203b51(%rip)    # 0x22fc40
jne 0x2c0f6
jmp 0x2c6bc
leaq 0x648(%rsp), %rdi
callq 0x11bad0
leaq 0x648(%rsp), %rdi
callq 0x321a0
movl $0x0, 0x644(%rsp)
movsd 0x18eefd(%rip), %xmm0   # 0x1bb020
movsd %xmm0, 0x638(%rsp)
movsd 0x18ef44(%rip), %xmm0   # 0x1bb078
movsd %xmm0, 0x630(%rsp)
cvtsi2sdl 0x1fd947(%rip), %xmm0 # 0x229a8c
cvtsi2sdl 0x1fd93b(%rip), %xmm1 # 0x229a88
divsd %xmm1, %xmm0
movsd %xmm0, 0x628(%rsp)
movsd 0x628(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movsd 0x1fd91f(%rip), %xmm0   # 0x229a90
callq 0x234f0
movaps %xmm0, %xmm1
movsd 0x30(%rsp), %xmm0
mulsd %xmm1, %xmm0
callq 0x237e0
movsd %xmm0, 0x620(%rsp)
leaq 0x193430(%rip), %rax    # 0x1bf5c8
movsd (%rax), %xmm0
movsd 0x18ee84(%rip), %xmm1   # 0x1bb028
divsd %xmm1, %xmm0
movsd %xmm0, 0x618(%rsp)
movsd 0x618(%rsp), %xmm0
callq 0x24360
movsd %xmm0, 0x610(%rsp)
movl $0x0, 0x60c(%rsp)
movl 0x60c(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x203a5b(%rip), %rdi    # 0x22fc40
callq 0x32400
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2c64a
movq 0x203a41(%rip), %rdi    # 0x22fc40
movl 0x60c(%rsp), %esi
callq 0x359b0
movq %rax, %rsi
leaq 0x5f0(%rsp), %rdi
callq 0xd9f80
leaq 0x1933c6(%rip), %rax    # 0x1bf5e8
movsd (%rax), %xmm0
divsd 0x2039d2(%rip), %xmm0   # 0x22fc00
movsd 0x18ee52(%rip), %xmm1   # 0x1bb088
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x5ec(%rsp)
movl $0x0, 0x5e8(%rsp)
movl 0x5e8(%rsp), %eax
cmpl 0x5ec(%rsp), %eax
jge 0x2c632
cvtsi2sdl 0x5e8(%rsp), %xmm0
leaq 0x193374(%rip), %rax    # 0x1bf5e8
movsd (%rax), %xmm1
cvtsi2sdl 0x5ec(%rsp), %xmm2
divsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x5e0(%rsp)
movl 0x1fd7ec(%rip), %eax    # 0x229a84
addl $0x1, %eax
movl $0x3, %ecx
cltd
idivl %ecx
movl %edx, %esi
leaq 0x20c7fc(%rip), %rdi    # 0x238aa8
callq 0x32530
movq %rax, %rsi
leaq 0x5c8(%rsp), %rdi
callq 0xdb0e0
movl 0x1fd7bd(%rip), %esi    # 0x229a84
movsd 0x5e0(%rsp), %xmm0
leaq 0x5c8(%rsp), %rdi
callq 0xdbc30
movsd 0x610(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd %xmm0, 0x20(%rsp)
movl 0x1fd77b(%rip), %esi    # 0x229a84
leaq 0x5c8(%rsp), %rdi
callq 0x334e0
movsd 0x20(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x5c8(%rsp), %rdi
callq 0xdb800
movsd 0x1fd783(%rip), %xmm0   # 0x229ab8
leaq 0x598(%rsp), %rdi
leaq 0x5c8(%rsp), %rsi
callq 0x324a0
leaq 0x5b0(%rsp), %rdi
leaq 0x5f0(%rsp), %rsi
leaq 0x598(%rsp), %rdx
callq 0xdaea0
movl 0x1fd717(%rip), %esi    # 0x229a84
leaq 0x20c734(%rip), %rdi    # 0x238aa8
callq 0x32530
movq %rax, %rdx
leaq 0x580(%rsp), %rdi
leaq 0x5c8(%rsp), %rsi
callq 0xdbee0
leaq 0x580(%rsp), %rdi
callq 0xdb800
leaq 0x568(%rsp), %rdi
leaq 0x580(%rsp), %rsi
leaq 0x5c8(%rsp), %rdx
callq 0xdbee0
leaq 0x568(%rsp), %rdi
callq 0xdb800
movsd 0x18ec70(%rip), %xmm0   # 0x1bb040
movsd %xmm0, 0x560(%rsp)
leaq 0x518(%rsp), %rdi
leaq 0x5c8(%rsp), %rsi
callq 0xdc390
leaq 0x530(%rsp), %rdi
leaq 0x5f0(%rsp), %rsi
leaq 0x518(%rsp), %rdx
xorl %ecx, %ecx
callq 0xd9830
movq 0x203824(%rip), %rdi    # 0x22fc38
movsd 0x1fd69c(%rip), %xmm1   # 0x229ab8
leaq 0x530(%rsp), %rsi
xorl %eax, %eax
movl %eax, %r9d
leaq 0x560(%rsp), %rax
movsd 0x18ec17(%rip), %xmm0   # 0x1bb050
movq %r9, %rdx
movq %r9, %rcx
movq %r9, %r8
movq $0x0, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x388b0
cmpl $0x0, %eax
je 0x2c4c5
movsd 0x560(%rsp), %xmm1
movsd 0x1fd646(%rip), %xmm0   # 0x229ab0
ucomisd %xmm1, %xmm0
jbe 0x2c475
jmp 0x2c5fa
movsd 0x560(%rsp), %xmm0
leaq 0x4e8(%rsp), %rdi
leaq 0x5c8(%rsp), %rsi
callq 0x324a0
leaq 0x500(%rsp), %rdi
leaq 0x5f0(%rsp), %rsi
leaq 0x4e8(%rsp), %rdx
callq 0xdaea0
leaq 0x5b0(%rsp), %rdi
leaq 0x500(%rsp), %rsi
callq 0xda5d0
movsd 0x1fd5c3(%rip), %xmm0   # 0x229a90
movsd 0x620(%rsp), %xmm1
movsd 0x638(%rsp), %xmm2
movsd 0x630(%rsp), %xmm3
leaq 0x458(%rsp), %rdi
leaq 0x5b0(%rsp), %rsi
leaq 0x5c8(%rsp), %rdx
leaq 0x568(%rsp), %rcx
callq 0x67810
movq 0x203724(%rip), %rsi    # 0x22fc38
leaq 0x458(%rsp), %rdi
xorl %eax, %eax
movl %eax, %edx
movl $0x1, %ecx
callq 0x2f130
leaq 0x458(%rsp), %rdi
callq 0x32350
leaq 0x458(%rsp), %rdi
callq 0x32550
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2c554
jp 0x2c554
jmp 0x2c5fa
leaq 0x458(%rsp), %rdi
callq 0x32550
movaps %xmm0, %xmm1
movsd 0x203684(%rip), %xmm0   # 0x22fbf0
ucomisd %xmm1, %xmm0
jbe 0x2c577
jmp 0x2c5fa
movl 0x60c(%rsp), %ecx
movl 0x5e8(%rsp), %r8d
leaq 0x18f1c9(%rip), %rsi    # 0x1bb756
leaq 0x18f1cb(%rip), %rdx    # 0x1bb75f
xorl %eax, %eax
leaq 0x50(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x23150
movl $0x98, %edi
callq 0x239b0
movq 0x10(%rsp), %rdx
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x18(%rsp)
leaq 0x458(%rsp), %rsi
callq 0x32570
jmp 0x2c5ce
movq 0x18(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rsi
leaq 0x20359c(%rip), %rdi    # 0x22fb80
callq 0x32370
movl 0x644(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x644(%rsp)
movl 0x5e8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5e8(%rsp)
jmp 0x2c250
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x40(%rsp)
movl %eax, 0x3c(%rsp)
movl $0x98, %esi
callq 0x239d0
jmp 0x2c6c4
jmp 0x2c634
movl 0x60c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x60c(%rsp)
jmp 0x2c1d3
cmpl $0x0, 0x203563(%rip)    # 0x22fbb4
je 0x2c6bc
leaq 0x18f10c(%rip), %rdi    # 0x1bb766
movb $0x0, %al
callq 0x23090
leaq 0x648(%rsp), %rdi
callq 0x11bb90
leaq 0x18edc5(%rip), %rdi    # 0x1bb43a
movb $0x1, %al
callq 0x23090
movq 0x2035bd(%rip), %rdi    # 0x22fc40
callq 0x32400
movl %eax, %esi
leaq 0x18eef7(%rip), %rdi    # 0x1bb588
movb $0x0, %al
callq 0x23090
movl 0x644(%rsp), %esi
leaq 0x18ee59(%rip), %rdi    # 0x1bb4ff
movb $0x0, %al
callq 0x23090
movq 0x1fc8dc(%rip), %rax    # 0x228f90
movq (%rax), %rdi
callq 0x23bc0
addq $0x658, %rsp            # imm = 0x658
retq
movq 0x40(%rsp), %rdi
callq 0x24250
nop