// File: tomfunkhouser[P]gaps/apps/scn2cam/scn2cam.cpp
// Function: ComputeViewpointMask(gaps::R3SceneNode*, gaps::R2Grid&)
static int
ComputeViewpointMask(R3SceneNode *room_node, R2Grid& mask) 
{
  // Get/check room, wall, floor, and ceiling nodes 
  if (!room_node) return 0;
  if (!room_node->Name()) return 0;
  if (strncmp(room_node->Name(), "Room#", 5)) return 0;
  if (room_node->NChildren() < 3) return 0;
  R3SceneNode *floor_node = room_node->Child(0);
  if (!floor_node->Name()) return 0;
  if (strncmp(floor_node->Name(), "Floor#", 6)) return 0;
  R3SceneNode *ceiling_node = room_node->Child(1);
  if (!ceiling_node->Name()) return 0;
  if (strncmp(ceiling_node->Name(), "Ceiling#", 8)) return 0;
  R3SceneNode *wall_node = room_node->Child(2);
  if (!wall_node->Name()) return 0;
  if (strncmp(wall_node->Name(), "Wall#", 5)) return 0;

  // Get bounding boxes in world coordinates
  R3Box room_bbox = room_node->BBox();
  R3Box floor_bbox = floor_node->BBox();
  R3Box ceiling_bbox = ceiling_node->BBox();

  // Get/check grid extent and resolution in world coordinates
  RNScalar grid_sampling_factor = 2;
  RNScalar grid_sample_spacing = min_distance_from_obstacle / grid_sampling_factor;
  if (grid_sample_spacing == 0) grid_sample_spacing = 0.05;
  if (grid_sample_spacing > 0.1) grid_sample_spacing = 0.1;
  R2Box grid_bbox(room_bbox.ZMin(), room_bbox.XMin(), room_bbox.ZMax(), room_bbox.XMax());
  int res1 = (int) (grid_bbox.XLength() / grid_sample_spacing);
  int res2 = (int) (grid_bbox.YLength() / grid_sample_spacing);
  if ((res1 < 3) || (res2 < 3)) return 0;

  // Compute floor mask
  R2Grid floor_mask = R2Grid(res1, res2, grid_bbox);
  RasterizeIntoZXGrid(floor_mask, floor_node, floor_bbox);
  floor_mask.Threshold(0.5, 0, 1);

  // Initialize object mask
  R2Grid object_mask = R2Grid(res1, res2, grid_bbox);
  R3Box object_bbox = room_bbox;
  object_bbox[RN_LO][gravity_dimension] = floor_bbox[RN_HI][gravity_dimension] + RN_EPSILON;
  object_bbox[RN_HI][gravity_dimension] = ceiling_bbox[RN_LO][gravity_dimension] - RN_EPSILON;

  // Rasterize objects associated with this room into object mask
  for (int i = 0; i < room_node->NChildren(); i++) {
    R3SceneNode *node = room_node->Child(i);
    if ((node == floor_node) || (node == ceiling_node)) continue;
    RasterizeIntoZXGrid(object_mask, node, object_bbox);
  }

  // Rasterize objects associated with no room into object mask
  for (int i = 0; i < room_node->Parent()->NChildren(); i++) {
    R3SceneNode *node = room_node->Parent()->Child(i);
    if (node->NChildren() > 0) continue;
    RasterizeIntoZXGrid(object_mask, node, object_bbox);
  }
  
  // Reverse object mask to by 1 in areas not occupied by objects
  object_mask.Threshold(0.5, 1, 0);

  // Erode object mask to cover viewpoints at least min_distance_from_obstacle
  if (min_distance_from_obstacle > 0) {
    object_mask.Erode(min_distance_from_obstacle / grid_sample_spacing);
  }

  // Combine the two masks
  mask = floor_mask;
  mask.Mask(object_mask);
  
#if 0
  // Debugging
  char buffer[4096];
  sprintf(buffer, "%s_floor_mask.jpg", room_node->Name());
  floor_mask.WriteFile(buffer);
  sprintf(buffer, "%s_object_mask.jpg", room_node->Name());
  object_mask.WriteFile(buffer);
  sprintf(buffer, "%s_mask.jpg", room_node->Name());
  mask.WriteFile(buffer);
#endif
  
  // Return success
  return 1;
}

