// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Scene.cpp
// Function: gaps::R3Scene::ReadSUNCGModelFile(char const*)
int R3Scene::
ReadSUNCGModelFile(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "r");
  if (!fp) {
    RNFail("Unable to open lights file %s\n", filename);
    return 0;
  }

  // Read keys from first line
  int line_number = 1;
  char key_buffer[4096];
  RNArray<char *> keys;
  if (fgets(key_buffer, 4096, fp)) {
    char *token = strtok(key_buffer, ",\r\n");
    while (token) {
      keys.Insert(RNStrdup(token));
      token = strtok(NULL, ",\r\n");
    }
  }

  // Extract index of model_id
  int model_id_k = -1;
  for (int i = 0; i < keys.NEntries(); i++) {
    if (!strcmp(keys[i], "model_id")) {
      model_id_k = i;
      break;
    }
  }

  // Check if found model_id
  if (model_id_k < 0) {
    RNFail("Did not find \"model_id\" in header on line %d of %s\n", line_number, filename);
    return 0;
  }

  // Read subsequent lines of file
  char value_buffer[4096];
  while (fgets(value_buffer, 4096, fp)) {
    line_number++;

    // Read values
    RNArray<char *> values;
    char *token = strtok(value_buffer, ",\r\n");
    while (token) {
      values.Insert(RNStrdup(token));
      token = strtok(NULL, ",\r\n");
    }

    // Check number of values
    if (values.NEntries() == 0) continue;
    if (values.NEntries() != keys.NEntries()) {
      RNFail("Invalid number of entries at line %d in %s\n", line_number, filename);
      return 0;
    }

    // Get model id
    const char *model_id = values[model_id_k];
    if (!model_id) continue;
    int model_id_length = strlen(model_id);
    if (model_id_length == 0) continue;

    // Assign key-value info to nodes matching model_id
    for (int i = 0; i < NNodes(); i++) {
      R3SceneNode *node = Node(i);

      // Determine if node name matches model_id
      if (node->Name()) {
        char node_name[1024];
        strncpy(node_name, node->Name(), 1023);
        char *model_name = strchr(node_name, '#');
        if (model_name) { *model_name = '\0'; model_name++; }
        else model_name = node_name;
        if (!strcmp(node_name, model_id) || !strcmp(model_name, model_id)) {
          for (int j = 0; j < keys.NEntries(); j++) node->InsertInfo(keys[j], values[j]);
        }
      }

      // Determine if referenced scene name matches model_id
      for (int j = 0; j < node->NReferences(); j++) {
        R3SceneReference *reference = node->Reference(j);
        R3Scene *referenced_scene = reference->ReferencedScene();
        R3SceneNode *root = referenced_scene->Root();
        if (!root->Name()) continue;
        char node_name[1024];
        strncpy(node_name, root->Name(), 1023);
        char *model_name = strchr(node_name, '#');
        if (model_name) { *model_name = '\0'; model_name++; }
        else model_name = node_name;
        if (!strcmp(node_name, model_id) || !strcmp(model_name, model_id)) {
          for (int j = 0; j < keys.NEntries(); j++) node->InsertInfo(keys[j], values[j]);
          break;
        }
      }
    }

    // Assign key-value info to root node of referenced scene matching model_id
    R3Scene *model = ReferencedScene(model_id);
    if (model) {
      for (int i = 0; i < keys.NEntries(); i++) {
        model->Root()->InsertInfo(keys[i], values[i]);
      }
    }
  }

  // Close file
  fclose(fp);

  // Delete inactive nodes
  RNArray<R3SceneNode *> tmp;
  for (int i = 0; i < NNodes(); i++)
    tmp.Insert(Node(i));
  for (int i = 0; i < tmp.NEntries(); i++) {
    R3SceneNode *node = tmp.Kth(i);
    const char *active = node->Info("active");
    if (!active) continue;
    if (strcmp(active, "0")) continue;
    delete node;
  }

  
#if 0
  // Print result
  for (int i = 0; i < NNodes(); i++) {
    R3SceneNode *node = Node(i);
    const char *model_index = node->Info("index");
    if (model_index) printf("%s %s\n", node->Name(), model_index);
  }
#endif
  
  // Return success
  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2458, %rsp           # imm = 0x2458
