Transforming points vs. actual vectors

From my understanding the methods…

  • localToWorld
  • worldToLocal

… work for points, though not for vectors. While in the javadoc it’s stated that localToWorld converts “a vector (in) from this spatials’ local coordinate space to world coordinate space” I’m sure that remark actually refers to the Vector3f class that points and vectors both share.

Q1: Am I right with this assumption?

Though, what really puzzles me is that I’m not able to find a note about this aspect that I would consider quite confusing for at least some: not in the documentation, not in any tutorials or this forum. I’m afraid, there is something so obvious lurking here, that I somehow manage to overlook it.

Q2: What’s that obvious thing I do not see?

I’m also wondering why for example the localToWorld/worldToLocal method has no equivalent for (actual) vectors (or a flag in the parameters that indicates the intended use) – it would surprise me if the need to transform vectors is actually such a rare one.

My solution to transform a vector from world to local looks like this at the moment (the vector’s length isn’t important here, though I guess, if it was I have to additionally aply the scaling transformation):

Matrix4f ltwMatrix = localNode.getLocalToWorldMatrix(null);
Vector3f direction_local = new Vector3f(direction_world);

Q3: What’s a better way to do this?

Thanks in advance!

A vector can be seen as a line from point a to point b, I guess you’re aware of that?

It would help us if you could explain what you think the difference between a vector and a point is, exactly.

Probably you are asking if the localToWorld/worldToLocal methods that operate on a vector are affected or not by the scale and maybe position of the Node that you are calling the methods from. Direction vectors should not be affected by any scale nor position, but points in space vectors are affected.

Of course. Vector has a direction and length and no particular position. Point = position. If I transform a Vector by for example the localToWorld method, generally it should lose its role as a Vector since the translational part would “distort” the original vector information, i.e. pointing into another direction. Hence the try to bypass the translation in my example.

What I would take away from this, would be to simply transform 2 defining points, subtract them, et voilà…

/* transforming an “actual vector”: (0,0,0) x----------> “tip” */
Vector3f worldOrigin_local = localNode.worldToLocal(Vector3f.ZERO, null);
Vector3f actualVectorTip_local = localNode.worldToLocal(actualVector_world, null);
Vector3f actualVector_local = actualVectorTip_local.subtract(worldOrigin_local);

Though as I understand there’s no way for jME to differ between directional vectors and points when they both use Vector3f as a data structure – that falls to the programmer. I do not consider this an actual problem, but it is the reason why I was so surprised to not find any mentioning of it in the documentation (given for example that there’s an entry in the FAQ about the difference between world and local coords).

You are mixing meaning an representation
A Position is represented by a Vector from space origin to position.
A vector can also represent a direction.
But that doesn’t change the math to use to transform them.
and to burst your buble a bit more…a Position is also a Direction because it represents the direction from the origin of the space to the position.

This is a misconception. Transforming a vector will transform its representation, not its meaning. IE the direction will be the same.

There is no doc about that because there is no actual problem.
The problem is your misunderstanding.

So, I interpret the question now as “how do I convert a direction vector to/from local space?” worldToLocal() and localToWorld() only do position vectors. They are all vectors, though.

If you only want to rotate a vector then yeah, only rotate it.

Vector3f localDir = spatial.getWorldRotation().mult(worldDir);

Vector3f worldDir = spatial.getWorldRotation().inverse().mult(localDir);

Dang. I’m afraid, that is the only puzzling statement that’s left in my book.

2 meanings: 1. position (aka “the special direction, pointing from origin to position”) 2. direction. Both represented by: vector. Totally fine.

Example: spaceship_position = (1, 1, 1); spaceship_shooting_direction = (1, 1, 1);

Now we apply the same translation, adding (0, 1, 0) to both of them. Both representations changed? Check! Meaning changed? Well, kind of. I mean, my program would still handle spaceship_shooting_direction as a directional vector, everything else would be quite surprising, though it didn’t survived the translation to well, meaning, the direction isn’t the same anymore. (Sure, I do not consider your mind blown right now, I just want to show where exactly the blockage in my head occurs.) Oh, wait, I probably mixed meaning and representation again in that last bit, didn’t I?

Yes, wholeheartedly agreeing. Thanks!

Maybe I’m the one not understanding what you want to achieve actually.
I thought wanted to transform a vector from local space to world space… Wasn’t it the first question?
Transforming from one space to another is not just applying a translation.

Oh no, you understood that correctly. I was choosing the translation only as it is the one thing that I consider the “game changer,” the “shatterer of directional-vectors” (over-dramatic voice).

Just a note: neither of these are direction vectors as direction vectors will have length 1.

Edit: well, I guess you could consider it a scaled direction like velocity… in which case your post still applies. For direction vectors, you only want to rotate them so you can easily do that in one line of code. For position vectors, the logic is more complicated to go to/from world/local so JME provides some convenience methods.

Either way, in 3D game programming you will have to have a basic fundamental grasp of 3D math which is why we put the math for dummies tutorial together.

1 Like