// File: tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: CreatePathInRoomCameras()
static void
CreatePathInRoomCameras(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 one camera trajectory per door
  for (int i = 0; i < scene->NNodes(); i++) {
    R3SceneNode *room_node = scene->Node(i);
    if (!IsRoom(room_node)) continue;
    R3Box room_bbox = room_node->BBox();

    // Compute viewpoint mask
    R2Grid viewpoint_mask;
    if (!ComputeViewpointMask(room_node, viewpoint_mask)) continue;

    // Find largest connected component
    R2Grid component_mask = viewpoint_mask;
    component_mask.ConnectedComponentSizeFilter(RN_EPSILON);
    RNScalar component_size = component_mask.Maximum();
    component_mask.Threshold(component_size - 0.5, 0, 1.0);
    component_mask.Substitute(0, R2_GRID_UNKNOWN_VALUE);
    
    // Find path between distant pair of points in largest connected component
    int path_size = 0;
    int random_point_index = FindIndexOfRandomPoint(component_mask);
    if (random_point_index < 0) continue;
    int start_point_index = FindIndexOfFurthestPointAlongPath(component_mask, random_point_index);
    if (start_point_index < 0) continue;
    int *path_indices = new int [ component_mask.NEntries() ];
    int end_point_index = FindIndexOfFurthestPointAlongPath(component_mask, start_point_index, path_indices, &path_size);
    if (end_point_index <= 0) { delete [] path_indices; continue; }

    // Find the lookat point
    RNScalar lookat_weight = 0;
    R3Point lookat_position = R3zero_point;
    for (int j = 0; j < room_node->NChildren(); j++) {
      R3SceneNode *child_node = room_node->Child(j);
      RNScalar weight = child_node->NFacets().Max();
      lookat_position += weight * child_node->Centroid();
      lookat_weight += weight;
    }
    if (lookat_weight > 0) lookat_position /= lookat_weight;
    else lookat_position = room_node->Centroid();
    
    // Sample viewpoints on the path
    int sample_ix, sample_iy;
    int path_step = position_sampling * component_mask.WorldToGridScaleFactor();
    if (path_step == 0) path_step = 1;
    for (int i = 0; i < path_size; i += path_step) {
      // Compute viewpoint
      int sample_index = path_indices[i];
      component_mask.IndexToIndices(sample_index, sample_ix, sample_iy);
      R2Point viewpoint_mask_position = component_mask.WorldPosition(sample_ix+0.5, sample_iy+0.5);  // ZX      

      // Compute height
      RNScalar y = room_bbox.YMin() + eye_height;
      y += 2.0*(RNRandomScalar()-0.5) * eye_height_radius;
      if (y > room_bbox.YMax()) continue;

      // Compute camera
      R3Point viewpoint(viewpoint_mask_position[1], y, viewpoint_mask_position[0]);
      if (R3Contains(viewpoint, lookat_position)) continue;
      R3Vector towards = lookat_position - viewpoint;
      towards.Normalize();
      R3Vector right = towards % R3xyz_triad[gravity_dimension];
      right.Normalize();
      R3Vector up = right % towards;
      up.Normalize();
      R3Camera best_camera(viewpoint, towards, up, xfov, yfov, neardist, fardist);

      // Insert camera
      if (print_debug) printf("PATH %s : %d / %d\n", room_node->Name(), i, path_size);
      char name[1024];
      sprintf(name, "%s_%d", room_node->Name(), i);
      Camera *camera = new Camera(best_camera, name);
      cameras.Insert(camera);
      camera_count++;
    }

    // Delete temporary memory
    delete [] path_indices;
  }
        
  // Print statistics
  if (print_verbose) {
    printf("Created room cameras ...\n");
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Cameras = %d\n", camera_count++);
    fflush(stdout);
  }
}

