// File: tomfunkhouser[P]gaps/pkgs/R3Surfels/R3SurfelUtils.cpp
// Function: gaps::InsertNodes(gaps::R3SurfelNodeSet*, gaps::R3SurfelTree*, gaps::R3SurfelNode*, gaps::R3SurfelConstraint const*, gaps::R3Point const&, double, double, double, double)
static int
InsertNodes(R3SurfelNodeSet *nodeset, 
  R3SurfelTree *tree, R3SurfelNode *node,
  const R3SurfelConstraint *constraint,
  const R3Point& xycenter, RNLength xyradius,
  RNScalar center_resolution, RNScalar perimeter_resolution,
  RNScalar focus_exponent)
{
  // Check if node satisfies constraint
  if (constraint && !constraint->Check(node)) {
    return 0;
  }

  // Check if node is outside perimeter
  if ((perimeter_resolution == 0) && (xyradius > 0)) {
    RNScalar xydistance = XYDistance(xycenter, node->BBox());
    if (xydistance > xyradius) return 0;
  }

  // Check if this node is a leaf
  if (node->NParts() == 0) {
    nodeset->InsertNode(node);
    return 1;
  }

  // Check if this node has target resolution 
  if ((node->NBlocks() > 0) && (center_resolution > 0)) {
    // Compute the target resolution at node
    RNScalar target_resolution = center_resolution;
    if ((xyradius > 0) && (perimeter_resolution < center_resolution)) {
      RNLength xydistance =  XYDistance(xycenter, node->BBox());
      RNScalar t = 1 - xydistance / xyradius;
      target_resolution = perimeter_resolution + 
        (center_resolution - perimeter_resolution) * pow(t, focus_exponent);
    }
      
    // Check if this node is within the target resolution
    for (int i = 0; i < node->NParts(); i++) {
      R3SurfelNode *part = node->Part(i);
      if (part->Resolution() > target_resolution) {
        nodeset->InsertNode(node);
        return 1;
      }
    }
  }

  // Consider parts
  int status = 0;
  for (int i = 0; i < node->NParts(); i++) {
    R3SurfelNode *part = node->Part(i);
    status |= InsertNodes(nodeset, tree, part, constraint, xycenter, xyradius, 
      center_resolution, perimeter_resolution, focus_exponent);
  }

  // Return whether anything was added
  return status;
}

// Assembly:
subq $0xb8, %rsp
movq %rdi, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movq %rdx, 0x98(%rsp)
movq %rcx, 0x90(%rsp)
movq %r8, 0x88(%rsp)
movsd %xmm0, 0x80(%rsp)
movsd %xmm1, 0x78(%rsp)
movsd %xmm2, 0x70(%rsp)
movsd %xmm3, 0x68(%rsp)
cmpq $0x0, 0x90(%rsp)
je 0x3c980
movq 0x90(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
callq *0x18(%rax)
cmpl $0x0, %eax
jne 0x3c980
movl $0x0, 0xb4(%rsp)
jmp 0x3cc57
movsd 0x70(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x3c9f3
jp 0x3c9f3
movsd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3c9f3
movq 0x88(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x98(%rsp), %rdi
callq 0x5ee30
movq 0x20(%rsp), %rdi
movq %rax, %rsi
callq 0x43100
movsd %xmm0, 0x60(%rsp)
movsd 0x60(%rsp), %xmm0
ucomisd 0x80(%rsp), %xmm0
jbe 0x3c9f1
movl $0x0, 0xb4(%rsp)
jmp 0x3cc57
jmp 0x3c9f3
movq 0x98(%rsp), %rdi
callq 0x31660
cmpl $0x0, %eax
jne 0x3ca2b
movq 0xa8(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
callq *0x38(%rax)
movl $0x1, 0xb4(%rsp)
jmp 0x3cc57
movq 0x98(%rsp), %rdi
callq 0x186b0
cmpl $0x0, %eax
jle 0x3cbac
movsd 0x78(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3cbac
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movsd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3cb26
movsd 0x70(%rsp), %xmm1
movsd 0x78(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x3cb26
movq 0x88(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x98(%rsp), %rdi
callq 0x5ee30
movq 0x8(%rsp), %rdi
movq %rax, %rsi
callq 0x43100
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm1
divsd 0x80(%rsp), %xmm1
movsd 0x167698(%rip), %xmm0   # 0x1a4168
subsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
movsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x78(%rsp), %xmm0
subsd 0x70(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x48(%rsp), %xmm0
movsd 0x68(%rsp), %xmm1
callq 0x13960
movsd 0x10(%rsp), %xmm1
movaps %xmm0, %xmm2
movsd 0x18(%rsp), %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x58(%rsp)
movl $0x0, 0x44(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0x98(%rsp), %rdi
callq 0x31660
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jge 0x3cbaa
movq 0x98(%rsp), %rdi
movl 0x44(%rsp), %esi
callq 0x43680
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rdi
callq 0x5ecf0
ucomisd 0x58(%rsp), %xmm0
jbe 0x3cb9b
movq 0xa8(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq (%rdi), %rax
callq *0x38(%rax)
movl $0x1, 0xb4(%rsp)
jmp 0x3cc57
jmp 0x3cb9d
movl 0x44(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x44(%rsp)
jmp 0x3cb2e
jmp 0x3cbac
movl $0x0, 0x34(%rsp)
movl $0x0, 0x30(%rsp)
movl 0x30(%rsp), %eax
movl %eax, (%rsp)
movq 0x98(%rsp), %rdi
callq 0x31660
movl %eax, %ecx
movl (%rsp), %eax
cmpl %ecx, %eax
jge 0x3cc4c
movq 0x98(%rsp), %rdi
movl 0x30(%rsp), %esi
callq 0x43680
movq %rax, 0x28(%rsp)
movq 0xa8(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq 0x90(%rsp), %rcx
movq 0x88(%rsp), %r8
movsd 0x80(%rsp), %xmm0
movsd 0x78(%rsp), %xmm1
movsd 0x70(%rsp), %xmm2
movsd 0x68(%rsp), %xmm3
callq 0x3c900
orl 0x34(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x3cbbc
movl 0x34(%rsp), %eax
movl %eax, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
addq $0xb8, %rsp
retq
nopw %cs:(%rax,%rax)