// Assembly:
subq $0x398, %rsp            # imm = 0x398
movq %rdi, 0x388(%rsp)
movq %rsi, 0x380(%rsp)
cmpq $0x0, 0x388(%rsp)
jne 0x2ff42
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
jne 0x2ff65
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x18b806(%rip), %rsi    # 0x1bb782
movl $0x5, %edx
callq 0x23430
cmpl $0x0, %eax
je 0x2ff9b
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
callq 0x33610
cmpl $0x3, %eax
jge 0x2ffbd
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
xorl %esi, %esi
callq 0x33630
movq %rax, 0x378(%rsp)
movq 0x378(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
jne 0x2fff7
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x378(%rsp), %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x18b7ab(%rip), %rsi    # 0x1bb7b9
movl $0x6, %edx
callq 0x23430
cmpl $0x0, %eax
je 0x3002d
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
movl $0x1, %esi
callq 0x33630
movq %rax, 0x370(%rsp)
movq 0x370(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
jne 0x3006a
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x370(%rsp), %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x18b73f(%rip), %rsi    # 0x1bb7c0
movl $0x8, %edx
callq 0x23430
cmpl $0x0, %eax
je 0x300a0
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
movl $0x2, %esi
callq 0x33630
movq %rax, 0x368(%rsp)
movq 0x368(%rsp), %rdi
callq 0x32460
cmpq $0x0, %rax
jne 0x300dd
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x368(%rsp), %rdi
callq 0x32460
movq %rax, %rdi
leaq 0x18b6d5(%rip), %rsi    # 0x1bb7c9
movl $0x5, %edx
callq 0x23430
cmpl $0x0, %eax
je 0x30113
movl $0x0, 0x394(%rsp)
jmp 0x307a1
movq 0x388(%rsp), %rdi
callq 0x60be0
movq %rax, %rsi
leaq 0x330(%rsp), %rdi
callq 0xc4a10
movq 0x378(%rsp), %rdi
callq 0x60be0
movq %rax, 0x68(%rsp)
jmp 0x30144
movq 0x68(%rsp), %rsi
leaq 0x2f8(%rsp), %rdi
callq 0xc4a10
jmp 0x30158
movq 0x370(%rsp), %rdi
callq 0x60be0
movq %rax, 0x60(%rsp)
jmp 0x3016c
movq 0x60(%rsp), %rsi
leaq 0x2b0(%rsp), %rdi
callq 0xc4a10
jmp 0x30180
movsd 0x18ae88(%rip), %xmm0   # 0x1bb010
movsd %xmm0, 0x2a8(%rsp)
movsd 0x1ffa4f(%rip), %xmm0   # 0x22fbe8
divsd 0x2a8(%rsp), %xmm0
movsd %xmm0, 0x2a0(%rsp)
movsd 0x2a0(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x30204
jp 0x30204
movsd 0x18aed9(%rip), %xmm0   # 0x1bb0a0
movsd %xmm0, 0x2a0(%rsp)
jmp 0x30204
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x30792
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x30785
movsd 0x2a0(%rsp), %xmm0
movsd 0x18ae3b(%rip), %xmm1   # 0x1bb050
ucomisd %xmm1, %xmm0
jbe 0x3022c
movsd 0x18ae2d(%rip), %xmm0   # 0x1bb050
movsd %xmm0, 0x2a0(%rsp)
leaq 0x330(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x34940
movq 0x40(%rsp), %rdi
movsd %xmm0, 0x58(%rsp)
callq 0x348d0
movq 0x40(%rsp), %rdi
movsd %xmm0, 0x48(%rsp)
callq 0x34920
movq 0x40(%rsp), %rdi
movsd %xmm0, 0x50(%rsp)
callq 0x34880
movsd 0x48(%rsp), %xmm1
movsd 0x50(%rsp), %xmm2
movaps %xmm0, %xmm3
movsd 0x58(%rsp), %xmm0
leaq 0x278(%rsp), %rdi
callq 0x1089d0
jmp 0x30292
leaq 0x278(%rsp), %rdi
callq 0x35b30
movsd %xmm0, 0x38(%rsp)
jmp 0x302a7
movsd 0x38(%rsp), %xmm0
movsd 0x2a0(%rsp), %xmm1
divsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x274(%rsp)
leaq 0x278(%rsp), %rdi
callq 0x35b50
movsd %xmm0, 0x30(%rsp)
jmp 0x302da
movsd 0x30(%rsp), %xmm0
divsd 0x2a0(%rsp), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x270(%rsp)
cmpl $0x3, 0x274(%rsp)
jl 0x30308
cmpl $0x3, 0x270(%rsp)
jge 0x30355
movl $0x0, 0x394(%rsp)
movl $0x1, 0x26c(%rsp)
jmp 0x30735
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x30778
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x3076b
movl 0x274(%rsp), %esi
movl 0x270(%rsp), %edx
leaq 0x198(%rsp), %rdi
leaq 0x278(%rsp), %rcx
callq 0xf1450
jmp 0x3037a
movq 0x378(%rsp), %rsi
leaq 0x198(%rsp), %rdi
leaq 0x2f8(%rsp), %rdx
callq 0x307c0
jmp 0x30399
leaq 0x198(%rsp), %rdi
movsd 0x18ac87(%rip), %xmm0   # 0x1bb030
xorps %xmm1, %xmm1
movsd 0x18acd4(%rip), %xmm2   # 0x1bb088
callq 0xf5650
jmp 0x303bb
movl 0x274(%rsp), %esi
movl 0x270(%rsp), %edx
leaq 0xc8(%rsp), %rdi
leaq 0x278(%rsp), %rcx
callq 0xf1450
jmp 0x303e0
leaq 0x90(%rsp), %rdi
leaq 0x330(%rsp), %rsi
callq 0xc4a10
jmp 0x303f7
leaq 0x2f8(%rsp), %rdi
movl $0x1, %esi
callq 0x34960
movq %rax, %rdi
movl 0x1f9672(%rip), %esi    # 0x229a84
callq 0x32510
movsd (%rax), %xmm0
leaq 0x1f9e66(%rip), %rax    # 0x22a288
addsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
leaq 0x90(%rsp), %rdi
xorl %esi, %esi
callq 0x34960
movq %rax, %rdi
movl 0x1f9640(%rip), %esi    # 0x229a84
callq 0x32510
movsd 0x20(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x2b0(%rsp), %rdi
xorl %esi, %esi
callq 0x34960
movq %rax, %rdi
movl 0x1f9619(%rip), %esi    # 0x229a84
callq 0x32510
movsd (%rax), %xmm0
leaq 0x1f9e0d(%rip), %rax    # 0x22a288
subsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
leaq 0x90(%rsp), %rdi
movl $0x1, %esi
callq 0x34960
movq %rax, %rdi
movl 0x1f95e4(%rip), %esi    # 0x229a84
callq 0x32510
movsd 0x28(%rsp), %xmm0
movsd %xmm0, (%rax)
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x388(%rsp), %rdi
callq 0x33610
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x305bd
movq 0x388(%rsp), %rdi
movl 0x8c(%rsp), %esi
callq 0x33630
movq %rax, 0x10(%rsp)
jmp 0x304fb
movq 0x10(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rax
cmpq 0x378(%rsp), %rax
je 0x3052c
movq 0x80(%rsp), %rax
cmpq 0x370(%rsp), %rax
jne 0x30586
jmp 0x305a7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x30726
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
jmp 0x30719
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2f0(%rsp)
movl %eax, 0x2ec(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x33500
jmp 0x30719
movq 0x80(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
leaq 0x90(%rsp), %rdx
callq 0x307c0
jmp 0x305a5
jmp 0x305a7
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x304ba
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x388(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
callq 0x33610
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x30653
movq 0x388(%rsp), %rdi
callq 0x324e0
movq %rax, %rdi
movl 0x7c(%rsp), %esi
callq 0x33630
movq %rax, (%rsp)
jmp 0x3060b
movq (%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rdi
callq 0x33610
cmpl $0x0, %eax
jle 0x30625
jmp 0x30643
movq 0x70(%rsp), %rsi
leaq 0xc8(%rsp), %rdi
leaq 0x90(%rsp), %rdx
callq 0x307c0
jmp 0x30641
jmp 0x30643
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x305c5
leaq 0xc8(%rsp), %rdi
movsd 0x18a9cd(%rip), %xmm0   # 0x1bb030
movsd 0x18aa1d(%rip), %xmm1   # 0x1bb088
xorps %xmm2, %xmm2
callq 0xf5650
jmp 0x30675
movsd 0x1ff56b(%rip), %xmm0   # 0x22fbe8
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x306ac
movsd 0x1ff55a(%rip), %xmm0   # 0x22fbe8
movsd 0x2a0(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0xc8(%rsp), %rdi
callq 0xf5760
jmp 0x306aa
jmp 0x306ac
movq 0x380(%rsp), %rdi
leaq 0x198(%rsp), %rsi
callq 0xf22f0
jmp 0x306c3
movq 0x380(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0xf9c30
jmp 0x306da
movl $0x1, 0x394(%rsp)
movl $0x1, 0x26c(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x33500
leaq 0xc8(%rsp), %rdi
callq 0xf2760
leaq 0x198(%rsp), %rdi
callq 0xf2760
jmp 0x30735
leaq 0xc8(%rsp), %rdi
callq 0xf2760
leaq 0x198(%rsp), %rdi
callq 0xf2760
jmp 0x3076b
leaq 0x278(%rsp), %rdi
callq 0x35b70
leaq 0x2b0(%rsp), %rdi
callq 0x33500
leaq 0x2f8(%rsp), %rdi
callq 0x33500
leaq 0x330(%rsp), %rdi
callq 0x33500
jmp 0x307a1
leaq 0x278(%rsp), %rdi
callq 0x35b70
leaq 0x2b0(%rsp), %rdi
callq 0x33500
leaq 0x2f8(%rsp), %rdi
callq 0x33500
leaq 0x330(%rsp), %rdi
callq 0x33500
jmp 0x307b0
movl 0x394(%rsp), %eax
addq $0x398, %rsp            # imm = 0x398
retq
movq 0x2f0(%rsp), %rdi
callq 0x24250
nopl (%rax)