// File: Crawler995[P]Cpp-Ray-Tracing/libs/render_engine.cpp
// Function: RenderEngine::render(PerspectiveCamera&, GeometryUnion&, _IO_FILE*, unsigned char*)
void RenderEngine::render(
    PerspectiveCamera &camera, 
    GeometryUnion &geo_union,
    FILE *f, 
    unsigned char *output_img_data
) {
    int index = 0;
    int two_percent_num = image_width * image_height / 50;
    unsigned char *p = output_img_data;
    clock_t start, end;
    start = clock();

    std::string progress_char;
    std::cout << "Start rendering..." << std::endl;

    for(int i = image_height - 1; i >= 0; i--) {
        for(int j = 0; j < image_width; j++) {
            Color color(0, 0, 0);

            for(int k = 0; k < sample_times; k++) {
                double u = 1.0 * (j + rand_num_0_to_1()) / image_width;
                double v = 1.0 * (i + rand_num_0_to_1()) / image_height;

                Ray3 ray = camera.generate_ray(u, v);
                color = color.add(ray_tracing_recursive(ray, geo_union, 0));
            }

            color = color.multiply(1.0 / sample_times);

            *p++ = (unsigned char)color.get_r();
            *p++ = (unsigned char)color.get_g();
            *p++ = (unsigned char)color.get_b();

            index++;
            if(index % two_percent_num == 0) {
                update_progress(progress_char);
            }
        }
    }

    end = clock();
    double run_time = (double)(end - start) / CLOCKS_PER_SEC;

    svpng(f, image_width, image_height, output_img_data, 0);
    
    std::cout << std::endl << "Render done! Spend " << run_time << "s." << std::endl;

    fclose(f);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rcx
movq %rcx, -0x188(%rbp)
movl $0x0, -0x2c(%rbp)
movl (%rcx), %eax
movl 0x4(%rcx), %ecx
imull %ecx, %eax
cltq
imulq $0x51eb851f, %rax, %rax # imm = 0x51EB851F
movq %rax, %rcx
shrq $0x3f, %rcx
sarq $0x24, %rax
addl %ecx, %eax
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x38(%rbp)
callq 0x20b0
movq %rax, -0x40(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x2180
movq 0x4de5(%rip), %rdi      # 0xcfd8
leaq 0x1011(%rip), %rsi      # 0x920b
callq 0x2110
movq %rax, -0x180(%rbp)
jmp 0x8208
movq -0x180(%rbp), %rdi
movq 0x4db2(%rip), %rsi      # 0xcfc8
callq 0x2150
jmp 0x821d
movq -0x188(%rbp), %rax
movl 0x4(%rax), %eax
subl $0x1, %eax
movl %eax, -0x78(%rbp)
cmpl $0x0, -0x78(%rbp)
jl 0x85d7
movl $0x0, -0x7c(%rbp)
movq -0x188(%rbp), %rcx
movl -0x7c(%rbp), %eax
cmpl (%rcx), %eax
jge 0x85c7
leaq -0x88(%rbp), %rdi
xorl %ecx, %ecx
movl %ecx, %esi
movl %ecx, %edx
callq 0x4c50
jmp 0x8264
movl $0x0, -0x8c(%rbp)
movq -0x188(%rbp), %rcx
movl -0x8c(%rbp), %eax
cmpl 0x8(%rcx), %eax
jge 0x8492
cvtsi2sdl -0x7c(%rbp), %xmm0
movsd %xmm0, -0x198(%rbp)
callq 0x4f90
movsd %xmm0, -0x190(%rbp)
jmp 0x82a0
movq -0x188(%rbp), %rax
movsd -0x190(%rbp), %xmm1
movsd -0x198(%rbp), %xmm0
addsd %xmm1, %xmm0
cvtsi2sdl (%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x98(%rbp)
cvtsi2sdl -0x78(%rbp), %xmm0
movsd %xmm0, -0x1a8(%rbp)
callq 0x4f90
movsd %xmm0, -0x1a0(%rbp)
jmp 0x82e7
movq -0x188(%rbp), %rax
movsd -0x1a0(%rbp), %xmm1
movsd -0x1a8(%rbp), %xmm0
addsd %xmm1, %xmm0
cvtsi2sdl 0x4(%rax), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0xa0(%rbp)
movq -0x10(%rbp), %rsi
movsd -0x98(%rbp), %xmm0
movsd -0xa0(%rbp), %xmm1
leaq -0xd0(%rbp), %rdi
callq 0x3df0
jmp 0x8335
movq -0x188(%rbp), %rdi
movups -0xd0(%rbp), %xmm0
movups -0xc0(%rbp), %xmm1
movups -0xb0(%rbp), %xmm2
movaps %xmm2, -0x100(%rbp)
movaps %xmm1, -0x110(%rbp)
movaps %xmm0, -0x120(%rbp)
movq -0x18(%rbp), %rsi
movaps -0x120(%rbp), %xmm0
movaps -0x110(%rbp), %xmm1
movaps -0x100(%rbp), %xmm2
movq %rsp, %rax
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
xorl %edx, %edx
callq 0x7cd0
movl %edx, -0x1b4(%rbp)
movq %rax, -0x1b0(%rbp)
jmp 0x83a3
movl -0x1b4(%rbp), %eax
movq -0x1b0(%rbp), %rcx
movq %rcx, -0x130(%rbp)
movl %eax, -0x128(%rbp)
movl -0x128(%rbp), %eax
movl %eax, -0xe0(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0xe8(%rbp)
movl -0xe0(%rbp), %eax
movl %eax, -0x138(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rsi
movl -0x138(%rbp), %edx
leaq -0x88(%rbp), %rdi
callq 0x4cf0
movl %edx, -0x1c4(%rbp)
movq %rax, -0x1c0(%rbp)
jmp 0x8419
movl -0x1c4(%rbp), %eax
movq -0x1c0(%rbp), %rcx
movq %rcx, -0x150(%rbp)
movl %eax, -0x148(%rbp)
movq -0x150(%rbp), %rax
movq %rax, -0xdc(%rbp)
movl -0x148(%rbp), %eax
movl %eax, -0xd4(%rbp)
movq -0xdc(%rbp), %rax
movq %rax, -0x88(%rbp)
movl -0xd4(%rbp), %eax
movl %eax, -0x80(%rbp)
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x826e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x20a0
jmp 0x86c8
movq -0x188(%rbp), %rax
cvtsi2sdl 0x8(%rax), %xmm1
movsd 0xbf2(%rip), %xmm0      # 0x9098
divsd %xmm1, %xmm0
leaq -0x88(%rbp), %rdi
callq 0x4d50
movl %edx, -0x1d4(%rbp)
movq %rax, -0x1d0(%rbp)
jmp 0x84c5
movl -0x1d4(%rbp), %eax
movq -0x1d0(%rbp), %rcx
movq %rcx, -0x170(%rbp)
movl %eax, -0x168(%rbp)
movl -0x168(%rbp), %eax
movl %eax, -0x158(%rbp)
movq -0x170(%rbp), %rax
movq %rax, -0x160(%rbp)
movl -0x158(%rbp), %eax
movl %eax, -0x80(%rbp)
movq -0x160(%rbp), %rax
movq %rax, -0x88(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x4e90
movl %eax, -0x1d8(%rbp)
jmp 0x8524
movl -0x1d8(%rbp), %eax
movb %al, %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
incq %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
leaq -0x88(%rbp), %rdi
callq 0x4ec0
movl %eax, -0x1dc(%rbp)
jmp 0x8550
movl -0x1dc(%rbp), %eax
movb %al, %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
incq %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
leaq -0x88(%rbp), %rdi
callq 0x4ea0
movl %eax, -0x1e0(%rbp)
jmp 0x857c
movl -0x1e0(%rbp), %eax
movb %al, %cl
movq -0x38(%rbp), %rax
movq %rax, %rdx
addq $0x1, %rdx
movq %rdx, -0x38(%rbp)
movb %cl, (%rax)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cltd
idivl -0x30(%rbp)
cmpl $0x0, %edx
jne 0x85b7
leaq -0x68(%rbp), %rdi
callq 0x4f40
jmp 0x85b5
jmp 0x85b7
jmp 0x85b9
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x823e
jmp 0x85c9
movl -0x78(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x822d
callq 0x20b0
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq %rcx, -0x48(%rbp)
movq -0x48(%rbp), %rcx
movq -0x40(%rbp), %rdx
subq %rdx, %rcx
cvtsi2sd %rcx, %xmm0
movsd 0xb9e(%rip), %xmm1      # 0x91a0
divsd %xmm1, %xmm0
movsd %xmm0, -0x178(%rbp)
movq -0x20(%rbp), %rdi
movl (%rax), %esi
movl 0x4(%rax), %edx
movq -0x28(%rbp), %rcx
xorl %r8d, %r8d
callq 0x6ea0
jmp 0x8625
movq 0x49ac(%rip), %rdi      # 0xcfd8
movq 0x4995(%rip), %rsi      # 0xcfc8
callq 0x2150
movq %rax, -0x1e8(%rbp)
jmp 0x8641
movq -0x1e8(%rbp), %rdi
leaq 0xbcf(%rip), %rsi       # 0x921e
callq 0x2110
movq %rax, -0x1f0(%rbp)
jmp 0x865d
movq -0x1f0(%rbp), %rdi
movsd -0x178(%rbp), %xmm0
callq 0x2200
movq %rax, -0x1f8(%rbp)
jmp 0x867a
movq -0x1f8(%rbp), %rdi
leaq 0xbaa(%rip), %rsi       # 0x9232
callq 0x2110
movq %rax, -0x200(%rbp)
jmp 0x8696
movq -0x200(%rbp), %rdi
movq 0x4924(%rip), %rsi      # 0xcfc8
callq 0x2150
jmp 0x86ab
movq -0x20(%rbp), %rdi
callq 0x2120
jmp 0x86b6
leaq -0x68(%rbp), %rdi
callq 0x20a0
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x21e0
nopw %cs:(%rax,%rax)