// File: tomfunkhouser[P]gaps/pkgs/R3Utils/R3SurfelViewer.cpp
// Function: gaps::R3SurfelViewer::SplitLeafNodes(gaps::R3SurfelNode*, gaps::R3SurfelConstraint const&, gaps::RNArray<gaps::R3SurfelNode*>*, gaps::RNArray<gaps::R3SurfelNode*>*)
int R3SurfelViewer::
SplitLeafNodes(R3SurfelNode *source_node, const R3SurfelConstraint& constraint, 
  RNArray<R3SurfelNode *> *nodesA, RNArray<R3SurfelNode *> *nodesB)
{
  // Get convenient variables
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return 0;
  if (!source_node) source_node = tree->RootNode();
  if (!source_node) return 0;

  // Split leaf nodes, WHILE UPDATING NODES IN VIEWER'S RESIDENT SET
  int countA = 0;
  int countB = 0;
  RNArray<R3SurfelNode *> stack;
  stack.Insert(source_node);
  while (!stack.IsEmpty()) {
    R3SurfelNode *node = stack.Tail();
    stack.RemoveTail();
    if (node->NParts() == 0) {
      // Check if node is resident in working set
      int resident_index = resident_nodes.NodeIndex(node);
    
      // Split leaf node
      RNArray<R3SurfelNode *> partsA, partsB;
      if (tree->SplitLeafNodes(node, constraint, &partsA, &partsB)) {
        // Update resident set
        if (resident_index >= 0) {
          node->ReleaseBlocks(); // ???
          resident_nodes.RemoveNode(resident_index);
          for (int j = 0; j < partsA.NEntries(); j++) {
            R3SurfelNode *partA = partsA.Kth(j);
            resident_nodes.InsertNode(partA);
          }
          for (int j = 0; j < partsB.NEntries(); j++) {
            R3SurfelNode *partB = partsB.Kth(j);
            resident_nodes.InsertNode(partB);
          }
        }
      }

      // Insert parts into result
      if (nodesA) nodesA->Append(partsA);
      if (nodesB) nodesB->Append(partsB);
      countA += partsA.NEntries();
      countB += partsB.NEntries();
    }
    else {
      for (int i = 0; i < node->NParts(); i++) {
        R3SurfelNode *part = node->Part(i);
        stack.Insert(part);
      }
    } 
  }

  // Invalidate VBO buffers
  InvalidateVBO();

  // Return status
  if (countA == 0) return 0;
  if (countB == 0) return 0;
  return 1;
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x128(%rsp)
movq %rsi, 0x120(%rsp)
movq %rdx, 0x118(%rsp)
movq %rcx, 0x110(%rsp)
movq %r8, 0x108(%rsp)
movq 0x128(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x8(%rax), %rdi
callq 0x2f020
movq %rax, 0x100(%rsp)
cmpq $0x0, 0x100(%rsp)
jne 0x3b8e8
movl $0x0, 0x134(%rsp)
jmp 0x3bde0
cmpq $0x0, 0x120(%rsp)
jne 0x3b908
movq 0x100(%rsp), %rdi
callq 0x3eb30
movq %rax, 0x120(%rsp)
cmpq $0x0, 0x120(%rsp)
jne 0x3b923
movl $0x0, 0x134(%rsp)
jmp 0x3bde0
movl $0x0, 0xfc(%rsp)
movl $0x0, 0xf8(%rsp)
leaq 0xe8(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x3eda0
movq 0x60(%rsp), %rdi
movq 0x120(%rsp), %rsi
callq 0x3edb0
jmp 0x3b95f
jmp 0x3b961
leaq 0xe8(%rsp), %rdi
callq 0x3ede0
movl %eax, 0x5c(%rsp)
jmp 0x3b974
movl 0x5c(%rsp), %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x3b989
jmp 0x3bd5e
leaq 0xe8(%rsp), %rdi
callq 0x3ee00
movq %rax, 0x50(%rsp)
jmp 0x3b99d
movq 0x50(%rsp), %rax
movq %rax, 0xd0(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x3ee10
jmp 0x3b9b9
movq 0xd0(%rsp), %rdi
callq 0x2f260
movl %eax, 0x4c(%rsp)
jmp 0x3b9cc
movl 0x4c(%rsp), %eax
cmpl $0x0, %eax
jne 0x3bcd4
movq 0x68(%rsp), %rdi
addq $0x10, %rdi
movq 0xd0(%rsp), %rsi
callq 0x3ee80
movl %eax, 0x48(%rsp)
jmp 0x3b9f5
movl 0x48(%rsp), %eax
movl %eax, 0xcc(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x3eda0
jmp 0x3ba0f
leaq 0xa8(%rsp), %rdi
callq 0x3eda0
jmp 0x3ba1e
movq 0x100(%rsp), %rdi
movq 0xd0(%rsp), %rsi
movq 0x118(%rsp), %rdx
movq (%rdi), %rax
movq 0x30(%rax), %rax
leaq 0xb8(%rsp), %rcx
leaq 0xa8(%rsp), %r8
callq *%rax
movl %eax, 0x44(%rsp)
jmp 0x3ba55
movl 0x44(%rsp), %eax
cmpl $0x0, %eax
je 0x3bc0f
cmpl $0x0, 0xcc(%rsp)
jl 0x3bc0d
movq 0xd0(%rsp), %rdi
xorl %esi, %esi
callq 0x59bd0
jmp 0x3ba81
movq 0x68(%rsp), %rdi
addq $0x10, %rdi
movl 0xcc(%rsp), %esi
callq 0x5b8b0
jmp 0x3ba98
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x3c(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x2f1c0
movl %eax, 0x40(%rsp)
jmp 0x3bac1
movl 0x3c(%rsp), %eax
movl 0x40(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3bb81
movl 0xa4(%rsp), %esi
leaq 0xb8(%rsp), %rdi
callq 0x2f220
movq %rax, 0x30(%rsp)
jmp 0x3baec
movq 0x68(%rsp), %rdi
movq 0x30(%rsp), %rax
movq %rax, 0x98(%rsp)
addq $0x10, %rdi
movq 0x98(%rsp), %rsi
callq 0x5b7c0
jmp 0x3bb11
jmp 0x3bb13
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x3baa3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x3bdd1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
jmp 0x3bcc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xe0(%rsp)
movl %eax, 0xdc(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x3ee30
jmp 0x3bcc2
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x28(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x2f1c0
movl %eax, 0x2c(%rsp)
jmp 0x3bbaa
movl 0x28(%rsp), %eax
movl 0x2c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3bc0b
movl 0x94(%rsp), %esi
leaq 0xa8(%rsp), %rdi
callq 0x2f220
movq %rax, 0x20(%rsp)
jmp 0x3bbd1
movq 0x68(%rsp), %rdi
movq 0x20(%rsp), %rax
movq %rax, 0x88(%rsp)
addq $0x10, %rdi
movq 0x88(%rsp), %rsi
callq 0x5b7c0
jmp 0x3bbf6
jmp 0x3bbf8
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x3bb8c
jmp 0x3bc0d
jmp 0x3bc0f
cmpq $0x0, 0x110(%rsp)
je 0x3bc33
movq 0x110(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x1a39f0
jmp 0x3bc31
jmp 0x3bc33
cmpq $0x0, 0x108(%rsp)
je 0x3bc57
movq 0x108(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x1a39f0
jmp 0x3bc55
jmp 0x3bc57
leaq 0xb8(%rsp), %rdi
callq 0x2f1c0
movl %eax, 0x1c(%rsp)
jmp 0x3bc6a
movl 0x1c(%rsp), %ecx
movl 0xfc(%rsp), %eax
addl %ecx, %eax
movl %eax, 0xfc(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x2f1c0
movl %eax, 0x18(%rsp)
jmp 0x3bc91
movl 0x18(%rsp), %eax
addl 0xf8(%rsp), %eax
movl %eax, 0xf8(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x3ee30
leaq 0xb8(%rsp), %rdi
callq 0x3ee30
jmp 0x3bd59
leaq 0xb8(%rsp), %rdi
callq 0x3ee30
jmp 0x3bdd1
movl $0x0, 0x84(%rsp)
movl 0x84(%rsp), %eax
movl %eax, 0x10(%rsp)
movq 0xd0(%rsp), %rdi
callq 0x2f260
movl %eax, 0x14(%rsp)
jmp 0x3bcfd
movl 0x10(%rsp), %eax
movl 0x14(%rsp), %ecx
cmpl %ecx, %eax
jge 0x3bd57
movq 0xd0(%rsp), %rdi
movl 0x84(%rsp), %esi
callq 0x3eba0
movq %rax, 0x8(%rsp)
jmp 0x3bd24
movq 0x8(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rsi
leaq 0xe8(%rsp), %rdi
callq 0x3edb0
jmp 0x3bd42
jmp 0x3bd44
movl 0x84(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x84(%rsp)
jmp 0x3bcdf
jmp 0x3bd59
jmp 0x3b961
movq 0x68(%rsp), %rdi
movq (%rdi), %rax
movq 0x378(%rax), %rax
callq *%rax
jmp 0x3bd71
cmpl $0x0, 0xfc(%rsp)
jne 0x3bd90
movl $0x0, 0x134(%rsp)
movl $0x1, 0x74(%rsp)
jmp 0x3bdc2
cmpl $0x0, 0xf8(%rsp)
jne 0x3bdaf
movl $0x0, 0x134(%rsp)
movl $0x1, 0x74(%rsp)
jmp 0x3bdc2
movl $0x1, 0x134(%rsp)
movl $0x1, 0x74(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x3ee30
jmp 0x3bde0
leaq 0xe8(%rsp), %rdi
callq 0x3ee30
jmp 0x3bdef
movl 0x134(%rsp), %eax
addq $0x138, %rsp            # imm = 0x138
retq
movq 0xe0(%rsp), %rdi
callq 0x292e0
nopl (%rax)