// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::SplitObject(gaps::R3SurfelObject*, gaps::R3SurfelConstraint const*, gaps::R3SurfelObject**, gaps::R3SurfelObject**)
int
SplitObject(R3SurfelObject *object, const R3SurfelConstraint *constraint,
  R3SurfelObject **resultA, R3SurfelObject **resultB)
{
  // Get useful variables
  if (!object) return 0;
  if (!constraint) return 0;
  if (object->NNodes() == 0) return 0;
  assert(strcmp(object->Name(), "Root"));
  R3SurfelScene *scene = object->Scene();
  if (!scene) return 0;
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return 0;

  // Create constraint
  R3SurfelMultiConstraint multi_constraint;
  R3SurfelObjectConstraint object_constraint(object);
  multi_constraint.InsertConstraint(constraint);
  multi_constraint.InsertConstraint(&object_constraint);

  // Create array of nodes
  RNArray<R3SurfelNode *> nodes;
  for (int i = 0; i < object->NNodes(); i++) {
    R3SurfelNode *node = object->Node(i);
    nodes.Insert(node);
  }

  // Split all nodes
  RNArray<R3SurfelNode *> nodesA, nodesB;
  for (int i = 0; i < nodes.NEntries(); i++) {
    R3SurfelNode *node = nodes.Kth(i);
    tree->SplitLeafNodes(node, *constraint, &nodesA, &nodesB);
  }

  // Check nodesA
  if (nodesA.NEntries() == 0) {
    if (resultA) *resultA = NULL;
    if (resultB) *resultB = object; 
    return 0;
  }
    
  // Check nodesB
  if (nodesB.NEntries() == 0) {
    if (resultA) *resultA = object;
    if (resultB) *resultB = NULL; 
    return 0;
  }

  // Create new objects
  R3SurfelObject *objectA = new R3SurfelObject();
  R3SurfelObject *objectB = new R3SurfelObject();
  if (!objectA || !objectB) return 0;
      
  // Remove nodes from object
  while (object->NNodes() > 0) {
    R3SurfelNode *node = object->Node(0);
    object->RemoveNode(node);
  }
  
  // Insert nodes into objectA
  for (int j = 0; j < nodesA.NEntries(); j++) {
    R3SurfelNode *nodeA = nodesA.Kth(j);
    if (nodeA->Object()) continue;
    objectA->InsertNode(nodeA);
  }
  
  // Insert nodes into objectB
  for (int j = 0; j < nodesB.NEntries(); j++) {
    R3SurfelNode *nodeB = nodesB.Kth(j);
    if (nodeB->Object()) continue;
    objectB->InsertNode(nodeB);
  }
      
  // Copy result
  if (resultA) *resultA = objectA;
  if (resultB) *resultB = objectB;
  
  // Return success
  return 1;
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdi, 0x178(%rsp)
movq %rsi, 0x170(%rsp)
movq %rdx, 0x168(%rsp)
movq %rcx, 0x160(%rsp)
cmpq $0x0, 0x178(%rsp)
jne 0x36a22
movl $0x0, 0x184(%rsp)
jmp 0x37148
cmpq $0x0, 0x170(%rsp)
jne 0x36a3d
movl $0x0, 0x184(%rsp)
jmp 0x37148
movq 0x178(%rsp), %rdi
callq 0x18660
cmpl $0x0, %eax
jne 0x36a5f
movl $0x0, 0x184(%rsp)
jmp 0x37148
movq 0x178(%rsp), %rdi
callq 0x43a90
movq %rax, 0x158(%rsp)
cmpq $0x0, 0x158(%rsp)
jne 0x36a8f
movl $0x0, 0x184(%rsp)
jmp 0x37148
movq 0x158(%rsp), %rdi
callq 0x16ce0
movq %rax, 0x150(%rsp)
cmpq $0x0, 0x150(%rsp)
jne 0x36abf
movl $0x0, 0x184(%rsp)
jmp 0x37148
leaq 0x138(%rsp), %rdi
callq 0x53f90
movq 0x178(%rsp), %rsi
leaq 0x120(%rsp), %rdi
xorl %edx, %edx
callq 0x536d0
jmp 0x36ae5
movq 0x170(%rsp), %rsi
leaq 0x138(%rsp), %rdi
callq 0x53ff0
jmp 0x36afc
leaq 0x138(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x53ff0
jmp 0x36b13
leaq 0x100(%rsp), %rdi
callq 0x1b960
jmp 0x36b22
movl $0x0, 0xfc(%rsp)
movl 0xfc(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0x178(%rsp), %rdi
callq 0x18660
movl %eax, 0x7c(%rsp)
jmp 0x36b4b
movl 0x78(%rsp), %eax
movl 0x7c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x36bfd
movq 0x178(%rsp), %rdi
movl 0xfc(%rsp), %esi
callq 0x18680
movq %rax, 0x70(%rsp)
jmp 0x36b76
movq 0x70(%rsp), %rax
movq %rax, 0xf0(%rsp)
movq 0xf0(%rsp), %rsi
leaq 0x100(%rsp), %rdi
callq 0x1bee0
jmp 0x36b9a
jmp 0x36b9c
movl 0xfc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xfc(%rsp)
jmp 0x36b2d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x37139
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x3712c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x3711f
leaq 0xe0(%rsp), %rdi
callq 0x1b960
jmp 0x36c0c
leaq 0xd0(%rsp), %rdi
callq 0x1b960
jmp 0x36c1b
movl $0x0, 0xcc(%rsp)
movl 0xcc(%rsp), %eax
movl %eax, 0x68(%rsp)
leaq 0x100(%rsp), %rdi
callq 0x16d50
movl %eax, 0x6c(%rsp)
jmp 0x36c44
movl 0x68(%rsp), %eax
movl 0x6c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x36cf9
movl 0xcc(%rsp), %esi
leaq 0x100(%rsp), %rdi
callq 0x310e0
movq %rax, 0x60(%rsp)
jmp 0x36c6f
movq 0x60(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq 0x150(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq 0x170(%rsp), %rdx
movq (%rdi), %rax
movq 0x30(%rax), %rax
leaq 0xe0(%rsp), %rcx
leaq 0xd0(%rsp), %r8
callq *%rax
jmp 0x36caf
jmp 0x36cb1
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x36c26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x37112
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
jmp 0x37105
leaq 0xe0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x5c(%rsp)
jmp 0x36d0c
movl 0x5c(%rsp), %eax
cmpl $0x0, %eax
jne 0x36d68
cmpq $0x0, 0x168(%rsp)
je 0x36d2f
movq 0x168(%rsp), %rax
movq $0x0, (%rax)
cmpq $0x0, 0x160(%rsp)
je 0x36d4d
movq 0x178(%rsp), %rcx
movq 0x160(%rsp), %rax
movq %rcx, (%rax)
movl $0x0, 0x184(%rsp)
movl $0x1, 0xbc(%rsp)
jmp 0x370c2
leaq 0xd0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x58(%rsp)
jmp 0x36d7b
movl 0x58(%rsp), %eax
cmpl $0x0, %eax
jne 0x36dd7
cmpq $0x0, 0x168(%rsp)
je 0x36da2
movq 0x178(%rsp), %rcx
movq 0x168(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x160(%rsp)
je 0x36dbc
movq 0x160(%rsp), %rax
movq $0x0, (%rax)
movl $0x0, 0x184(%rsp)
movl $0x1, 0xbc(%rsp)
jmp 0x370c2
movl $0xf8, %edi
callq 0x13570
movq %rax, 0x50(%rsp)
jmp 0x36de8
movq 0x50(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x189f0
jmp 0x36df8
movq 0x50(%rsp), %rax
movq %rax, 0xb0(%rsp)
movl $0xf8, %edi
callq 0x13570
movq %rax, 0x48(%rsp)
jmp 0x36e16
movq 0x48(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x189f0
jmp 0x36e26
movq 0x48(%rsp), %rax
movq %rax, 0xa8(%rsp)
cmpq $0x0, 0xb0(%rsp)
je 0x36e49
cmpq $0x0, 0xa8(%rsp)
jne 0x36eb4
movl $0x0, 0x184(%rsp)
movl $0x1, 0xbc(%rsp)
jmp 0x370c2
movq 0x50(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
movl $0xf8, %esi
callq 0x13580
jmp 0x37105
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x118(%rsp)
movl %eax, 0x114(%rsp)
movl $0xf8, %esi
callq 0x13580
jmp 0x37105
jmp 0x36eb6
movq 0x178(%rsp), %rdi
callq 0x18660
movl %eax, 0x44(%rsp)
jmp 0x36ec9
movl 0x44(%rsp), %eax
cmpl $0x0, %eax
jle 0x36f0e
movq 0x178(%rsp), %rdi
xorl %esi, %esi
callq 0x18680
movq %rax, 0x38(%rsp)
jmp 0x36ee8
movq 0x38(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x178(%rsp), %rdi
movq 0xa0(%rsp), %rsi
callq 0x191d0
jmp 0x36f0c
jmp 0x36eb6
movl $0x0, 0x9c(%rsp)
movl 0x9c(%rsp), %eax
movl %eax, 0x30(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x34(%rsp)
jmp 0x36f37
movl 0x30(%rsp), %eax
movl 0x34(%rsp), %ecx
cmpl %ecx, %eax
jge 0x36fbf
movl 0x9c(%rsp), %esi
leaq 0xe0(%rsp), %rdi
callq 0x310e0
movq %rax, 0x28(%rsp)
jmp 0x36f5e
movq 0x28(%rsp), %rax
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x5f2c0
movq %rax, 0x20(%rsp)
jmp 0x36f83
movq 0x20(%rsp), %rax
cmpq $0x0, %rax
je 0x36f90
jmp 0x36fa9
movq 0xb0(%rsp), %rdi
movq 0x90(%rsp), %rsi
callq 0x1ac10
jmp 0x36fa7
jmp 0x36fa9
movl 0x9c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x9c(%rsp)
jmp 0x36f19
movl $0x0, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
movl %eax, 0x18(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x16d50
movl %eax, 0x1c(%rsp)
jmp 0x36fe8
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x37070
movl 0x8c(%rsp), %esi
leaq 0xd0(%rsp), %rdi
callq 0x310e0
movq %rax, 0x10(%rsp)
jmp 0x3700f
movq 0x10(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x5f2c0
movq %rax, 0x8(%rsp)
jmp 0x37034
movq 0x8(%rsp), %rax
cmpq $0x0, %rax
je 0x37041
jmp 0x3705a
movq 0xa8(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0x1ac10
jmp 0x37058
jmp 0x3705a
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x8c(%rsp)
jmp 0x36fca
cmpq $0x0, 0x168(%rsp)
je 0x3708e
movq 0xb0(%rsp), %rcx
movq 0x168(%rsp), %rax
movq %rcx, (%rax)
cmpq $0x0, 0x160(%rsp)
je 0x370ac
movq 0xa8(%rsp), %rcx
movq 0x160(%rsp), %rax
movq %rcx, (%rax)
movl $0x1, 0x184(%rsp)
movl $0x1, 0xbc(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x1b9a0
leaq 0xe0(%rsp), %rdi
callq 0x1b9a0
leaq 0x100(%rsp), %rdi
callq 0x1b9a0
leaq 0x120(%rsp), %rdi
callq 0x43a30
leaq 0x138(%rsp), %rdi
callq 0x43a50
jmp 0x37148
leaq 0xd0(%rsp), %rdi
callq 0x1b9a0
leaq 0xe0(%rsp), %rdi
callq 0x1b9a0
leaq 0x100(%rsp), %rdi
callq 0x1b9a0
leaq 0x120(%rsp), %rdi
callq 0x43a30
leaq 0x138(%rsp), %rdi
callq 0x43a50
jmp 0x37157
movl 0x184(%rsp), %eax
addq $0x188, %rsp            # imm = 0x188
retq
movq 0x118(%rsp), %rdi
callq 0x13970
nopw %cs:(%rax,%rax)