// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::MaskToSeededConnectedComponent(gaps::R3Grid&, gaps::R3Grid const&, double)
static int 
MaskToSeededConnectedComponent(R3Grid& grid, const R3Grid& seeds, RNScalar isolevel)
{
  // Allocate grid of marks
  R3Grid marks(grid);
  marks.Clear(0);

  // Initialize stack 
  const RNScalar *grid_values = grid.GridValues();
  RNArray<const RNScalar *> stack;
  for (int i = 0; i < grid.NEntries(); i++) {
    RNScalar seed_value = seeds.GridValue(i);
    if (seed_value == 0) continue;
    RNScalar grid_value = grid.GridValue(i);
    if (grid_value > isolevel) {
      stack.Insert(&grid_values[i]);
      marks.SetGridValue(i, 1.0);
    }
    else {
      marks.SetGridValue(i, -1.0);
    }
  }

  // Find connected grid cells
  while (!stack.IsEmpty()) {
    // Pop tail off stack
    const RNScalar *grid_valuesp = stack.Tail();
    stack.RemoveTail();

    // Get grid index
    int grid_index = grid_valuesp - grid_values;
    assert(grid_index >= 0);
    assert(grid_index < grid.NEntries());
    assert(marks.GridValue(grid_index) == 1.0);
    assert(grid.GridValue(grid_index) > isolevel);

    // Mark connected neighbors
    int cx, cy, cz, neighbor_index;
    grid.IndexToIndices(grid_index, cx, cy, cz);
    for (int i = 0; i < 6; i++) {
      int ix = (i == 0) ? cx-1 : ((i == 1) ? cx+1 : cx);
      if ((ix >= 0) && (ix < grid.XResolution())) {
        int iy = (i == 2) ? cy-1 : ((i == 3) ? cy+1 : cy);
        if ((iy >= 0) && (iy < grid.YResolution())) {
          int iz = (i == 4) ? cz-1 : ((i == 5) ? cz+1 : cz);
          if ((iz >= 0) && (iz < grid.ZResolution())) {
            grid.IndicesToIndex(ix, iy, iz, neighbor_index);
            if (marks.GridValue(neighbor_index) == 0.0) {
              RNScalar neighbor_value = grid.GridValue(neighbor_index);
              if (neighbor_value > isolevel) {
                stack.Insert(&grid_values[neighbor_index]);
                marks.SetGridValue(neighbor_index, 1.0);
              }
              else {
                marks.SetGridValue(neighbor_index, -1.0);
              }
            }
          }
        }
      }
    }
  }

  // Mask grid
  marks.Threshold(0.5, 0.0, 1.0);
  grid.Mask(marks);

  // Return success
  return 1;
}

