Screen position of 3D point? [Solved]

I’ve been Googling around for a long time on the subject but haven’t found anything that works 100% correctly yet. I’m pretty sure it has to do with a lot of matrices and is an expensive calculation, but does anyone have any idea of how to get the 2D screen point of a 3D point in space?

@SkyTheCoder -

https://coolcodea.wordpress.com/2013/05/30/70a-touching-an-object-on-a-3d-screen/

@Ignatz I’ve seen that, but that’s not my problem. I want to get the screen coordinate of a 3D point, not which object I pressed. That’s kind of the opposite, getting the 3D point of a screen position.

Edit: example: I have a godray shader, but it works in screen space. I need to specify the point on the screen that is the position of the godray light. I can set it to 0.5, 0.5, but then it is in the middle of the screen, wherever I look. If I turn, I want it to move as if it were a 3D point in space.

@SkyTheCoder - why wouldn’t your ray be in 3D space? Why 2D?

@Ignatz Because 3D godrays would require volumetric rendering and 3D computations of angles and raycasting…

Either way, how would I get a screen position of a 3D point? There are other uses I was thinking of that would require it.

I think you need professional help, @LoopSpace to the rescue

@Ignatz I got this off the internet:

projectionMatrix() * (viewMatrix() * position_in_3d)

But it always seemed a little bit off, no matter what I did.

@skythecoder if it is always in the same direction, maybe you have forgotten a translate() somewhere else before?

@SkyTheCoder Try this (and yes, you’d need to know a bit about matrices to figure this out otherwise!).

Basically, call this BEFORE your ortho() command once you’ve done your camera updates with the point in space you’re querying as a vec3. Sprite the output using the resulting vec2 AFTER you’ve done the ortho() bit and reset your viewMatrix back to identity:

(Ps. Based on some great work Andrew Stacey did on this topic a few years ago)

I use this a lot in most of my 3d games :wink:

function _3d_to_2d(vector)
-- Takes a vec3 of a point in 3d space and returns a vec2 of the 2d point relating to the screen WIDTH and HEIGHT
-- Should be called prior to resetting the view matrix via ortho()
        
    local m = modelMatrix() * viewMatrix() * projectionMatrix() 
    m = m:translate(vector.x,vector.y, vector.z)
    return vec2(WIDTH * (m[13]/m[16] + 1)/2, HEIGHT * (m[14]/m[16]+1)/2)
end

So what the matrices do is to convert a 3D point to its final position in front of the camera.

Then in the last part, m[13] is the x translation, which is scaled for distance by dividing it by the factor in m[16], then the same is done for y.

Cool B-)

yep, just looked up mine and it’s the same in an old “game” I never got done…

If you translated already so (0,0,0) is middle of your object for the draw then you can skip the m = m:translate(x,y,z) since modelMatrix already includes your translation. So for instance in the draw for my 3d objects I have something like:

function obj:draw()
    resetMatrix()
    translate(self.position.x, self.position.y, self.position.z)
    self.mesh:draw()
    local l = modelMatrix()*viewMatrix()*projectionMatrix()
    self.screenPosition = vec2((l[13]/l[16]+1)*WIDTH/2, (l[14]/l[16]+1)*HEIGHT/2)
end

And I use the obj.screenPosition(s) later to add some HUD type stuff in 2d drawing mode.

@andymac3d @spacemonkey Thanks so much! That was exactly what I was looking for!

Ditto that @spacemonkey - I tend to use it as a HUD overlay in my own custom GUI class. Really useful for debugging 3D games and tracking attributes attached to objects etc - it’s a nightmare otherwise.

Glad people found it useful - Merry Xmas :smiley:

Here’s the detailed explanation http://loopspace.mathforge.org/HowDidIDoThat/Codea/Matrices/. The function that andymac3d uses is in sections 8 and 9.

All right, I have a bit of a follow-up question that I decided wasn’t different enough to create a new discussion - is there any way to get the world position of a screen point? (Along a fixed x, y, or z plane)

Sorry for a bump-like post, but it is a new question…

Example: a 3D top-down level editor, to get the coordinates you wanted to edit at

See section 11 of the link I posted just above.

@LoopSpace I’m not very good with traditional math equations that are written out with all those symbols…do you think you could make a code version?

Section 13?

Also, try reading the post from the beginning to get familiar with “traditional math equations”. They’re sort of useful.

@SkyTheCoder - here is code that LoopSpace wrote to detect a 2D touch on a 3D object. As I understand it, it works by translating the 2D touch to a ray, and calculating the intersection with one of the planes of the object. While this sounds close to what you want, the code will need adapting, and it is not commented, so good luck.

https://gist.github.com/dermotbalson/5914883

@LoopSpace - to be fair to SkyTheCoder, he has probably never seen math like this. I have, but many years ago, and so I also find the matrix post difficult to follow. I wish I did understand it, because it contains some brilliant stuff.

Point taken, but what would make it clearer?