// Assembly:
subq $0x8c8, %rsp            # imm = 0x8C8
leaq 0x8b8(%rsp), %rdi
callq 0x11bad0
leaq 0x8b8(%rsp), %rdi
callq 0x321a0
movl $0x0, 0x8b4(%rsp)
movq 0x2028f5(%rip), %rdi    # 0x22fc38
callq 0x32290
movq %rax, %rdi
callq 0x322b0
movaps %xmm0, %xmm1
movsd 0x18dcc5(%rip), %xmm0   # 0x1bb020
mulsd %xmm1, %xmm0
movsd %xmm0, 0x8a8(%rsp)
movq 0x2028c9(%rip), %rdi    # 0x22fc38
callq 0x32290
movq %rax, %rdi
callq 0x322b0
movaps %xmm0, %xmm1
movsd 0x18dc91(%rip), %xmm0   # 0x1bb018
mulsd %xmm1, %xmm0
movsd %xmm0, 0x8a0(%rsp)
cvtsi2sdl 0x1fc6f0(%rip), %xmm0 # 0x229a8c
cvtsi2sdl 0x1fc6e4(%rip), %xmm1 # 0x229a88
divsd %xmm1, %xmm0
movsd %xmm0, 0x898(%rsp)
movsd 0x898(%rsp), %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0x1fc6c5(%rip), %xmm0   # 0x229a90
callq 0x234f0
movaps %xmm0, %xmm1
movsd 0xb0(%rsp), %xmm0
mulsd %xmm1, %xmm0
callq 0x237e0
movsd %xmm0, 0x890(%rsp)
movl $0x0, 0x88c(%rsp)
movl 0x88c(%rsp), %eax
movl %eax, 0xac(%rsp)
movq 0x20282a(%rip), %rdi    # 0x22fc38
callq 0x321c0
movl %eax, %ecx
movl 0xac(%rsp), %eax
cmpl %ecx, %eax
jge 0x2dd46
movq 0x20280d(%rip), %rdi    # 0x22fc38
movl 0x88c(%rsp), %esi
callq 0x32430
movq %rax, 0x880(%rsp)
movq 0x880(%rsp), %rdi
callq 0x2fe80
cmpl $0x0, %eax
jne 0x2d456
jmp 0x2dd07
movq 0x880(%rsp), %rdi
callq 0x60be0
movq %rax, %rsi
leaq 0x848(%rsp), %rdi
callq 0xc4a10
leaq 0x778(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0xf12b0
jmp 0x2d486
movq 0x880(%rsp), %rdi
leaq 0x778(%rsp), %rsi
callq 0x2ff10
movl %eax, 0xa8(%rsp)
jmp 0x2d4a4
movl 0xa8(%rsp), %eax
cmpl $0x0, %eax
jne 0x2d4f2
movl $0x4, 0x768(%rsp)
jmp 0x2dcdc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x770(%rsp)
movl %eax, 0x76c(%rsp)
jmp 0x2dd37
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x770(%rsp)
movl %eax, 0x76c(%rsp)
jmp 0x2dd2a
leaq 0x698(%rsp), %rdi
leaq 0x778(%rsp), %rsi
callq 0xf2470
jmp 0x2d509
leaq 0x1fcd78(%rip), %rax    # 0x22a288
movsd (%rax), %xmm0
leaq 0x698(%rsp), %rdi
callq 0x100220
jmp 0x2d523
leaq 0x698(%rsp), %rdi
callq 0x35ff0
movsd %xmm0, 0xa0(%rsp)
jmp 0x2d53b
movsd 0xa0(%rsp), %xmm0
movsd %xmm0, 0x690(%rsp)
movsd 0x690(%rsp), %xmm0
movsd 0x18daea(%rip), %xmm1   # 0x1bb048
addsd %xmm1, %xmm0
leaq 0x698(%rsp), %rdi
xorps %xmm1, %xmm1
movsd 0x18db13(%rip), %xmm2   # 0x1bb088
callq 0xf5650
jmp 0x2d57c
leaq 0x698(%rsp), %rdi
xorps %xmm0, %xmm0
movsd 0x18db01(%rip), %xmm1   # 0x1bb090
callq 0xf9520
jmp 0x2d596
movl $0x0, 0x68c(%rsp)
leaq 0x698(%rsp), %rdi
callq 0x30fb0
movl %eax, 0x9c(%rsp)
jmp 0x2d5b7
movl 0x9c(%rsp), %eax
movl %eax, 0x688(%rsp)
cmpl $0x0, 0x688(%rsp)
jge 0x2d5f8
movl $0x4, 0x768(%rsp)
jmp 0x2dccf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x770(%rsp)
movl %eax, 0x76c(%rsp)
jmp 0x2dd1d
movl 0x688(%rsp), %esi
xorl %eax, %eax
movl %eax, %ecx
leaq 0x698(%rsp), %rdi
movq %rcx, %rdx
callq 0x31070
movl %eax, 0x98(%rsp)
jmp 0x2d61c
movl 0x98(%rsp), %eax
movl %eax, 0x684(%rsp)
cmpl $0x0, 0x684(%rsp)
jge 0x2d644
movl $0x4, 0x768(%rsp)
jmp 0x2dccf
leaq 0x698(%rsp), %rdi
callq 0x33520
cltq
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x23040
movq %rax, 0x90(%rsp)
jmp 0x2d678
movq 0x90(%rsp), %rax
movq %rax, 0x678(%rsp)
movl 0x684(%rsp), %esi
movq 0x678(%rsp), %rdx
leaq 0x698(%rsp), %rdi
leaq 0x68c(%rsp), %rcx
callq 0x31070
movl %eax, 0x8c(%rsp)
jmp 0x2d6b5
movl 0x8c(%rsp), %eax
movl %eax, 0x674(%rsp)
cmpl $0x0, 0x674(%rsp)
jg 0x2d700
movq 0x678(%rsp), %rax
movq %rax, 0x80(%rsp)
cmpq $0x0, %rax
je 0x2d6f0
movq 0x80(%rsp), %rdi
callq 0x23d70
movl $0x4, 0x768(%rsp)
jmp 0x2dccf
movq $0x0, 0x668(%rsp)
leaq 0x20b9ed(%rip), %rsi    # 0x239100
leaq 0x650(%rsp), %rdi
callq 0xd9f80
jmp 0x2d722
movl $0x0, 0x64c(%rsp)
movl 0x64c(%rsp), %eax
movl %eax, 0x7c(%rsp)
movq 0x880(%rsp), %rdi
callq 0x33610
movl %eax, %ecx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2d841
movq 0x880(%rsp), %rdi
movl 0x64c(%rsp), %esi
callq 0x33630
movq %rax, 0x70(%rsp)
jmp 0x2d76e
movq 0x70(%rsp), %rax
movq %rax, 0x640(%rsp)
movq 0x640(%rsp), %rsi
leaq 0x628(%rsp), %rdi
callq 0x5fc60
jmp 0x2d792
leaq 0x628(%rsp), %rdi
callq 0x36020
movsd %xmm0, 0x68(%rsp)
jmp 0x2d7a7
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x638(%rsp)
movsd 0x638(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x640(%rsp), %rsi
leaq 0x5f8(%rsp), %rdi
callq 0x60f80
jmp 0x2d7dc
movsd 0x60(%rsp), %xmm0
leaq 0x610(%rsp), %rdi
leaq 0x5f8(%rsp), %rsi
callq 0x36030
jmp 0x2d7f9
leaq 0x650(%rsp), %rdi
leaq 0x610(%rsp), %rsi
callq 0xdac10
jmp 0x2d810
movsd 0x638(%rsp), %xmm0
addsd 0x668(%rsp), %xmm0
movsd %xmm0, 0x668(%rsp)
movl 0x64c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64c(%rsp)
jmp 0x2d72d
movsd 0x668(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2d86d
movsd 0x668(%rsp), %xmm0
leaq 0x650(%rsp), %rdi
callq 0xdad50
jmp 0x2d86b
jmp 0x2d89d
movq 0x880(%rsp), %rsi
leaq 0x5e0(%rsp), %rdi
callq 0x60f80
jmp 0x2d884
leaq 0x650(%rsp), %rdi
leaq 0x5e0(%rsp), %rsi
callq 0xda5d0
jmp 0x2d89b
jmp 0x2d89d
movsd 0x1fc223(%rip), %xmm0   # 0x229ac8
movsd %xmm0, 0x50(%rsp)
leaq 0x698(%rsp), %rdi
callq 0x36070
movsd %xmm0, 0x58(%rsp)
jmp 0x2d8c0
movsd 0x58(%rsp), %xmm1
movsd 0x50(%rsp), %xmm0
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x5d4(%rsp)
cmpl $0x0, 0x5d4(%rsp)
jne 0x2d8f0
movl $0x1, 0x5d4(%rsp)
movl $0x0, 0x5d0(%rsp)
movl 0x5d0(%rsp), %eax
cmpl 0x68c(%rsp), %eax
jge 0x2dca9
movq 0x678(%rsp), %rax
movslq 0x5d0(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, 0x5cc(%rsp)
movl 0x5cc(%rsp), %esi
leaq 0x698(%rsp), %rdi
leaq 0x5dc(%rsp), %rdx
leaq 0x5d8(%rsp), %rcx
callq 0x36090
jmp 0x2d94f
cvtsi2sdl 0x5dc(%rsp), %xmm0
movsd 0x18d6d0(%rip), %xmm2   # 0x1bb030
addsd %xmm2, %xmm0
cvtsi2sdl 0x5d8(%rsp), %xmm1
addsd %xmm2, %xmm1
leaq 0x5b8(%rsp), %rdi
leaq 0x698(%rsp), %rsi
callq 0xfedb0
jmp 0x2d988
leaq 0x848(%rsp), %rdi
callq 0x324f0
movsd %xmm0, 0x48(%rsp)
jmp 0x2d99d
movsd 0x48(%rsp), %xmm0
movsd 0x1fc0ed(%rip), %xmm1   # 0x229a98
addsd %xmm1, %xmm0
movsd %xmm0, 0x5b0(%rsp)
callq 0x11f4d0
movsd %xmm0, 0x40(%rsp)
jmp 0x2d9c5
movsd 0x40(%rsp), %xmm1
movsd 0x18d65d(%rip), %xmm0   # 0x1bb030
subsd %xmm0, %xmm1
movsd 0x18d631(%rip), %xmm0   # 0x1bb010
mulsd %xmm1, %xmm0
movsd 0x1fc0b5(%rip), %xmm2   # 0x229aa0
movsd 0x5b0(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x5b0(%rsp)
movsd 0x5b0(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
leaq 0x848(%rsp), %rdi
callq 0x348f0
movaps %xmm0, %xmm1
movsd 0x38(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2da35
jmp 0x2dc6a
leaq 0x5b8(%rsp), %rdi
movq %rdi, 0x20(%rsp)
movl $0x1, %esi
callq 0x334a0
movq 0x20(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x5b0(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
xorl %esi, %esi
callq 0x334a0
movsd 0x28(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
movsd (%rax), %xmm2
leaq 0x598(%rsp), %rdi
callq 0xd9f40
jmp 0x2da90
leaq 0x598(%rsp), %rdi
leaq 0x650(%rsp), %rsi
callq 0x7cc30
movl %eax, 0x1c(%rsp)
jmp 0x2daab
movl 0x1c(%rsp), %eax
cmpl $0x0, %eax
je 0x2dab9
jmp 0x2dc6a
leaq 0x580(%rsp), %rdi
leaq 0x650(%rsp), %rsi
leaq 0x598(%rsp), %rdx
callq 0xda2a0
jmp 0x2dad8
leaq 0x580(%rsp), %rdi
callq 0xdb800
jmp 0x2dae7
movl 0x1fbf97(%rip), %esi    # 0x229a84
leaq 0x20afb4(%rip), %rdi    # 0x238aa8
callq 0x32530
movq %rax, 0x10(%rsp)
jmp 0x2db00
movq 0x10(%rsp), %rdx
leaq 0x568(%rsp), %rdi
leaq 0x580(%rsp), %rsi
callq 0xdbee0
jmp 0x2db1c
leaq 0x568(%rsp), %rdi
callq 0xdb800
jmp 0x2db2b
leaq 0x550(%rsp), %rdi
leaq 0x568(%rsp), %rsi
leaq 0x580(%rsp), %rdx
callq 0xdbee0
jmp 0x2db4a
leaq 0x550(%rsp), %rdi
callq 0xdb800
jmp 0x2db59
movsd 0x1fbf2f(%rip), %xmm0   # 0x229a90
movsd 0x890(%rsp), %xmm1
movsd 0x8a8(%rsp), %xmm2
movsd 0x8a0(%rsp), %xmm3
leaq 0x4c0(%rsp), %rdi
leaq 0x598(%rsp), %rsi
leaq 0x580(%rsp), %rdx
leaq 0x550(%rsp), %rcx
callq 0x67810
jmp 0x2dba3
cmpl $0x0, 0x20200e(%rip)    # 0x22fbb8
je 0x2dbdc
movq 0x880(%rsp), %rdi
callq 0x32460
movq %rax, %rsi
movl 0x5d0(%rsp), %edx
movl 0x68c(%rsp), %ecx
leaq 0x18dbfe(%rip), %rdi    # 0x1bb7cf
xorl %eax, %eax
callq 0x23090
jmp 0x2dbda
jmp 0x2dbdc
movq 0x880(%rsp), %rdi
callq 0x32460
movq %rax, %rdx
movl 0x5d0(%rsp), %ecx
leaq 0x18db9f(%rip), %rsi    # 0x1bb799
xorl %eax, %eax
leaq 0xc0(%rsp), %rdi
callq 0x23150
movl $0x98, %edi
callq 0x239b0
movq %rax, 0x8(%rsp)
jmp 0x2dc1a
movq 0x8(%rsp), %rdi
leaq 0x4c0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
callq 0x32570
jmp 0x2dc36
movq 0x8(%rsp), %rax
movq %rax, 0xb8(%rsp)
movq 0xb8(%rsp), %rsi
leaq 0x201f2e(%rip), %rdi    # 0x22fb80
callq 0x32370
jmp 0x2dc59
movl 0x8b4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8b4(%rsp)
movl 0x5d4(%rsp), %eax
addl 0x5d0(%rsp), %eax
movl %eax, 0x5d0(%rsp)
jmp 0x2d8fb
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x770(%rsp)
movl %eax, 0x76c(%rsp)
movl $0x98, %esi
callq 0x239d0
jmp 0x2dd1d
movq 0x678(%rsp), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0x2dcc4
movq (%rsp), %rdi
callq 0x23d70
movl $0x0, 0x768(%rsp)
leaq 0x698(%rsp), %rdi
callq 0xf2760
leaq 0x778(%rsp), %rdi
callq 0xf2760
leaq 0x848(%rsp), %rdi
callq 0x33500
movl 0x768(%rsp), %eax
testl %eax, %eax
je 0x2dd05
jmp 0x2dd03
jmp 0x2dd07
jmp 0x2dd07
movl 0x88c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88c(%rsp)
jmp 0x2d3f9
leaq 0x698(%rsp), %rdi
callq 0xf2760
leaq 0x778(%rsp), %rdi
callq 0xf2760
leaq 0x848(%rsp), %rdi
callq 0x33500
jmp 0x2ddb0
cmpl $0x0, 0x201e67(%rip)    # 0x22fbb4
je 0x2dda8
leaq 0x18da49(%rip), %rdi    # 0x1bb79f
movb $0x0, %al
callq 0x23090
leaq 0x8b8(%rsp), %rdi
callq 0x11bb90
leaq 0x18d6c9(%rip), %rdi    # 0x1bb43a
movb $0x1, %al
callq 0x23090
movl 0x8b4(%rsp), %esi
movl %esi, %eax
addl $0x1, %eax
movl %eax, 0x8b4(%rsp)
leaq 0x18d76d(%rip), %rdi    # 0x1bb4ff
movb $0x0, %al
callq 0x23090
movq 0x1fb1f0(%rip), %rax    # 0x228f90
movq (%rax), %rdi
callq 0x23bc0
addq $0x8c8, %rsp            # imm = 0x8C8
retq
movq 0x770(%rsp), %rdi
callq 0x24250
nopl (%rax)