// File: /workspace/github_cpp_makefile_star2_O1/tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreateClusterObjects(gaps::R3SurfelScene*, gaps::R3SurfelNode*, gaps::R3SurfelConstraint const*, gaps::R3SurfelObject*, gaps::R3SurfelNode*, int, double, double, double, int, double)
RNArray<R3SurfelObject *> *
CreateClusterObjects(R3SurfelScene *scene, 
  R3SurfelNode *source_node, const R3SurfelConstraint *constraint,
  R3SurfelObject *parent_object, R3SurfelNode *parent_node, 
  int max_neighbors, RNLength max_neighbor_distance, 
  RNLength max_offplane_distance, RNAngle max_normal_angle,
  int min_points_per_object, 
  RNLength chunk_size)
{
  // Get convenient variables
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return NULL;
  if (!source_node) source_node = tree->RootNode();
  const R3Box& source_bbox = source_node->BBox();
  int nxchunks = 1;
  int nychunks = 1;
  RNLength xchunk = source_bbox.XLength();
  RNLength ychunk = source_bbox.YLength();
  if (chunk_size > 0) {
    nxchunks = (int) (source_bbox.XLength() / chunk_size) + 1;
    nychunks = (int) (source_bbox.YLength() / chunk_size) + 1;
    xchunk = source_bbox.XLength() / nxchunks;
    ychunk = source_bbox.YLength() / nychunks;
  }

  // Create array of objects
  RNArray<R3SurfelObject *> *objects = new RNArray<R3SurfelObject *>();
  if (!objects) {
    RNFail("Unable to allocate array of objects\n");
    return NULL;
  }

  // Fill array of objects chunk-by-chunk
  for (int j = 0; j < nychunks; j++) {
    for (int i = 0; i < nxchunks; i++) {
      // Compute chunk bounding box
      R3Box chunk_bbox = source_bbox;
      chunk_bbox[0][0] = source_bbox.XMin() + i     * xchunk;
      chunk_bbox[1][0] = source_bbox.XMin() + (i+1) * xchunk;
      chunk_bbox[0][1] = source_bbox.YMin() + j     * ychunk;
      chunk_bbox[1][1] = source_bbox.YMin() + (j+1) * ychunk;

      // Print debug message
      printf("  %6d/%6d %6d/%6d\n",j, nychunks, i, nxchunks);

      // Create graph
      R3SurfelBoxConstraint box_constraint(chunk_bbox);
      R3SurfelMultiConstraint multi_constraint;
      multi_constraint.InsertConstraint(&box_constraint);
      if (constraint) multi_constraint.InsertConstraint(constraint);
      R3SurfelPointGraph *graph = CreatePointGraph(scene, 
        source_node, &multi_constraint, 
        max_neighbors, max_neighbor_distance);
      if (!graph) continue;

      printf("    %9d : %9.3f %9.3f %9.3f  %9.3f %9.3f %9.3f\n",  graph->NPoints(),
            graph->BBox().XMin(), graph->BBox().YMin(), graph->BBox().ZMin(), 
            graph->BBox().XMax(), graph->BBox().YMax(), graph->BBox().ZMax());

      // Create objects
      RNArray<R3SurfelObject *> *chunk_objects = CreateClusterObjects(scene, graph, parent_object, parent_node, min_points_per_object);
      if (!chunk_objects) { delete graph; continue; }

      // Insert into result
      for (int k = 0; k < chunk_objects->NEntries(); k++) {
        R3SurfelObject *object = chunk_objects->Kth(k);
        char object_name[256];
        sprintf(object_name, "ClusterObject%d\n", objects->NEntries());
        object->SetName(object_name);
        objects->Insert(object);
      }

      // Delete array of chunk objects
      delete chunk_objects;

      // Delete graph
      delete graph;
    }
  }

  // Return objects
  return objects;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x248, %rsp            # imm = 0x248
movsd %xmm0, 0xa0(%rsp)
movl %r9d, 0x1c(%rsp)
movq %r8, 0x80(%rsp)
movq %rcx, 0x78(%rsp)
movq %rdi, 0x30(%rsp)
movq 0x8(%rdi), %rax
testq %rax, %rax
je 0x2a7b1
movq %rdx, %r15
movq %rsi, %rbp
movaps %xmm3, 0x60(%rsp)
testq %rsi, %rsi
jne 0x2a743
movq 0x18(%rax), %rax
movq (%rax), %rbp
movq %rbp, %rdi
callq 0x37838
movupd 0x8(%rax), %xmm0
movq %rax, 0x98(%rsp)
movupd 0x20(%rax), %xmm2
subpd %xmm0, %xmm2
movl $0x1, 0x8(%rsp)
xorpd %xmm0, %xmm0
movapd 0x60(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x2a7b8
unpcklpd %xmm1, %xmm1            # xmm1 = xmm1[0,0]
movapd %xmm2, %xmm0
divpd %xmm1, %xmm0
cvttpd2dq %xmm0, %xmm0
pcmpeqd %xmm1, %xmm1
psubd %xmm1, %xmm0
cvtdq2pd %xmm0, %xmm1
divpd %xmm1, %xmm2
movapd %xmm2, 0x50(%rsp)
movd %xmm0, %r14d
pshufd $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movd %xmm0, 0x8(%rsp)
jmp 0x2a7c4
xorl %ebx, %ebx
jmp 0x2ab17
movapd %xmm2, 0x50(%rsp)
movl $0x1, %r14d
movl $0x10, %edi
callq 0x134e0
movq %rax, %rbx
movq %rax, %rdi
callq 0xaaf34
cmpl $0x0, 0x8(%rsp)
movapd 0x50(%rsp), %xmm0
jle 0x2ab17
movq %r15, 0x90(%rsp)
xorps %xmm1, %xmm1
cvtsi2sdl 0x280(%rsp), %xmm1
movsd %xmm1, 0x70(%rsp)
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
movapd %xmm0, 0xf0(%rsp)
leaq 0x104e00(%rip), %rax    # 0x12f618
addq $0x10, %rax
movq %rax, 0x20(%rsp)
leaq 0x104850(%rip), %rax    # 0x12f078
addq $0x10, %rax
movq %rax, 0x28(%rsp)
leaq 0x140(%rsp), %r12
movq $0x0, 0x10(%rsp)
movq %rbp, 0x88(%rsp)
movl %r14d, 0xc(%rsp)
testl %r14d, %r14d
leaq 0x100(%rsp), %r15
jle 0x2ab01
movq 0x10(%rsp), %rax
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
incl %eax
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
xorl %eax, %eax
movapd 0xf0(%rsp), %xmm0
mulsd %xmm0, %xmm1
movsd %xmm1, 0xb0(%rsp)
mulsd %xmm0, %xmm2
movsd %xmm2, 0xa8(%rsp)
movl %eax, %r13d
leaq 0xb8(%rsp), %rdi
movq 0x98(%rsp), %r14
movq %r14, %rsi
callq 0x6df88
xorps %xmm0, %xmm0
cvtsi2sd %r13d, %xmm0
movapd 0x50(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd 0x8(%r14), %xmm0
leal 0x1(%r13), %eax
movl %eax, 0x60(%rsp)
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd %xmm0, 0xc0(%rsp)
mulsd %xmm2, %xmm1
addsd 0x8(%r14), %xmm1
movsd %xmm1, 0xd8(%rsp)
movsd 0x10(%r14), %xmm0
addsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
movsd 0x10(%r14), %xmm0
movl 0xc(%rsp), %r14d
addsd 0xa8(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
leaq 0xb43c7(%rip), %rdi     # 0xdecfb
movq 0x10(%rsp), %rsi
movl 0x8(%rsp), %edx
movl %r13d, %ecx
leaq 0xb8(%rsp), %r13
movl %r14d, %r8d
xorl %eax, %eax
callq 0x13070
movq %r15, %rdi
movq %r13, %rsi
callq 0x30704
leaq 0x38(%rsp), %r15
movq %r15, %rdi
callq 0x31f4c
movq %r15, %rdi
leaq 0x100(%rsp), %rsi
callq 0x31f60
movq 0x90(%rsp), %r15
testq %r15, %r15
je 0x2a994
leaq 0x38(%rsp), %rdi
movq %r15, %rsi
callq 0x31f60
movq 0x30(%rsp), %rdi
movq %rbp, %rsi
leaq 0x38(%rsp), %rdx
movl 0x1c(%rsp), %ecx
movsd 0xa0(%rsp), %xmm0
callq 0x22be6
movq %rax, %rbp
testq %rax, %rax
je 0x2aa9c
movl 0x18(%rbp), %esi
movsd 0x28(%rbp), %xmm0
movsd 0x30(%rbp), %xmm1
movsd 0x38(%rbp), %xmm2
movsd 0x40(%rbp), %xmm3
movsd 0x48(%rbp), %xmm4
movsd 0x50(%rbp), %xmm5
leaq 0xb4327(%rip), %rdi     # 0xded0e
movb $0x6, %al
callq 0x13070
movq 0x30(%rsp), %rdi
movq %rbp, %rsi
movq 0x78(%rsp), %rdx
movq 0x80(%rsp), %rcx
movsd 0x70(%rsp), %xmm0
movsd 0xb3967(%rip), %xmm1    # 0xde378
movl $0x19, %r8d
callq 0x29ccb
movq %rax, %r13
testq %rax, %rax
je 0x2aa8a
cmpl $0x0, 0xc(%r13)
jle 0x2aa70
xorl %r14d, %r14d
movq (%r13), %rax
movq (%rax,%r14,8), %r15
movl 0xc(%rbx), %edx
movq %r12, %rdi
leaq 0xb42fb(%rip), %rsi     # 0xded3e
xorl %eax, %eax
callq 0x130e0
movq (%r15), %rax
movq %r15, %rdi
movq %r12, %rsi
callq *0x10(%rax)
movl 0xc(%rbx), %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0xaafca
incq %r14
movslq 0xc(%r13), %rax
cmpq %rax, %r14
jl 0x2aa2e
movq %r13, %rdi
callq 0xaaf9e
movl $0x10, %esi
movq %r13, %rdi
callq 0x134f0
movl 0xc(%rsp), %r14d
movq (%rbp), %rax
movq %rbp, %rdi
callq *0x8(%rax)
leaq 0xb8(%rsp), %r13
movq 0x20(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x40(%rsp), %rdi
callq 0xaaf9e
leaq 0x38(%rsp), %rdi
callq 0x321ae
movq 0x28(%rsp), %rax
movq %rax, 0x100(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x6ede0
leaq 0x100(%rsp), %r15
movq %r15, %rdi
callq 0x321ae
movq %r13, %rdi
callq 0x6ede0
movl 0x60(%rsp), %eax
cmpl %r14d, %eax
movq 0x88(%rsp), %rbp
jne 0x2a89a
movq 0x10(%rsp), %rax
incl %eax
movq %rax, 0x10(%rsp)
cmpl 0x8(%rsp), %eax
jne 0x2a84f
movq %rbx, %rax
addq $0x248, %rsp            # imm = 0x248
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
movl $0x10, %esi
movq %rbx, %rdi
callq 0x134f0
jmp 0x2ab9e
jmp 0x2ab4e
jmp 0x2ab4e
movq %rax, %r14
jmp 0x2ab91
movq %rax, %r14
jmp 0x2ab6e
jmp 0x2ab4e
movq %rax, %r14
leaq 0x40(%rsp), %rdi
movq 0x20(%rsp), %rax
movq %rax, -0x8(%rdi)
callq 0xaaf9e
leaq 0x38(%rsp), %rdi
callq 0x321ae
leaq 0x108(%rsp), %rdi
movq 0x28(%rsp), %rax
movq %rax, -0x8(%rdi)
callq 0x6ede0
leaq 0x100(%rsp), %rdi
callq 0x321ae
leaq 0xb8(%rsp), %rdi
callq 0x6ede0
movq %r14, %rdi
callq 0x138b0