// File: tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: CreateObjectCameras()
static void
CreateObjectCameras(void)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();
  int camera_count = 0;

  // Get useful variables
  RNScalar neardist = 0.01 * scene->BBox().DiagonalRadius();
  RNScalar fardist = 100 * scene->BBox().DiagonalRadius();
  RNScalar aspect = (RNScalar) height / (RNScalar) width;
  RNAngle yfov = atan(aspect * tan(xfov));

  // Create camera with close up view of each object
  for (int i = 0; i < scene->NNodes(); i++) {
    R3SceneNode *node = scene->Node(i);
    if (!node->Name()) continue;
    if (!IsObject(node)) continue;
    if (node->NElements() == 0) continue;
    R3Camera best_camera;

    // Get node's centroid and radius in world coordinate system
    R3Point centroid = node->BBox().Centroid();
    RNScalar radius = node->BBox().DiagonalRadius();

    // Check lots of directions
    int nangles = (int) (RN_PI * RN_TWO_PI / angle_sampling + 0.5);
    for (int j = 0; j < nangles; j++) {
      // Determine view direction
      R3Vector view_direction = R3RandomDirection();
      // view_direction[gravity_dimension] = -0.2;
      view_direction.Normalize();
            
      // Determine camera viewpoint
      RNScalar min_distance = radius;
      RNScalar max_distance = 1.5 * radius/tan(xfov);
      if (min_distance < min_distance_from_obstacle) min_distance = min_distance_from_obstacle;
      if (max_distance < min_distance_from_obstacle) max_distance = min_distance_from_obstacle;
      R3Point viewpoint = centroid - max_distance * view_direction;

      // Project camera viewpoint onto eye height plane (special for SUNCG)
      if (node->Parent() && node->Parent()->Parent()) {
        if (node->Parent()->Parent()->Name()) {
          if (strstr(node->Parent()->Parent()->Name(), "Room") || strstr(node->Parent()->Parent()->Name(), "Level")) {
            R3Point floor = node->Parent()->Parent()->Centroid();
            floor[1] = node->Parent()->Parent()->BBox().YMin();
            viewpoint[1] = floor[1] + eye_height;
            viewpoint[1] += 2.0*(RNRandomScalar()-0.5) * eye_height_radius;
          }
        }
      }

      // Ensure centroid is not occluded
      R3Vector back = viewpoint - centroid;
      back.Normalize();
      R3Ray ray(centroid, back);
      RNScalar hit_t = FLT_MAX;
      if (scene->Intersects(ray, NULL, NULL, NULL, NULL, NULL, &hit_t, min_distance, max_distance)) {
        viewpoint = centroid + (hit_t - min_distance_from_obstacle) * back;
      }

      // Compute camera
      R3Vector towards = centroid - viewpoint;
      towards.Normalize();
      R3Vector right = towards % R3xyz_triad[gravity_dimension];
      right.Normalize();
      R3Vector up = right % towards;
      up.Normalize();
      R3Camera camera(viewpoint, towards, up, xfov, yfov, neardist, fardist);

      // Compute score for camera
      camera.SetValue(ObjectCoverageScore(camera, scene, node));
      if (camera.Value() == 0) continue;
      if (camera.Value() < min_score) continue;
                            
      // Remember best camera
      if (camera.Value() > best_camera.Value()) {
        best_camera = camera;
      }
    }

    // Insert best camera
    if (best_camera.Value() > 0) {
      char camera_name[1024];
      const char *node_name = (node->Name()) ? node->Name() : "-";
      const char *parent_name = (node->Parent() && node->Parent()->Name()) ? node->Parent()->Name() : "-";
      sprintf(camera_name, "%s#%s", parent_name, node_name);
      if (print_debug) printf("%s %g\n", camera_name, best_camera.Value());
      Camera *camera = new Camera(best_camera, camera_name);
      cameras.Insert(camera);
      camera_count++;
    }
  }

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

