使用“up-”和“center-vec3”参数有效替代glm :: rotate()?

时间:2022-09-10 17:15:17

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:

我正在研究一个3D引擎,我想使用“向上” - 矢量和“标题” - 或“中心” - 矢量作为3d对象的旋转位置的指示器。要为OpenGL着色器创建旋转矩阵,GLM提供函数rotate(mat4(),radians,axis_of_rotation)。但是,因为我没有跟踪axis_of_rotation,也没有跟踪旋转3d对象的弧度,我不能直接使用此函数。目前我使用的自定义函数如下所示:

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:

然而,虽然我认为我可以提高这个功能的效率,但我觉得这个想法对于3D游戏引擎而言是无效的。我试图理解lookAt函数,因为它看起来与我的函数类似但我不理解代码:

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?

我的问题是,是否已经有一个函数可以创建一个mat4,它将vec3(0.0,0.0,1.0)旋转到heading和vec3(0.0,1.0,0.0)为up或至少有一种更有效的方法来执行此操作?

1 个解决方案

#1


0  

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

好的,我的解决方案是使用GLM的lookAt-code但删除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).

并删除眼睛/(位置)参数。工作良好。输出与lookat相同(vec3(0.0f,0.0f,0.0f),center,up)。

#1


0  

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

好的,我的解决方案是使用GLM的lookAt-code但删除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).

并删除眼睛/(位置)参数。工作良好。输出与lookat相同(vec3(0.0f,0.0f,0.0f),center,up)。