// File: /workspace/github_cpp_makefile_star2_O2/alan0201tw[P]RayTracer/src/util.cpp
// Function: random_scene()
std::shared_ptr<hitable> random_scene()
{
    int n = 500;
    std::vector<std::shared_ptr<hitable>> list;
    list.reserve(n + 1);

    std::shared_ptr<texture> _checker_texture = std::make_shared<checker_texture>(
        std::make_shared<constant_texture>(vec3(0.2f, 0.3f, 0.1f)),
        std::make_shared<constant_texture>(vec3(0.9f, 0.9f, 0.9f))
    );
    std::shared_ptr<texture> _image_texture = std::make_shared<image_texture>("./resources/texture.jpg");

    list.push_back(std::make_shared<sphere>(vec3(0,-1000,0), 1000, std::make_shared<lambertian>(_checker_texture)));

    for (int a = -10; a < 10; a++) {
        for (int b = -10; b < 10; b++) {
            float choose_mat = drand48();
            vec3 center(a + 0.9 * drand48(), 0.2f, b + 0.9 * drand48()); 
            if ((center-vec3(4,0.2,0)).length() > 0.9) { 
                if (choose_mat < 0.8f) 
                {
                    // diffuse
                    //list.push_back(std::make_shared<sphere>(center, 0.2, std::make_shared<lambertian>(vec3(drand48()*drand48(), drand48()*drand48(), drand48()*drand48()))));
                    std::shared_ptr<texture> random_texture = std::make_shared<constant_texture>(
                        vec3(drand48()*drand48(), drand48()*drand48(), drand48()*drand48()));

                    list.push_back(std::make_shared<moving_sphere>(
                        center, center + vec3(0, 0.5f * drand48(), 0.0f), 
                        0.0f, 1.0f, // start and end time
                        0.2f, std::make_shared<lambertian>(random_texture)));
                }
                else if (choose_mat < 0.95f)
                {
                    // metal
                    list.push_back(std::make_shared<sphere>(center, 0.2,
                        std::make_shared<metal>(vec3(0.5*(1 + drand48()), 0.5*(1 + drand48()), 0.5*(1 + drand48())),  0.5*drand48())));
                }
                else
                {
                    // glass
                    list.push_back(std::make_shared<sphere>(center, 0.2, std::make_shared<dielectric>(1.5)));
                }
            }
        }
    }
    std::shared_ptr<texture> _color_texture = std::make_shared<constant_texture>(vec3(4.0f, 4.0f, 4.0f));

    list.push_back(std::make_shared<sphere>(vec3(-4, 1, 2.0f), 1.0, std::make_shared<dielectric>(1.5)));
    //list.push_back(std::make_shared<sphere>(vec3(-4, 1, 0), 1.0, std::make_shared<lambertian>(vec3(0.4, 0.2, 0.1))));
    // list.push_back(std::make_shared<sphere>(vec3(-4, 1, 2.0f), 1.0, std::make_shared<lambertian>(_image_texture)));
    list.push_back(std::make_shared<sphere>(vec3(0, 1, 0), 1.0, std::make_shared<diffuse_light>(_color_texture)));
    list.push_back(std::make_shared<sphere>(vec3(4, 1, 0), 1.0, std::make_shared<metal>(vec3(0.7, 0.6, 0.5), 0.0)));

    //return std::make_shared<hitable_list>(list, list.size());

    // change to bvh
    return std::make_shared<bvh_node>(list, 0.0f, 1.0f);

    // using O(N) search ( hitable_list )
    // real    4m49.214s
    // user    13m57.995s
    // sys     0m7.843s
    //
    // using BVH
    // real    1m21.986s
    // user    4m50.992s
    // sys     0m4.199s
    //
    // using BVH and functors
    // real    1m18.025s
    // user    4m20.477s
    // sys     0m3.869s
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movq %rdi, %rbx
xorps %xmm0, %xmm0
leaq 0xc0(%rsp), %rdi
movaps %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
movl $0x1f5, %esi            # imm = 0x1F5
callq 0x71e8
movsd 0x1e366(%rip), %xmm0    # 0x30550
leaq 0x30(%rsp), %rsi
movsd %xmm0, (%rsi)
movl $0x3dcccccd, 0x8(%rsi)  # imm = 0x3DCCCCCD
leaq 0x40(%rsp), %rdi
callq 0x16b90
movsd 0x1e354(%rip), %xmm0    # 0x30560
leaq 0x58(%rsp), %rsi
movsd %xmm0, (%rsi)
movl $0x3f666666, 0x8(%rsi)  # imm = 0x3F666666
leaq 0x10(%rsp), %rdi
callq 0x16b90
leaq 0x80(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x16b6f
leaq 0xf8(%rsp), %rax
leaq 0x88(%rsp), %rdi
movaps -0x8(%rdi), %xmm0
movaps %xmm0, -0x8(%rax)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%rdi)
callq 0x7426
leaq 0x18(%rsp), %rdi
callq 0x7426
leaq 0x48(%rsp), %rdi
callq 0x7426
leaq 0x1ea85(%rip), %rsi     # 0x30d01
leaq 0x40(%rsp), %rdi
callq 0x16bae
leaq 0x88(%rsp), %rax
leaq 0x48(%rsp), %rdi
movaps -0x8(%rdi), %xmm0
movaps %xmm0, -0x8(%rax)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%rdi)
callq 0x7426
movsd 0x1e2c1(%rip), %xmm0    # 0x30570
movsd %xmm0, 0x58(%rsp)
andl $0x0, 0x60(%rsp)
movl $0x3e8, 0x20(%rsp)      # imm = 0x3E8
leaq 0x30(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x16bf0
leaq 0x10(%rsp), %rdi
leaq 0x58(%rsp), %r12
leaq 0x20(%rsp), %rdx
leaq 0x30(%rsp), %rcx
movq %r12, %rsi
callq 0x16bcc
movq %rbx, 0x108(%rsp)
leaq 0x48(%rsp), %r15
leaq 0x18(%rsp), %rbx
movaps -0x8(%rbx), %xmm0
movaps %xmm0, -0x8(%r15)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%rbx)
leaq 0xc0(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x7b8a
movq %r15, %rdi
callq 0x7426
movq %rbx, %rdi
callq 0x7426
leaq 0x38(%rsp), %rdi
callq 0x7426
pushq $-0xa
popq %rax
leaq 0x10(%rsp), %r13
leaq 0x30(%rsp), %r14
leaq 0x70(%rsp), %r15
leaq 0xc0(%rsp), %rbx
cmpl $0xa, %eax
je 0x12731
movl %eax, 0x98(%rsp)
cvtsi2sd %eax, %xmm0
movsd %xmm0, 0x118(%rsp)
pushq $-0xa
popq %rbp
cmpl $0xa, %ebp
je 0x12723
callq 0x63e0
movsd %xmm0, 0xe0(%rsp)
callq 0x63e0
movsd 0x1e13c(%rip), %xmm1    # 0x304d8
mulsd %xmm1, %xmm0
addsd 0x118(%rsp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0xb0(%rsp)
cvtsi2sd %ebp, %xmm0
movsd %xmm0, 0xa0(%rsp)
callq 0x63e0
movsd 0x1e108(%rip), %xmm1    # 0x304d8
mulsd %xmm1, %xmm0
addsd 0xa0(%rsp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss 0xb0(%rsp), %xmm2
movss %xmm2, 0x20(%rsp)
movl $0x3e4ccccd, 0x24(%rsp) # imm = 0x3E4CCCCD
movss %xmm0, 0x28(%rsp)
addss 0x1e106(%rip), %xmm2    # 0x3050c
mulss %xmm2, %xmm2
addss 0x1e082(%rip), %xmm2    # 0x30494
mulss %xmm0, %xmm0
addss %xmm2, %xmm0
sqrtss %xmm0, %xmm0
cvtss2sd %xmm0, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1271c
cvtsd2ss 0xe0(%rsp), %xmm0
movss 0x1e0d3(%rip), %xmm1    # 0x30510
ucomiss %xmm0, %xmm1
jbe 0x125cd
callq 0x63e0
movaps %xmm0, 0xb0(%rsp)
callq 0x63e0
movaps %xmm0, 0xa0(%rsp)
callq 0x63e0
movaps %xmm0, 0xe0(%rsp)
callq 0x63e0
movaps %xmm0, 0x120(%rsp)
callq 0x63e0
movsd %xmm0, 0x110(%rsp)
callq 0x63e0
mulsd 0x110(%rsp), %xmm0
cvtsd2ss %xmm0, %xmm0
movapd 0xb0(%rsp), %xmm1
unpcklpd 0xe0(%rsp), %xmm1       # xmm1 = xmm1[0],mem[0]
movapd 0xa0(%rsp), %xmm2
unpcklpd 0x120(%rsp), %xmm2      # xmm2 = xmm2[0],mem[0]
mulpd %xmm1, %xmm2
cvtpd2ps %xmm2, %xmm1
movlpd %xmm1, 0x30(%rsp)
movss %xmm0, 0x38(%rsp)
movq %r13, %rdi
movq %r14, %rsi
callq 0x16b90
movapd 0x10(%rsp), %xmm0
movapd %xmm0, 0x40(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0x10(%rsp)
leaq 0x18(%rsp), %rdi
callq 0x7426
callq 0x63e0
mulsd 0x1dfd6(%rip), %xmm0    # 0x304e0
cvtsd2ss %xmm0, %xmm0
movsd 0x20(%rsp), %xmm1
xorpd %xmm2, %xmm2
unpcklps %xmm0, %xmm2            # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
addps %xmm1, %xmm2
movss 0x28(%rsp), %xmm0
addss 0x1df68(%rip), %xmm0    # 0x30494
andl $0x0, 0x68(%rsp)
movlps %xmm2, 0x70(%rsp)
movss %xmm0, 0x78(%rsp)
movl $0x3f800000, 0xd8(%rsp) # imm = 0x3F800000
movl $0x3e4ccccd, 0x9c(%rsp) # imm = 0x3E4CCCCD
movq %r12, %rdi
leaq 0x40(%rsp), %rsi
callq 0x16bf0
movq %r12, (%rsp)
movq %r14, %rdi
leaq 0x20(%rsp), %rsi
movq %r15, %rdx
leaq 0x68(%rsp), %rcx
leaq 0xd8(%rsp), %r8
leaq 0x9c(%rsp), %r9
callq 0x16c0e
movaps 0x30(%rsp), %xmm0
movaps %xmm0, 0x10(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x7b8a
leaq 0x18(%rsp), %rdi
callq 0x7426
leaq 0x38(%rsp), %rdi
callq 0x7426
leaq 0x60(%rsp), %rdi
callq 0x7426
leaq 0x48(%rsp), %rdi
jmp 0x12717
movss 0x1df3f(%rip), %xmm1    # 0x30514
movabsq $0x3fc999999999999a, %rax # imm = 0x3FC999999999999A
ucomiss %xmm0, %xmm1
jbe 0x126ad
movq %rax, 0x70(%rsp)
callq 0x63e0
movaps %xmm0, 0xb0(%rsp)
callq 0x63e0
movaps %xmm0, 0xa0(%rsp)
callq 0x63e0
addsd 0x1de9c(%rip), %xmm0    # 0x304b0
movsd 0x1dec4(%rip), %xmm1    # 0x304e0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movapd 0xb0(%rsp), %xmm1
unpcklpd 0xa0(%rsp), %xmm1       # xmm1 = xmm1[0],mem[0]
addpd 0x1df42(%rip), %xmm1    # 0x30580
mulpd 0x1df4a(%rip), %xmm1    # 0x30590
cvtpd2ps %xmm1, %xmm1
movlpd %xmm1, 0x58(%rsp)
movss %xmm0, 0x60(%rsp)
callq 0x63e0
mulsd 0x1de7d(%rip), %xmm0    # 0x304e0
movsd %xmm0, 0x68(%rsp)
movq %r14, %rdi
movq %r12, %rsi
leaq 0x68(%rsp), %rdx
callq 0x16c63
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
movq %r15, %rdx
movq %r14, %rcx
callq 0x16c3f
movaps 0x10(%rsp), %xmm0
movaps %xmm0, 0x40(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq %rbx, %rdi
leaq 0x40(%rsp), %rsi
callq 0x7b8a
jmp 0x126fe
movq %rax, 0x58(%rsp)
movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000
movq %rax, 0x70(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x16ca8
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
movq %r12, %rdx
movq %r14, %rcx
callq 0x16c84
movaps 0x10(%rsp), %xmm0
movaps %xmm0, 0x40(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movq %rbx, %rdi
leaq 0x40(%rsp), %rsi
callq 0x7b8a
leaq 0x48(%rsp), %rdi
callq 0x7426
leaq 0x18(%rsp), %rdi
callq 0x7426
leaq 0x38(%rsp), %rdi
callq 0x7426
incl %ebp
jmp 0x12378
movl 0x98(%rsp), %eax
incl %eax
jmp 0x12358
movsd 0x1de67(%rip), %xmm0    # 0x305a0
leaq 0x30(%rsp), %rsi
movsd %xmm0, (%rsi)
movl $0x40800000, 0x8(%rsi)  # imm = 0x40800000
leaq 0x10(%rsp), %rdi
callq 0x16b90
leaq 0x48(%rsp), %rbx
leaq 0x18(%rsp), %rdi
movaps -0x8(%rdi), %xmm0
movaps %xmm0, -0x8(%rbx)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%rdi)
callq 0x7426
movsd 0x1de37(%rip), %xmm0    # 0x305b0
movsd %xmm0, 0x20(%rsp)
movl $0x40000000, 0x28(%rsp) # imm = 0x40000000
movabsq $0x3ff0000000000000, %r14 # imm = 0x3FF0000000000000
movq %r14, 0x70(%rsp)
leaq 0x68(%rsp), %rsi
movabsq $0x3ff8000000000000, %rax # imm = 0x3FF8000000000000
movq %rax, (%rsi)
leaq 0x58(%rsp), %rdi
callq 0x16ca8
leaq 0x30(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x70(%rsp), %rdx
leaq 0x58(%rsp), %rcx
callq 0x16cc6
leaq 0x18(%rsp), %r12
leaq 0x38(%rsp), %r15
movaps -0x8(%r15), %xmm0
movaps %xmm0, -0x8(%r12)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%r15)
leaq 0xc0(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x7b8a
movq %r12, %rdi
callq 0x7426
movq %r15, %rdi
callq 0x7426
leaq 0x60(%rsp), %rdi
callq 0x7426
movsd 0x1d9f4(%rip), %xmm0    # 0x30210
movsd %xmm0, 0x20(%rsp)
andl $0x0, 0x28(%rsp)
movq %r14, 0x70(%rsp)
leaq 0x58(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x16d0e
leaq 0x30(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x70(%rsp), %rdx
leaq 0x58(%rsp), %rcx
callq 0x16cea
leaq 0x18(%rsp), %r12
leaq 0x38(%rsp), %r15
movaps -0x8(%r15), %xmm0
movaps %xmm0, -0x8(%r12)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%r15)
leaq 0xc0(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x7b8a
movq %r12, %rdi
callq 0x7426
movq %r15, %rdi
callq 0x7426
leaq 0x60(%rsp), %rdi
callq 0x7426
movsd 0x1dd1b(%rip), %xmm0    # 0x305c0
movsd %xmm0, 0x20(%rsp)
andl $0x0, 0x28(%rsp)
movq %r14, 0x68(%rsp)
movsd 0x1dd13(%rip), %xmm0    # 0x305d0
leaq 0x70(%rsp), %rsi
movsd %xmm0, (%rsi)
movl $0x3f000000, 0x8(%rsi)  # imm = 0x3F000000
leaq 0xd8(%rsp), %rdx
andq $0x0, (%rdx)
leaq 0x58(%rsp), %rdi
callq 0x16c63
leaq 0x30(%rsp), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x68(%rsp), %rdx
leaq 0x58(%rsp), %rcx
callq 0x16d2c
leaq 0x18(%rsp), %r12
leaq 0x38(%rsp), %r15
movaps -0x8(%r15), %xmm0
movaps %xmm0, -0x8(%r12)
xorps %xmm0, %xmm0
movaps %xmm0, -0x8(%r15)
leaq 0xc0(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x7b8a
movq %r12, %rdi
callq 0x7426
movq %r15, %rdi
callq 0x7426
leaq 0x60(%rsp), %r14
movq %r14, %rdi
callq 0x7426
leaq 0x30(%rsp), %rdx
andl $0x0, (%rdx)
movl $0x3f800000, -0x8(%r14) # imm = 0x3F800000
leaq 0x10(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
leaq 0x58(%rsp), %rcx
callq 0x16d50
leaq 0x18(%rsp), %rdi
movaps -0x8(%rdi), %xmm0
andq $0x0, (%rdi)
movq 0x108(%rsp), %r14
movups %xmm0, (%r14)
andq $0x0, -0x8(%rdi)
callq 0x7426
movq %rbx, %rdi
callq 0x7426
leaq 0x88(%rsp), %rdi
callq 0x7426
leaq 0xf8(%rsp), %rdi
callq 0x7426
leaq 0xc0(%rsp), %rdi
callq 0x7404
movq %r14, %rax
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x12a08
jmp 0x129e4
jmp 0x129f9
jmp 0x12a08
jmp 0x129e4
jmp 0x129f9
jmp 0x12a08
movq %rax, %r14
movq %r12, %rdi
callq 0x7426
movq %r15, %rdi
callq 0x7426
jmp 0x129fc
movq %rax, %r14
leaq 0x60(%rsp), %rdi
callq 0x7426
jmp 0x12a0b
movq %rax, %r14
movq %rbx, %rdi
jmp 0x12ab5
jmp 0x12abc
movq %rax, %r14
movq %r15, %rdi
callq 0x7426
movq %rbx, %rdi
jmp 0x12a72
jmp 0x12a79
jmp 0x12abc
movq %rax, %r14
jmp 0x12acc
movq %rax, %r14
leaq 0x18(%rsp), %rdi
callq 0x7426
jmp 0x12a49
movq %rax, %r14
leaq 0x48(%rsp), %rdi
jmp 0x12ad4
jmp 0x12a55
movq %rax, %r14
jmp 0x12ad9
jmp 0x12a79
jmp 0x12a60
jmp 0x12abc
movq %rax, %r14
leaq 0x48(%rsp), %rdi
callq 0x7426
leaq 0x18(%rsp), %rdi
callq 0x7426
jmp 0x12a7c
movq %rax, %r14
leaq 0x38(%rsp), %rdi
jmp 0x12ab5
jmp 0x12abc
movq %rax, %r14
leaq 0x18(%rsp), %rdi
callq 0x7426
leaq 0x38(%rsp), %rdi
callq 0x7426
jmp 0x12aa1
movq %rax, %r14
leaq 0x60(%rsp), %rdi
callq 0x7426
jmp 0x12ab0
movq %rax, %r14
leaq 0x48(%rsp), %rdi
callq 0x7426
jmp 0x12abf
movq %rax, %r14
leaq 0x88(%rsp), %rdi
callq 0x7426
leaq 0xf8(%rsp), %rdi
callq 0x7426
leaq 0xc0(%rsp), %rdi
callq 0x7404
movq %r14, %rdi
callq 0x6710