// File: tomfunkhouser[P]gaps/apps/sflprocess/sflprocess.cpp
// Function: LoadSurfels(gaps::R3SurfelScene*, char const*, char const*, char const*, char const*, char const*)
static R3SurfelNode *
LoadSurfels(R3SurfelScene *scene, const char *surfels_filename, 
  const char *object_name, const char *parent_object_name,
  const char *node_name, const char *parent_node_name)
{
  // Start statistics
  RNTime start_time;
  start_time.Read();

  // Get surfel tree
  R3SurfelTree *tree = scene->Tree();
  if (!tree) {
    RNFail("Scene has no tree\n");
    return NULL;
  }    

  // Get surfel database
  R3SurfelDatabase *database = tree->Database();
  if (!database) {
    RNFail("Scene has no database\n");
    return NULL;
  }    

  // Find parent object
  R3SurfelObject *parent_object = NULL;
  if (parent_object_name && 
      strcmp(parent_object_name, "None") && 
      strcmp(parent_object_name, "none") && 
      strcmp(parent_object_name, "NONE")) {
    parent_object = scene->FindObjectByName(parent_object_name);
    if (!parent_object) {
      RNFail("Unable to find parent object with name %s\n", parent_object_name);
      return NULL;
    }
  }

  // Find parent node
  R3SurfelNode *parent_node = tree->FindNodeByName(parent_node_name);
  if (!parent_node) {
    RNFail("Unable to find parent node with name %s\n", parent_node_name);
    return NULL;
  }

  // Create node
  R3SurfelNode *node = new R3SurfelNode(node_name);
  if (!node) {
    RNFail("Unable to allocate node for %s\n", surfels_filename);
    return NULL;
  }

  // Insert node into tree
  tree->InsertNode(node, parent_node);

  // Create block
  R3SurfelBlock *block = new R3SurfelBlock();
  if (!block) {
    RNFail("Unable to allocate block for %s\n", surfels_filename);
    return NULL;
  }

  // Read block
  if (!block->ReadFile(surfels_filename)) {
    RNFail("Unable to read block from %s\n", surfels_filename);
    return NULL;
  }

  // Extract subset of surfels
  if (aerial_only || terrestrial_only) {
    // Create subset
    R3SurfelPointSet *subset = new R3SurfelPointSet();

    // Fill subset
    for (int i = 0; i < block->NSurfels(); i++) {
      const R3Surfel *surfel = block->Surfel(i);
      if (surfel->IsAerial() && terrestrial_only) continue;
      if (!surfel->IsAerial() && aerial_only) continue;
      R3SurfelPoint point(block, surfel);
      subset->InsertPoint(point);
    }

    // Replace block with subset
    // Note: it is important to delete subset first, since it references block
    R3SurfelBlock *subset_block = new R3SurfelBlock(subset);
    delete subset;
    delete block;
    block = subset_block;
  }

  // Update block properties
  block->UpdateProperties();

  // Insert block into database
  database->InsertBlock(block);

  // Insert block into node
  node->InsertBlock(block);

  // Update node properties
  node->UpdateProperties();

  // Create object
  if (object_name && 
      strcmp(object_name, "None") && 
      strcmp(object_name, "none") && 
      strcmp(object_name, "NONE") && 
      parent_object) {
    // Create object
    R3SurfelObject *object = new R3SurfelObject(object_name);
    if (!object) {
      RNFail("Unable to create object\n");
      return NULL;
    }

    // Insert object into scene
    scene->InsertObject(object, parent_object);

    // Insert node into object
    object->InsertNode(node);
      
    // Update object properties
    object->UpdateProperties();
  }

  // Release block
  database->ReleaseBlock(block);

  // Print statistics
  if (print_verbose) {
    printf("Loaded surfels from %s ...\n", surfels_filename);
    printf("  Time = %.2f seconds\n", start_time.Elapsed());
    printf("  # Surfels = %g\n", node->Complexity());
    fflush(stdout);
  }

  // Return node
  return node;
}

