// File: /workspace/github_cpp_makefile_star2_O3/kryffin[P]software-rasterizer/./geometry.cpp
// Function: lookAt(Vec3f, Vec3f, Vec3f)
Mat4f lookAt (Vec3f eye, Vec3f target, Vec3f upDir) {
    // compute the forward vector from target to eye
    Vec3f forward = (eye - target).normalize();

    // compute the left vector
    Vec3f left = (upDir.cross(forward)).normalize(); // cross product

    // recompute the orthonormal up vector
    Vec3f up = forward.cross(left);    // cross product

    // init 4x4 matrix
    Mat4f M = Mat4f(1.f);

    // set rotation part, inverse rotation matrix: M^-1 = M^T for Euclidean transform
    M.m[0][0] = left.x;
    M.m[1][0] = left.y;
    M.m[2][0] = left.z;
    M.m[0][1] = up.x;
    M.m[1][1] = up.y;
    M.m[2][1] = up.z;
    M.m[0][2] = forward.x;
    M.m[1][2] = forward.y;
    M.m[2][2] = forward.z;

    // set translation part
    M.m[3][0] = -left.x * eye.x - left.y * eye.y - left.z * eye.z;
    M.m[3][1] = -up.x * eye.x - up.y * eye.y - up.z * eye.z;
    M.m[3][2] = -forward.x * eye.x - forward.y * eye.y - forward.z * eye.z;

    return M;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, %rax
movaps %xmm0, %xmm7
subps %xmm2, %xmm7
movaps %xmm7, %xmm6
shufps $0x55, %xmm7, %xmm6     # xmm6 = xmm6[1,1],xmm7[1,1]
movaps %xmm1, %xmm2
subss %xmm3, %xmm2
movaps %xmm6, %xmm3
mulss %xmm6, %xmm3
movaps %xmm7, %xmm8
mulss %xmm7, %xmm8
addss %xmm3, %xmm8
movaps %xmm2, %xmm3
mulss %xmm2, %xmm3
addss %xmm8, %xmm3
sqrtss %xmm3, %xmm3
divss %xmm3, %xmm7
divss %xmm3, %xmm6
divss %xmm3, %xmm2
movaps %xmm4, %xmm3
shufps $0x55, %xmm4, %xmm3     # xmm3 = xmm3[1,1],xmm4[1,1]
movaps %xmm6, %xmm8
mulss %xmm5, %xmm8
movaps %xmm7, %xmm9
mulss %xmm3, %xmm9
mulss %xmm2, %xmm3
subss %xmm8, %xmm3
movaps %xmm2, %xmm8
mulss %xmm4, %xmm8
mulss %xmm7, %xmm5
subss %xmm8, %xmm5
mulss %xmm6, %xmm4
subss %xmm9, %xmm4
movaps %xmm5, %xmm8
mulss %xmm5, %xmm8
movaps %xmm3, %xmm9
mulss %xmm3, %xmm9
addss %xmm8, %xmm9
movaps %xmm4, %xmm8
mulss %xmm4, %xmm8
addss %xmm9, %xmm8
sqrtss %xmm8, %xmm8
divss %xmm8, %xmm3
divss %xmm8, %xmm5
divss %xmm8, %xmm4
movaps %xmm5, %xmm9
mulss %xmm2, %xmm9
movaps %xmm6, %xmm8
mulss %xmm4, %xmm8
subss %xmm9, %xmm8
movaps 0x2970(%rip), %xmm11    # 0x5050
movaps %xmm4, %xmm10
mulss %xmm7, %xmm10
movaps %xmm2, %xmm9
mulss %xmm3, %xmm9
subss %xmm10, %xmm9
movaps %xmm3, %xmm12
mulss %xmm6, %xmm12
movaps %xmm7, %xmm10
mulss %xmm5, %xmm10
subss %xmm12, %xmm10
xorps %xmm12, %xmm12
movups %xmm12, 0xc(%rdi)
movups %xmm12, 0x1c(%rdi)
movl $0x0, 0x2c(%rdi)
movl $0x3f800000, 0x3c(%rdi) # imm = 0x3F800000
movss %xmm3, (%rdi)
movss %xmm5, 0x10(%rdi)
movss %xmm4, 0x20(%rdi)
movss %xmm8, 0x4(%rdi)
movss %xmm9, 0x14(%rdi)
movss %xmm10, 0x24(%rdi)
movss %xmm7, 0x8(%rdi)
xorps %xmm11, %xmm7
xorps %xmm11, %xmm3
mulss %xmm0, %xmm3
xorps %xmm11, %xmm8
mulss %xmm0, %xmm8
mulss %xmm0, %xmm7
shufps $0x55, %xmm0, %xmm0     # xmm0 = xmm0[1,1,1,1]
movss %xmm6, 0x18(%rdi)
movss %xmm2, 0x28(%rdi)
mulss %xmm0, %xmm5
subss %xmm5, %xmm3
mulss %xmm1, %xmm4
subss %xmm4, %xmm3
movss %xmm3, 0x30(%rdi)
mulss %xmm0, %xmm9
subss %xmm9, %xmm8
mulss %xmm1, %xmm10
subss %xmm10, %xmm8
movss %xmm8, 0x34(%rdi)
mulss %xmm0, %xmm6
subss %xmm6, %xmm7
mulss %xmm1, %xmm2
subss %xmm2, %xmm7
movss %xmm7, 0x38(%rdi)
popq %rbp
retq