// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/pkgs/R3Graphics/R3Scene.cpp
// Function: gaps::CopyScene(gaps::R3Scene*, gaps::R3Scene*, gaps::R3SceneNode*, gaps::RNArray<gaps::R3Material*> const*)
static void
CopyScene(R3Scene *src_scene, R3Scene *dst_scene,
  R3SceneNode *dst_root_node = NULL, const RNArray<R3Material *> *materials = NULL)
{
  // Get/check inputs
  if (!src_scene || !dst_scene) return;
  if (!dst_root_node) dst_root_node = dst_scene->Root();
  
  // Copy lights
  RNArray<R3Light *> dst_lights;
  for (int i = 0; i < src_scene->NLights(); i++) {
    R3Light *src_light = src_scene->Light(i);
    R3Light *dst_light = src_light->Copy();
    dst_scene->InsertLight(dst_light);
    dst_lights.Insert(dst_light);
  }

  // Copy textures
  RNArray<R2Texture *> dst_textures;
  for (int i = 0; i < src_scene->NTextures(); i++) {
    R2Texture *src_texture = src_scene->Texture(i);
    R2Texture *dst_texture = new R2Texture(*src_texture);
    dst_textures.Insert(dst_texture);
    dst_scene->InsertTexture(dst_texture);
  }

  // Copy brdfs
  RNArray<R3Brdf *> dst_brdfs;
  for (int i = 0; i < src_scene->NBrdfs(); i++) {
    R3Brdf *src_brdf = src_scene->Brdf(i);
    R3Brdf *dst_brdf = new R3Brdf(*src_brdf);
    dst_brdfs.Insert(dst_brdf);
    dst_scene->InsertBrdf(dst_brdf);
  }

  // Copy materials
  RNArray<R3Material *> dst_materials;
  for (int i = 0; i < src_scene->NMaterials(); i++) {
    R3Material *dst_material = (i < materials->NEntries()) ? materials->Kth(i) : NULL;
    if (!dst_material) {
      R3Material *src_material = src_scene->Material(i);
      R3Brdf *dst_brdf = (src_material->Brdf()) ? dst_brdfs[src_material->Brdf()->SceneIndex()] : NULL;
      R2Texture *dst_texture = (src_material->Texture()) ? dst_textures[src_material->Texture()->SceneIndex()] : NULL;
      dst_material = new R3Material(dst_brdf, dst_texture, src_material->Name());
      dst_scene->InsertMaterial(dst_material);
    }
    dst_materials.Insert(dst_material);
  }

  // Copy nodes 
  RNArray<R3SceneNode *> dst_nodes;
  for (int i = 0; i < src_scene->NNodes(); i++) {
    R3SceneNode *src_node = src_scene->Node(i);
    R3SceneNode *dst_node = new R3SceneNode(*src_node);
    dst_scene->InsertNode(dst_node);
    dst_nodes.Insert(dst_node);

    // Copy elements
    for (int i = 0; i < src_node->NElements(); i++) {
      R3SceneElement *src_element = src_node->Element(i);
      R3Material *src_material = src_element->Material();
      R3Material *dst_material = (src_material) ? dst_materials[src_material->SceneIndex()] : NULL;
      R3SceneElement *dst_element = new R3SceneElement(dst_material);
      dst_node->InsertElement(dst_element);
      for (int j = 0; j < src_element->NShapes(); j++) {
        R3Shape *src_shape = src_element->Shape(j);
        R3Shape *dst_shape = src_shape->Copy();
        dst_element->InsertShape(dst_shape);
      }
    }

    // Copy references
    for (int i = 0; i < src_node->NReferences(); i++) {
      R3SceneReference *src_reference = src_node->Reference(i);
      R3Scene *src_referenced_scene = src_reference->ReferencedScene();
      RNArray<R3Material *> dst_reference_materials;
      for (int j = 0; j < src_reference->NMaterials(); j++) {
        R3Material *src_material = src_reference->Material(j);
        R3Material *dst_material = dst_materials[src_material->SceneIndex()];
        dst_scene->InsertMaterial(dst_material);
      }
      CopyScene(src_referenced_scene, dst_scene, dst_node, &dst_reference_materials);
    }
  }
  
  // Copy node hierarchy
  for (int i = 0; i < src_scene->NNodes(); i++) {
    R3SceneNode *src_node = src_scene->Node(i);
    R3SceneNode *dst_node = dst_nodes.Kth(i);
    R3SceneNode *src_parent = src_node->Parent();
    R3SceneNode *dst_parent = (src_parent) ? dst_nodes[src_parent->SceneIndex()] : dst_root_node;
    dst_parent->InsertChild(dst_node);
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rcx, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
testq %rdi, %rdi
sete %al
testq %rsi, %rsi
sete %cl
orb %al, %cl
jne 0x3427d
movq %rsi, %r15
movq %rdx, 0x18(%rsp)
testq %rdx, %rdx
jne 0x33ed7
movq (%r15), %rax
movq %rax, 0x18(%rsp)
leaq 0x78(%rsp), %rbx
movq %rbx, %rdi
callq 0x7c1c6
xorl %r12d, %r12d
movq 0x8(%rsp), %rcx
movslq 0x24(%rcx), %rax
cmpq %rax, %r12
jge 0x33f20
movq 0x18(%rcx), %rax
movq (%rax,%r12,8), %rdi
callq 0x3e746
movq %rax, %r14
movq %r15, %rdi
movq %rax, %rsi
callq 0x277fe
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2737a
incq %r12
jmp 0x33ee7
leaq 0x50(%rsp), %rdi
callq 0x7c1c6
xorl %r12d, %r12d
pushq $0x50
popq %rbx
leaq 0x50(%rsp), %r14
movq 0x8(%rsp), %rcx
movslq 0x54(%rcx), %rax
cmpq %rax, %r12
jge 0x33f7e
movq 0x48(%rcx), %rax
movq (%rax,%r12,8), %rbp
movq %rbx, %rdi
callq 0x218d0
movq %rax, %r13
movq %rax, %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0x3fb22
movq %r14, %rdi
movq %r13, %rsi
callq 0x2737a
movq %r15, %rdi
movq %r13, %rsi
callq 0x278d2
incq %r12
jmp 0x33f35
leaq 0x40(%rsp), %rdi
callq 0x7c1c6
xorl %r12d, %r12d
leaq 0x40(%rsp), %rbx
movq 0x8(%rsp), %rcx
movslq 0x44(%rcx), %rax
cmpq %rax, %r12
jge 0x33fdb
movq 0x38(%rcx), %rax
movq (%rax,%r12,8), %r13
movl $0xb8, %edi
callq 0x218d0
movq %rax, %r14
movq %rax, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0x3f100
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2737a
movq %r15, %rdi
movq %r14, %rsi
callq 0x2788a
incq %r12
jmp 0x33f90
leaq 0x20(%rsp), %rdi
callq 0x7c1c6
xorl %r13d, %r13d
movq 0x8(%rsp), %rax
movslq 0x34(%rax), %rax
cmpq %rax, %r13
jge 0x3409a
movq 0x10(%rsp), %rax
movslq 0xc(%rax), %rax
cmpq %rax, %r13
jge 0x34019
movq 0x10(%rsp), %rax
movq (%rax), %rax
movq (%rax,%r13,8), %r14
testq %r14, %r14
jne 0x34085
movq 0x8(%rsp), %rax
movq 0x28(%rax), %rax
movq (%rax,%r13,8), %r12
movq 0x18(%r12), %rax
testq %rax, %rax
je 0x3403f
movslq 0x10(%rax), %rax
movq 0x40(%rsp), %rcx
movq (%rcx,%rax,8), %rbp
jmp 0x34041
xorl %ebp, %ebp
movq 0x20(%r12), %rax
testq %rax, %rax
je 0x3405a
movslq 0x8(%rax), %rax
movq 0x50(%rsp), %rcx
movq (%rcx,%rax,8), %rbx
jmp 0x3405c
xorl %ebx, %ebx
pushq $0x30
popq %rdi
callq 0x218d0
movq %rax, %r14
movq 0x10(%r12), %rcx
movq %rax, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x3ee68
movq %r15, %rdi
movq %r14, %rsi
callq 0x27846
leaq 0x20(%rsp), %rdi
movq %r14, %rsi
callq 0x2737a
incq %r13
jmp 0x33fe8
leaq 0x30(%rsp), %rdi
callq 0x7c1c6
xorl %ebx, %ebx
movq 0x8(%rsp), %rcx
movslq 0x14(%rcx), %rax
cmpq %rax, %rbx
jge 0x34207
movq 0x8(%rcx), %rax
movq (%rax,%rbx,8), %r12
movl $0x1b0, %edi            # imm = 0x1B0
callq 0x218d0
movq %rax, %r14
movq %rax, %rdi
movq %r12, %rsi
callq 0x37b90
movq %r15, %rdi
movq %r14, %rsi
callq 0x277ba
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x2737a
movq %r14, 0x10(%rsp)
movq %rbx, 0x60(%rsp)
xorl %ebp, %ebp
movslq 0x3c(%r12), %rax
cmpq %rax, %rbp
jge 0x34182
movq 0x30(%r12), %rax
movq (%rax,%rbp,8), %rbx
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x34127
movslq 0x8(%rax), %rax
movq 0x20(%rsp), %rcx
movq (%rcx,%rax,8), %r13
jmp 0x3412a
xorl %r13d, %r13d
pushq $0x60
popq %rdi
callq 0x218d0
movq %rax, %r14
movq %rax, %rdi
movq %r13, %rsi
callq 0x394c0
movq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x389c8
xorl %r13d, %r13d
movslq 0x1c(%rbx), %rax
cmpq %rax, %r13
jge 0x3417a
movq 0x10(%rbx), %rax
movq (%rax,%r13,8), %rdi
movq (%rdi), %rax
callq *0x98(%rax)
movq %r14, %rdi
movq %rax, %rsi
callq 0x3971a
incq %r13
jmp 0x34150
incq %rbp
jmp 0x340fc
xorl %ebx, %ebx
leaq 0x68(%rsp), %rbp
movslq 0x4c(%r12), %rax
cmpq %rax, %rbx
jge 0x341fa
movq 0x40(%r12), %rax
movq (%rax,%rbx,8), %r13
movq (%r13), %r14
movq %rbp, %rdi
callq 0x7c1c6
xorl %ebp, %ebp
movslq 0x14(%r13), %rax
cmpq %rax, %rbp
jge 0x341d5
movq 0x8(%r13), %rax
movq (%rax,%rbp,8), %rax
movslq 0x8(%rax), %rax
movq 0x20(%rsp), %rcx
movq (%rcx,%rax,8), %rsi
movq %r15, %rdi
callq 0x27846
incq %rbp
jmp 0x341aa
movq %r14, %rdi
movq %r15, %rsi
movq 0x10(%rsp), %rdx
leaq 0x68(%rsp), %rbp
movq %rbp, %rcx
callq 0x33e93
movq %rbp, %rdi
callq 0x7c234
incq %rbx
jmp 0x34189
movq 0x60(%rsp), %rbx
incq %rbx
jmp 0x340a6
xorl %ebx, %ebx
movq 0x18(%rsp), %r14
movq %rcx, %r15
cltq
cmpq %rax, %rbx
jge 0x3424b
movq 0x8(%r15), %rax
movq (%rax,%rbx,8), %rcx
movq 0x30(%rsp), %rax
movq 0x10(%rcx), %rcx
movq %r14, %rdi
testq %rcx, %rcx
je 0x34239
movslq 0x8(%rcx), %rcx
movq (%rax,%rcx,8), %rdi
movq (%rax,%rbx,8), %rsi
callq 0x3898c
incq %rbx
movl 0x14(%r15), %eax
jmp 0x34211
leaq 0x30(%rsp), %rdi
callq 0x7c234
leaq 0x20(%rsp), %rdi
callq 0x7c234
leaq 0x40(%rsp), %rdi
callq 0x7c234
leaq 0x50(%rsp), %rdi
callq 0x7c234
leaq 0x78(%rsp), %rdi
callq 0x7c234
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x342d7
jmp 0x342de
jmp 0x342e3
jmp 0x342e8
movq %rax, %r15
pushq $0x30
popq %rsi
movq %r14, %rdi
callq 0x218f0
jmp 0x3431f
jmp 0x34312
movq %rax, %r15
movl $0x1b0, %esi            # imm = 0x1B0
jmp 0x342f7
jmp 0x342d7
movq %rax, %r15
movl $0xb8, %esi
movq %r14, %rdi
callq 0x218f0
jmp 0x34329
movq %rax, %r15
pushq $0x50
popq %rsi
movq %r13, %rdi
callq 0x218f0
jmp 0x34333
movq %rax, %r15
jmp 0x3431f
jmp 0x34312
movq %rax, %r15
jmp 0x34329
movq %rax, %r15
jmp 0x34333
movq %rax, %r15
jmp 0x3433d
jmp 0x34303
jmp 0x34312
movq %rax, %r15
pushq $0x60
popq %rsi
movq %r14, %rdi
callq 0x218f0
jmp 0x34315
jmp 0x34312
movq %rax, %r15
leaq 0x68(%rsp), %rdi
callq 0x7c234
jmp 0x34315
movq %rax, %r15
leaq 0x30(%rsp), %rdi
callq 0x7c234
leaq 0x20(%rsp), %rdi
callq 0x7c234
leaq 0x40(%rsp), %rdi
callq 0x7c234
leaq 0x50(%rsp), %rdi
callq 0x7c234
leaq 0x78(%rsp), %rdi
callq 0x7c234
movq %r15, %rdi
callq 0x220e0
nop