How to convert 3d direction to 2d direction thanks to the camera?

Hello monkeys,

It’s been a while since I posted here. I just recently get back to JMonkey and started a new learning experience on it. And like always I have problem implementing what I want… And like always I ask for help. Today I have a really dumb math problem that I can’t resolve by myself. (In fact I might be able to resolve it but I need some advice !)

So the problem is simple and i’ll explain it to you with 2 representative images

As you can see I have my models in the 3d space with a set of 3 axes that I can drag to move it around the world. And it’s working pretty smoothly. But the only thing is that I can’t convert the mouse movement to be along those 3 axes. To be more precise the X axis can be drag only X same as Z and Y only in Y.

So here came this idea !

If I can project the camera onto those three 3d direction and ‘convert’ it into 2d direction I just have to do an orthogonal projection on those 2d direction to know where am I on this 2d line and then just have to compare the last position and the current position.

Keys of the problem :

Camera cam;
Node axes → axeX
→ axeY
→ axeZ
Vector2f currentMouse;
Vector2f lastMouse;
Geometry currentGeom;

Axes Direction :
currentGeom.getRotationColumn(0)
currentGeom.getRotationColumn(1)
currentGeom.getRotationColumn(2)

If you want the full code tell me and i’ll post it. Thanks, and sorry to bother you for such simple things.

Isn’t what you want in here?

In the last code, under Pick a Target Using the Mouse Pointer you can see how to get the 3D location where the mouse “is”. You can use that to move your 3D object alongside the scene.

1 Like

So you tell me that I can simply take the 3D representation of the mouse coordinates in 3D and constraint it along the desired axe ? GENIUS ! I never tough of that before. I won’t be able to test it before one week but i’ll give it a try when i’ll be back !

Thanks

Maybe is not the way you want to do it but you can also have a look at this :
https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java#L43

1 Like

I forced my self to not look into the source of the scene composer because I consider it like an easy way to avoid your weakness. But now that I’ve seen the pandora box… I’ll take a look :smiley: !

Well that not a shame to look at existing code, but i do not want to impose this or that solution. There are no ONE solution and it nice to see different way of doing something.

Well guys I found the Solution ! And it was really simple just as you said.

Juste take the mouse 3d coordinate juste like that

    Vector2f click2dn = inputManager.getCursorPosition();
    Vector3f click3d = cam.getWorldCoordinates(new Vector2f(click2dn.x, click2dn.y), 0f).clone();
    Vector3f currentDir = cam.getWorldCoordinates(new Vector2f(click2dn.x, click2dn.y), 1f).subtractLocal(click3d).normalizeLocal();

And Substract it to the last 3d mouse position which give you the direction

    Vector3f sub = currentDir.subtract(dir3d);

And then you can simply get the rotation column of you axe wich give you global 3d direction vector. After that you just have to project your 3d point onto the 3d direction vector like that

    if (xAxis) {
        Vector3f directionToMove = sub.project(arrow.getLocalRotation().getRotationColumn(0));
        directionToMove.multLocal(value*dist*1000);
        currentGeom.move(directionToMove);
    } else if (yAxis) {
        Vector3f directionToMove = sub.project(arrow.getLocalRotation().getRotationColumn(1));
        directionToMove.multLocal(value*dist*1000);
        currentGeom.move(directionToMove);
    } else if (zAxis) {
        Vector3f directionToMove = sub.project(arrow.getLocalRotation().getRotationColumn(2));
        directionToMove.multLocal(value*dist*1000);
        currentGeom.move(directionToMove);
    }

Where xAxis,yAxis,zAxis are the constraint direction

And here we go you can move your object along you axis even if you rotate your object and go behind it etc…

And now how to rotate this model along 3d donuts :smiley:

Just a tip because I see this all the time and it makes my eyes bleed…

is semi-expensive and expressively gobbledegook. It works but is confusing.

arrow.getLocalRotation().mult(Vector3f.UNIT_X)

is equivalent…should be cheaper and is clear exactly what is happening. Moreover if you ever want to support directions not axis-aligned then it’s clear how to do so.

1 Like

To be honest I never looked in getRotationColumn() source :frowning:. And I wish I had… I tough it was doing exactly what you told me to. But instead it does a bunch of computation ! Thanks for that advice.

But now i’m really wondering what getRotationColumn() is doin…

This is the aim of my subject is to supports directions. Because the arrow object is linked to the mesh and rotate with him so basicly it work for every direction with his own ‘arrow’. Maybe im misunderstanding what you are trying to tell me by directions and axis-aligned.

Effectively, it’s turning the quaternion into a rotation matrix and grabbing one of the columns of that matrix. A completely useless method in my opinion especially given that it is almost exclusively used by people who don’t know any better.

Well, you are axis-aligned within the local space of your object and that’s probably all you will ever want to do. But in the general case, getLocalRotation().mult(Vector3f.UNIT_X) is clearer because it’s showing exactly what it’s doing and works even if you pick an arbitrary vector for some reason… ie: it’s re-enforcing knowledge that is useful everywhere.

getRotationColumn() is useless magic voodoo in comparison. :slight_smile:

1 Like

So basically, getRoationColumn has nothing to do in a the Quaternion Definition… But from what I know, the Quaternion is just a concatenation of a RotationMatrix so, when you multiply a RotationMatrix by a Vector it does the same thing as when you multiply the Quaternion. So in a way getRotationColumn is relevant if you are working with a RotationMatrix !

Well… Sorry, I lost my self in my explanation… Just thanks for the tip i’ll deepen my knowledge on Quaternion before trying to talk about something I don’t really know about. :smiley:

A Quaternion is a 4 value compact representation of a rotation (in our case). A rotation matrix is 9 values that represent the three axes of a new reference frame. If they are all orthogonal then it is essentially a bulky equivalent of a Quaternion. More multiplies to do the same thing plus a chance that many concatenations will make the rotation matrix no longer orthogonal (which means strange results).

There are many reasons to go from Quaternion to rotation Matrix3f and back again… but I’ve never seen a good reason to just grab one column of the matrix at a time from a Quaternion.

1 Like