// File: tomfunkhouser[P]gaps/apps/mshalign/mshalign.cpp
// Function: CreatePointPointCorrespondences(gaps::R3Mesh*, gaps::R3Point const*, int, gaps::R3Mesh*, gaps::R3Point const*, int, gaps::R3Affine const&, gaps::R3Affine const&, gaps::R3Point*, gaps::R3Point*, int)
static int
CreatePointPointCorrespondences(
  R3Mesh *mesh1, const R3Point *points1, int npoints1,
  R3Mesh *mesh2, const R3Point *points2, int npoints2, 
  const R3Affine& affine12, const R3Affine& affine21,
  R3Point *correspondences1, R3Point *correspondences2, 
  int max_correspondences)
{
  // Build kdtree for points1
  static R3Kdtree<const R3Point *> *tree1 = NULL;
  if (!tree1) {
    RNArray<const R3Point *> array1;
    for (int i = 0; i < npoints1; i++) array1.Insert(&points1[i]);
    tree1 = new R3Kdtree<const R3Point *>(array1);
  }

  // Build kdtree for points2
  static R3Kdtree<const R3Point *> *tree2 = NULL;
  if (!tree2) {
    RNArray<const R3Point *> array2;
    for (int i = 0; i < npoints2; i++) array2.Insert(&points2[i]);
    tree2 = new R3Kdtree<const R3Point *>(array2);
  }

  // Initialize number of correspondences
  assert(max_correspondences == npoints1 + npoints2);
  int ncorrespondences = 0;

  // Compute correspondences for points1 -> mesh2
  for (int i = 0; i < npoints1; i++) {
    R3Point position1 = points1[i];
    position1.Transform(affine12);
    const R3Point *closest = tree2->FindClosest(position1);
    assert(ncorrespondences < max_correspondences);
    correspondences1[ncorrespondences] = points1[i];
    correspondences2[ncorrespondences] = *closest;
    ncorrespondences++;
  }

  // Compute correspondences for points2 -> mesh1
  for (int i = 0; i < npoints2; i++) {
    R3Point position2 = points2[i];
    position2.Transform(affine21);
    const R3Point *closest = tree1->FindClosest(position2);
    assert(ncorrespondences < max_correspondences);
    correspondences1[ncorrespondences] = *closest;
    correspondences2[ncorrespondences] = points2[i];
    ncorrespondences++;
  }

  // Return number of correspondences
  assert(ncorrespondences == npoints1 + npoints2);
  assert(ncorrespondences == max_correspondences);
  return ncorrespondences;
}

