// File: tomfunkhouser[P]gaps/pkgs/R3Shapes/R3MeshSearchTree.cpp
// Function: gaps::R3MeshSearchTree::InsertFace(gaps::R3MeshSearchTreeFace*, gaps::R3MeshSearchTreeNode*, gaps::R3Box const&, int)
void R3MeshSearchTree::
InsertFace(R3MeshSearchTreeFace *face, R3MeshSearchTreeNode *node, const R3Box& node_box, int depth) 
{
  // Check if face intersects box
  if (!R3Intersects(mesh, face->face, node_box)) return;

  // Check if interior node
  if (node->children[0]) {
    // Interior node -- Insert into children
    assert(node->children[1]);
    const R3Box& face_box = mesh->FaceBBox(face->face);
    if (face_box[RN_LO][node->split_dimension] <= node->split_coordinate) {
      R3Box node0_box(node_box);
      node0_box[RN_HI][node->split_dimension] = node->split_coordinate;
      InsertFace(face, node->children[0], node0_box, depth + 1);
    }
    if (face_box[RN_HI][node->split_dimension] >= node->split_coordinate) {
      R3Box node1_box(node_box);
      node1_box[RN_LO][node->split_dimension] = node->split_coordinate;
      InsertFace(face, node->children[1], node1_box, depth + 1);
    }
  }
  else {
    // Check face area 
    RNScalar node_diagonal = node_box.DiagonalLength();
    if (node_diagonal == 0) return;
    RNScalar node_area = node_diagonal * node_diagonal;
    RNScalar area_ratio = face->area / node_area;
    if ((area_ratio >= max_area_ratio) || 
        (depth >= max_depth)) {
      // Face is too big/deep to be sorted into children, insert into big faces list
      node->big_faces.Insert(face);
      assert(face->reference_count >= 0);
      face->reference_count++;
    }
    else {
      // Leaf node -- Check if there is room for this face
      if (node->small_faces.NEntries() < max_faces_per_node) {
        // Simply insert face into list
        node->small_faces.Insert(face);
        face->reference_count++;
      }
      else {
        // Create two children 
        node->children[0] = new R3MeshSearchTreeNode(node);
        node->children[1] = new R3MeshSearchTreeNode(node);
        node->split_dimension = node_box.LongestAxis();
        node->split_coordinate = node_box.AxisCenter(node->split_dimension);
        nnodes += 2;
      
        // Re-insert faces into subtree
        InsertFace(face, node, node_box, depth+1);
        for (int i = 0; i < node->small_faces.NEntries(); i++) {
          InsertFace(node->small_faces[i], node, node_box, depth+1);
        }
      
        // Clear out faces from node that is now interior
        for (int i = 0; i < node->small_faces.NEntries(); i++) {
          assert(node->small_faces[i]->reference_count > 0);
          node->small_faces[i]->reference_count--;
        }
        node->small_faces.Empty();
      }
    }
  }
}

