// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::VisitResidentSurfels(gaps::R3SurfelScene*, void (*)(gaps::R3SurfelBlock const*, gaps::R3Surfel const*, void*), gaps::R3SurfelNode*, gaps::R3SurfelConstraint const*, void*)
void
VisitResidentSurfels(R3SurfelScene *scene,
  void (*callback_function)(const R3SurfelBlock *block, const R3Surfel *surfel, void *callback_data),
  R3SurfelNode *source_node,
  const R3SurfelConstraint *constraint,
  void *callback_data)
{
  // Check node
  if (constraint && !constraint->Check(source_node)) return;

  // Check if leaf node
  if (source_node->NParts() == 0) {
    // Visit blocks
    for (int i = 0; i < source_node->NBlocks(); i++) {
      R3SurfelBlock *block = source_node->Block(i);
      if (block->NSurfels() == 0) continue;
      if (!constraint->Check(block->BBox())) continue;
      if (block->Database() && !block->Database()->IsBlockResident(block)) continue;

      // Visit surfels
      for (int i = 0; i < block->NSurfels(); i++) {
        const R3Surfel *surfel = block->Surfel(i);
        if (!constraint->Check(block, surfel)) continue;
        (*callback_function)(block, surfel, callback_data);
      }
    }
  }
  else {
    // Consider parts
    for (int i = 0; i < source_node->NParts(); i++) {
      R3SurfelNode *part = source_node->Part(i);
      VisitResidentSurfels(scene, callback_function, part, constraint, callback_data);
    }
  }
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x70(%rsp)
movq %rsi, 0x68(%rsp)
movq %rdx, 0x60(%rsp)
movq %rcx, 0x58(%rsp)
movq %r8, 0x50(%rsp)
cmpq $0x0, 0x58(%rsp)
je 0x33a2f
movq 0x58(%rsp), %rdi
movq 0x60(%rsp), %rsi
movq (%rdi), %rax
callq *0x18(%rax)
cmpl $0x0, %eax
jne 0x33a2f
jmp 0x33bd9
movq 0x60(%rsp), %rdi
callq 0x31660
cmpl $0x0, %eax
jne 0x33b75
movl $0x0, 0x4c(%rsp)
movl 0x4c(%rsp), %eax
movl %eax, 0x1c(%rsp)
movq 0x60(%rsp), %rdi
callq 0x186b0
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x33b73
movq 0x60(%rsp), %rdi
movl 0x4c(%rsp), %esi
callq 0x186d0
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
callq 0x1c0e0
cmpl $0x0, %eax
jne 0x33a91
jmp 0x33b63
movq 0x58(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x40(%rsp), %rdi
callq 0x4a500
movq 0x10(%rsp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
callq *0x30(%rax)
cmpl $0x0, %eax
jne 0x33abd
jmp 0x33b63
movq 0x40(%rsp), %rdi
callq 0x43610
cmpq $0x0, %rax
je 0x33aeb
movq 0x40(%rsp), %rdi
callq 0x43610
movq %rax, %rdi
movq 0x40(%rsp), %rsi
callq 0x43630
cmpl $0x0, %eax
jne 0x33aeb
jmp 0x33b63
movl $0x0, 0x3c(%rsp)
movl 0x3c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x40(%rsp), %rdi
callq 0x1c0e0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x33b61
movq 0x40(%rsp), %rdi
movl 0x3c(%rsp), %esi
callq 0x43660
movq %rax, 0x30(%rsp)
movq 0x58(%rsp), %rdi
movq 0x40(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq (%rdi), %rax
callq *0x28(%rax)
cmpl $0x0, %eax
jne 0x33b3e
jmp 0x33b54
movq 0x68(%rsp), %rax
movq 0x40(%rsp), %rdi
movq 0x30(%rsp), %rsi
movq 0x50(%rsp), %rdx
callq *%rax
movl 0x3c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c(%rsp)
jmp 0x33af3
jmp 0x33b63
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x33a4a
jmp 0x33bd9
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x8(%rsp)
movq 0x60(%rsp), %rdi
callq 0x31660
movl %eax, %ecx
movl 0x8(%rsp), %eax
cmpl %ecx, %eax
jge 0x33bd7
movq 0x60(%rsp), %rdi
movl 0x2c(%rsp), %esi
callq 0x43680
movq %rax, 0x20(%rsp)
movq 0x70(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x20(%rsp), %rdx
movq 0x58(%rsp), %rcx
movq 0x50(%rsp), %r8
callq 0x339f0
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x33b7d
jmp 0x33bd9
addq $0x78, %rsp
retq
nop