// File: tomfunkhouser[P]gaps/apps/msh2df/msh2df.cpp
// Function: RefineDistanceUsingKdtree(gaps::R3Grid*, gaps::R3Mesh*, int)
static int
RefineDistanceUsingKdtree(R3Grid *grid, R3Mesh *mesh, int refinement_radius)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Create mesh search tree
  R3MeshSearchTree search_tree(mesh);

  // Compute the precise distance at every grid cell
  RNLength grid_spacing = grid->GridToWorldScaleFactor();
  RNScalar max_distance = refinement_radius * grid_spacing;
  if (max_distance > mesh->BBox().DiagonalLength()) max_distance = mesh->BBox().DiagonalLength();
  if (max_distance > truncation_distance) max_distance = truncation_distance;
  for (int iz = 0; iz < grid->ZResolution(); iz++) {
    for (int iy = 0; iy < grid->YResolution(); iy++) {
      for (int ix = 0; ix < grid->XResolution(); ix++) {
        R3Point world_position = grid->WorldPosition(ix, iy, iz);
        RNScalar grid_distance = grid->GridValue(ix, iy, iz);
        RNScalar sign = (grid_distance >= 0) ? 1 : -1;
        grid_distance = fabs(grid_distance);
        if (grid_distance > max_distance) continue;
        RNScalar distance = (grid_distance > grid_spacing) ? grid_distance : grid_spacing;
        while (distance < max_distance) {
          distance *= 1.25;
          R3MeshIntersection closest;
          search_tree.FindClosest(world_position, closest, 0, distance);
          if (closest.type != R3_MESH_NULL_TYPE) {
            grid->SetGridValue(ix, iy, iz, sign * closest.t);
            break;
          }
        }
      }
    }
  }
  
  // Print statistics
  if (print_verbose) {
    printf("Refined distance using kdtree ...\n");
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  Resolution = %d %d %d\n", grid->XResolution(), grid->YResolution(), grid->ZResolution());
    printf("  Spacing = %g\n", grid->GridToWorldScaleFactor());
    printf("  Cardinality = %d\n", grid->Cardinality());
    printf("  Volume = %g\n", grid->Volume());
    RNInterval grid_range = grid->Range();
    printf("  Minimum = %g\n", grid_range.Min());
    printf("  Maximum = %g\n", grid_range.Max());
    printf("  L1Norm = %g\n", grid->L1Norm());
    printf("  L2Norm = %g\n", grid->L2Norm());
    printf("  Refinement grid radius = %d\n", refinement_radius);
    printf("  Refinement world radius = %g\n", max_distance);
    fflush(stdout);
  }

  // Return success
  return 1;
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movq %rdi, 0x150(%rsp)
movq %rsi, 0x148(%rsp)
movl %edx, 0x144(%rsp)
leaq 0x130(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0xddf30
movq 0x58(%rsp), %rdi
callq 0x17860
movq 0x148(%rsp), %rsi
leaq 0x118(%rsp), %rdi
callq 0x1b120
movq 0x150(%rsp), %rdi
callq 0x17b20
movsd %xmm0, 0x110(%rsp)
cvtsi2sdl 0x144(%rsp), %xmm0
movsd 0x110(%rsp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x108(%rsp)
movsd 0x108(%rsp), %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x148(%rsp), %rdi
callq 0x17740
movq %rax, %rdi
callq 0x685a0
movsd %xmm0, 0x68(%rsp)
jmp 0x13880
movsd 0x60(%rsp), %xmm0
movsd 0x68(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x138e6
movq 0x148(%rsp), %rdi
callq 0x17740
movq %rax, %rdi
callq 0x685a0
movsd %xmm0, 0x50(%rsp)
jmp 0x138af
movsd 0x50(%rsp), %xmm0
movsd %xmm0, 0x108(%rsp)
jmp 0x138e6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x100(%rsp)
movl %eax, 0xfc(%rsp)
leaq 0x118(%rsp), %rdi
callq 0x1b2e0
jmp 0x13db3
movsd 0x108(%rsp), %xmm0
ucomisd 0x172ce9(%rip), %xmm0   # 0x1865e0
jbe 0x1390a
movsd 0x172cdf(%rip), %xmm0   # 0x1865e0
movsd %xmm0, 0x108(%rsp)
movl $0x0, 0xf8(%rsp)
movl 0xf8(%rsp), %eax
movl %eax, 0x4c(%rsp)
movq 0x150(%rsp), %rdi
callq 0x17b80
movl %eax, %ecx
movl 0x4c(%rsp), %eax
cmpl %ecx, %eax
jge 0x13bba
movl $0x0, 0xf4(%rsp)
movl 0xf4(%rsp), %eax
movl %eax, 0x48(%rsp)
movq 0x150(%rsp), %rdi
callq 0x17b60
movl %eax, %ecx
movl 0x48(%rsp), %eax
cmpl %ecx, %eax
jge 0x13ba2
movl $0x0, 0xf0(%rsp)
movl 0xf0(%rsp), %eax
movl %eax, 0x44(%rsp)
movq 0x150(%rsp), %rdi
callq 0x17b40
movl %eax, %ecx
movl 0x44(%rsp), %eax
cmpl %ecx, %eax
jge 0x13b8a
movq 0x150(%rsp), %rsi
cvtsi2sdl 0xf0(%rsp), %xmm0
cvtsi2sdl 0xf4(%rsp), %xmm1
cvtsi2sdl 0xf8(%rsp), %xmm2
leaq 0xd8(%rsp), %rdi
callq 0x87100
jmp 0x139cf
movq 0x150(%rsp), %rdi
movl 0xf0(%rsp), %esi
movl 0xf4(%rsp), %edx
movl 0xf8(%rsp), %ecx
callq 0x17e80
movsd %xmm0, 0x38(%rsp)
jmp 0x139f9
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0xd0(%rsp)
movsd 0xd0(%rsp), %xmm0
xorps %xmm1, %xmm1
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl $0x1, %ecx
ucomisd %xmm1, %xmm0
cmovael %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0xc8(%rsp)
movsd 0xd0(%rsp), %xmm0
movaps 0x12c61e(%rip), %xmm1   # 0x140060
pand %xmm1, %xmm0
movsd %xmm0, 0xd0(%rsp)
movsd 0xd0(%rsp), %xmm0
ucomisd 0x108(%rsp), %xmm0
jbe 0x13a68
jmp 0x13b74
movsd 0xd0(%rsp), %xmm0
ucomisd 0x110(%rsp), %xmm0
jbe 0x13a8d
movsd 0xd0(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x13a9c
movsd 0x110(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0xc0(%rsp)
movsd 0xc0(%rsp), %xmm1
movsd 0x108(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x13b72
movsd 0xc0(%rsp), %xmm0
movsd 0x12c540(%rip), %xmm1   # 0x140018
mulsd %xmm1, %xmm0
movsd %xmm0, 0xc0(%rsp)
leaq 0x80(%rsp), %rdi
callq 0x17ed0
jmp 0x13af4
movsd 0xc0(%rsp), %xmm1
xorl %eax, %eax
movl %eax, %r8d
leaq 0x118(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0x80(%rsp), %rdx
xorps %xmm0, %xmm0
movq %r8, %rcx
callq 0x1e510
jmp 0x13b27
cmpl $0x0, 0x80(%rsp)
je 0x13b6d
movq 0x150(%rsp), %rdi
movl 0xf0(%rsp), %esi
movl 0xf4(%rsp), %edx
movl 0xf8(%rsp), %ecx
movsd 0xc8(%rsp), %xmm0
movsd 0xb8(%rsp), %xmm1
mulsd %xmm1, %xmm0
callq 0x17ef0
jmp 0x13b6b
jmp 0x13b72
jmp 0x13aab
jmp 0x13b74
movl 0xf0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf0(%rsp)
jmp 0x13977
jmp 0x13b8c
movl 0xf4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf4(%rsp)
jmp 0x13946
jmp 0x13ba4
movl 0xf8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf8(%rsp)
jmp 0x13915
cmpl $0x0, 0x172a37(%rip)    # 0x1865f8
je 0x13d99
leaq 0x12c74c(%rip), %rdi    # 0x14031a
xorl %eax, %eax
callq 0xf070
jmp 0x13bd7
leaq 0x130(%rsp), %rdi
callq 0xddff0
movsd %xmm0, 0x28(%rsp)
jmp 0x13bec
movsd 0x28(%rsp), %xmm0
leaq 0x12c62a(%rip), %rdi    # 0x140223
movb $0x1, %al
callq 0xf070
jmp 0x13c02
movq 0x150(%rsp), %rdi
callq 0x17b40
movl %eax, 0x20(%rsp)
movq 0x150(%rsp), %rdi
callq 0x17b60
movl %eax, 0x24(%rsp)
movq 0x150(%rsp), %rdi
callq 0x17b80
movl 0x20(%rsp), %esi
movl 0x24(%rsp), %edx
movl %eax, %ecx
leaq 0x12c64e(%rip), %rdi    # 0x140290
xorl %eax, %eax
callq 0xf070
jmp 0x13c4b
movq 0x150(%rsp), %rdi
callq 0x17b20
leaq 0x12c64a(%rip), %rdi    # 0x1402a9
movb $0x1, %al
callq 0xf070
jmp 0x13c68
movq 0x150(%rsp), %rdi
callq 0x7b1f0
movl %eax, 0x1c(%rsp)
jmp 0x13c7b
movl 0x1c(%rsp), %esi
leaq 0x12c633(%rip), %rdi    # 0x1402b9
xorl %eax, %eax
callq 0xf070
jmp 0x13c8f
movq 0x150(%rsp), %rdi
callq 0x17ba0
movsd %xmm0, 0x10(%rsp)
jmp 0x13ca4
movsd 0x10(%rsp), %xmm0
leaq 0x12c61c(%rip), %rdi    # 0x1402cd
movb $0x1, %al
callq 0xf070
jmp 0x13cba
movq 0x150(%rsp), %rsi
leaq 0x70(%rsp), %rdi
callq 0x7aff0
jmp 0x13cce
leaq 0x70(%rsp), %rdi
callq 0x17be0
leaq 0x12c5fd(%rip), %rdi    # 0x1402dc
movb $0x1, %al
callq 0xf070
jmp 0x13ce8
leaq 0x70(%rsp), %rdi
callq 0x17bf0
leaq 0x12c5f3(%rip), %rdi    # 0x1402ec
movb $0x1, %al
callq 0xf070
jmp 0x13d02
movq 0x150(%rsp), %rdi
callq 0x7b0e0
movsd %xmm0, 0x8(%rsp)
jmp 0x13d17
movsd 0x8(%rsp), %xmm0
leaq 0x12c5d8(%rip), %rdi    # 0x1402fc
movb $0x1, %al
callq 0xf070
jmp 0x13d2d
movq 0x150(%rsp), %rdi
callq 0x17c00
movsd %xmm0, (%rsp)
jmp 0x13d41
movsd (%rsp), %xmm0
leaq 0x12c5be(%rip), %rdi    # 0x14030b
movb $0x1, %al
callq 0xf070
jmp 0x13d56
movl 0x144(%rsp), %esi
leaq 0x12c5d9(%rip), %rdi    # 0x14033d
xorl %eax, %eax
callq 0xf070
jmp 0x13d6d
movsd 0x108(%rsp), %xmm0
leaq 0x12c5df(%rip), %rdi    # 0x14035c
movb $0x1, %al
callq 0xf070
jmp 0x13d86
movq 0x169203(%rip), %rax    # 0x17cf90
movq (%rax), %rdi
callq 0xf5d0
jmp 0x13d97
jmp 0x13d99
leaq 0x118(%rsp), %rdi
callq 0x1b2e0
movl $0x1, %eax
addq $0x158, %rsp            # imm = 0x158
retq
movq 0x100(%rsp), %rdi
callq 0xf890