movq %rsi, %r12
movq %rdi, %r15
leaq 0x98383(%rip), %rsi     # 0xcbda3
movq %r12, %rdi
callq 0x21ab0
testq %rax, %rax
je 0x33ad1
movq %rax, %r13
leaq 0x8(%rsp), %rdi
callq 0x7c1c6
leaq 0x1450(%rsp), %rdi
movl $0x1000, %esi           # imm = 0x1000
movq %r13, %rdx
callq 0x21f50
testq %rax, %rax
je 0x33a98
leaq 0x92aa5(%rip), %rbx     # 0xc6504
leaq 0x1450(%rsp), %rdi
movq %rbx, %rsi
callq 0x21f00
leaq 0x8(%rsp), %r14
testq %rax, %rax
je 0x33a98
movq %rax, %rdi
callq 0x7e6a9
movq %r14, %rdi
movq %rax, %rsi
callq 0x2737a
xorl %edi, %edi
movq %rbx, %rsi
callq 0x21f00
jmp 0x33a74
movq %r15, 0x30(%rsp)
movl 0x14(%rsp), %r14d
movq 0x8(%rsp), %r15
xorl %ebp, %ebp
testl %r14d, %r14d
cmovlel %ebp, %r14d
leaq 0x92a51(%rip), %rbx     # 0xc6508
cmpq %rbp, %r14
je 0x33ae9
movq (%r15,%rbp,8), %rdi
movq %rbx, %rsi
callq 0x21d30
testl %eax, %eax
je 0x33b04
incq %rbp
jmp 0x33ab7
leaq 0x9284d(%rip), %rdi     # 0xc6325
xorl %ebx, %ebx
movq %r12, %rsi
xorl %eax, %eax
callq 0x7e83e
jmp 0x33e41
xorl %ebx, %ebx
leaq 0x92a1f(%rip), %rdi     # 0xc6511
pushq $0x1
popq %rsi
movq %r12, %rdx
xorl %eax, %eax
callq 0x7e83e
jmp 0x33e37
movq %r12, 0x38(%rsp)
pushq $0x1
popq %rbx
leaq 0x450(%rsp), %r14
leaq 0x50(%rsp), %r12
movq 0x30(%rsp), %r15
movq %r13, 0x40(%rsp)
movq %rbp, 0x48(%rsp)
movq %r14, %rdi
movl $0x1000, %esi           # imm = 0x1000
movq %r13, %rdx
callq 0x21f50
testq %rax, %rax
je 0x33d7b
leaq 0x20(%rsp), %rdi
callq 0x7c1c6
incl %ebx
movq %r14, %rdi
leaq 0x929ad(%rip), %rsi     # 0xc6504
callq 0x21f00
leaq 0x20(%rsp), %r14
testq %rax, %rax
je 0x33b89
movq %rax, %rdi
callq 0x7e6a9
movq %r14, %rdi
movq %rax, %rsi
callq 0x2737a
xorl %edi, %edi
leaq 0x92982(%rip), %rsi     # 0xc6504
callq 0x21f00
jmp 0x33b61
movl %ebx, 0x1c(%rsp)
movl 0x2c(%rsp), %eax
testl %eax, %eax
je 0x33d60
cmpl 0x14(%rsp), %eax
jne 0x33e14
movq 0x20(%rsp), %rax
movq 0x48(%rsp), %rcx
movq (%rax,%rcx,8), %rbp
testq %rbp, %rbp
je 0x33d60
movq %rbp, %rdi
callq 0x21370
testl %eax, %eax
je 0x33d60
xorl %r13d, %r13d
movslq 0x14(%r15), %rax
cmpq %rax, %r13
jge 0x33d1c
movq 0x8(%r15), %rax
movq (%rax,%r13,8), %rbx
movq 0x1a0(%rbx), %rsi
testq %rsi, %rsi
je 0x33c3d
movl $0x3ff, %edx            # imm = 0x3FF
movq %r12, %rdi
callq 0x21440
movq %r12, %rdi
pushq $0x23
popq %rsi
callq 0x21320
movq %r12, %r14
testq %rax, %rax
je 0x33c17
movb $0x0, (%rax)
incq %rax
movq %rax, %r14
movq %r12, %rdi
movq %rbp, %rsi
callq 0x21d30
testl %eax, %eax
je 0x33cec
movq %r14, %rdi
movq %rbp, %rsi
callq 0x21d30
testl %eax, %eax
je 0x33cec
xorl %r15d, %r15d
movslq 0x4c(%rbx), %rax
cmpq %rax, %r15
jge 0x33cdf
movq 0x40(%rbx), %rax
movq (%rax,%r15,8), %rax
movq (%rax), %rax
movq (%rax), %rax
movq 0x1a0(%rax), %rsi
testq %rsi, %rsi
je 0x33cae
movl $0x3ff, %edx            # imm = 0x3FF
movq %r12, %rdi
callq 0x21440
movq %r12, %rdi
pushq $0x23
popq %rsi
callq 0x21320
movq %r12, %r14
testq %rax, %rax
je 0x33c90
movb $0x0, (%rax)
incq %rax
movq %rax, %r14
movq %r12, %rdi
movq %rbp, %rsi
callq 0x21d30
testl %eax, %eax
je 0x33cb3
movq %r14, %rdi
movq %rbp, %rsi
callq 0x21d30
testl %eax, %eax
je 0x33cb3
incq %r15
jmp 0x33c40
xorl %r14d, %r14d
movslq 0x14(%rsp), %rax
cmpq %rax, %r14
jge 0x33cdf
movq 0x8(%rsp), %rax
movq (%rax,%r14,8), %rsi
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rdx
movq %rbx, %rdi
callq 0x389f8
incq %r14
jmp 0x33cb6
incq %r13
movq 0x30(%rsp), %r15
jmp 0x33bcd
xorl %r14d, %r14d
movslq 0x14(%rsp), %rax
cmpq %rax, %r14
jge 0x33c3d
movq 0x8(%rsp), %rax
movq (%rax,%r14,8), %rsi
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rdx
movq %rbx, %rdi
callq 0x389f8
incq %r14
jmp 0x33cef
movq %r15, %rdi
movq %rbp, %rsi
callq 0x2776c
testq %rax, %rax
movq 0x40(%rsp), %r13
je 0x33d60
movq %rax, %rbx
xorl %r14d, %r14d
movslq 0x14(%rsp), %rax
cmpq %rax, %r14
jge 0x33d60
movq (%rbx), %rdi
movq 0x8(%rsp), %rax
movq (%rax,%r14,8), %rsi
movq 0x20(%rsp), %rax
movq (%rax,%r14,8), %rdx
callq 0x389f8
incq %r14
jmp 0x33d37
leaq 0x20(%rsp), %rdi
callq 0x7c234
movl 0x1c(%rsp), %ebx
leaq 0x450(%rsp), %r14
jmp 0x33b28
movq %r13, %rdi
callq 0x218c0
leaq 0x50(%rsp), %rdi
callq 0x7c1c6
xorl %r14d, %r14d
leaq 0x50(%rsp), %rbx
movslq 0x14(%r15), %rax
cmpq %rax, %r14
jge 0x33db3
movq 0x8(%r15), %rax
movq (%rax,%r14,8), %rsi
movq %rbx, %rdi
callq 0x2737a
incq %r14
jmp 0x33d95
xorl %r15d, %r15d
leaq 0x927b4(%rip), %rbx     # 0xc6571
movslq 0x5c(%rsp), %rax
cmpq %rax, %r15
jge 0x33e05
movq 0x50(%rsp), %rax
movq (%rax,%r15,8), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x34662
testq %rax, %rax
je 0x33e00
cmpb $0x30, (%rax)
jne 0x33e00
cmpb $0x0, 0x1(%rax)
jne 0x33e00
movq %r14, %rdi
callq 0x37cc0
movl $0x1b0, %esi            # imm = 0x1B0
movq %r14, %rdi
callq 0x218f0
incq %r15
jmp 0x33dbd
leaq 0x50(%rsp), %rdi
callq 0x7c234
pushq $0x1
popq %rbx
jmp 0x33e37
leaq 0x9272a(%rip), %rdi     # 0xc6545
xorl %ebx, %ebx
movl 0x1c(%rsp), %esi
movq 0x38(%rsp), %rdx
xorl %eax, %eax
callq 0x7e83e
leaq 0x20(%rsp), %rdi
callq 0x7c234
leaq 0x8(%rsp), %rdi
callq 0x7c234
movl %ebx, %eax
addq $0x2458, %rsp           # imm = 0x2458
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x33e74
jmp 0x33e69
jmp 0x33e69
jmp 0x33e5d
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
jmp 0x33e7c
jmp 0x33e69
movq %rax, %rbx
jmp 0x33e81
jmp 0x33e74
jmp 0x33e74
jmp 0x33e74
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x7c234
leaq 0x8(%rsp), %rdi
callq 0x7c234
movq %rbx, %rdi
callq 0x220e0