// File: graphitemaster[P]smbf/smbf.cpp
// Function: calculateTangent(std::vector<m::vec3, std::allocator<m::vec3>> const&, std::vector<m::vec3, std::allocator<m::vec3>> const&, unsigned long, unsigned long, unsigned long, m::vec3&, m::vec3&)
static void calculateTangent(const u::vector<m::vec3> &vertices,
                             const u::vector<m::vec3> &coordinates,
                             size_t v0,
                             size_t v1,
                             size_t v2,
                             m::vec3 &tangent,
                             m::vec3 &bitangent)
{
    const m::vec3 &x = vertices[v0];
    const m::vec3 &y = vertices[v1];
    const m::vec3 &z = vertices[v2];
    const m::vec3 q1(y - x);
    const m::vec3 q2(z - x);
    const float s1 = coordinates[v1].x - coordinates[v0].x;
    const float s2 = coordinates[v2].x - coordinates[v0].x;
    const float t1 = coordinates[v1].y - coordinates[v0].y;
    const float t2 = coordinates[v2].y - coordinates[v0].y;
    const float det = s1*t2 - s2*t1;
    if (m::abs(det) <= m::kEpsilon) {
        // Unable to compute tangent + bitangent, default tangent along xAxis and
        // bitangent along yAxis.
        tangent = m::vec3::xAxis;
        bitangent = m::vec3::yAxis;
        return;
    }

    const float inv = 1.0f / det;
    tangent = m::vec3(inv * (t2 * q1.x - t1 * q2.x),
                      inv * (t2 * q1.y - t1 * q2.y),
                      inv * (t2 * q1.z - t1 * q2.z));
    bitangent = m::vec3(inv * (-s2 * q1.x + s1 * q2.x),
                        inv * (-s2 * q1.y + s1 * q2.y),
                        inv * (-s2 * q1.z + s1 * q2.z));
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xaa60
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xaa60
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xaa60
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0xaa80
movss %xmm1, -0x60(%rbp)
movlpd %xmm0, -0x68(%rbp)
movl -0x60(%rbp), %eax
movl %eax, -0x50(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x48(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0xaa80
movss %xmm1, -0x80(%rbp)
movlpd %xmm0, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x74(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0x6c(%rbp)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xaa60
movss (%rax), %xmm0
movss %xmm0, -0xc8(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xaa60
movss -0xc8(%rbp), %xmm0
subss (%rax), %xmm0
movss %xmm0, -0x8c(%rbp)
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xaa60
movss (%rax), %xmm0
movss %xmm0, -0xc4(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xaa60
movss -0xc4(%rbp), %xmm0
subss (%rax), %xmm0
movss %xmm0, -0x90(%rbp)
movq -0x10(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0xaa60
movss 0x4(%rax), %xmm0
movss %xmm0, -0xc0(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xaa60
movss -0xc0(%rbp), %xmm0
subss 0x4(%rax), %xmm0
movss %xmm0, -0x94(%rbp)
movq -0x10(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xaa60
movss 0x4(%rax), %xmm0
movss %xmm0, -0xbc(%rbp)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0xaa60
movss -0xbc(%rbp), %xmm0
subss 0x4(%rax), %xmm0
movss %xmm0, -0x98(%rbp)
movss -0x8c(%rbp), %xmm0
movss -0x98(%rbp), %xmm2
movss -0x90(%rbp), %xmm1
mulss -0x94(%rbp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
mulss %xmm2, %xmm0
addss %xmm1, %xmm0
movss %xmm0, -0x9c(%rbp)
movss -0x9c(%rbp), %xmm0
callq 0xad30
movaps %xmm0, %xmm1
movss 0xa011(%rip), %xmm0     # 0x1001c
ucomiss %xmm1, %xmm0
jb 0x6043
movq -0x30(%rbp), %rax
movq 0xa029(%rip), %rcx      # 0x10044
movq %rcx, (%rax)
movl 0xa028(%rip), %ecx      # 0x1004c
movl %ecx, 0x8(%rax)
movq 0x10(%rbp), %rax
movq 0xa01e(%rip), %rcx      # 0x10050
movq %rcx, (%rax)
movl 0xa01d(%rip), %ecx      # 0x10058
movl %ecx, 0x8(%rax)
jmp 0x6203
movss 0x9fc1(%rip), %xmm0     # 0x1000c
divss -0x9c(%rbp), %xmm0
movss %xmm0, -0xa0(%rbp)
movss -0xa0(%rbp), %xmm0
movss -0x98(%rbp), %xmm1
movss -0x58(%rbp), %xmm3
movss -0x94(%rbp), %xmm2
mulss -0x74(%rbp), %xmm2
movd %xmm2, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm2
mulss %xmm3, %xmm1
addss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss -0xa0(%rbp), %xmm1
movss -0x98(%rbp), %xmm2
movss -0x54(%rbp), %xmm4
movss -0x94(%rbp), %xmm3
mulss -0x70(%rbp), %xmm3
movd %xmm3, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm3
mulss %xmm4, %xmm2
addss %xmm3, %xmm2
mulss %xmm2, %xmm1
movss -0xa0(%rbp), %xmm2
movss -0x98(%rbp), %xmm3
movss -0x50(%rbp), %xmm5
movss -0x94(%rbp), %xmm4
mulss -0x6c(%rbp), %xmm4
movd %xmm4, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm4
mulss %xmm5, %xmm3
addss %xmm4, %xmm3
mulss %xmm3, %xmm2
leaq -0xac(%rbp), %rdi
callq 0x7a70
movq -0x30(%rbp), %rax
movq -0xac(%rbp), %rcx
movq %rcx, (%rax)
movl -0xa4(%rbp), %ecx
movl %ecx, 0x8(%rax)
movss -0xa0(%rbp), %xmm0
movss -0x90(%rbp), %xmm1
movd %xmm1, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm1
movss -0x58(%rbp), %xmm3
movss -0x8c(%rbp), %xmm2
mulss -0x74(%rbp), %xmm2
mulss %xmm3, %xmm1
addss %xmm2, %xmm1
mulss %xmm1, %xmm0
movss -0xa0(%rbp), %xmm1
movss -0x90(%rbp), %xmm2
movd %xmm2, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm2
movss -0x54(%rbp), %xmm4
movss -0x8c(%rbp), %xmm3
mulss -0x70(%rbp), %xmm3
mulss %xmm4, %xmm2
addss %xmm3, %xmm2
mulss %xmm2, %xmm1
movss -0xa0(%rbp), %xmm2
movss -0x90(%rbp), %xmm3
movd %xmm3, %eax
xorl $0x80000000, %eax       # imm = 0x80000000
movd %eax, %xmm3
movss -0x50(%rbp), %xmm5
movss -0x8c(%rbp), %xmm4
mulss -0x6c(%rbp), %xmm4
mulss %xmm5, %xmm3
addss %xmm4, %xmm3
mulss %xmm3, %xmm2
leaq -0xb8(%rbp), %rdi
callq 0x7a70
movq 0x10(%rbp), %rax
movq -0xb8(%rbp), %rcx
movq %rcx, (%rax)
movl -0xb0(%rbp), %ecx
movl %ecx, 0x8(%rax)
addq $0xd0, %rsp
popq %rbp
retq
nopl (%rax)