// File: /workspace/github_cpp_makefile_star2_O1/tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::CreateClusterObjects(gaps::R3SurfelScene*, gaps::R3SurfelPointGraph*, gaps::R3SurfelObject*, gaps::R3SurfelNode*, double, double, int)
RNArray<R3SurfelObject *> *
CreateClusterObjects(R3SurfelScene *scene, R3SurfelPointGraph *graph, 
  R3SurfelObject *parent_object, R3SurfelNode *parent_node, 
  RNLength max_offplane_distance, RNAngle max_normal_angle,
  int min_points_per_object)
{
  // Get convenient variables
  R3SurfelTree *tree = scene->Tree();
  if (!tree) return 0;
  R3SurfelDatabase *database = tree->Database();
  if (!database) return 0;

  // Check number of points
  if (graph->NPoints() < min_points_per_object) return NULL;

  // Check parent object
  if (!parent_object) parent_object = scene->RootObject();

  // Check parent node
  if (!parent_node) parent_node = tree->RootNode();

  // Create normals
  R3Vector *normals = NULL;
  if ((max_offplane_distance > 0) || (max_normal_angle > 0)) {
    normals = CreateNormals(graph, FALSE);
  }

  // Create cluster for every point
  RNArray<R3SurfelCluster *> clusters;
  for (int i = 0; i < graph->NPoints(); i++) {
    R3SurfelPoint *point = graph->Point(i);
    R3Point position = point->Position();
    R3SurfelCluster *cluster = new R3SurfelCluster();
    cluster->parent = NULL;
    cluster->points.Insert(point);
    cluster->bbox.Reset(position, position);
    cluster->id = i;
    clusters.Insert(cluster);
  }

  // Check clusters
  if (clusters.IsEmpty()) {
    if (normals) delete [] normals;
    return NULL;  
  }

  // Create cluster pairs and add to heap
  R3SurfelClusterPair tmp;
  RNHeap<R3SurfelClusterPair *> heap(&tmp, &tmp.similarity, NULL, FALSE);;
  for (int index0 = 0; index0 < graph->NPoints(); index0++) {
    R3SurfelPoint *point0 = graph->Point(index0);
    R3SurfelCluster *cluster0 = clusters.Kth(index0);
    R3Point position0 = point0->Position();
    const R3Vector& normal0 = (normals) ? normals[index0] : R3zero_vector;
    R3Plane plane0(position0, normal0);
    for (int j = 0; j < graph->NNeighbors(index0); j++) {
      R3SurfelPoint *point1 = graph->Neighbor(index0, j);
      int index1 = graph->PointIndex(point1);
      if (index1 < index0) continue;
      R3Point position1 = point1->Position();

      // Compute plane similarity
      RNScalar plane_similarity = 1;
      if (max_offplane_distance > 0) {
        RNScalar offplane_distance = R3Distance(plane0, position1);
        if (offplane_distance > max_offplane_distance) continue;
        plane_similarity *= 1.0 - 0.9 * offplane_distance / max_offplane_distance;
      }

      // Compute normal similarity
      RNScalar normal_similarity = 1;
      if (max_normal_angle > 0) {
        if (normals) {
          const R3Vector& normal1 = normals[index1];
          RNScalar dot = fabs(normal0.Dot(normal1));
          RNAngle normal_angle = (dot < 1) ? acos(dot) : 0;
          if (normal_angle > max_normal_angle) continue;
          normal_similarity *= 1.0 - 0.9 * normal_angle / max_normal_angle;
        }
      }

      // Compute distance similarity
      RNScalar distance_similarity = 1.0;
      if (graph->MaxDistance() > 0) {
        RNScalar distance = R3Distance(position0, position1);
        distance_similarity = 1.0 - 0.99 * distance / graph->MaxDistance();
      }

      // Create pair
      R3SurfelCluster *cluster1 = clusters.Kth(index1);
      R3SurfelClusterPair *pair = new R3SurfelClusterPair();
      pair->clusters[0] = cluster0;
      pair->clusters[1] = cluster1;
      pair->similarity = distance_similarity * normal_similarity * plane_similarity;
      heap.Push(pair);
    }
  }

  // Check cluster pairs
  if (heap.IsEmpty()) {
    for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
    if (normals) delete [] normals;
    return NULL;
  }

  // Merge clusters hierarchically
  while (!heap.IsEmpty()) {
    // Get pair
    R3SurfelClusterPair *pair = heap.Pop();

    // Get clusters
    R3SurfelCluster *cluster0 = pair->clusters[0];
    R3SurfelCluster *cluster1 = pair->clusters[1];
    while (cluster0->parent) cluster0 = cluster0->parent;
    while (cluster1->parent) cluster1 = cluster1->parent;
    if (cluster0 == cluster1) continue;

    // Merge clusters
    cluster0->points.Append(cluster1->points);
    cluster0->bbox.Union(cluster1->bbox);
    cluster1->parent = cluster0;
    cluster1->points.Empty(TRUE);
    cluster1->bbox = R3null_box;

    // Delete pair
    delete pair;
  }

  // Create array of objects
  RNArray<R3SurfelObject *> *objects = new RNArray<R3SurfelObject *>();
  if (!objects) {
    RNFail("Unable to create array of objects\n");
    for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
    if (normals) delete [] normals;
    return NULL;
  }

  // Create objects with copies of surfels
  for (int i = 0; i < clusters.NEntries(); i++) {
    R3SurfelCluster *cluster = clusters.Kth(i);

    // Check cluster
    if (cluster->points.NEntries() < min_points_per_object) { delete cluster; continue; }
    if (cluster->parent) { delete cluster; continue; }

    // Create surfels
    R3Point origin = cluster->bbox.Centroid();
    R3Surfel *surfels = new R3Surfel [ cluster->points.NEntries() ];
    for (int j = 0; j < cluster->points.NEntries(); j++) {
      R3SurfelPoint *point = cluster->points.Kth(j);
      R3SurfelBlock *block = point->Block();
      const R3Surfel *surfel = point->Surfel();
      RNCoord x = surfel->X() + block->PositionOrigin().X() - origin.X();
      RNCoord y = surfel->Y() + block->PositionOrigin().Y() - origin.Y();
      RNCoord z = surfel->Z() + block->PositionOrigin().Z() - origin.Z();
      surfels[j].SetPosition(x, y, z);
      surfels[j].SetColor(surfel->Color());
      surfels[j].SetAerial(surfel->IsAerial());
    }

    // Create block
    R3SurfelBlock *block = new R3SurfelBlock(surfels, cluster->points.NEntries(), origin);
    if (!block) {
      RNFail("Unable to create node\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete [] surfels;
      return NULL;
    }

    // Delete surfels
    delete [] surfels;

    // Create node
    char node_name[256];
    sprintf(node_name, "O%d\n", objects->NEntries());
    R3SurfelNode *node = new R3SurfelNode(node_name);
    if (!node) {
      RNFail("Unable to create node\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete block;
      return NULL;
    }

    // Create object
    char object_name[256];
    sprintf(object_name, "O%d\n", objects->NEntries());
    R3SurfelObject *object = new R3SurfelObject(object_name);
    if (!object) {
      RNFail("Unable to create object\n");
      for (int i = 0; i < clusters.NEntries(); i++) delete clusters[i];
      if (normals) delete [] normals;
      delete block;
      delete node;
      return NULL;
    }
     
    // Insert everything
    block->UpdateProperties();
    database->InsertBlock(block);
    node->InsertBlock(block);
    tree->InsertNode(node, parent_node);
    object->InsertNode(node);
    scene->InsertObject(object, parent_object);
    objects->Insert(object);

    // Delete cluster
    delete cluster;

    // Print debug statement
    printf("    %d %d\n", i, block->NSurfels());
  }
  
  // Delete normals
  delete [] normals;

  // Return objects
  return objects;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2f8, %rsp            # imm = 0x2F8
movsd %xmm1, 0x38(%rsp)
movsd %xmm0, 0x18(%rsp)
movq %rsi, %r12
movq 0x8(%rdi), %rsi
testq %rsi, %rsi
je 0x29d04
movq 0x10(%rsi), %r9
testq %r9, %r9
je 0x29d04
cmpl %r8d, 0x18(%r12)
jge 0x29d1c
xorl %r12d, %r12d
movq %r12, %rax
addq $0x2f8, %rsp            # imm = 0x2F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %rdx, %rdx
jne 0x29d28
movq 0x10(%rdi), %rax
movq (%rax), %rdx
testq %rcx, %rcx
jne 0x29d34
movq 0x18(%rsi), %rax
movq (%rax), %rcx
xorpd %xmm0, %xmm0
movsd 0x18(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movl %r8d, 0x34(%rsp)
movq %rcx, 0x90(%rsp)
movq %rdi, 0x80(%rsp)
movq %rdx, 0x78(%rsp)
movq %rsi, 0x88(%rsp)
movq %r9, 0x98(%rsp)
ja 0x29d85
movsd 0x38(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x29d85
movq $0x0, 0x10(%rsp)
jmp 0x29d94
movq %r12, %rdi
xorl %esi, %esi
callq 0x2713c
movq %rax, 0x10(%rsp)
leaq 0x20(%rsp), %rdi
callq 0xaaf34
cmpl $0x0, 0x18(%r12)
jle 0x29eb5
xorl %ebx, %ebx
leaq 0x1f0(%rsp), %rbp
movq $0x0, 0x40(%rsp)
movq 0x10(%r12), %r13
movq (%r13,%rbx), %rax
movq 0x8(%r13,%rbx), %rcx
xorps %xmm0, %xmm0
cvtss2sd (%rcx), %xmm0
addsd 0x10(%rax), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rcx), %xmm1
addsd 0x18(%rax), %xmm1
cvtss2sd 0x8(%rcx), %xmm2
addsd 0x20(%rax), %xmm2
movq %rbp, %rdi
callq 0x84d7e
movq %rbx, 0x50(%rsp)
movl $0x58, %edi
callq 0x134e0
movq %rax, %r14
movq %rbp, %rbx
xorpd %xmm0, %xmm0
movapd %xmm0, 0x40(%rax)
movapd %xmm0, 0x30(%rax)
movapd %xmm0, 0x20(%rax)
movapd %xmm0, 0x10(%rax)
movapd %xmm0, (%rax)
movq $0x0, 0x50(%rax)
leaq 0x8(%rax), %rbp
movq %rbp, %rdi
callq 0xaaf34
movq %r14, %r15
addq $0x18, %r15
movq %r15, %rdi
callq 0x6df44
addq 0x50(%rsp), %r13
movq $0x0, (%r14)
movl 0x14(%r14), %edx
movq %rbp, %rdi
movq %r13, %rsi
callq 0xaafca
movq %rbx, %rbp
movq %r15, %rdi
movq %rbx, %rsi
movq %rbx, %rdx
callq 0x6ed8a
movq 0x40(%rsp), %rax
movl %eax, 0x50(%r14)
movl 0x2c(%rsp), %edx
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0xaafca
movq 0x40(%rsp), %rdx
incq %rdx
movslq 0x18(%r12), %rax
movq 0x50(%rsp), %rbx
addq $0x10, %rbx
movq %rdx, 0x40(%rsp)
cmpq %rax, %rdx
jl 0x29dbd
cmpl $0x0, 0x2c(%rsp)
je 0x2a5ae
xorpd %xmm0, %xmm0
movapd %xmm0, 0xb0(%rsp)
movupd %xmm0, 0xc8(%rsp)
movupd %xmm0, 0xd4(%rsp)
movabsq $-0xfffffff0, %rax      # imm = 0xFFFFFFFF00000010
movq %rax, 0xc0(%rsp)
cmpl $0x0, 0x18(%r12)
jle 0x2a1e4
xorpd %xmm1, %xmm1
movsd 0x38(%rsp), %xmm0
ucomisd %xmm1, %xmm0
seta %al
cmpq $0x0, 0x10(%rsp)
setne %cl
andb %al, %cl
movb %cl, 0xf(%rsp)
xorl %r15d, %r15d
movq 0x10(%r12), %rax
movq %r15, %r13
shlq $0x4, %r13
movq 0x20(%rsp), %rcx
movq (%rcx,%r15,8), %rbx
movq (%rax,%r13), %rcx
movq 0x8(%rax,%r13), %rax
xorps %xmm0, %xmm0
cvtss2sd (%rax), %xmm0
addsd 0x10(%rcx), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rax), %xmm1
addsd 0x18(%rcx), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rax), %xmm2
addsd 0x20(%rcx), %xmm2
leaq 0xf0(%rsp), %rdi
callq 0x84d7e
movq 0x10(%rsp), %rcx
testq %rcx, %rcx
jne 0x29f84
leaq 0xbc24e(%rip), %rdx     # 0xe61d0
jmp 0x29f8c
leaq (%r15,%r15,2), %rax
leaq (%rcx,%rax,8), %rdx
leaq 0x1f0(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
movq %rdx, 0xa0(%rsp)
callq 0x838fe
movq 0x68(%r12), %rax
cmpl $0x0, 0xc(%rax,%r13)
jle 0x2a1d3
xorl %r14d, %r14d
movq (%rax,%r13), %rax
movq (%rax,%r14,8), %rax
movq %rax, %rbp
subq 0x10(%r12), %rbp
shrq $0x4, %rbp
movslq %ebp, %rcx
cmpq %rcx, %r15
jg 0x2a1bd
movq (%rax), %rcx
movq 0x8(%rax), %rax
xorps %xmm0, %xmm0
cvtss2sd (%rax), %xmm0
addsd 0x10(%rcx), %xmm0
xorps %xmm1, %xmm1
cvtss2sd 0x4(%rax), %xmm1
addsd 0x18(%rcx), %xmm1
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rax), %xmm2
addsd 0x20(%rcx), %xmm2
leaq 0x60(%rsp), %rdi
callq 0x84d7e
movsd 0x18(%rsp), %xmm0
ucomisd 0xb4366(%rip), %xmm0    # 0xde388
movsd 0xb4126(%rip), %xmm3    # 0xde150
movapd %xmm3, %xmm2
jbe 0x2a081
leaq 0x60(%rsp), %rdi
leaq 0x1f0(%rsp), %rsi
callq 0x50a76
ucomisd 0x18(%rsp), %xmm0
movapd %xmm0, %xmm1
mulsd 0xb4ad4(%rip), %xmm1    # 0xdeb28
ja 0x2a1bd
movsd 0x18(%rsp), %xmm2
divsd %xmm2, %xmm1
movsd 0xb40e4(%rip), %xmm3    # 0xde150
addsd %xmm3, %xmm1
cmpnltsd %xmm0, %xmm2
andpd %xmm2, %xmm1
andnpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movapd %xmm2, 0x40(%rsp)
movapd %xmm3, %xmm2
cmpb $0x0, 0xf(%rsp)
je 0x2a119
movslq %ebp, %rax
leaq (%rax,%rax,2), %rax
movq 0x10(%rsp), %rcx
leaq (%rcx,%rax,8), %rsi
movq 0xa0(%rsp), %rdi
callq 0x85aae
movapd %xmm0, %xmm1
andpd 0xb4311(%rip), %xmm1    # 0xde3d0
xorpd %xmm0, %xmm0
movsd 0xb4085(%rip), %xmm2    # 0xde150
ucomisd %xmm1, %xmm2
jbe 0x2a0da
movapd %xmm1, %xmm0
callq 0x13490
ucomisd 0x38(%rsp), %xmm0
movapd %xmm0, %xmm1
mulsd 0xb4a3c(%rip), %xmm1    # 0xdeb28
ja 0x2a1bd
movsd 0x38(%rsp), %xmm2
divsd %xmm2, %xmm1
movsd 0xb404c(%rip), %xmm3    # 0xde150
addsd %xmm3, %xmm1
cmpnltsd %xmm0, %xmm2
andpd %xmm2, %xmm1
andnpd %xmm3, %xmm2
orpd %xmm1, %xmm2
movapd %xmm2, 0x50(%rsp)
movsd 0x78(%r12), %xmm0
ucomisd 0xb425a(%rip), %xmm0    # 0xde388
jbe 0x2a161
leaq 0xf0(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x508bc
movapd %xmm0, %xmm3
mulsd 0xb49e2(%rip), %xmm3    # 0xdeb30
divsd 0x78(%r12), %xmm3
movsd 0xb3ff3(%rip), %xmm0    # 0xde150
addsd %xmm0, %xmm3
movsd %xmm3, 0xa8(%rsp)
movq 0x20(%rsp), %rax
movslq %ebp, %rcx
movq (%rax,%rcx,8), %rbp
movl $0x18, %edi
callq 0x134e0
xorpd %xmm0, %xmm0
movapd %xmm0, (%rax)
movq %rbx, (%rax)
movq %rbp, 0x8(%rax)
movapd 0x50(%rsp), %xmm1
mulsd 0xa8(%rsp), %xmm1
movapd 0x40(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0x10(%rax)
leaq 0xb0(%rsp), %rdi
movq %rax, %rsi
callq 0x2ade6
incq %r14
movq 0x68(%r12), %rax
movslq 0xc(%rax,%r13), %rcx
cmpq %rcx, %r14
jl 0x29fbd
incq %r15
movslq 0x18(%r12), %rax
cmpq %rax, %r15
jl 0x29f20
cmpl $0x0, 0xb8(%rsp)
je 0x2a5c2
cmpl $0x0, 0xb8(%rsp)
je 0x2a2a5
leaq 0x10b7c1(%rip), %r14    # 0x1359c8
leaq 0x8(%r14), %r15
addq $0x20, %r14
leaq 0xb0(%rsp), %rdi
callq 0x2aee2
movq %rax, %r12
movq (%rax), %rcx
movq 0x8(%rax), %rax
movq %rcx, %rbx
movq (%rcx), %rcx
testq %rcx, %rcx
jne 0x2a226
movq %rax, %r13
movq (%rax), %rax
testq %rax, %rax
jne 0x2a231
cmpq %r13, %rbx
je 0x2a297
leaq 0x8(%rbx), %rdi
leaq 0x8(%r13), %rbp
movq %rbp, %rsi
callq 0xab264
leaq 0x18(%rbx), %rdi
leaq 0x18(%r13), %rsi
callq 0x6ea70
movq %rbx, (%r13)
movq %rbp, %rdi
movl $0x1, %esi
callq 0xab174
leaq 0x20(%r13), %rdi
movq %r15, %rsi
callq 0x850ec
addq $0x38, %r13
movq %r13, %rdi
movq %r14, %rsi
callq 0x850ec
movl $0x18, %esi
movq %r12, %rdi
callq 0x134f0
cmpl $0x0, 0xb8(%rsp)
jne 0x2a20f
movl $0x10, %edi
callq 0x134e0
movq %rax, %r12
movq %rax, %rdi
callq 0xaaf34
movq 0x10(%rsp), %rdi
movl 0x34(%rsp), %ecx
cmpl $0x0, 0x2c(%rsp)
jle 0x2a60e
xorl %r14d, %r14d
movq %r12, 0x50(%rsp)
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rbp
leaq 0x8(%rbp), %r15
cmpl %ecx, 0x14(%rbp)
jge 0x2a319
movl $0x19, %ebx
testq %rbp, %rbp
je 0x2a585
leaq 0x18(%rbp), %rdi
callq 0x6ede0
movq %r15, %rdi
callq 0xaaf9e
movl $0x58, %esi
movq %rbp, %rdi
callq 0x134f0
jmp 0x2a585
cmpq $0x0, (%rbp)
je 0x2a348
leaq 0x18(%rbp), %rdi
callq 0x6ede0
movq %r15, %rdi
callq 0xaaf9e
movl $0x58, %esi
movq %rbp, %rdi
callq 0x134f0
movl $0x19, %ebx
jmp 0x2a585
movq %r15, 0x18(%rsp)
leaq 0x18(%rbp), %rsi
leaq 0x60(%rsp), %rdi
movq %rsi, 0x40(%rsp)
callq 0x6e7ca
movslq 0x14(%rbp), %r15
movq %r15, %rax
movl $0x30, %ecx
mulq %rcx
movq %rax, %rbx
movq $-0x1, %rax
cmovoq %rax, %rbx
movq %rbx, %rdi
callq 0x13030
movq %rax, %r13
testl %r15d, %r15d
je 0x2a3aa
shlq $0x4, %r15
leaq (%r15,%r15,2), %r15
xorl %r12d, %r12d
leaq (%r12,%r13), %rdi
callq 0x2b548
addq $0x30, %r12
cmpq %r12, %r15
jne 0x2a398
cmpl $0x0, 0x14(%rbp)
jle 0x2a440
movapd 0x60(%rsp), %xmm0
movsd 0x70(%rsp), %xmm1
movq %r13, %rax
addq $0x2f, %rax
xorl %ecx, %ecx
movq 0x8(%rbp), %rdx
movq (%rdx,%rcx,8), %rdx
movq 0x8(%rdx), %rsi
xorps %xmm2, %xmm2
cvtss2sd 0x8(%rsi), %xmm2
movq (%rdx), %rdx
addsd 0x20(%rdx), %xmm2
subsd %xmm1, %xmm2
cvtsd2ss %xmm2, %xmm2
cvtps2pd (%rsi), %xmm3
movupd 0x10(%rdx), %xmm4
addpd %xmm3, %xmm4
subpd %xmm0, %xmm4
cvtpd2ps %xmm4, %xmm3
movlpd %xmm3, -0x2f(%rax)
movss %xmm2, -0x27(%rax)
movb 0x2c(%rsi), %dl
movb %dl, -0x3(%rax)
movb 0x2d(%rsi), %dl
movb %dl, -0x2(%rax)
movb 0x2e(%rsi), %dl
movb %dl, -0x1(%rax)
movb 0x2f(%rsi), %dl
andb $0x2, %dl
movb (%rax), %sil
andb $-0x3, %sil
orb %dl, %sil
movb %sil, (%rax)
incq %rcx
movslq 0x14(%rbp), %rdx
addq $0x30, %rax
cmpq %rdx, %rcx
jl 0x2a3c9
movl $0xc8, %edi
callq 0x134e0
movq 0x50(%rsp), %r12
leaq 0x1f0(%rsp), %r15
movq %rax, %rbx
movl 0x14(%rbp), %edx
xorpd %xmm0, %xmm0
movq %rax, %rdi
movq %r13, %rsi
leaq 0x60(%rsp), %rcx
callq 0x2c68a
movq %r13, %rdi
callq 0x13680
movl 0xc(%r12), %edx
movq %r15, %rdi
leaq 0xb4863(%rip), %rsi     # 0xdeceb
xorl %eax, %eax
callq 0x130e0
movl $0xd0, %edi
callq 0x134e0
movq %rax, %r13
movq %rax, %rdi
movq %r15, %rsi
callq 0x37448
movl 0xc(%r12), %edx
leaq 0xf0(%rsp), %rdi
leaq 0xb4830(%rip), %rsi     # 0xdeceb
xorl %eax, %eax
callq 0x130e0
movl $0xf8, %edi
callq 0x134e0
movq %rax, %r15
movq %rax, %rdi
leaq 0xf0(%rsp), %rsi
callq 0x16bb8
movq %rbx, %rdi
callq 0x2e364
movq 0x98(%rsp), %rdi
movq (%rdi), %rax
movq %rbx, %rsi
callq *0x10(%rax)
movq (%r13), %rax
movq %r13, %rdi
movq %rbx, %rsi
callq *0x28(%rax)
movq 0x88(%rsp), %rdi
movq %r13, %rsi
movq 0x90(%rsp), %rdx
callq 0x39272
movq %r15, %rdi
movq %r13, %rsi
callq 0x17e86
movq 0x80(%rsp), %rdi
movq (%rdi), %rax
movq %r15, %rsi
movq 0x78(%rsp), %rdx
callq *0x18(%rax)
movl 0xc(%r12), %edx
movq %r12, %rdi
movq %r15, %rsi
callq 0xaafca
movq 0x40(%rsp), %rdi
callq 0x6ede0
movq 0x18(%rsp), %rdi
callq 0xaaf9e
movl $0x58, %esi
movq %rbp, %rdi
callq 0x134f0
movl 0x8(%rbx), %edx
xorl %ebx, %ebx
leaq 0xb4775(%rip), %rdi     # 0xdecf0
movl %r14d, %esi
xorl %eax, %eax
callq 0x13070
cmpl $0x19, %ebx
je 0x2a592
testl %ebx, %ebx
jne 0x2a618
incq %r14
movslq 0x2c(%rsp), %rax
cmpq %rax, %r14
movq 0x10(%rsp), %rdi
movl 0x34(%rsp), %ecx
jl 0x2a2d6
jmp 0x2a60e
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2a5bd
callq 0x13680
xorl %r12d, %r12d
jmp 0x2a62a
cmpl $0x0, 0x2c(%rsp)
jle 0x2a606
xorl %r14d, %r14d
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rbx
testq %rbx, %rbx
je 0x2a5f9
leaq 0x18(%rbx), %rdi
callq 0x6ede0
leaq 0x8(%rbx), %rdi
callq 0xaaf9e
movl $0x58, %esi
movq %rbx, %rdi
callq 0x134f0
incq %r14
movslq 0x2c(%rsp), %rax
cmpq %rax, %r14
jl 0x2a5cc
xorl %r12d, %r12d
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0x2a618
callq 0x13680
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2a62a
callq 0x13680
leaq 0x20(%rsp), %rdi
callq 0xaaf9e
jmp 0x29d07
movq %rax, %r14
movl $0x10, %esi
movq %r12, %rdi
jmp 0x2a66f
jmp 0x2a6c7
movq %rax, %r14
movl $0xf8, %esi
movq %r15, %rdi
jmp 0x2a66f
movq %rax, %r14
movl $0xd0, %esi
movq %r13, %rdi
jmp 0x2a66f
jmp 0x2a6c7
movq %rax, %r14
movl $0xc8, %esi
movq %rbx, %rdi
callq 0x134f0
jmp 0x2a6ca
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
movq %rax, %r14
movq %r13, %rdi
movq %rbx, %rsi
callq 0x139b0
jmp 0x2a6ca
jmp 0x2a6c0
movq %rax, %rbx
jmp 0x2a6a6
movq %rax, %rbx
movq %rbp, %rdi
callq 0xaaf9e
movl $0x58, %esi
movq %r14, %rdi
callq 0x134f0
movq %rbx, %r14
jmp 0x2a6dc
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
jmp 0x2a6c7
movq %rax, %r14
jmp 0x2a6dc
jmp 0x2a6c7
movq %rax, %r14
movq 0xb0(%rsp), %rdi
testq %rdi, %rdi
je 0x2a6dc
callq 0x13680
leaq 0x20(%rsp), %rdi
callq 0xaaf9e
movq %r14, %rdi
callq 0x138b0