// File: tomfunkhouser[P]gaps/apps/msh2pts/msh2pts.cpp
// Function: CreateSignedDistanceGrid(gaps::R3Mesh*, gaps::R3Box const&)
static R3Grid *
CreateSignedDistanceGrid(R3Mesh *mesh, const R3Box& b)
{
  // Allocate grid
  int grid_resolution = 256;
  RNScalar target_spacing = b.LongestAxisLength() / grid_resolution;

  // Allocate grid
  R3Grid *grid = new R3Grid(b, target_spacing, 5, 2*grid_resolution, 5);
  if (!grid) {
    RNFail("Unable to allocate grid\n");
    return NULL;
  }

  // Rasterize each triangle into grid
  for (int i = 0; i < mesh->NFaces(); i++) {
    R3MeshFace *face = mesh->Face(i);
    const R3Point& p0 = mesh->VertexPosition(mesh->VertexOnFace(face, 0));
    const R3Point& p1 = mesh->VertexPosition(mesh->VertexOnFace(face, 1));
    const R3Point& p2 = mesh->VertexPosition(mesh->VertexOnFace(face, 2));
    grid->RasterizeWorldTriangle(p0, p1, p2, i+1, R3_GRID_REPLACE_OPERATION);
  }

  // Estimate distance to closest face (at grid resolution)
  grid->SquaredDistanceTransform();
  grid->Sqrt();
  grid->Multiply(grid->GridToWorldScaleFactor());
  
  // Initialize sign grid
  R3Grid sign_grid(*grid);
  sign_grid.Clear(-1);

  // Seed search with border voxels (assumed outside)
  RNArray<const RNScalar *> stack;
  const RNScalar *sign_grid_values = sign_grid.GridValues();
  RNLength grid_spacing = grid->GridToWorldScaleFactor();
  RNScalar max_grid_value = sqrt(3)*grid_spacing;
  int ix, iy, iz, grid_index;
  for (int i = 0; i < sign_grid.XResolution(); i++) {
    for (int j = 0; j < sign_grid.YResolution(); j++) {
      for (int k = 0; k < sign_grid.ZResolution(); k++) {
        if ((i == 0) || (i == sign_grid.XResolution()-1) ||
            (j == 0) || (j == sign_grid.YResolution()-1) ||
            (k == 0) || (k == sign_grid.ZResolution()-1)) {
          if (grid->GridValue(i, j, k) < grid_spacing) continue;
          sign_grid.IndicesToIndex(i, j, k, grid_index);
          stack.Insert(&sign_grid_values[grid_index]);
          sign_grid.SetGridValue(grid_index, 1);
        }
      }
    }
  }

  // Flood fill
  while (!stack.IsEmpty()) {
    const RNScalar *sign_grid_valuep = stack.Tail(); stack.RemoveTail();
    int grid_index = sign_grid_valuep - sign_grid_values;
    assert((grid_index >= 0) && (grid_index < sign_grid.NEntries()));
    sign_grid.IndexToIndices(grid_index, ix, iy, iz);
    for (int dz = -1; dz <= 1; dz++) {
      int gz = iz + dz;
      if ((gz < 0) || (gz >= sign_grid.ZResolution())) continue;
      for (int dy = -1; dy <= 1; dy++) {
        int gy = iy + dy;
        if ((gy < 0) || (gy >= sign_grid.YResolution())) continue;
        for (int dx = -1; dx <= 1; dx++) {
          int gx = ix + dx;
          if ((gx < 0) || (gx >= sign_grid.XResolution())) continue;
          if (sign_grid.GridValue(gx, gy, gz) > 0) continue;

          // Check if reached the boundary
          RNScalar d = grid->GridValue(ix, iy, iz);
          if (d < max_grid_value) continue;
             
          // Mark cell as outside and continue DFS 
          sign_grid.IndicesToIndex(gx, gy, gz, grid_index);
          stack.Insert(&sign_grid_values[grid_index]);
          sign_grid.SetGridValue(grid_index, 1);
        }
      }
    }
  }
  
  // Apply signs
  sign_grid.Threshold(0, -1, 1);
  grid->Multiply(sign_grid);

  // Return signed distance grid
  return grid;
}

