// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelTree.cpp
// Function: gaps::R3SurfelTree::SplitLeafNodes(gaps::R3SurfelNode*, gaps::R3SurfelConstraint const&, gaps::RNArray<gaps::R3SurfelNode*>*, gaps::RNArray<gaps::R3SurfelNode*>*)
int R3SurfelTree::
SplitLeafNodes(R3SurfelNode *node, const R3SurfelConstraint& constraint, 
  RNArray<R3SurfelNode *> *nodesA, RNArray<R3SurfelNode *> *nodesB)
{
  // Initialize return value (whether any node was split)
  int status = 0;

  // Check if node is a leaf
  if (node->NParts() == 0) {
    // Check constraint
    int check = constraint.Check(node->BBox());
    if (check == R3_SURFEL_CONSTRAINT_PASS) {
      if (nodesA) nodesA->Insert(node);
    }
    else if (check == R3_SURFEL_CONSTRAINT_FAIL) {
      if (nodesB) nodesB->Insert(node);
    }
    else {
      // Split blocks in leaf node
      RNArray<R3SurfelBlock *> blocksA, blocksB;
      if (SplitBlocks(node, constraint, &blocksA, &blocksB)) {
        // Create new nodes
        R3SurfelNode *nodeA = new R3SurfelNode();
        R3SurfelNode *nodeB = new R3SurfelNode();

        // Move blocks from node to nodeA
        for (int i = 0; i < blocksA.NEntries(); i++) {
          R3SurfelBlock *block = blocksA.Kth(i);
          node->RemoveBlock(block);
          nodeA->InsertBlock(block);
        }
    
        // Move blocks from node to nodeB
        for (int i = 0; i < blocksB.NEntries(); i++) {
          R3SurfelBlock *block = blocksB.Kth(i);
          node->RemoveBlock(block);
          nodeB->InsertBlock(block);
        }
    
        // Insert new nodes into tree
        InsertNode(nodeA, node);
        InsertNode(nodeB, node);

        // Update return values
        if (nodesA) nodesA->Insert(nodeA);
        if (nodesB) nodesB->Insert(nodeB);
        status = 1;
      }
      else {
        // Blocks were all inside or outside constraint, update return values
        if (nodesA && !blocksA.IsEmpty()) nodesA->Insert(node);
        if (nodesB && !blocksB.IsEmpty()) nodesB->Insert(node);
      }
    }
  }
  else {
    // Check constraint
    if (!nodesA || !nodesB) {
      int check = constraint.Check(node->BBox());
      if ((check == R3_SURFEL_CONSTRAINT_PASS) && !nodesA) return 0;
      if ((check == R3_SURFEL_CONSTRAINT_FAIL) && !nodesB) return 0;
    }

    // Consider each child node
    for (int i = 0; i < node->NParts(); i++) {
      R3SurfelNode *part = node->Part(i);
      status |= SplitLeafNodes(part, constraint, nodesA, nodesB);
    }
  }

  // Return whether any nodes were split
  return status;
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
movq %rdi, 0xf8(%rsp)
movq %rsi, 0xf0(%rsp)
movq %rdx, 0xe8(%rsp)
movq %rcx, 0xe0(%rsp)
movq %r8, 0xd8(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x58(%rsp)
movl $0x0, 0xd4(%rsp)
movq 0xf0(%rsp), %rdi
callq 0x31660
cmpl $0x0, %eax
jne 0x6537b
movq 0xe8(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0xf0(%rsp), %rdi
callq 0x5ee30
movq 0x50(%rsp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
callq *0x30(%rax)
movl %eax, 0xd0(%rsp)
cmpl $0x2, 0xd0(%rsp)
jne 0x64f7b
cmpq $0x0, 0xe0(%rsp)
je 0x64f76
movq 0xe0(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1bee0
jmp 0x65376
cmpl $0x0, 0xd0(%rsp)
jne 0x64faa
cmpq $0x0, 0xd8(%rsp)
je 0x64fa5
movq 0xd8(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1bee0
jmp 0x65374
leaq 0xc0(%rsp), %rdi
callq 0x436b0
leaq 0xb0(%rsp), %rdi
callq 0x436b0
jmp 0x64fc6
movq 0x58(%rsp), %rdi
movq 0xf0(%rsp), %rsi
movq 0xe8(%rsp), %rdx
movq (%rdi), %rax
movq 0x58(%rax), %rax
leaq 0xc0(%rsp), %rcx
leaq 0xb0(%rsp), %r8
callq *%rax
movl %eax, 0x4c(%rsp)
jmp 0x64ffa
movl 0x4c(%rsp), %eax
cmpl $0x0, %eax
je 0x652b7
movl $0xd0, %edi
callq 0x13570
movq %rax, 0x40(%rsp)
jmp 0x65018
movq 0x40(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5e770
jmp 0x65028
movq 0x40(%rsp), %rax
movq %rax, 0x98(%rsp)
movl $0xd0, %edi
callq 0x13570
movq %rax, 0x38(%rsp)
jmp 0x65046
movq 0x38(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5e770
jmp 0x65056
movq 0x38(%rsp), %rax
movq %rax, 0x90(%rsp)
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
movl %eax, 0x30(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x34(%rsp)
jmp 0x6508c
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jge 0x65194
movl 0x8c(%rsp), %esi
leaq 0xc0(%rsp), %rdi
callq 0x436f0
movq %rax, 0x28(%rsp)
jmp 0x650b7
movq 0x28(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0xf0(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq (%rdi), %rax
movq 0x30(%rax), %rax
callq *%rax
jmp 0x650df
movq 0x98(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x650fa
jmp 0x650fc
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x6506e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
jmp 0x65362
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
jmp 0x65355
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
movl $0xd0, %esi
callq 0x13580
jmp 0x65355
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xa8(%rsp)
movl %eax, 0xa4(%rsp)
movl $0xd0, %esi
callq 0x13580
jmp 0x65355
movl $0x0, 0x7c(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0x20(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x24(%rsp)
jmp 0x651b7
movl 0x20(%rsp), %eax
movl 0x24(%rsp), %ecx
cmpl %ecx, %eax
jge 0x65227
movl 0x7c(%rsp), %esi
leaq 0xb0(%rsp), %rdi
callq 0x436f0
movq %rax, 0x18(%rsp)
jmp 0x651db
movq 0x18(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0xf0(%rsp), %rdi
movq 0x70(%rsp), %rsi
movq (%rdi), %rax
movq 0x30(%rax), %rax
callq *%rax
jmp 0x651fd
movq 0x90(%rsp), %rdi
movq 0x70(%rsp), %rsi
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x65215
jmp 0x65217
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x6519c
movq 0x58(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0x620c0
jmp 0x65243
movq 0x58(%rsp), %rdi
movq 0x90(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0x620c0
jmp 0x6525f
cmpq $0x0, 0xe0(%rsp)
je 0x65283
movq 0xe0(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x1bee0
jmp 0x65281
jmp 0x65283
cmpq $0x0, 0xd8(%rsp)
je 0x652a7
movq 0xd8(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x1bee0
jmp 0x652a5
jmp 0x652a7
movl $0x1, 0xd4(%rsp)
jmp 0x65339
cmpq $0x0, 0xe0(%rsp)
je 0x652f7
leaq 0xc0(%rsp), %rdi
callq 0x31da0
movl %eax, 0x14(%rsp)
jmp 0x652d5
movl 0x14(%rsp), %eax
cmpl $0x0, %eax
jne 0x652f7
movq 0xe0(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1bee0
jmp 0x652f5
jmp 0x652f7
cmpq $0x0, 0xd8(%rsp)
je 0x65337
leaq 0xb0(%rsp), %rdi
callq 0x31da0
movl %eax, 0x10(%rsp)
jmp 0x65315
movl 0x10(%rsp), %eax
cmpl $0x0, %eax
jne 0x65337
movq 0xd8(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1bee0
jmp 0x65335
jmp 0x65337
jmp 0x65339
leaq 0xb0(%rsp), %rdi
callq 0x43730
leaq 0xc0(%rsp), %rdi
callq 0x43730
jmp 0x65374
leaq 0xb0(%rsp), %rdi
callq 0x43730
leaq 0xc0(%rsp), %rdi
callq 0x43730
jmp 0x654a2
jmp 0x65376
jmp 0x65485
cmpq $0x0, 0xe0(%rsp)
je 0x65391
cmpq $0x0, 0xd8(%rsp)
jne 0x65403
movq 0xe8(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0xf0(%rsp), %rdi
callq 0x5ee30
movq 0x8(%rsp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
callq *0x30(%rax)
movl %eax, 0x6c(%rsp)
cmpl $0x2, 0x6c(%rsp)
jne 0x653df
cmpq $0x0, 0xe0(%rsp)
jne 0x653df
movl $0x0, 0x104(%rsp)
jmp 0x65493
cmpl $0x0, 0x6c(%rsp)
jne 0x65401
cmpq $0x0, 0xd8(%rsp)
jne 0x65401
movl $0x0, 0x104(%rsp)
jmp 0x65493
jmp 0x65403
movl $0x0, 0x68(%rsp)
movl 0x68(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0xf0(%rsp), %rdi
callq 0x31660
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jge 0x65483
movq 0xf0(%rsp), %rdi
movl 0x68(%rsp), %esi
callq 0x43680
movq 0x58(%rsp), %rdi
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rsi
movq 0xe8(%rsp), %rdx
movq 0xe0(%rsp), %rcx
movq 0xd8(%rsp), %r8
movq (%rdi), %rax
callq *0x30(%rax)
orl 0xd4(%rsp), %eax
movl %eax, 0xd4(%rsp)
movl 0x68(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x68(%rsp)
jmp 0x6540b
jmp 0x65485
movl 0xd4(%rsp), %eax
movl %eax, 0x104(%rsp)
movl 0x104(%rsp), %eax
addq $0x108, %rsp            # imm = 0x108
retq
movq 0xa8(%rsp), %rdi
callq 0x13970
nop