// Assembly:
subq $0x768, %rsp            # imm = 0x768
leaq 0x758(%rsp), %rdi
callq 0x11bad0
leaq 0x758(%rsp), %rdi
callq 0x321a0
movl $0x0, 0x754(%rsp)
movq 0x206545(%rip), %rdi    # 0x22fc38
callq 0x32290
movq %rax, %rdi
callq 0x322b0
movaps %xmm0, %xmm1
movsd 0x191915(%rip), %xmm0   # 0x1bb020
mulsd %xmm1, %xmm0
movsd %xmm0, 0x748(%rsp)
movq 0x206519(%rip), %rdi    # 0x22fc38
callq 0x32290
movq %rax, %rdi
callq 0x322b0
movaps %xmm0, %xmm1
movsd 0x1918e1(%rip), %xmm0   # 0x1bb018
mulsd %xmm1, %xmm0
movsd %xmm0, 0x740(%rsp)
cvtsi2sdl 0x200340(%rip), %xmm0 # 0x229a8c
cvtsi2sdl 0x200334(%rip), %xmm1 # 0x229a88
divsd %xmm1, %xmm0
movsd %xmm0, 0x738(%rsp)
movsd 0x738(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x200318(%rip), %xmm0   # 0x229a90
callq 0x234f0
movaps %xmm0, %xmm1
movsd 0x70(%rsp), %xmm0
mulsd %xmm1, %xmm0
callq 0x237e0
movsd %xmm0, 0x730(%rsp)
movl $0x0, 0x72c(%rsp)
movl 0x72c(%rsp), %eax
movl %eax, 0x6c(%rsp)
movq 0x206483(%rip), %rdi    # 0x22fc38
callq 0x321c0
movl %eax, %ecx
movl 0x6c(%rsp), %eax
cmpl %ecx, %eax
jge 0x29fda
movq 0x206469(%rip), %rdi    # 0x22fc38
movl 0x72c(%rsp), %esi
callq 0x32430
movq %rax, 0x720(%rsp)
movq 0x720(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
jne 0x297fb
jmp 0x29fc4
movq 0x720(%rsp), %rdi
callq 0x2e9e0
cmpl $0x0, %eax
jne 0x29812
jmp 0x29fc4
movq 0x720(%rsp), %rdi
callq 0x32480
cmpl $0x0, %eax
jne 0x29829
jmp 0x29fc4
leaq 0x690(%rsp), %rdi
callq 0x67570
movq 0x720(%rsp), %rdi
callq 0x60be0
movq %rax, %rsi
movq (%rsi), %rax
leaq 0x678(%rsp), %rdi
callq *0x68(%rax)
movq 0x720(%rsp), %rdi
callq 0x60be0
movq %rax, %rdi
callq 0x322b0
movsd %xmm0, 0x670(%rsp)
leaq 0x195d4f(%rip), %rax    # 0x1bf5c8
movsd (%rax), %xmm0
leaq 0x195d64(%rip), %rax    # 0x1bf5e8
mulsd (%rax), %xmm0
divsd 0x206370(%rip), %xmm0   # 0x22fc00
movsd 0x191798(%rip), %xmm1   # 0x1bb030
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x66c(%rsp)
movl $0x0, 0x668(%rsp)
movl 0x668(%rsp), %eax
cmpl 0x66c(%rsp), %eax
jge 0x29e20
leaq 0x650(%rsp), %rdi
callq 0xdc640
leaq 0x650(%rsp), %rdi
callq 0xdb800
movsd 0x670(%rsp), %xmm0
movsd %xmm0, 0x648(%rsp)
movsd 0x19173e(%rip), %xmm0   # 0x1bb038
mulsd 0x670(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movsd 0x20017f(%rip), %xmm0   # 0x229a90
callq 0x234f0
movaps %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, 0x640(%rsp)
movsd 0x648(%rsp), %xmm1
movsd 0x2062ab(%rip), %xmm0   # 0x22fbe8
ucomisd %xmm1, %xmm0
jbe 0x29954
movsd 0x20629d(%rip), %xmm0   # 0x22fbe8
movsd %xmm0, 0x648(%rsp)
movsd 0x640(%rsp), %xmm1
movsd 0x206283(%rip), %xmm0   # 0x22fbe8
ucomisd %xmm1, %xmm0
jbe 0x2997c
movsd 0x206275(%rip), %xmm0   # 0x22fbe8
movsd %xmm0, 0x640(%rsp)
movsd 0x640(%rsp), %xmm0
leaq 0x610(%rsp), %rdi
leaq 0x650(%rsp), %rsi
callq 0x324a0
leaq 0x628(%rsp), %rdi
leaq 0x678(%rsp), %rsi
leaq 0x610(%rsp), %rdx
callq 0xdaea0
movq 0x720(%rsp), %rdi
callq 0x324e0
cmpq $0x0, %rax
je 0x29b8e
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
cmpq $0x0, %rax
je 0x29b8e
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x32460
cmpq $0x0, %rax
je 0x29b8c
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x191bbc(%rip), %rsi    # 0x1bb5f7
callq 0x23180
cmpq $0x0, %rax
jne 0x29a7c
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x191b8f(%rip), %rsi    # 0x1bb5fc
callq 0x23180
cmpq $0x0, %rax
je 0x29b8a
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
movq %rax, %rsi
leaq 0x5f8(%rsp), %rdi
callq 0x60f80
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x60be0
movq %rax, %rdi
callq 0x324f0
movsd %xmm0, 0x40(%rsp)
leaq 0x5f8(%rsp), %rdi
movl $0x1, %esi
callq 0x32510
movsd 0x40(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x5f8(%rsp), %rdi
movl $0x1, %esi
callq 0x32510
movsd (%rax), %xmm0
addsd 0x1fff92(%rip), %xmm0   # 0x229a98
movsd %xmm0, 0x48(%rsp)
leaq 0x628(%rsp), %rdi
movl $0x1, %esi
callq 0x32510
movsd 0x48(%rsp), %xmm0
movsd %xmm0, (%rax)
callq 0x11f4d0
movaps %xmm0, %xmm1
movsd 0x1914f8(%rip), %xmm0   # 0x1bb030
subsd %xmm0, %xmm1
movsd 0x1914cc(%rip), %xmm0   # 0x1bb010
mulsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x1fff4a(%rip), %xmm0   # 0x229aa0
movsd %xmm0, 0x58(%rsp)
leaq 0x628(%rsp), %rdi
movl $0x1, %esi
callq 0x32510
movsd 0x50(%rsp), %xmm0
movsd 0x58(%rsp), %xmm2
movsd (%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rax)
jmp 0x29b8c
jmp 0x29b8e
leaq 0x5e0(%rsp), %rdi
leaq 0x628(%rsp), %rsi
leaq 0x678(%rsp), %rdx
callq 0xda2a0
leaq 0x5e0(%rsp), %rdi
callq 0xdb800
leaq 0x5b0(%rsp), %rdi
leaq 0x678(%rsp), %rsi
leaq 0x5e0(%rsp), %rdx
xorl %ecx, %ecx
callq 0xd9830
movsd 0x191461(%rip), %xmm0   # 0x1bb040
movsd %xmm0, 0x5a8(%rsp)
movq 0x206049(%rip), %rdi    # 0x22fc38
movsd 0x648(%rsp), %xmm0
movsd 0x640(%rsp), %xmm1
leaq 0x5b0(%rsp), %rsi
xorl %eax, %eax
movl %eax, %r9d
leaq 0x5a8(%rsp), %rax
movq %r9, %rdx
movq %r9, %rcx
movq %r9, %r8
movq $0x0, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x388b0
cmpl $0x0, %eax
je 0x29c8e
movsd 0x5a8(%rsp), %xmm0
subsd 0x205fa1(%rip), %xmm0   # 0x22fbe8
leaq 0x578(%rsp), %rdi
leaq 0x5e0(%rsp), %rsi
callq 0x324a0
leaq 0x590(%rsp), %rdi
leaq 0x678(%rsp), %rsi
leaq 0x578(%rsp), %rdx
callq 0xda500
leaq 0x628(%rsp), %rdi
leaq 0x590(%rsp), %rsi
callq 0xda5d0
leaq 0x560(%rsp), %rdi
leaq 0x678(%rsp), %rsi
leaq 0x628(%rsp), %rdx
callq 0xda2a0
leaq 0x560(%rsp), %rdi
callq 0xdb800
movl 0x1ffdc6(%rip), %esi    # 0x229a84
leaq 0x20ede3(%rip), %rdi    # 0x238aa8
callq 0x32530
movq %rax, %rdx
leaq 0x548(%rsp), %rdi
leaq 0x560(%rsp), %rsi
callq 0xdbee0
leaq 0x548(%rsp), %rdi
callq 0xdb800
leaq 0x530(%rsp), %rdi
leaq 0x548(%rsp), %rsi
leaq 0x560(%rsp), %rdx
callq 0xdbee0
leaq 0x530(%rsp), %rdi
callq 0xdb800
movsd 0x1ffd6f(%rip), %xmm0   # 0x229a90
movsd 0x730(%rsp), %xmm1
movsd 0x748(%rsp), %xmm2
movsd 0x740(%rsp), %xmm3
leaq 0x4a0(%rsp), %rdi
leaq 0x628(%rsp), %rsi
leaq 0x560(%rsp), %rdx
leaq 0x530(%rsp), %rcx
callq 0x67810
movq 0x205ed0(%rip), %rsi    # 0x22fc38
movq 0x720(%rsp), %rdx
leaq 0x4a0(%rsp), %rdi
callq 0x2eae0
leaq 0x4a0(%rsp), %rdi
callq 0x32350
leaq 0x4a0(%rsp), %rdi
callq 0x32550
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x29da4
jp 0x29da4
jmp 0x29e0a
leaq 0x4a0(%rsp), %rdi
callq 0x32550
movaps %xmm0, %xmm1
movsd 0x205e34(%rip), %xmm0   # 0x22fbf0
ucomisd %xmm1, %xmm0
jbe 0x29dc4
jmp 0x29e0a
leaq 0x4a0(%rsp), %rdi
callq 0x32550
movsd %xmm0, 0x38(%rsp)
leaq 0x690(%rsp), %rdi
callq 0x32550
movaps %xmm0, %xmm1
movsd 0x38(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x29e08
leaq 0x690(%rsp), %rdi
leaq 0x4a0(%rsp), %rsi
callq 0x68860
jmp 0x29e0a
movl 0x668(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x668(%rsp)
jmp 0x298b2
leaq 0x690(%rsp), %rdi
callq 0x32550
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x29fc2
movq 0x720(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
je 0x29e61
movq 0x720(%rsp), %rdi
callq 0x32460
movq %rax, 0x30(%rsp)
jmp 0x29e6f
leaq 0x19179a(%rip), %rax    # 0x1bb602
movq %rax, 0x30(%rsp)
jmp 0x29e6f
movq 0x30(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0x720(%rsp), %rdi
callq 0x324e0
cmpq $0x0, %rax
je 0x29ec6
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x32460
cmpq $0x0, %rax
je 0x29ec6
movq 0x720(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x32460
movq %rax, 0x28(%rsp)
jmp 0x29ed4
leaq 0x191735(%rip), %rax    # 0x1bb602
movq %rax, 0x28(%rsp)
jmp 0x29ed4
movq 0x28(%rsp), %rax
movq %rax, 0x90(%rsp)
leaq 0xa0(%rsp), %rdi
movq 0x90(%rsp), %rdx
movq 0x98(%rsp), %rcx
leaq 0x191704(%rip), %rsi    # 0x1bb604
movb $0x0, %al
callq 0x23150
cmpl $0x0, 0x205caa(%rip)    # 0x22fbb8
je 0x29f3d
leaq 0xa0(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0x690(%rsp), %rdi
callq 0x32550
movq 0x20(%rsp), %rsi
leaq 0x1916d4(%rip), %rdi    # 0x1bb60a
movb $0x1, %al
callq 0x23090
movl $0x98, %edi
callq 0x239b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x18(%rsp)
leaq 0x690(%rsp), %rsi
leaq 0xa0(%rsp), %rdx
callq 0x32570
jmp 0x29f69
movq 0x18(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rsi
leaq 0x205bfb(%rip), %rdi    # 0x22fb80
callq 0x32370
movl 0x754(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x754(%rsp)
jmp 0x29fc2
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x80(%rsp)
movl %eax, 0x7c(%rsp)
movl $0x98, %esi
callq 0x239d0
jmp 0x2a044
jmp 0x29fc4
movl 0x72c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x72c(%rsp)
jmp 0x297a3
cmpl $0x0, 0x205bd3(%rip)    # 0x22fbb4
je 0x2a03c
leaq 0x191627(%rip), %rdi    # 0x1bb611
movb $0x0, %al
callq 0x23090
leaq 0x758(%rsp), %rdi
callq 0x11bb90
leaq 0x191435(%rip), %rdi    # 0x1bb43a
movb $0x1, %al
callq 0x23090
movl 0x754(%rsp), %esi
movl %esi, %eax
addl $0x1, %eax
movl %eax, 0x754(%rsp)
leaq 0x1914d9(%rip), %rdi    # 0x1bb4ff
movb $0x0, %al
callq 0x23090
movq 0x1fef5c(%rip), %rax    # 0x228f90
movq (%rax), %rdi
callq 0x23bc0
addq $0x768, %rsp            # imm = 0x768
retq
movq 0x80(%rsp), %rdi
callq 0x24250
nopw %cs:(%rax,%rax)