// Assembly:
subq $0x348, %rsp            # imm = 0x348
movq %rdi, 0x340(%rsp)
movq %rsi, 0x338(%rsp)
movsd %xmm0, 0x330(%rsp)
movq 0x340(%rsp), %rsi
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0xdffb0
movq 0x60(%rsp), %rdi
xorps %xmm0, %xmm0
callq 0xe5d60
jmp 0x3ae69
movq 0x340(%rsp), %rdi
callq 0x45650
movq %rax, 0x58(%rsp)
jmp 0x3ae7d
movq 0x58(%rsp), %rax
movq %rax, 0xc8(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x45670
jmp 0x3ae99
movl $0x0, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
movl %eax, 0x54(%rsp)
movq 0x340(%rsp), %rdi
callq 0x43fd0
movl %eax, %ecx
movl 0x54(%rsp), %eax
cmpl %ecx, %eax
jge 0x3b001
movq 0x338(%rsp), %rdi
movl 0xb4(%rsp), %esi
callq 0x45680
movsd %xmm0, 0x48(%rsp)
jmp 0x3aee6
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0xa8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3af4d
jp 0x3af4d
jmp 0x3afeb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
jmp 0x3b39a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xd8(%rsp)
movl %eax, 0xd4(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x456e0
jmp 0x3b39a
movq 0x340(%rsp), %rdi
movl 0xb4(%rsp), %esi
callq 0x45680
movsd %xmm0, 0x40(%rsp)
jmp 0x3af69
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movsd 0xa0(%rsp), %xmm0
ucomisd 0x330(%rsp), %xmm0
jbe 0x3afcd
movq 0xc8(%rsp), %rax
movslq 0xb4(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x456a0
jmp 0x3afaf
movl 0xb4(%rsp), %esi
leaq 0xe0(%rsp), %rdi
movsd 0x1691a2(%rip), %xmm0   # 0x1a4168
callq 0x45490
jmp 0x3afe9
movl 0xb4(%rsp), %esi
leaq 0xe0(%rsp), %rdi
movsd 0x16919c(%rip), %xmm0   # 0x1a4180
callq 0x45490
jmp 0x3afeb
movl 0xb4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb4(%rsp)
jmp 0x3aea4
jmp 0x3b003
leaq 0xb8(%rsp), %rdi
callq 0x31da0
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x3b021
jmp 0x3b33a
leaq 0xb8(%rsp), %rdi
callq 0x456d0
movq %rax, 0x38(%rsp)
jmp 0x3b035
movq 0x38(%rsp), %rax
movq %rax, 0x98(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x1c0c0
jmp 0x3b051
movq 0x98(%rsp), %rax
movq 0xc8(%rsp), %rcx
subq %rcx, %rax
sarq $0x3, %rax
movl %eax, 0x94(%rsp)
movq 0x340(%rsp), %rdi
movl 0x94(%rsp), %esi
leaq 0x90(%rsp), %rdx
leaq 0x8c(%rsp), %rcx
leaq 0x88(%rsp), %r8
callq 0x45560
movl $0x0, 0x80(%rsp)
cmpl $0x6, 0x80(%rsp)
jge 0x3b335
cmpl $0x0, 0x80(%rsp)
jne 0x3b0ce
movl 0x90(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0x3b0fb
cmpl $0x1, 0x80(%rsp)
jne 0x3b0e8
movl 0x90(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x3b0f3
movl 0x90(%rsp), %eax
movl %eax, 0x30(%rsp)
movl 0x30(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x34(%rsp), %eax
movl %eax, 0x7c(%rsp)
cmpl $0x0, 0x7c(%rsp)
jl 0x3b31d
movl 0x7c(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x340(%rsp), %rdi
callq 0x454c0
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x3b31d
cmpl $0x2, 0x80(%rsp)
jne 0x3b14b
movl 0x8c(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x28(%rsp)
jmp 0x3b178
cmpl $0x3, 0x80(%rsp)
jne 0x3b165
movl 0x8c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x3b170
movl 0x8c(%rsp), %eax
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %eax
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %eax
movl %eax, 0x78(%rsp)
cmpl $0x0, 0x78(%rsp)
jl 0x3b31b
movl 0x78(%rsp), %eax
movl %eax, 0x20(%rsp)
movq 0x340(%rsp), %rdi
callq 0x454e0
movl %eax, %ecx
movl 0x20(%rsp), %eax
cmpl %ecx, %eax
jge 0x3b31b
cmpl $0x4, 0x80(%rsp)
jne 0x3b1c8
movl 0x88(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x3b1f5
cmpl $0x5, 0x80(%rsp)
jne 0x3b1e2
movl 0x88(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0x3b1ed
movl 0x88(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0x18(%rsp), %eax
movl %eax, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movl %eax, 0x74(%rsp)
cmpl $0x0, 0x74(%rsp)
jl 0x3b319
movl 0x74(%rsp), %eax
movl %eax, 0x14(%rsp)
movq 0x340(%rsp), %rdi
callq 0x45500
movl %eax, %ecx
movl 0x14(%rsp), %eax
cmpl %ecx, %eax
jge 0x3b319
movq 0x340(%rsp), %rdi
movl 0x7c(%rsp), %esi
movl 0x78(%rsp), %edx
movl 0x74(%rsp), %ecx
leaq 0x84(%rsp), %r8
callq 0x45520
movl 0x84(%rsp), %esi
leaq 0xe0(%rsp), %rdi
callq 0x45680
movsd %xmm0, 0x8(%rsp)
jmp 0x3b268
movsd 0x8(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3b317
jp 0x3b317
movq 0x340(%rsp), %rdi
movl 0x84(%rsp), %esi
callq 0x45680
movsd %xmm0, (%rsp)
jmp 0x3b29c
movsd (%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movsd 0x68(%rsp), %xmm0
ucomisd 0x330(%rsp), %xmm0
jbe 0x3b2f9
movq 0xc8(%rsp), %rax
movslq 0x84(%rsp), %rcx
leaq (%rax,%rcx,8), %rsi
leaq 0xb8(%rsp), %rdi
callq 0x456a0
jmp 0x3b2db
movl 0x84(%rsp), %esi
leaq 0xe0(%rsp), %rdi
movsd 0x168e76(%rip), %xmm0   # 0x1a4168
callq 0x45490
jmp 0x3b315
movl 0x84(%rsp), %esi
leaq 0xe0(%rsp), %rdi
movsd 0x168e70(%rip), %xmm0   # 0x1a4180
callq 0x45490
jmp 0x3b317
jmp 0x3b319
jmp 0x3b31b
jmp 0x3b31d
jmp 0x3b31f
movl 0x80(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x80(%rsp)
jmp 0x3b0a6
jmp 0x3b003
leaq 0xe0(%rsp), %rdi
movsd 0x168e0e(%rip), %xmm0   # 0x1a4158
xorps %xmm1, %xmm1
movsd 0x168e13(%rip), %xmm2   # 0x1a4168
callq 0xe3040
jmp 0x3b35c
movq 0x340(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0xe69c0
jmp 0x3b373
leaq 0xb8(%rsp), %rdi
callq 0x456e0
leaq 0xe0(%rsp), %rdi
callq 0xe0050
movl $0x1, %eax
addq $0x348, %rsp            # imm = 0x348
retq
leaq 0xe0(%rsp), %rdi
callq 0xe0050
movq 0xd8(%rsp), %rdi
callq 0x13970
nopw %cs:(%rax,%rax)