// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreatePlanarObjects(gaps::R3SurfelScene*, gaps::R3SurfelNode*, gaps::R3SurfelConstraint const*, gaps::R3SurfelObject*, gaps::R3SurfelNode*, int, double, double, double, double, double, int, double, double, double)
RNArray<R3SurfelObject *> *
CreatePlanarObjects(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,
  RNArea min_area, RNScalar min_density, int min_points,
  RNLength grid_spacing, RNScalar accuracy_factor, 
  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;

      // 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;

      // Create planar grids
      RNArray<R3PlanarGrid *> *chunk_grids = CreatePlanarGrids(graph,
        max_offplane_distance, max_normal_angle, 
        min_area, min_density, min_points, 
        grid_spacing, accuracy_factor);
      if (!chunk_grids) { delete graph; continue; }

      // Delete graph
      delete graph;

      // Create objects 
      for (int k = 0; k < chunk_grids->NEntries(); k++) {
        R3PlanarGrid *grid = chunk_grids->Kth(k);
        char object_name[256];
        sprintf(object_name, "PlanarGrid%d\n", objects->NEntries());
        R3SurfelPlanarGridConstraint planar_grid_constraint(grid, max_offplane_distance);
        multi_constraint.InsertConstraint(&planar_grid_constraint);
        R3SurfelObject *object = CreateObject(scene, source_node, &multi_constraint, 
          parent_object, object_name, parent_node, object_name);
        multi_constraint.RemoveConstraint(&planar_grid_constraint);
        printf("  %6d/%6d %6d/%6d %6d/%6d : %9.3g %9.3g\n", j, nychunks, i, nxchunks, k, chunk_grids->NEntries(), grid->L1Norm(), grid->Area());
        if (object) objects->Insert(object);
        delete grid;
      }

      // Delete array of grids
      delete chunk_grids;
    }
  }

  // Return objects
  return objects;
}

