0
votes

i am working on a 3d-engine and i want to use an "up"-vector and a "heading"- or "center"-vector as indicators for the rotated-Position of an 3d-object. To create a rotation-matrix for the OpenGL-shaders GLM provides the function rotate(mat4(), radians, axis_of_rotation). However, because i don't keep track of the axis_of_rotation nor how many radians a 3d-object is rotated, i can't use this function directly. Currently i am using a custom function that looks like this:

mat4 altRotate(vec3 center, vec3 up) {

        GLfloat alpha_y = acos(dot(normalize(vec2(center.z, center.x)), vec2(1.0f, 0.0f)));
        if (center.x < 0.0f)
            alpha_y = -alpha_y;

        mat4 Ry = {
            cos(alpha_y),   0,                  sin(alpha_y),   0,
            0,              1,                  0,              0,
            -sin(alpha_y),  0,                  cos(alpha_y),   0,
            0,              0,                  0,              1
        };
        center = vec3(Ry * vec4(center, 1.0f));
        up = vec3(Ry * vec4(up, 1.0f));

        GLfloat alpha_x = acos(dot(normalize(vec2(center.z, center.y)), vec2(1.0f, 0.0f)));
        if (center.y > 0.0f)
            alpha_x = -alpha_x;

        mat4 Rx = {
            1,               0,                 0,              0,
            0,              cos(alpha_x),       -sin(alpha_x),  0,
            0,              sin(alpha_x),       cos(alpha_x),   0,
            0,              0,                  0,              1
        };
        center = vec3(Rx * vec4(center, 1.0f));
        up = vec3(Rx * vec4(up, 1.0f));

        GLfloat alpha_z = acos(dot(normalize(vec2(up.y, up.x)), vec2(1.0f, 0.0f)));
        if (up.x < 0.0f)
            alpha_z = -alpha_z;

        mat4 Rz = {
            cos(alpha_z),   -sin(alpha_z),      0,              0,
            sin(alpha_z),   cos(alpha_z),       0,              0,
            0,              0,                  1,              0,
            0,              0,                  0,              1
        };

        return Ry * Rx * Rz;        
    }

However, although i think i could improve the efficiency of this function, i have the feeling that the idea is way to unefficient for a 3d-game-engine. I tried to understand the lookAt-function because what it does seems similar to my function but i didn't understand the code:

template <typename T, precision P>
    GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAtRH
    (
        tvec3<T, P> const & eye,
        tvec3<T, P> const & center,
        tvec3<T, P> const & up
    )
    {
        tvec3<T, P> const f(normalize(center - eye));
        tvec3<T, P> const s(normalize(cross(f, up)));
        tvec3<T, P> const u(cross(s, f));

        tmat4x4<T, P> Result(1);
        Result[0][0] = s.x;
        Result[1][0] = s.y;
        Result[2][0] = s.z;
        Result[0][1] = u.x;
        Result[1][1] = u.y;
        Result[2][1] = u.z;
        Result[0][2] =-f.x;
        Result[1][2] =-f.y;
        Result[2][2] =-f.z;
        Result[3][0] =-dot(s, eye);
        Result[3][1] =-dot(u, eye);
        Result[3][2] = dot(f, eye);
        return Result;
    }

My question is if there is already a function that can create a mat4 that rotates the vec3 (0.0, 0.0, 1.0) to heading and vec3 (0.0, 1.0, 0.0) to up or is there at least a more efficient way to do this?

1
That's exactly what lookAt does, in addition to moving the origin to eye. If you know linear algebra you should be able to understand the math behind it, if not then this is not a place to teach you linear algebra.Yakov Galka

1 Answers

0
votes

Ok, my solution is to use the lookAt-code by GLM but remove the lins

    Result[3][0] =-dot(s, eye);
    Result[3][1] =-dot(u, eye);
    Result[3][2] = dot(f, eye);

and to remove the eye / (position) argument. Works fine. The output will be the same as lookat(vec3(0.0f, 0.0f, 0.0f), center, up).