// Assembly:
subq $0x398, %rsp            # imm = 0x398
movq %rdi, 0x388(%rsp)
movq %rsi, 0x380(%rsp)
movl $0x100, 0x37c(%rsp) # imm = 0x100
movq 0x380(%rsp), %rdi
callq 0x721a0
cvtsi2sdl 0x37c(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x370(%rsp)
movl $0x250, %edi            # imm = 0x250
callq 0xf4d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x68(%rsp)
movq 0x380(%rsp), %rsi
movsd 0x370(%rsp), %xmm0
movl 0x37c(%rsp), %ecx
addl %ecx, %ecx
movl $0x5, %r8d
movl %r8d, %edx
callq 0x83ea0
jmp 0x1aa94
movq 0x68(%rsp), %rax
movq %rax, 0x368(%rsp)
cmpq $0x0, 0x368(%rsp)
jne 0x1aaf3
leaq 0x12fc45(%rip), %rdi    # 0x14a6f8
movb $0x0, %al
callq 0xebe00
movq $0x0, 0x390(%rsp)
jmp 0x1b298
movq 0x68(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x360(%rsp)
movl %eax, 0x35c(%rsp)
movl $0x250, %esi            # imm = 0x250
callq 0xf4e0
jmp 0x1b2a8
movl $0x0, 0x358(%rsp)
movl 0x358(%rsp), %eax
movl %eax, 0x64(%rsp)
movq 0x388(%rsp), %rdi
callq 0x1b420
movl %eax, %ecx
movl 0x64(%rsp), %eax
cmpl %ecx, %eax
jge 0x1ac40
movq 0x388(%rsp), %rdi
movl 0x358(%rsp), %esi
callq 0x1b480
movq %rax, 0x350(%rsp)
movq 0x388(%rsp), %rax
movq %rax, 0x48(%rsp)
movq 0x388(%rsp), %rdi
movq 0x350(%rsp), %rsi
xorl %edx, %edx
callq 0x1b870
movq 0x48(%rsp), %rdi
movq %rax, %rsi
callq 0x1b740
movq %rax, 0x348(%rsp)
movq 0x388(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x388(%rsp), %rdi
movq 0x350(%rsp), %rsi
movl $0x1, %edx
callq 0x1b870
movq 0x50(%rsp), %rdi
movq %rax, %rsi
callq 0x1b740
movq %rax, 0x340(%rsp)
movq 0x388(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x388(%rsp), %rdi
movq 0x350(%rsp), %rsi
movl $0x2, %edx
callq 0x1b870
movq 0x58(%rsp), %rdi
movq %rax, %rsi
callq 0x1b740
movq %rax, 0x338(%rsp)
movq 0x368(%rsp), %rdi
movq 0x348(%rsp), %rsi
movq 0x340(%rsp), %rdx
movq 0x338(%rsp), %rcx
movl 0x358(%rsp), %eax
addl $0x1, %eax
cvtsi2sd %eax, %xmm0
movl $0x2, %r8d
callq 0x1f480
movl 0x358(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x358(%rsp)
jmp 0x1aafe
movq 0x368(%rsp), %rdi
callq 0x86d90
movq 0x368(%rsp), %rdi
callq 0x86950
movq 0x368(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x1ba70
movq 0x38(%rsp), %rdi
callq 0x8afa0
movq 0x368(%rsp), %rsi
leaq 0xe8(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x84930
movq 0x40(%rsp), %rdi
movsd 0x12f39b(%rip), %xmm0   # 0x14a038
callq 0x8a6e0
jmp 0x1aca4
leaq 0xd8(%rsp), %rdi
callq 0x1bc80
jmp 0x1acb3
leaq 0xe8(%rsp), %rdi
callq 0x1ba50
movq %rax, 0xd0(%rsp)
movq 0x368(%rsp), %rdi
callq 0x1ba70
movsd %xmm0, 0xc8(%rsp)
movl $0x3, %edi
callq 0x1f520
movsd %xmm0, 0x30(%rsp)
jmp 0x1acf0
movsd 0x30(%rsp), %xmm0
mulsd 0xc8(%rsp), %xmm0
movsd %xmm0, 0xc0(%rsp)
movl $0x0, 0xac(%rsp)
movl 0xac(%rsp), %eax
movl %eax, 0x2c(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bc90
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1af59
movl $0x0, 0xa8(%rsp)
movl 0xa8(%rsp), %eax
movl %eax, 0x28(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcb0
movl %eax, %ecx
movl 0x28(%rsp), %eax
cmpl %ecx, %eax
jge 0x1af41
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x24(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcd0
movl %eax, %ecx
movl 0x24(%rsp), %eax
cmpl %ecx, %eax
jge 0x1af29
cmpl $0x0, 0xac(%rsp)
je 0x1ae30
movl 0xac(%rsp), %eax
movl %eax, 0x20(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bc90
movl %eax, %ecx
movl 0x20(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x1ae30
cmpl $0x0, 0xa8(%rsp)
je 0x1ae30
movl 0xa8(%rsp), %eax
movl %eax, 0x1c(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcb0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x1ae30
cmpl $0x0, 0xa4(%rsp)
je 0x1ae30
movl 0xa4(%rsp), %eax
movl %eax, 0x18(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcd0
movl %eax, %ecx
movl 0x18(%rsp), %eax
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x1af11
movq 0x368(%rsp), %rdi
movl 0xac(%rsp), %esi
movl 0xa8(%rsp), %edx
movl 0xa4(%rsp), %ecx
callq 0x1be30
movaps %xmm0, %xmm1
movsd 0xc8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1aea8
jmp 0x1af13
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x360(%rsp)
movl %eax, 0x35c(%rsp)
jmp 0x1b289
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x360(%rsp)
movl %eax, 0x35c(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x1c080
jmp 0x1b289
movl 0xac(%rsp), %esi
movl 0xa8(%rsp), %edx
movl 0xa4(%rsp), %ecx
leaq 0xe8(%rsp), %rdi
leaq 0xb0(%rsp), %r8
callq 0x1bcf0
movq 0xd0(%rsp), %rax
movslq 0xb0(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xd8(%rsp), %rdi
callq 0x1bd30
jmp 0x1aef5
movl 0xb0(%rsp), %esi
leaq 0xe8(%rsp), %rdi
movsd 0x12f114(%rip), %xmm0   # 0x14a020
callq 0x1bd60
jmp 0x1af13
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x1ad75
jmp 0x1af2b
movl 0xa8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa8(%rsp)
jmp 0x1ad44
jmp 0x1af43
movl 0xac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xac(%rsp)
jmp 0x1ad13
jmp 0x1af5b
leaq 0xd8(%rsp), %rdi
callq 0x1bd90
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x1af79
jmp 0x1b224
leaq 0xd8(%rsp), %rdi
callq 0x1bdb0
movq %rax, 0x10(%rsp)
jmp 0x1af8d
movq 0x10(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x1b580
jmp 0x1afa9
movq 0x98(%rsp), %rax
movq 0xd0(%rsp), %rcx
subq %rcx, %rax
sarq $0x3, %rax
movl %eax, 0x94(%rsp)
movl 0x94(%rsp), %esi
leaq 0xe8(%rsp), %rdi
leaq 0xbc(%rsp), %rdx
leaq 0xb8(%rsp), %rcx
leaq 0xb4(%rsp), %r8
callq 0x1bdc0
movl $0xffffffff, 0x90(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x90(%rsp)
jg 0x1b21f
movl 0xb4(%rsp), %eax
addl 0x90(%rsp), %eax
movl %eax, 0x8c(%rsp)
cmpl $0x0, 0x8c(%rsp)
jl 0x1b04d
movl 0x8c(%rsp), %eax
movl %eax, 0xc(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcd0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jl 0x1b052
jmp 0x1b209
movl $0xffffffff, 0x88(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x88(%rsp)
jg 0x1b207
movl 0xb8(%rsp), %eax
addl 0x88(%rsp), %eax
movl %eax, 0x84(%rsp)
cmpl $0x0, 0x84(%rsp)
jl 0x1b0ac
movl 0x84(%rsp), %eax
movl %eax, 0x8(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bcb0
movl %eax, %ecx
movl 0x8(%rsp), %eax
cmpl %ecx, %eax
jl 0x1b0b1
jmp 0x1b1f1
movl $0xffffffff, 0x80(%rsp) # imm = 0xFFFFFFFF
cmpl $0x1, 0x80(%rsp)
jg 0x1b1ef
movl 0xbc(%rsp), %eax
addl 0x80(%rsp), %eax
movl %eax, 0x7c(%rsp)
cmpl $0x0, 0x7c(%rsp)
jl 0x1b102
movl 0x7c(%rsp), %eax
movl %eax, 0x4(%rsp)
leaq 0xe8(%rsp), %rdi
callq 0x1bc90
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jl 0x1b107
jmp 0x1b1d9
movl 0x7c(%rsp), %esi
movl 0x84(%rsp), %edx
movl 0x8c(%rsp), %ecx
leaq 0xe8(%rsp), %rdi
callq 0x1be30
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x1b134
jmp 0x1b1d9
movq 0x368(%rsp), %rdi
movl 0xbc(%rsp), %esi
movl 0xb8(%rsp), %edx
movl 0xb4(%rsp), %ecx
callq 0x1be30
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm1
movsd 0xc0(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1b173
jmp 0x1b1d9
movl 0x7c(%rsp), %esi
movl 0x84(%rsp), %edx
movl 0x8c(%rsp), %ecx
leaq 0xe8(%rsp), %rdi
leaq 0x94(%rsp), %r8
callq 0x1bcf0
movq 0xd0(%rsp), %rax
movslq 0x94(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xd8(%rsp), %rdi
callq 0x1bd30
jmp 0x1b1bd
movl 0x94(%rsp), %esi
leaq 0xe8(%rsp), %rdi
movsd 0x12ee4c(%rip), %xmm0   # 0x14a020
callq 0x1bd60
movl 0x80(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x80(%rsp)
jmp 0x1b0bc
jmp 0x1b1f1
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x88(%rsp)
jmp 0x1b05d
jmp 0x1b209
movl 0x90(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x90(%rsp)
jmp 0x1affe
jmp 0x1af5b
leaq 0xe8(%rsp), %rdi
xorps %xmm0, %xmm0
movsd 0x12ee01(%rip), %xmm1   # 0x14a038
movsd 0x12ede1(%rip), %xmm2   # 0x14a020
callq 0x879c0
jmp 0x1b246
movq 0x368(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x8b010
jmp 0x1b25d
movq 0x368(%rsp), %rax
movq %rax, 0x390(%rsp)
leaq 0xd8(%rsp), %rdi
callq 0x1c080
leaq 0xe8(%rsp), %rdi
callq 0x849d0
jmp 0x1b298
leaq 0xe8(%rsp), %rdi
callq 0x849d0
jmp 0x1b2a8
movq 0x390(%rsp), %rax
addq $0x398, %rsp            # imm = 0x398
retq
movq 0x360(%rsp), %rdi
callq 0xf8a0
nopw %cs:(%rax,%rax)
nop