// Assembly:
subq $0xd8, %rsp
movl 0x100(%rsp), %eax
movq 0xf8(%rsp), %rax
movq 0xf0(%rsp), %rax
movq 0xe8(%rsp), %rax
movq 0xe0(%rsp), %rax
movq %rdi, 0xd0(%rsp)
movq %rsi, 0xc8(%rsp)
movl %edx, 0xc4(%rsp)
movq %rcx, 0xb8(%rsp)
movq %r8, 0xb0(%rsp)
movl %r9d, 0xac(%rsp)
cmpq $0x0, 0xb8543(%rip)     # 0xcdc28
jne 0x157dc
leaq 0x98(%rsp), %rdi
callq 0x16630
movl $0x0, 0x94(%rsp)
movl 0x94(%rsp), %eax
cmpl 0xc4(%rsp), %eax
jge 0x15765
movq 0xc8(%rsp), %rax
movslq 0x94(%rsp), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x98(%rsp), %rdi
callq 0x16640
jmp 0x1573a
jmp 0x1573c
movl 0x94(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x94(%rsp)
jmp 0x15703
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
jmp 0x157ca
movl $0x60, %edi
callq 0xd3d0
movq %rax, 0x10(%rsp)
jmp 0x15776
movq 0x10(%rsp), %rdi
leaq 0x98(%rsp), %rsi
xorl %edx, %edx
callq 0x16670
jmp 0x1578c
movq 0x10(%rsp), %rax
movq %rax, 0xb8490(%rip)     # 0xcdc28
leaq 0x98(%rsp), %rdi
callq 0x16910
jmp 0x157dc
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
movl $0x60, %esi
callq 0xd3e0
leaq 0x98(%rsp), %rdi
callq 0x16910
jmp 0x15a79
cmpq $0x0, 0xb844c(%rip)     # 0xcdc30
jne 0x158bd
leaq 0x70(%rsp), %rdi
callq 0x16630
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x1584f
movq 0xb0(%rsp), %rax
movslq 0x6c(%rsp), %rcx
leaq (%rcx,%rcx,2), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0x70(%rsp), %rdi
callq 0x16640
jmp 0x1582a
jmp 0x1582c
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x157fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
jmp 0x158ae
movl $0x60, %edi
callq 0xd3d0
movq %rax, 0x8(%rsp)
jmp 0x15860
movq 0x8(%rsp), %rdi
leaq 0x70(%rsp), %rsi
xorl %edx, %edx
callq 0x16670
jmp 0x15873
movq 0x8(%rsp), %rax
movq %rax, 0xb83b1(%rip)     # 0xcdc30
leaq 0x70(%rsp), %rdi
callq 0x16910
jmp 0x158bd
movq 0x8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x88(%rsp)
movl %eax, 0x84(%rsp)
movl $0x60, %esi
callq 0xd3e0
leaq 0x70(%rsp), %rdi
callq 0x16910
jmp 0x15a79
movl $0x0, 0x68(%rsp)
movl $0x0, 0x64(%rsp)
movl 0x64(%rsp), %eax
cmpl 0xc4(%rsp), %eax
jge 0x15999
movq 0xc8(%rsp), %rsi
movslq 0x64(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x48(%rsp), %rdi
callq 0x7d390
movq 0xe0(%rsp), %rsi
leaq 0x48(%rsp), %rdi
callq 0x7dfc0
movq 0xb831b(%rip), %rdi     # 0xcdc30
leaq 0x48(%rsp), %rsi
xorps %xmm0, %xmm0
movsd 0x9170b(%rip), %xmm1    # 0xa7030
xorl %eax, %eax
movl %eax, %edx
callq 0x16920
movq %rax, 0x40(%rsp)
movq 0xc8(%rsp), %rsi
movslq 0x64(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
movq 0xf0(%rsp), %rdi
movslq 0x68(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x7d9e0
movq 0x40(%rsp), %rsi
movq 0xf8(%rsp), %rdi
movslq 0x68(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x7d9e0
movl 0x68(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x68(%rsp)
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0x158cd
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x15a6d
movq 0xb0(%rsp), %rsi
movslq 0x3c(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x20(%rsp), %rdi
callq 0x7d390
movq 0xe8(%rsp), %rsi
leaq 0x20(%rsp), %rdi
callq 0x7dfc0
movq 0xb823f(%rip), %rdi     # 0xcdc28
leaq 0x20(%rsp), %rsi
xorps %xmm0, %xmm0
movsd 0x91637(%rip), %xmm1    # 0xa7030
xorl %eax, %eax
movl %eax, %edx
callq 0x16920
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rsi
movq 0xf0(%rsp), %rdi
movslq 0x68(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x7d9e0
movq 0xb0(%rsp), %rsi
movslq 0x3c(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rsi
movq 0xf8(%rsp), %rdi
movslq 0x68(%rsp), %rax
imulq $0x18, %rax, %rax
addq %rax, %rdi
callq 0x7d9e0
movl 0x68(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x68(%rsp)
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x159a1
movl 0x68(%rsp), %eax
addq $0xd8, %rsp
retq
movq 0x88(%rsp), %rdi
callq 0xd6a0
nopw %cs:(%rax,%rax)