// Assembly:
subq $0x108, %rsp            # imm = 0x108
movq %rdi, 0xf8(%rsp)
movq %rsi, 0xf0(%rsp)
movq %rdx, 0xe8(%rsp)
movq %rcx, 0xe0(%rsp)
movq %r8, 0xd8(%rsp)
movq %r9, 0xd0(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x16dd30
leaq 0xc0(%rsp), %rdi
callq 0x263f0
movq 0xf8(%rsp), %rdi
callq 0x26780
movq %rax, 0xb8(%rsp)
cmpq $0x0, 0xb8(%rsp)
jne 0x1e720
leaq 0x1d9fea(%rip), %rdi    # 0x1f86f2
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movq 0xb8(%rsp), %rdi
callq 0x26790
movq %rax, 0xb0(%rsp)
cmpq $0x0, 0xb0(%rsp)
jne 0x1e75f
leaq 0x1da097(%rip), %rdi    # 0x1f87de
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movq $0x0, 0xa8(%rsp)
cmpq $0x0, 0xe0(%rsp)
je 0x1e81a
movq 0xe0(%rsp), %rdi
leaq 0x1d9fe9(%rip), %rsi    # 0x1f8772
callq 0x16a80
cmpl $0x0, %eax
je 0x1e81a
movq 0xe0(%rsp), %rdi
leaq 0x1d9fd1(%rip), %rsi    # 0x1f8777
callq 0x16a80
cmpl $0x0, %eax
je 0x1e81a
movq 0xe0(%rsp), %rdi
leaq 0x1d9fbd(%rip), %rsi    # 0x1f877c
callq 0x16a80
cmpl $0x0, %eax
je 0x1e81a
movq 0xf8(%rsp), %rdi
movq 0xe0(%rsp), %rsi
callq 0x70d50
movq %rax, 0xa8(%rsp)
cmpq $0x0, 0xa8(%rsp)
jne 0x1e818
movq 0xe0(%rsp), %rsi
leaq 0x1d9f47(%rip), %rdi    # 0x1f8747
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
jmp 0x1e81a
movq 0xb8(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x60280
movq %rax, 0xa0(%rsp)
cmpq $0x0, 0xa0(%rsp)
jne 0x1e869
movq 0xd0(%rsp), %rsi
leaq 0x1d9eb4(%rip), %rdi    # 0x1f8705
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movl $0xd0, %edi
callq 0x16740
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x40(%rsp)
movq 0xd8(%rsp), %rsi
callq 0x5c600
jmp 0x1e88d
movq 0x40(%rsp), %rax
movq %rax, 0x98(%rsp)
cmpq $0x0, 0x98(%rsp)
jne 0x1e8f4
movq 0xf0(%rsp), %rsi
leaq 0x1d9f41(%rip), %rdi    # 0x1f87f5
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movq 0x40(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
movl $0xd0, %esi
callq 0x16750
jmp 0x1edca
movq 0xb8(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0xa0(%rsp), %rdx
callq 0x60080
movl $0xc8, %edi
callq 0x16740
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x38(%rsp)
callq 0x46d00
jmp 0x1e92d
movq 0x38(%rsp), %rax
movq %rax, 0x80(%rsp)
cmpq $0x0, 0x80(%rsp)
jne 0x1e994
movq 0xf0(%rsp), %rsi
leaq 0x1d9ec1(%rip), %rdi    # 0x1f8815
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movq 0x38(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
movl $0xc8, %esi
callq 0x16750
jmp 0x1edca
movq 0x80(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x4be10
cmpl $0x0, %eax
jne 0x1e9d5
movq 0xf0(%rsp), %rsi
leaq 0x1d9e79(%rip), %rdi    # 0x1f8836
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
cmpl $0x0, 0x245ddc(%rip)    # 0x2647b8
jne 0x1e9eb
cmpl $0x0, 0x245dd7(%rip)    # 0x2647bc
je 0x1ebc5
movl $0x60, %edi
callq 0x16740
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x30(%rsp)
callq 0x552d0
jmp 0x1ea07
movq 0x30(%rsp), %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x74(%rsp)
movl 0x74(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x80(%rsp), %rdi
callq 0x267d0
movl %eax, %ecx
movl 0x2c(%rsp), %eax
cmpl %ecx, %eax
jge 0x1eb1c
movq 0x80(%rsp), %rdi
movl 0x74(%rsp), %esi
callq 0x267e0
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
callq 0x26800
cmpl $0x0, %eax
je 0x1ea94
cmpl $0x0, 0x245d54(%rip)    # 0x2647bc
je 0x1ea94
jmp 0x1eae9
movq 0x30(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
movl $0x60, %esi
callq 0x16750
jmp 0x1edca
movq 0x68(%rsp), %rdi
callq 0x26800
cmpl $0x0, %eax
jne 0x1eaae
cmpl $0x0, 0x245d0e(%rip)    # 0x2647b8
je 0x1eaae
jmp 0x1eae9
movq 0x80(%rsp), %rsi
movq 0x68(%rsp), %rdx
leaq 0x58(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x54ba0
movq 0x20(%rsp), %rsi
movq 0x78(%rsp), %rdi
movq (%rdi), %rax
movq 0x68(%rax), %rax
callq *%rax
jmp 0x1eadf
leaq 0x58(%rsp), %rdi
callq 0x54c80
movl 0x74(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x74(%rsp)
jmp 0x1ea19
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x54c80
jmp 0x1edca
movl $0xc8, %edi
callq 0x16740
movq %rax, %rdi
movq %rdi, %rax
movq %rax, 0x18(%rsp)
movq 0x78(%rsp), %rsi
callq 0x472d0
jmp 0x1eb3d
movq 0x18(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0x1eb62
movq 0x10(%rsp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq 0x80(%rsp), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0x1eb8e
movq 0x8(%rsp), %rdi
callq 0x49290
movq 0x8(%rsp), %rdi
movl $0xc8, %esi
callq 0x16750
movq 0x50(%rsp), %rax
movq %rax, 0x80(%rsp)
jmp 0x1ebc5
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
movl $0xc8, %esi
callq 0x16750
jmp 0x1edca
movq 0x80(%rsp), %rdi
callq 0x4b450
movq 0xb0(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq (%rdi), %rax
callq *0x10(%rax)
movq 0x98(%rsp), %rdi
movq 0x80(%rsp), %rsi
movq (%rdi), %rax
callq *0x28(%rax)
movq 0x98(%rsp), %rdi
callq 0x5e580
cmpq $0x0, 0xe8(%rsp)
je 0x1ed31
movq 0xe8(%rsp), %rdi
leaq 0x1d9b49(%rip), %rsi    # 0x1f8772
callq 0x16a80
cmpl $0x0, %eax
je 0x1ed31
movq 0xe8(%rsp), %rdi
leaq 0x1d9b31(%rip), %rsi    # 0x1f8777
callq 0x16a80
cmpl $0x0, %eax
je 0x1ed31
movq 0xe8(%rsp), %rdi
leaq 0x1d9b19(%rip), %rsi    # 0x1f877c
callq 0x16a80
cmpl $0x0, %eax
je 0x1ed31
cmpq $0x0, 0xa8(%rsp)
je 0x1ed31
movl $0xf8, %edi
callq 0x16740
movq %rax, %rdi
movq %rdi, %rax
movq %rax, (%rsp)
movq 0xe8(%rsp), %rsi
callq 0x6ae00
jmp 0x1eca3
movq (%rsp), %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, 0x48(%rsp)
jne 0x1ecfa
leaq 0x1d9b99(%rip), %rdi    # 0x1f8854
movb $0x0, %al
callq 0x172cb0
movq $0x0, 0x100(%rsp)
jmp 0x1edba
movq (%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x90(%rsp)
movl %eax, 0x8c(%rsp)
movl $0xf8, %esi
callq 0x16750
jmp 0x1edca
movq 0xf8(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq 0xa8(%rsp), %rdx
movq (%rdi), %rax
callq *0x18(%rax)
movq 0x48(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x6d020
movq 0x48(%rsp), %rdi
callq 0x6dc90
movq 0xb0(%rsp), %rdi
movq 0x80(%rsp), %rsi
callq 0x26820
cmpl $0x0, 0x245a73(%rip)    # 0x2647c0
je 0x1edaa
movq 0xf0(%rsp), %rsi
leaq 0x1d9b0f(%rip), %rdi    # 0x1f886d
movb $0x0, %al
callq 0x16090
leaq 0xc0(%rsp), %rdi
callq 0x16ddf0
leaq 0x1d9806(%rip), %rdi    # 0x1f857f
movb $0x1, %al
callq 0x16090
movq 0x98(%rsp), %rdi
callq 0x5cb40
leaq 0x1d9af5(%rip), %rdi    # 0x1f8889
movb $0x1, %al
callq 0x16090
movq 0x23c1ee(%rip), %rax    # 0x25af90
movq (%rax), %rdi
callq 0x168c0
movq 0x98(%rsp), %rax
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rax
addq $0x108, %rsp            # imm = 0x108
retq
movq 0x90(%rsp), %rdi
callq 0x16ca0
nopw (%rax,%rax)