// Assembly:
subq $0x3e8, %rsp            # imm = 0x3E8
movl 0x3f0(%rsp), %eax
movq %rdi, 0x3d8(%rsp)
movq %rsi, 0x3d0(%rsp)
movq %rdx, 0x3c8(%rsp)
movq %rcx, 0x3c0(%rsp)
movq %r8, 0x3b8(%rsp)
movl %r9d, 0x3b4(%rsp)
movsd %xmm0, 0x3a8(%rsp)
movsd %xmm1, 0x3a0(%rsp)
movsd %xmm2, 0x398(%rsp)
movsd %xmm3, 0x390(%rsp)
movsd %xmm4, 0x388(%rsp)
movsd %xmm5, 0x380(%rsp)
movsd %xmm6, 0x378(%rsp)
movsd %xmm7, 0x370(%rsp)
movq 0x3d8(%rsp), %rdi
callq 0x16ce0
movq %rax, 0x368(%rsp)
cmpq $0x0, 0x368(%rsp)
jne 0x40047
movq $0x0, 0x3e0(%rsp)
jmp 0x409d3
cmpq $0x0, 0x3d0(%rsp)
jne 0x40067
movq 0x368(%rsp), %rdi
callq 0x31030
movq %rax, 0x3d0(%rsp)
movq 0x3d0(%rsp), %rdi
callq 0x5ee30
movq %rax, 0x360(%rsp)
movl $0x1, 0x35c(%rsp)
movl $0x1, 0x358(%rsp)
movq 0x360(%rsp), %rdi
callq 0x44130
movsd %xmm0, 0x350(%rsp)
movq 0x360(%rsp), %rdi
callq 0x44150
movsd %xmm0, 0x348(%rsp)
movsd 0x370(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x40162
movq 0x360(%rsp), %rdi
callq 0x44130
divsd 0x370(%rsp), %xmm0
cvttsd2si %xmm0, %eax
addl $0x1, %eax
movl %eax, 0x35c(%rsp)
movq 0x360(%rsp), %rdi
callq 0x44150
divsd 0x370(%rsp), %xmm0
cvttsd2si %xmm0, %eax
addl $0x1, %eax
movl %eax, 0x358(%rsp)
movq 0x360(%rsp), %rdi
callq 0x44130
cvtsi2sdl 0x35c(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x350(%rsp)
movq 0x360(%rsp), %rdi
callq 0x44150
cvtsi2sdl 0x358(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x348(%rsp)
movl $0x10, %edi
callq 0x13570
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x120(%rsp)
callq 0x1b920
jmp 0x40181
movq 0x120(%rsp), %rax
movq %rax, 0x340(%rsp)
cmpq $0x0, 0x340(%rsp)
jne 0x401e6
leaq 0x164bb7(%rip), %rdi    # 0x1a4d5a
movb $0x0, %al
callq 0x1464b0
movq $0x0, 0x3e0(%rsp)
jmp 0x409d3
movq 0x120(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x338(%rsp)
movl %eax, 0x334(%rsp)
movl $0x10, %esi
callq 0x13580
jmp 0x409e3
movl $0x0, 0x330(%rsp)
movl 0x330(%rsp), %eax
cmpl 0x358(%rsp), %eax
jge 0x409c3
movl $0x0, 0x32c(%rsp)
movl 0x32c(%rsp), %eax
cmpl 0x35c(%rsp), %eax
jge 0x409ab
movq 0x360(%rsp), %rsi
leaq 0x2f0(%rsp), %rdi
callq 0xc9de0
movq 0x360(%rsp), %rdi
callq 0x446e0
movsd %xmm0, 0x118(%rsp)
jmp 0x40251
movsd 0x118(%rsp), %xmm1
cvtsi2sdl 0x32c(%rsp), %xmm0
movsd 0x350(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x108(%rsp)
leaq 0x2f0(%rsp), %rdi
xorl %esi, %esi
callq 0x1bda0
movq %rax, 0x110(%rsp)
jmp 0x40296
movq 0x110(%rsp), %rdi
xorl %esi, %esi
callq 0x1bde0
movq %rax, 0x100(%rsp)
jmp 0x402af
movq 0x100(%rsp), %rax
movsd 0x108(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x360(%rsp), %rdi
callq 0x446e0
movsd %xmm0, 0xf8(%rsp)
jmp 0x402dc
movsd 0xf8(%rsp), %xmm1
movl 0x32c(%rsp), %eax
incl %eax
cvtsi2sd %eax, %xmm0
movsd 0x350(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xe8(%rsp)
leaq 0x2f0(%rsp), %rdi
movl $0x1, %esi
callq 0x1bda0
movq %rax, 0xf0(%rsp)
jmp 0x40328
movq 0xf0(%rsp), %rdi
xorl %esi, %esi
callq 0x1bde0
movq %rax, 0xe0(%rsp)
jmp 0x40341
movq 0xe0(%rsp), %rax
movsd 0xe8(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x360(%rsp), %rdi
callq 0x44700
movsd %xmm0, 0xd8(%rsp)
jmp 0x4036e
movsd 0xd8(%rsp), %xmm1
cvtsi2sdl 0x330(%rsp), %xmm0
movsd 0x348(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xc8(%rsp)
leaq 0x2f0(%rsp), %rdi
xorl %esi, %esi
callq 0x1bda0
movq %rax, 0xd0(%rsp)
jmp 0x403b3
movq 0xd0(%rsp), %rdi
movl $0x1, %esi
callq 0x1bde0
movq %rax, 0xc0(%rsp)
jmp 0x403cf
movq 0xc0(%rsp), %rax
movsd 0xc8(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x360(%rsp), %rdi
callq 0x44700
movsd %xmm0, 0xb8(%rsp)
jmp 0x403fc
movsd 0xb8(%rsp), %xmm1
movl 0x330(%rsp), %eax
incl %eax
cvtsi2sd %eax, %xmm0
movsd 0x348(%rsp), %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
leaq 0x2f0(%rsp), %rdi
movl $0x1, %esi
callq 0x1bda0
movq %rax, 0xb0(%rsp)
jmp 0x40448
movq 0xb0(%rsp), %rdi
movl $0x1, %esi
callq 0x1bde0
movq %rax, 0xa0(%rsp)
jmp 0x40464
movq 0xa0(%rsp), %rax
movsd 0xa8(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x2b0(%rsp), %rdi
leaq 0x2f0(%rsp), %rsi
callq 0x50d10
jmp 0x40490
leaq 0x298(%rsp), %rdi
callq 0x53f90
jmp 0x4049f
leaq 0x298(%rsp), %rdi
leaq 0x2b0(%rsp), %rsi
callq 0x53ff0
jmp 0x404b6
cmpq $0x0, 0x3c8(%rsp)
je 0x40525
movq 0x3c8(%rsp), %rsi
leaq 0x298(%rsp), %rdi
callq 0x53ff0
jmp 0x404d8
jmp 0x40525
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x338(%rsp)
movl %eax, 0x334(%rsp)
jmp 0x4099c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x338(%rsp)
movl %eax, 0x334(%rsp)
jmp 0x4098f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x338(%rsp)
movl %eax, 0x334(%rsp)
jmp 0x40982
movq 0x3d8(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
movl 0x3b4(%rsp), %ecx
movsd 0x3a8(%rsp), %xmm0
leaq 0x298(%rsp), %rdx
callq 0x33910
movq %rax, 0x98(%rsp)
jmp 0x4055c
movq 0x98(%rsp), %rax
movq %rax, 0x290(%rsp)
cmpq $0x0, 0x290(%rsp)
jne 0x40587
movl $0x7, 0x28c(%rsp)
jmp 0x40934
movq 0x290(%rsp), %rdi
movsd 0x3a0(%rsp), %xmm0
movsd 0x398(%rsp), %xmm1
movsd 0x390(%rsp), %xmm2
movsd 0x388(%rsp), %xmm3
movl 0x3f0(%rsp), %esi
movsd 0x380(%rsp), %xmm4
movsd 0x378(%rsp), %xmm5
callq 0x3e120
movq %rax, 0x90(%rsp)
jmp 0x405db
movq 0x90(%rsp), %rax
movq %rax, 0x280(%rsp)
cmpq $0x0, 0x280(%rsp)
jne 0x4062a
movq 0x290(%rsp), %rax
movq %rax, 0x88(%rsp)
cmpq $0x0, %rax
je 0x4061a
movq 0x88(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movl $0x7, 0x28c(%rsp)
jmp 0x40934
movq 0x290(%rsp), %rax
movq %rax, 0x80(%rsp)
cmpq $0x0, %rax
je 0x4064e
movq 0x80(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movl $0x0, 0x27c(%rsp)
movl 0x27c(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0x280(%rsp), %rdi
callq 0x16d50
movl %eax, 0x7c(%rsp)
jmp 0x40677
movl 0x78(%rsp), %eax
movl 0x7c(%rsp), %ecx
cmpl %ecx, %eax
jge 0x408fd
movq 0x280(%rsp), %rdi
movl 0x27c(%rsp), %esi
callq 0x44720
movq %rax, 0x70(%rsp)
jmp 0x406a2
movq 0x70(%rsp), %rax
movq %rax, 0x270(%rsp)
leaq 0x170(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x340(%rsp), %rdi
callq 0x16d50
movl %eax, 0x6c(%rsp)
jmp 0x406cf
movl 0x6c(%rsp), %edx
movq 0x60(%rsp), %rdi
leaq 0x1646a0(%rip), %rsi    # 0x1a4d7f
xorl %eax, %eax
movl %eax, 0x5c(%rsp)
callq 0x130f0
movl 0x5c(%rsp), %ecx
movq 0x270(%rsp), %rsi
movsd 0x3a0(%rsp), %xmm0
leaq 0x1bbe42(%rip), %rax    # 0x1fc548
movsd (%rax), %xmm1
leaq 0x130(%rsp), %rdi
movl $0x4, %edx
movl $0x1, %r8d
xorps %xmm3, %xmm3
movaps %xmm3, %xmm2
callq 0x51c30
jmp 0x4072a
leaq 0x298(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x53ff0
jmp 0x40741
movq 0x3d8(%rsp), %rdi
movq 0x3d0(%rsp), %rsi
movq 0x3c0(%rsp), %rcx
movq 0x3b8(%rsp), %r9
movq %rsp, %rax
leaq 0x170(%rsp), %r8
movq %r8, (%rax)
movl $0x1, 0x10(%rax)
movl $0x0, 0x8(%rax)
leaq 0x298(%rsp), %rdx
callq 0x35b10
movq %rax, 0x50(%rsp)
jmp 0x40791
movq 0x50(%rsp), %rax
movq %rax, 0x128(%rsp)
leaq 0x298(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0x54020
jmp 0x407b5
movl 0x330(%rsp), %eax
movl %eax, 0x38(%rsp)
movl 0x358(%rsp), %eax
movl %eax, 0x3c(%rsp)
movl 0x32c(%rsp), %eax
movl %eax, 0x40(%rsp)
movl 0x35c(%rsp), %eax
movl %eax, 0x44(%rsp)
movl 0x27c(%rsp), %eax
movl %eax, 0x48(%rsp)
movq 0x280(%rsp), %rdi
callq 0x16d50
movl %eax, 0x4c(%rsp)
jmp 0x407ff
movq 0x270(%rsp), %rdi
callq 0x44740
movsd %xmm0, 0x30(%rsp)
jmp 0x40814
movq 0x270(%rsp), %rdi
callq 0x44760
movsd %xmm0, 0x28(%rsp)
jmp 0x40829
movsd 0x28(%rsp), %xmm1
movsd 0x30(%rsp), %xmm0
movl 0x48(%rsp), %r9d
movl 0x44(%rsp), %r8d
movl 0x40(%rsp), %ecx
movl 0x3c(%rsp), %edx
movl 0x38(%rsp), %esi
movl 0x4c(%rsp), %edi
movq %rsp, %rax
movl %edi, (%rax)
leaq 0x164532(%rip), %rdi    # 0x1a4d8d
movb $0x2, %al
callq 0x13070
jmp 0x40864
cmpq $0x0, 0x128(%rsp)
je 0x408ae
movq 0x340(%rsp), %rdi
movq 0x128(%rsp), %rsi
callq 0x1be70
jmp 0x40886
jmp 0x408ae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x338(%rsp)
movl %eax, 0x334(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x44790
jmp 0x40982
movq 0x270(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x408da
movq 0x20(%rsp), %rdi
callq 0xdde20
movq 0x20(%rsp), %rdi
movl $0x240, %esi            # imm = 0x240
callq 0x13580
leaq 0x130(%rsp), %rdi
callq 0x44790
movl 0x27c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x27c(%rsp)
jmp 0x40659
movq 0x280(%rsp), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0x40929
movq 0x18(%rsp), %rdi
callq 0x44780
movq 0x18(%rsp), %rdi
movl $0x10, %esi
callq 0x13580
movl $0x0, 0x28c(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x43a50
leaq 0x2b0(%rsp), %rdi
callq 0x43740
leaq 0x2f0(%rsp), %rdi
callq 0x1b990
movl 0x28c(%rsp), %eax
testl %eax, %eax
je 0x4096a
jmp 0x40968
jmp 0x4096c
jmp 0x4096c
movl 0x32c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x32c(%rsp)
jmp 0x40210
leaq 0x298(%rsp), %rdi
callq 0x43a50
leaq 0x2b0(%rsp), %rdi
callq 0x43740
leaq 0x2f0(%rsp), %rdi
callq 0x1b990
jmp 0x409e3
jmp 0x409ad
movl 0x330(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x330(%rsp)
jmp 0x401f1
movq 0x340(%rsp), %rax
movq %rax, 0x3e0(%rsp)
movq 0x3e0(%rsp), %rax
addq $0x3e8, %rsp            # imm = 0x3E8
retq
movq 0x338(%rsp), %rdi
callq 0x13970