// File: /workspace/github_cpp_makefile_star2_O1/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2b8, %rsp            # imm = 0x2B8
xorl %ebp, %ebp
testq %rdi, %rdi
je 0x2bdb8
movq %rdi, %r14
movq 0x1a0(%rdi), %rdi
testq %rdi, %rdi
je 0x2bdb8
movq %rsi, %rbx
leaq 0xc8975(%rip), %rsi     # 0xf46ef
movl $0x5, %edx
callq 0x223b0
testl %eax, %eax
jne 0x2bdb8
cmpl $0x3, 0x2c(%r14)
jl 0x2bdb8
movq 0x20(%r14), %r13
movq (%r13), %r15
movq 0x1a0(%r15), %rdi
testq %rdi, %rdi
je 0x2bdb8
leaq 0xc8962(%rip), %rsi     # 0xf470c
movl $0x6, %edx
callq 0x223b0
testl %eax, %eax
je 0x2bdcc
movl %ebp, %eax
addq $0x2b8, %rsp            # imm = 0x2B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%r13), %r12
movq 0x1a0(%r12), %rdi
testq %rdi, %rdi
je 0x2bdb8
leaq 0xc892f(%rip), %rsi     # 0xf4713
movl $0x8, %edx
callq 0x223b0
testl %eax, %eax
jne 0x2bdb8
movq 0x10(%r13), %rax
movq 0x1a0(%rax), %rdi
testq %rdi, %rdi
je 0x2bdb8
leaq 0xc8913(%rip), %rsi     # 0xf471c
movl $0x5, %edx
callq 0x223b0
testl %eax, %eax
jne 0x2bdb8
movq %r14, %rdi
callq 0x4233c
leaq 0x38(%rsp), %rdi
movq %rax, %rsi
callq 0x75880
movq %r15, %rdi
callq 0x4233c
leaq 0xa8(%rsp), %rdi
movq %rax, %rsi
callq 0x75880
movq %r12, %rdi
callq 0x4233c
leaq 0xe0(%rsp), %rdi
movq %rax, %rsi
callq 0x75880
movsd 0x137a54(%rip), %xmm0   # 0x1638b8
movaps %xmm0, (%rsp)
movsd 0x40(%rsp), %xmm1
movsd 0x50(%rsp), %xmm0
movsd 0x68(%rsp), %xmm2
movsd 0x58(%rsp), %xmm3
leaq 0x10(%rsp), %rdi
callq 0x95bf8
movapd (%rsp), %xmm2
mulsd 0xc8171(%rip), %xmm2    # 0xf4008
xorpd %xmm0, %xmm0
cmpeqsd %xmm2, %xmm0
movsd 0xc8208(%rip), %xmm1    # 0xf40b0
andpd %xmm0, %xmm1
andnpd %xmm2, %xmm0
orpd %xmm1, %xmm0
movsd 0xc8184(%rip), %xmm2    # 0xf4040
minsd %xmm0, %xmm2
movupd 0x18(%rsp), %xmm0
movupd 0x28(%rsp), %xmm1
subpd %xmm0, %xmm1
movapd %xmm2, (%rsp)
movapd %xmm2, %xmm0
unpcklpd %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0]
divpd %xmm0, %xmm1
cvttpd2dq %xmm1, %xmm0
pshufd $0x50, %xmm0, %xmm1     # xmm1 = xmm0[0,0,1,1]
pcmpgtd 0xc81fe(%rip), %xmm1    # 0xf40f0
movmskpd %xmm1, %eax
xorl %ebp, %ebp
xorl $0x3, %eax
jne 0x2c0d4
movd %xmm0, %ebp
pshufd $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movd %xmm0, %r13d
leaq 0x1e8(%rsp), %rdi
leaq 0x10(%rsp), %rcx
movl %ebp, %esi
movl %r13d, %edx
callq 0x894c8
leaq 0x1e8(%rsp), %rdi
leaq 0xa8(%rsp), %rdx
movq %r15, %rsi
callq 0x2c188
leaq 0x1e8(%rsp), %rdi
movq 0xc80ba(%rip), %xmm0    # 0xf4008
movsd 0xc8142(%rip), %xmm2    # 0xf4098
xorpd %xmm1, %xmm1
callq 0x8ba0c
leaq 0x118(%rsp), %rdi
leaq 0x10(%rsp), %rcx
movl %ebp, %esi
movl %r13d, %edx
callq 0x894c8
leaq 0x70(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x75880
movslq 0x1329f4(%rip), %rax    # 0x15e980
leaq 0x133135(%rip), %rcx    # 0x15f0c8
movsd (%rcx), %xmm0
movsd 0xc8(%rsp,%rax,8), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x78(%rsp,%rax,8)
movsd 0xe8(%rsp,%rax,8), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, 0x90(%rsp,%rax,8)
cmpl $0x0, 0x2c(%r14)
jle 0x2c003
xorl %r13d, %r13d
leaq 0x70(%rsp), %rbp
movq 0x20(%r14), %rax
movq (%rax,%r13,8), %rsi
cmpq %r15, %rsi
sete %al
cmpq %r12, %rsi
sete %cl
orb %al, %cl
jne 0x2bff7
leaq 0x118(%rsp), %rdi
movq %rbp, %rdx
callq 0x2c188
incq %r13
movslq 0x2c(%r14), %rax
cmpq %rax, %r13
jl 0x2bfcf
movq 0x10(%r14), %rax
cmpl $0x0, 0x2c(%rax)
jle 0x2c046
xorl %r13d, %r13d
leaq 0x118(%rsp), %r15
leaq 0x70(%rsp), %r12
movq 0x20(%rax), %rax
movq (%rax,%r13,8), %rsi
cmpl $0x0, 0x2c(%rsi)
jg 0x2c036
movq %r15, %rdi
movq %r12, %rdx
callq 0x2c188
incq %r13
movq 0x10(%r14), %rax
movslq 0x2c(%rax), %rcx
cmpq %rcx, %r13
jl 0x2c01d
leaq 0x118(%rsp), %rdi
movsd 0xc7fb2(%rip), %xmm0    # 0xf4008
movsd 0xc803a(%rip), %xmm1    # 0xf4098
xorpd %xmm2, %xmm2
callq 0x8ba0c
movsd 0x137849(%rip), %xmm0   # 0x1638b8
ucomisd 0xc8031(%rip), %xmm0    # 0xf40a8
jbe 0x2c08b
divsd (%rsp), %xmm0
leaq 0x118(%rsp), %rdi
callq 0x8ba68
leaq 0x1e8(%rsp), %rsi
movq %rbx, %rdi
callq 0x89d44
leaq 0x118(%rsp), %rsi
movq %rbx, %rdi
callq 0x8e050
leaq 0x70(%rsp), %rdi
callq 0x766d8
leaq 0x118(%rsp), %rdi
callq 0x89ff8
leaq 0x1e8(%rsp), %rdi
callq 0x89ff8
movl $0x1, %ebp
leaq 0x10(%rsp), %rdi
callq 0x96478
leaq 0xe0(%rsp), %rdi
callq 0x766d8
leaq 0xa8(%rsp), %rdi
callq 0x766d8
leaq 0x38(%rsp), %rdi
callq 0x766d8
jmp 0x2bdb8
movq %rax, %rbx
jmp 0x2c138
jmp 0x2c113
movq %rax, %rbx
jmp 0x2c152
movq %rax, %rbx
jmp 0x2c145
movq %rax, %rbx
jmp 0x2c15c
jmp 0x2c12b
movq %rax, %rbx
jmp 0x2c169
movq %rax, %rbx
jmp 0x2c176
jmp 0x2c12b
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x766d8
leaq 0x118(%rsp), %rdi
callq 0x89ff8
leaq 0x1e8(%rsp), %rdi
callq 0x89ff8
leaq 0x10(%rsp), %rdi
callq 0x96478
leaq 0xe0(%rsp), %rdi
callq 0x766d8
leaq 0xa8(%rsp), %rdi
callq 0x766d8
leaq 0x38(%rsp), %rdi
callq 0x766d8
movq %rbx, %rdi
callq 0x230a0