4 ms·
I’ve encountered this misunderstanding many times, usually in the context of creating a rotation matrix for a given direction and “up” vector. People look baffl
by layoutIfNeeded 6y ago
I’ve encountered this misunderstanding many times, usually in the context of creating a rotation matrix for a given direction and “up” vector. People look baffled when I replace their elaborate Euler-rotation algorithm with three lines of code:
z = direction
x = up.cross(z).normalized()
y = z.cross(x)
M = [x, y, z]
- andi999 6y agoCould you explain this is more detail?
- kaetemi 6y agoCreates a matrix with one axis in a given direction. Then a second axis at a straight angle to that, based on a reference up axis. The third axis is simply perpendicular to both. Position goes into the last vector of the matrix.
- abaines 6y agoHow come y is z.cross(x) and not up? Edit: I think it has been answered by others - up is in world-space, and the camera is not necessarily aligned horizontally.
- tripletao 6y agoWe've already defined z and x by that stage, and we need y to be a unit vector perpendicular to both. So y can only be z.cross(x) (or x.cross(z) for mirrored).
- layoutIfNeeded 6y agoYep, the up vector is not necessarily orthogonal to the direction vector (which is also called “look at” vector in OpenGL [1]). Another approach would be to set y = up.reject(direction).normalized() where a.reject(b) = a - b.project(a) [1] https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml...
- bl0b 6y agoIt is usually used to create a matrix for the camera orientation given a) the camera position in XYZ coordinates, b) a point the camera is looking at in XYZ coordinates, and c) the direction of 'up' in the world (otherwise the camera would be able to spin freely along it's Z axis while still satisfying the 'look at point A from point B' requirement). You build up the 3 axes of the camera orientation step-by-step. The 3 axes can then be plugged directly into the transformation matrix, and voila. When I was learning 3D graphics, I found this site an excellent resource. Here is the page with a more in-depth explanation of the 'look at' function: https://learnopengl.com/Getting-started/Camera https://learnopengl.com/Getting-started/Camera
- tripletao 6y agoA matrix-vector multiplication (or any other linear operation) can be understood as a change of basis, with the matrix rows or columns as the new basis vectors. A rotation[1] changes to a new set of basis vectors that are (a) all unit length and (b) all perpendicular to each other. In the code, direction is assumed to be a unit vector, and that's your new z. x = up.cross(direction) is perpendicular to both up and direction, but may have arbitrary length since up and direction aren't generally perpendicular to each other; so x must also be normalized to length of one. y = z.cross(x) is perpendicular to both z and x, and doesn't need normalizing since they were already perpendicular (though extra normalizing doesn't hurt and sometimes--probably not here for most purposes--helps to clean up rounding error). It's almost never a good idea to use Euler angles unless you're modeling a system where they have physical meaning (e.g., robot arm, gimbal, etc.). The math is almost always simpler when you work in terms of the rotation matrix directly (or quaternions, or axis-angle rotation, or pretty much anything else). 1. Or mirroring, which is the same as a rotation but with any two of the basis vectors swapped or any one negated.