🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Rotating vector by vector with vector

Started by
8 comments, last by TheRealSmolt 5 years, 10 months ago

Right now I'm using LWJGL for a game engine I'm working on. My problem is that I need the ability to rotate a point around another point on each axis at the same time (as in Vector3 for position and Vector3 for rotation too). Basically, when translating an entity, I need to be able to translate it on a local axis. For example, if the camera is pointing halfway between the x and z axis, and I translate the camera along the z axis, I want the camera to move forward not at an angle. I'm using the "Minimal OpenGL" custom configuration of LWJGL with JOML, and I'm pretty sure that the ability to do this is somewhere in JOML but I don't know where. Thanks in advance.

Advertisement

I didn't understand everything in your post, but if all you're wanting to do is translate objects along their own local axes, that's straightforward.

There's more than one way to do it, but a straightforward way is to extract the direction vectors from the object's local-to-world transform matrix (what's often called the 'model' matrix, as opposed to e.g. view). You can get them from a view (world-to-local) matrix as well; in that case the direction vectors will be transposed with respect to local-to-world.

This is all assuming rotation only - no scaling or other transforms. If the transform is more complex than just rotation (translation doesn't matter for this), you may have to take some extra steps.

In short, for a rotation matrix, the direction vectors will be the rows or columns of the matrix, depending on convention and whether it's a view or model matrix. Once you have these vectors, you can translate an object along its local axes via simple vector math, e.g.:


position += forward * speed * dt;

Apologies if that's not what you're asking about.

I am guessing that you want:


Matrix4f modelMatrix = new Matrix4f()
  .translate(objectPos)
  .rotateXYZ(xAngle, yAngle, zAngle);

Matrix4f.rotateXYZ() post-multiplies a rotation around the local X axis, multiplied by a rotation around the local Y axis, multiplied by a rotation around the local Z axis, so you get: M = T * Rx * Ry * Rz.
Then multiply that model matrix to the right of your projection * view matrix.
You can do that last step either in Java using the Matrix4f.mul() method, or in a GLSL shader, passing it the individual matrices as uniforms.

Thanks for the responses, but I was very vague, so not what I was looking for. I have rendering done properly and working. I have a class on each Entity class called Transform that holds position as a vec3, rotation as a vec3, and scale as a vec3. I can create a matrix to render it properly, but my issue is within my code, that's where I was probably confusing. Within my Transform class, I have two methods: translate and rotate. Right now they simply add the incoming value. I want them to factor in rotation so that when I say


transform.translate(new Vector3f(0, 0, 1));

I want the entity to move forward along the local z axis, not along the global z axis. I need some sort of math to rotate a point. If it's still vague feel free to ask questions, Thanks.

Okay, I see. In this case, you can either extract the local forward axis of the object via Matrix4f.positiveZ() and translate by that or you store the whole transformation as a Matrix4f and when you translate you just Matrix4f.translateLocal(0, 0, 1).

This is definitely feasible, but I only generate the transformation matrix on render, not to store my data. Is there any way to "apply" rotation to a translation before applying it? (without the use of a Matrix4f)

You can compute the rotation transformation using Matrix3f or Quaternionf, like so:


// Using Matrix3f.rotateXYZ()
Vector3f translationRotated = new Matrix3f()
  .rotateXYZ(eulerAngles)
  .transform(new Vector3f(0, 0, 1));

// or Quaternionf.rotateXYZ()
Vector3f translationRotated = new Quaternionf()
  .rotateXYZ(eulerAngles
  .transform(new Vector3f(0, 0, 1));

I also recommend storing your rotation not as three Euler angles but as a Quaternion instead in the first place. This allows you to perform such transformations more efficiently and also interpolate between orientations.

Quote

I want the entity to move forward along the local z axis, not along the global z axis.

This is in fact the problem my earlier post was intended to address (that is, moving an entity along its own local axes). I'm not familiar with JOML, but perhaps the functions httpdigest mentioned are what you're looking for. I also see the function translateLocal() in the API reference, which might be of interest.

Quote

This is definitely feasible, but I only generate the transformation matrix on render, not to store my data.

If you're storing your orientation as Euler angles (which I assume is what you mean by storing it as a vec3), you're going to have to do something similar to building a rotation matrix from the Euler angles in order to have the direction vectors available for movement. Having the transform for an object available in matrix form can be useful for a variety of purposes, so you might consider making the entity transform matrix available outside of just rendering.

Quote

Is there any way to "apply" rotation to a translation before applying it?

Sure, and it looks like httpdigest just posted an example of how to do that. Keep in mind though that what he shows is equivalent to what I mentioned earlier (that is, extracting the direction vectors directly from the matrix). Although performance is unlikely to be an issue here, deriving the direction vectors by multiplying cardinal basis vectors (e.g. 0, 0, 1) does some unnecessary work, because the result is just going to a column or row of the matrix anyway.

httpdigest had the answer I was looking for, the only with was that i needed to reverse the rotation for some reason. Thanks.

This topic is closed to new replies.

Advertisement