// File: donqustix[P]SoftwareRenderer/src/main.cpp
// Function: (anonymous namespace)::load_obj(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
Mesh load_obj(const std::string& filepath)
    {
        std::ifstream stream{filepath, std::ios::in};
        if (!stream)
            throw std::runtime_error{"obj loading error"};

        std::vector<vec4f> vertex_positions, normals;
        std::vector<size_t> vertex_indices, normal_indices;
        std::string line;

        while (std::getline(stream, line))
        {
            std::stringstream line_stream{line};
            std::string c;
            line_stream >> c;

            if (c == "v")
            {
                float x, y, z;
                line_stream >> x >> y >> z;
                vertex_positions.emplace_back(x, y, z);
            }
            else if (c == "vn")
            {
                float x, y, z;
                line_stream >> x >> y >> z;
                normals.emplace_back(x, y, z);
            }
            else if (c == "f")
            {
                for (auto i = 0; i < 3; ++i)
                {
                    size_t vertex_index;
                    line_stream >> vertex_index;
                    line_stream.ignore(2);

                    size_t normal_index;
                    line_stream >> normal_index;

                    vertex_indices.push_back(vertex_index);
                    normal_indices.push_back(normal_index);
                }
            }
        }

        std::vector<Vertex> vertices;

        for (auto i : vertex_indices)
            vertices.push_back({vertex_positions[i - 1], normals[normal_indices[i - 1]]});

        return {vertices};
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x550, %rsp            # imm = 0x550
movq %rdi, -0x4f8(%rbp)
movq %rdi, %rax
movq %rax, -0x4f0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rsi
leaq -0x218(%rbp), %rdi
movl $0x8, %edx
callq 0x2340
movq -0x218(%rbp), %rax
movq -0x18(%rax), %rax
leaq -0x218(%rbp,%rax), %rdi
callq 0x2100
movb %al, -0x4e1(%rbp)
jmp 0x2ad9
movb -0x4e1(%rbp), %al
testb $0x1, %al
jne 0x2ae5
jmp 0x2b63
movl $0x10, %edi
callq 0x2120
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x500(%rbp)
leaq 0x55b5(%rip), %rsi      # 0x80b8
callq 0x20e0
jmp 0x2b0a
movq -0x500(%rbp), %rdi
movq 0x94d8(%rip), %rsi      # 0xbff0
movq 0x94a9(%rip), %rdx      # 0xbfc8
callq 0x2370
jmp 0x3076
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0x305e
movq -0x500(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
callq 0x2180
jmp 0x305e
leaq -0x240(%rbp), %rdi
callq 0x3ab0
leaq -0x258(%rbp), %rdi
callq 0x3ab0
leaq -0x270(%rbp), %rdi
callq 0x70b0
leaq -0x288(%rbp), %rdi
callq 0x70b0
leaq -0x2a8(%rbp), %rdi
callq 0x22d0
leaq -0x218(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x2080
movq %rax, -0x508(%rbp)
jmp 0x2bbb
movq -0x508(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x2280
movb %al, -0x509(%rbp)
jmp 0x2bd9
movb -0x509(%rbp), %al
testb $0x1, %al
jne 0x2be8
jmp 0x2ea0
movl $0x10, %edi
movl $0x8, %esi
callq 0x70d0
movl %eax, -0x510(%rbp)
jmp 0x2bff
movl -0x510(%rbp), %edx
leaq -0x430(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x2330
jmp 0x2c1a
leaq -0x450(%rbp), %rdi
movq %rdi, -0x518(%rbp)
callq 0x22d0
movq -0x518(%rbp), %rsi
leaq -0x430(%rbp), %rdi
callq 0x2290
jmp 0x2c42
leaq 0x5481(%rip), %rsi      # 0x80ca
leaq -0x450(%rbp), %rdi
callq 0x70f0
movb %al, -0x519(%rbp)
jmp 0x2c5d
movb -0x519(%rbp), %al
testb $0x1, %al
jne 0x2c6c
jmp 0x2d27
leaq -0x430(%rbp), %rdi
leaq -0x454(%rbp), %rsi
callq 0x2090
movq %rax, -0x528(%rbp)
jmp 0x2c88
movq -0x528(%rbp), %rdi
leaq -0x458(%rbp), %rsi
callq 0x2090
movq %rax, -0x530(%rbp)
jmp 0x2ca4
movq -0x530(%rbp), %rdi
leaq -0x45c(%rbp), %rsi
callq 0x2090
jmp 0x2cb9
leaq -0x240(%rbp), %rdi
leaq -0x454(%rbp), %rsi
leaq -0x458(%rbp), %rdx
leaq -0x45c(%rbp), %rcx
callq 0x3ad0
jmp 0x2cdc
jmp 0x2e83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
jmp 0x3022
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
leaq -0x450(%rbp), %rdi
callq 0x2170
leaq -0x430(%rbp), %rdi
callq 0x21c0
jmp 0x3022
leaq 0x539e(%rip), %rsi      # 0x80cc
leaq -0x450(%rbp), %rdi
callq 0x70f0
movb %al, -0x531(%rbp)
jmp 0x2d42
movb -0x531(%rbp), %al
testb $0x1, %al
jne 0x2d4e
jmp 0x2dc3
leaq -0x430(%rbp), %rdi
leaq -0x460(%rbp), %rsi
callq 0x2090
movq %rax, -0x540(%rbp)
jmp 0x2d6a
movq -0x540(%rbp), %rdi
leaq -0x464(%rbp), %rsi
callq 0x2090
movq %rax, -0x548(%rbp)
jmp 0x2d86
movq -0x548(%rbp), %rdi
leaq -0x468(%rbp), %rsi
callq 0x2090
jmp 0x2d9b
leaq -0x258(%rbp), %rdi
leaq -0x460(%rbp), %rsi
leaq -0x464(%rbp), %rdx
leaq -0x468(%rbp), %rcx
callq 0x3ad0
jmp 0x2dbe
jmp 0x2e81
leaq 0x5305(%rip), %rsi      # 0x80cf
leaq -0x450(%rbp), %rdi
callq 0x70f0
movb %al, -0x549(%rbp)
jmp 0x2dde
movb -0x549(%rbp), %al
testb $0x1, %al
jne 0x2ded
jmp 0x2e7f
movl $0x0, -0x46c(%rbp)
cmpl $0x3, -0x46c(%rbp)
jge 0x2e7d
leaq -0x430(%rbp), %rdi
leaq -0x478(%rbp), %rsi
callq 0x22e0
jmp 0x2e15
leaq -0x430(%rbp), %rdi
movl $0x2, %esi
callq 0x2050
jmp 0x2e28
leaq -0x430(%rbp), %rdi
leaq -0x480(%rbp), %rsi
callq 0x22e0
jmp 0x2e3d
leaq -0x270(%rbp), %rdi
leaq -0x478(%rbp), %rsi
callq 0x7120
jmp 0x2e52
leaq -0x288(%rbp), %rdi
leaq -0x480(%rbp), %rsi
callq 0x7120
jmp 0x2e67
jmp 0x2e69
movl -0x46c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x46c(%rbp)
jmp 0x2df7
jmp 0x2e7f
jmp 0x2e81
jmp 0x2e83
leaq -0x450(%rbp), %rdi
callq 0x2170
leaq -0x430(%rbp), %rdi
callq 0x21c0
jmp 0x2b9f
leaq -0x498(%rbp), %rdi
callq 0x3b60
leaq -0x270(%rbp), %rax
movq %rax, -0x4a0(%rbp)
movq -0x4a0(%rbp), %rdi
callq 0x7190
movq %rax, -0x4a8(%rbp)
movq -0x4a0(%rbp), %rdi
callq 0x71c0
movq %rax, -0x4b0(%rbp)
leaq -0x4a8(%rbp), %rdi
leaq -0x4b0(%rbp), %rsi
callq 0x71f0
testb $0x1, %al
jne 0x2efc
jmp 0x2fa9
leaq -0x4a8(%rbp), %rdi
callq 0x7230
movq (%rax), %rax
movq %rax, -0x4b8(%rbp)
movq -0x4b8(%rbp), %rsi
decq %rsi
leaq -0x240(%rbp), %rdi
callq 0x3bb0
movups (%rax), %xmm0
movaps %xmm0, -0x4e0(%rbp)
movq -0x4b8(%rbp), %rsi
decq %rsi
leaq -0x288(%rbp), %rdi
callq 0x7250
movq (%rax), %rsi
leaq -0x258(%rbp), %rdi
callq 0x3bb0
movups (%rax), %xmm0
movups %xmm0, -0x4d0(%rbp)
leaq -0x498(%rbp), %rdi
leaq -0x4e0(%rbp), %rsi
callq 0x3b80
jmp 0x2f76
jmp 0x2f78
leaq -0x4a8(%rbp), %rdi
callq 0x7270
jmp 0x2ee0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x220(%rbp)
movl %eax, -0x224(%rbp)
leaq -0x498(%rbp), %rdi
callq 0x3cc0
jmp 0x3022
movq -0x4f8(%rbp), %rdi
leaq -0x498(%rbp), %rsi
callq 0x3bd0
jmp 0x2fbe
leaq -0x498(%rbp), %rdi
callq 0x3cc0
leaq -0x2a8(%rbp), %rdi
callq 0x2170
leaq -0x288(%rbp), %rdi
callq 0x7290
leaq -0x270(%rbp), %rdi
callq 0x7290
leaq -0x258(%rbp), %rdi
callq 0x3d20
leaq -0x240(%rbp), %rdi
callq 0x3d20
leaq -0x218(%rbp), %rdi
callq 0x20a0
movq -0x4f0(%rbp), %rax
addq $0x550, %rsp            # imm = 0x550
popq %rbp
retq
leaq -0x2a8(%rbp), %rdi
callq 0x2170
leaq -0x288(%rbp), %rdi
callq 0x7290
leaq -0x270(%rbp), %rdi
callq 0x7290
leaq -0x258(%rbp), %rdi
callq 0x3d20
leaq -0x240(%rbp), %rdi
callq 0x3d20
leaq -0x218(%rbp), %rdi
callq 0x20a0
movq -0x220(%rbp), %rdi
callq 0x2380
nopw %cs:(%rax,%rax)