// Assembly:
subq $0x138, %rsp            # imm = 0x138
movq %rdi, 0x130(%rsp)
movq %rsi, 0x128(%rsp)
movq %rdx, 0x120(%rsp)
movq %rcx, 0x118(%rsp)
movl %r8d, 0x114(%rsp)
movq 0x130(%rsp), %rax
movq %rax, 0x60(%rsp)
movq (%rax), %rdi
movq 0x128(%rsp), %rax
movq (%rax), %rsi
movq 0x118(%rsp), %rdx
callq 0x1b330
cmpl $0x0, %eax
jne 0x1bad1
jmp 0x1c031
movq 0x120(%rsp), %rax
cmpq $0x0, 0x8(%rax)
je 0x1bd26
movq 0x60(%rsp), %rax
movq (%rax), %rdi
movq 0x128(%rsp), %rax
movq (%rax), %rsi
callq 0x3a630
movq %rax, 0x108(%rsp)
movq 0x108(%rsp), %rdi
xorl %esi, %esi
callq 0x21790
movq %rax, %rdi
movq 0x120(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x17e60
movaps %xmm0, %xmm1
movq 0x120(%rsp), %rax
movsd 0x18(%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x1bc16
movq 0x118(%rsp), %rsi
leaq 0xd0(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x67100
movq 0x48(%rsp), %rdi
movq 0x120(%rsp), %rax
movsd 0x18(%rax), %xmm0
movsd %xmm0, 0x50(%rsp)
movl $0x1, %esi
callq 0x17820
movq %rax, 0x58(%rsp)
jmp 0x1bb83
movq 0x58(%rsp), %rdi
movq 0x120(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x17800
movq %rax, 0x40(%rsp)
jmp 0x1bb9f
movq 0x60(%rsp), %rdi
movq 0x40(%rsp), %rax
movsd 0x50(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x128(%rsp), %rsi
movq 0x120(%rsp), %rax
movq 0x8(%rax), %rdx
movl 0x114(%rsp), %r8d
incl %r8d
leaq 0xd0(%rsp), %rcx
callq 0x1ba70
jmp 0x1bbe1
leaq 0xd0(%rsp), %rdi
callq 0x17670
jmp 0x1bc16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x17670
jmp 0x1c039
movq 0x108(%rsp), %rdi
movl $0x1, %esi
callq 0x21790
movq %rax, %rdi
movq 0x120(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x17e60
movq 0x120(%rsp), %rax
ucomisd 0x18(%rax), %xmm0
jb 0x1bd21
movq 0x118(%rsp), %rsi
leaq 0x88(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x67100
movq 0x28(%rsp), %rdi
movq 0x120(%rsp), %rax
movsd 0x18(%rax), %xmm0
movsd %xmm0, 0x30(%rsp)
xorl %esi, %esi
callq 0x17820
movq %rax, 0x38(%rsp)
jmp 0x1bc8e
movq 0x38(%rsp), %rdi
movq 0x120(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x17800
movq %rax, 0x20(%rsp)
jmp 0x1bcaa
movq 0x60(%rsp), %rdi
movq 0x20(%rsp), %rax
movsd 0x30(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x128(%rsp), %rsi
movq 0x120(%rsp), %rax
movq 0x10(%rax), %rdx
movl 0x114(%rsp), %r8d
incl %r8d
leaq 0x88(%rsp), %rcx
callq 0x1ba70
jmp 0x1bcec
leaq 0x88(%rsp), %rdi
callq 0x17670
jmp 0x1bd21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
leaq 0x88(%rsp), %rdi
callq 0x17670
jmp 0x1c039
jmp 0x1c031
movq 0x118(%rsp), %rdi
callq 0x685a0
movsd %xmm0, 0x80(%rsp)
movsd 0x80(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x1bd55
jp 0x1bd55
jmp 0x1c031
movsd 0x80(%rsp), %xmm0
mulsd 0x80(%rsp), %xmm0
movsd %xmm0, 0x78(%rsp)
movq 0x128(%rsp), %rax
movsd 0x8(%rax), %xmm0
divsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x70(%rsp)
movsd 0x70(%rsp), %xmm0
movsd 0x12482c(%rip), %xmm1   # 0x1405c0
ucomisd %xmm1, %xmm0
jae 0x1bda4
cmpl $0x40, 0x114(%rsp)
jl 0x1bdd3
movq 0x120(%rsp), %rdi
addq $0x28, %rdi
movq 0x128(%rsp), %rsi
callq 0x217d0
movq 0x128(%rsp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0x1c02f
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
callq 0x178e0
cmpl $0x80, %eax
jge 0x1be1a
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
movq 0x128(%rsp), %rsi
callq 0x217d0
movq 0x128(%rsp), %rax
movl 0x10(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x10(%rax)
jmp 0x1c02d
movl $0x48, %edi
callq 0xf4c0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x18(%rsp)
movq 0x120(%rsp), %rsi
callq 0x21680
jmp 0x1be3e
movq 0x18(%rsp), %rcx
movq 0x120(%rsp), %rax
movq %rcx, 0x8(%rax)
movl $0x48, %edi
callq 0xf4c0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x10(%rsp)
movq 0x120(%rsp), %rsi
callq 0x21680
jmp 0x1be73
movq 0x10(%rsp), %rcx
movq 0x120(%rsp), %rax
movq %rcx, 0x10(%rax)
movq 0x118(%rsp), %rdi
callq 0x68390
movl %eax, %ecx
movq 0x120(%rsp), %rax
movl %ecx, 0x20(%rax)
movq 0x118(%rsp), %rdi
movq 0x120(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x21800
movq 0x60(%rsp), %rdi
movq 0x120(%rsp), %rax
movsd %xmm0, 0x18(%rax)
movl 0x10(%rdi), %eax
addl $0x2, %eax
movl %eax, 0x10(%rdi)
movq 0x128(%rsp), %rsi
movq 0x120(%rsp), %rdx
movq 0x118(%rsp), %rcx
movl 0x114(%rsp), %r8d
addl $0x1, %r8d
callq 0x1ba70
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
callq 0x178e0
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0x1bfc1
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
movl 0x6c(%rsp), %esi
callq 0x21860
movq 0x60(%rsp), %rdi
movq (%rax), %rsi
movq 0x120(%rsp), %rdx
movq 0x118(%rsp), %rcx
movl 0x114(%rsp), %r8d
addl $0x1, %r8d
callq 0x1ba70
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x1bf02
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
movl $0x48, %esi
callq 0xf4d0
jmp 0x1c039
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc8(%rsp)
movl %eax, 0xc4(%rsp)
movl $0x48, %esi
callq 0xf4d0
jmp 0x1c039
movl $0x0, 0x68(%rsp)
movl 0x68(%rsp), %eax
movl %eax, 0x8(%rsp)
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
callq 0x178e0
movl %eax, %ecx
movl 0x8(%rsp), %eax
cmpl %ecx, %eax
jge 0x1c01a
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
movl 0x68(%rsp), %esi
callq 0x21860
movq (%rax), %rax
movl 0x10(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x10(%rax)
movl 0x68(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x68(%rsp)
jmp 0x1bfc9
movq 0x120(%rsp), %rdi
addq $0x38, %rdi
xorl %esi, %esi
callq 0xdef50
jmp 0x1c02f
jmp 0x1c031
addq $0x138, %rsp            # imm = 0x138
retq
movq 0xc8(%rsp), %rdi
callq 0xf890
nopw %cs:(%rax,%rax)