// File: tomfunkhouser[P]gaps/apps/scn2scn/scn2scn.cpp
// Function: RemoveNodes(gaps::R3Scene*, gaps::R3SceneNode*, gaps::R3SceneNode*, gaps::R3Grid*, gaps::R3Box const&)
static void
RemoveNodes(R3Scene *scene, R3SceneNode *node,
  R3SceneNode *select_subtree_node, R3Grid *select_grid, const R3Box& select_bbox)
{
  // Copy array of children -- because will be edited as iterate
  RNArray<R3SceneNode *> children;
  for (int i = 0; i < node->NChildren(); i++) {
    R3SceneNode *child = node->Child(i);
    children.Insert(child);
  }

  // Visit children recursively 
  for (int i = 0; i < children.NEntries(); i++) {
    R3SceneNode *child = children.Kth(i);
    RemoveNodes(scene, child, select_subtree_node, select_grid, select_bbox);
  }

  // Check if node must remain
  if (node == scene->Root()) return;
  if (node->NChildren() > 0) return;

  // Innocent until proven guilty
  RNBoolean remove = FALSE;

  // Check if should remove based on emptiness
  if ((node->NChildren() == 0) && (node->NReferences() == 0) && (node->NElements() == 0)) {
    remove = TRUE;
  }

  // Check if should remove based on bbox selection
  if (!select_bbox.IsEmpty()) {
    if (!R3Intersects(node->WorldBBox(), select_bbox)) {
      remove = TRUE;
    }
  }

  // Check if should remove based on subtree selection
  if (select_subtree_node) {
    if (node != select_subtree_node) {
      if (!node->IsAncestor(select_subtree_node)) { 
        if (!node->IsDecendent(select_subtree_node)) {
          remove = TRUE;
        }
      }
    }
  }

  // Check if should remove based on grid selection
  if (select_grid) {
    RNArea min_overlap = 0.5;
    RNScalar overlap = Overlap(node, select_grid);
    if (overlap < min_overlap) remove = TRUE;
    // R3Point centroid = node->WorldBBox().Centroid();
    // RNScalar grid_value = select_grid->WorldValue(centroid);
    // if (RNIsNegativeOrZero(grid_value)) remove = TRUE;
  }
  
  // Delete node 
  if (remove) delete node;
}

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x120(%rsp)
movq %rsi, 0x118(%rsp)
movq %rdx, 0x110(%rsp)
movq %rcx, 0x108(%rsp)
movq %r8, 0x100(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2ab90
movl $0x0, 0xec(%rsp)
movl 0xec(%rsp), %eax
movl %eax, 0x68(%rsp)
movq 0x118(%rsp), %rdi
callq 0x2aba0
movl %eax, 0x6c(%rsp)
jmp 0x299e5
movl 0x68(%rsp), %eax
movl 0x6c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x29a5e
movq 0x118(%rsp), %rdi
movl 0xec(%rsp), %esi
callq 0x2abc0
movq %rax, 0x60(%rsp)
jmp 0x29a0c
movq 0x60(%rsp), %rax
movq %rax, 0xd0(%rsp)
movq 0xd0(%rsp), %rsi
leaq 0xf0(%rsp), %rdi
callq 0x2abf0
jmp 0x29a30
jmp 0x29a32
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x299c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x29db2
movl $0x0, 0xcc(%rsp)
movl 0xcc(%rsp), %eax
movl %eax, 0x5c(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2aa50
movl %eax, %ecx
movl 0x5c(%rsp), %eax
cmpl %ecx, %eax
jge 0x29afa
movl 0xcc(%rsp), %esi
leaq 0xf0(%rsp), %rdi
callq 0x2ac20
movq %rax, 0x50(%rsp)
jmp 0x29aa6
movq 0x50(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0x120(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq 0x110(%rsp), %rdx
movq 0x108(%rsp), %rcx
movq 0x100(%rsp), %r8
callq 0x29980
jmp 0x29ae2
jmp 0x29ae4
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x29a69
movq 0x118(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0x120(%rsp), %rdi
callq 0x2a470
movq %rax, 0x48(%rsp)
jmp 0x29b1b
movq 0x40(%rsp), %rax
movq 0x48(%rsp), %rcx
cmpq %rcx, %rax
jne 0x29b3a
movl $0x1, 0xbc(%rsp)
jmp 0x29d9d
movq 0x118(%rsp), %rdi
callq 0x2aba0
movl %eax, 0x3c(%rsp)
jmp 0x29b4d
movl 0x3c(%rsp), %eax
cmpl $0x0, %eax
jle 0x29b66
movl $0x1, 0xbc(%rsp)
jmp 0x29d9d
movl $0x0, 0xb8(%rsp)
movq 0x118(%rsp), %rdi
callq 0x2aba0
movl %eax, 0x38(%rsp)
jmp 0x29b84
movl 0x38(%rsp), %eax
cmpl $0x0, %eax
jne 0x29bd0
movq 0x118(%rsp), %rdi
callq 0x2ac40
movl %eax, 0x34(%rsp)
jmp 0x29ba0
movl 0x34(%rsp), %eax
cmpl $0x0, %eax
jne 0x29bd0
movq 0x118(%rsp), %rdi
callq 0x2ac60
movl %eax, 0x30(%rsp)
jmp 0x29bbc
movl 0x30(%rsp), %eax
cmpl $0x0, %eax
jne 0x29bd0
movl $0x1, 0xb8(%rsp)
movq 0x100(%rsp), %rdi
callq 0x2a3b0
movl %eax, 0x2c(%rsp)
jmp 0x29be3
movl 0x2c(%rsp), %eax
cmpl $0x0, %eax
jne 0x29c82
movq 0x118(%rsp), %rsi
leaq 0x80(%rsp), %rdi
callq 0x55dc0
jmp 0x29c07
movq 0x100(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
leaq 0x80(%rsp), %rdi
callq 0x70a10
movl %eax, 0x28(%rsp)
jmp 0x29c26
movl 0x28(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
movb %al, 0x27(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x2a3a0
movb 0x27(%rsp), %al
testb $0x1, %al
jne 0x29c4d
jmp 0x29c80
movl $0x1, 0xb8(%rsp)
jmp 0x29c80
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x2a3a0
jmp 0x29db2
jmp 0x29c82
cmpq $0x0, 0x110(%rsp)
je 0x29cf8
movq 0x118(%rsp), %rax
cmpq 0x110(%rsp), %rax
je 0x29cf6
movq 0x118(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0x2ac80
movl %eax, 0x20(%rsp)
jmp 0x29cba
movl 0x20(%rsp), %eax
cmpl $0x0, %eax
jne 0x29cf4
movq 0x118(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0x56140
movl %eax, 0x1c(%rsp)
jmp 0x29cde
movl 0x1c(%rsp), %eax
cmpl $0x0, %eax
jne 0x29cf2
movl $0x1, 0xb8(%rsp)
jmp 0x29cf4
jmp 0x29cf6
jmp 0x29cf8
cmpq $0x0, 0x108(%rsp)
je 0x29d5a
movabsq $0x3fe0000000000000, %rax # imm = 0x3FE0000000000000
movq %rax, 0x78(%rsp)
movq 0x118(%rsp), %rdi
movq 0x108(%rsp), %rsi
callq 0x29dd0
movsd %xmm0, 0x10(%rsp)
jmp 0x29d2f
movsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm1
movsd 0x78(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x29d58
movl $0x1, 0xb8(%rsp)
jmp 0x29d5a
cmpl $0x0, 0xb8(%rsp)
je 0x29d92
movq 0x118(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x29d90
movq 0x8(%rsp), %rdi
callq 0x54a80
movq 0x8(%rsp), %rdi
movl $0x1b0, %esi            # imm = 0x1B0
callq 0x239b0
jmp 0x29d92
movl $0x0, 0xbc(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x2acb0
addq $0x128, %rsp            # imm = 0x128
retq
leaq 0xf0(%rsp), %rdi
callq 0x2acb0
movq 0xe0(%rsp), %rdi
callq 0x24210
nopl (%rax)