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?
lookAt
does, in addition to moving the origin toeye
. 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