I don't understand modelX/modelY

    @Override
    public void settings() {
        size(800, 800, P3D);
        smooth(8);
    }
    
    
    @Override
    public void setup() {
    }
    
    @Override
    public void draw() {
        background(0);
        
        translate(width / 2f, height / 2f);
        
        // Print world coordinates
        if(frameCount % 20 == 0) {
            System.out.println(modelX(400, 400, 0) + ", " + modelY(400, 400, 0));
        }
    }

After translating by width/2 and height/2, the model origin should be in the center of the 800x800 screen. So, when I convert point (400, 400) in screen space to model space, I should expect to see (0, 0) as the output. But instead I see (800, 800). What am I doing wrong?

1 Like

modelX just gives you the point in space including the translation before

(The point is calculated from the initial origin)

So its 400 + 400 in your example

One 400 is from translate() command and one 400 from modelX() command itself

Normally we call modelX with (0,0,0)

2 Likes

Hello @PianoMastR64,

Read the reference carefully:

May have to read a few times to digest this.

Consider model space as the co-ordinate system of the sketch window with the origin (0, 0, 0) in the upper left.

:)

1 Like

And later you need modelZ as well

(Other than screenX and screenY)

1 Like

Ok, I understand now. So, what’s the best way to get model coordinates based on given screen coordinates?

1 Like

What is your context and your goal?

What do you want to achieve?

No specific goal other than that I want to figure out where the mouse would be if it were expressed in model coordinates. It would be useful functionality in a handful of scenarios.

I figured out how to do it for JAVA2D and P2D, but things get a little weird with P3D.

    @Override
    public void settings() {
        size(800, 800);
    }

    @Override
    public void draw() {
        background(0);
        
        translate(50, 50);
        rotate(PI / 8f);
        
        PVector modelMouse = ModelMouse(this);
        
        circle(mouseX, mouseY, 10);
        circle(modelMouse.x, modelMouse.y, 10);
    }
    
    public static PVector ModelMouse(PApplet app) {
        PMatrix currentMatrix = app.getMatrix();
        currentMatrix.invert();
        return currentMatrix.mult(new PVector(app.mouseX, app.mouseY, 0), null);
    }

Here, the first circle is drawn where you’d expect it to be, given the transformations. The second circle is drawn at the mouse’s location.

When you switch to size(800, 800, P3D), the first circle is the same. But the second circle seems to be in the middle of the screen. I’ve figured out that you can compensate for that by subtracting half a screen from the mouse before doing the reverse transformation.

    public static PVector ModelMouse(PApplet app) {
        PMatrix currentMatrix = app.getMatrix();
        currentMatrix.invert();
        PVector mouse = new PVector(app.mouseX, app.mouseY, 0);
        if(app.g.is3D()) {
            mouse.x -= app.width / 2f;
            mouse.y -= app.height / 2f;
        }
        return currentMatrix.mult(mouse, null);
    }

Then I can also draw the sphere at the mouse like this. The method is generalized so I can add it to my custom PAppletUtility class

        push();
        translate(modelMouse.x, modelMouse.y);
        sphere(100);
        pop();

So I guess I got it. Took a hot annoying sec to figure out. I don’t know if this is the best way though or why I need to do that weird compensation for P3D.

Maybe in 2D the center is upper left corner and in 3D as
well, but the internal camera position is different

Idk. Drawing stuff at 0, 0, 0 in P3D does put it in the top left corner. Maybe I’ll investigate that someday.

You would think modelX/Y() would do what I thought it did because screenX/Y() gives that same information but in reverse. Instead, modelX/Y() seems to be the exact same thing as screenX/Y() other than taking an extra argument z. I’m still confused about that, and trying to understand.

1 Like

in your example, modelX/modelY doesn’t occur?

in fact, modelX/modelY has nothing to do with the mouse.

  • modelX/modelY/modelZ(!) gives you a point in 3D space, including translate and rotate before it. Useful for special purposes, nothing to do with the mouse (or the screen). modelX/modelY without modelZ doesn’t make sense btw.
  • screenX/screenY gives you a 2D screen pos from a 3D pos. So when you want to match a 3D pos with the mouse, use this.
  • The opposite of screenX/screenY (receiving a 3D point from a 2D screen point) doesn’t exist, It wouldn’t be possible, because of the 3D perspective there is a lack of information, you can have endless 3D number of 3D points that all have the same screenX/screenY.

Of course the view in 3D is totally different from 2D since we have a perspective and things shrink in the background.

Let’s ask one of the gurus, like @quark what they think of it

in your example, modelX/modelY doesn’t occur?

Turns out I didn’t need it for my purpose. I was just entirely too convinced it’s what I needed.

The opposite of screenX/screenY (receiving a 3D point from a 2D screen point) doesn’t exist, It wouldn’t be possible, because of the 3D perspective there is a lack of information, you can have endless 3D number of 3D points that all have the same screenX/screenY.

Not sure why I didn’t consider this. My example solves my problem perfectly. …as long as the point in model space is at exactly 0 on the z axis. Any different value throws it off. Negative values shift it inward, and positive outward. Even if I compensate for that by making sure the 3D coordinate always coincides with the mouse, there’s still an infinite line of variability which probably depends on the camera position or something.

When I get around to it, I’ll have a big think on how best to account for this.

One example for why I might need this is if I want to check which object the mouse is hovering over so I can move it around. For that, I actually don’t even need a point, but more of a vector.

Another example is to click somewhere on the screen and spawn an object, for which I will need a point. I’ll just have to find some way of deciding which point on that line matters to me in that moment.

hello,

That’s a good point (no pun intended). Here you can use screenX and screenY and compare them to the mouse pos.
Another method is an off-screen PGraphics, like point B here: Selecting & Moving 3D Primitives - urgent - #3 by Chrisir

Another very good point!

In fact I asked this here: Pro-Question: place a point in 3D with mouse and
here P3D Formula : opposite of screenX and screenY is ...?

I still think this is solvable.

For example when you place a new cube, you could assume the same Z value as the previous cube. Then the new x and y should be calculable.

Chrisir