3D Vector -> 2D Screen Coords

I’ve been pulling my hair out over this one. Basically, I need to get the 2D coordinates for a 3D vector.
Vector:ToScreen() is not an option, because i’m using a custom camera.

I half-found a solution here, but it’s noticeably off.
This is somewhat tricky, since unlike XNA, there are no matrix classes to play around with.

All help appreciated :smiley:

You can represent matrices in Lua:

If you wanted, you could even create your own matrix “classes” in Lua by defining some metatables.

After you have your matrices, I think you know where to go from there.

That’s the link he posted. He thinks the result is off.

I’ve never actually used Matrices before, worth learning. Thanks for this.

I’ve already tried this, sadly it’s off for me (maybe something to do with aspect, I don’t understand it)

Would using matrices to convert the coordinates be slow, or practically unnoticeable?

Are you sure you got the FOV right? ( It is 75 by default )

Just asking this because it works fine for me:

( At the left, the FOV is correct, at the right it is manually changed to 70 in the script )


What resolution is that? It’s still off for me (I’m testing by rotating the camera slowly around an object at [0,0,0], and drawing a marker at what the code thinks is [0,0,0])
The comments say something about 4:3, could it need changing to support other aspect ratios?

You’re right, actually. I looked at the original post, and the person who posted that script also created a fix that might have not made it to the wiki. Go to the wiki page for the script, follow the link to the user’s post, and scroll all the way down. The script had been fixed for widescreen ratios.

The wiki is currently down, but here is the code for different aspect ratio support:

cam_utils = {}

function cam_utils.ToScreen( cPos, cAng, cFov, scrW, scrH, vDir )
local vDir = cPos - vDir

local d = 4 * scrH / ( 6 * math.tan( 0.5 * cFov ) )
local fdp = cAng:Forward():Dot( vDir )

if ( fdp == 0 ) then
	return 0, 0, false, false

local vProj = ( d / fdp ) * vDir

local x = 0.5 * scrW + cAng:Right():Dot( vProj )
local y = 0.5 * scrH - cAng:Up():Dot( vProj )

return x, y, ( 0 < x && x < scrW && 0 < y && y < scrH ) && fdp < 0, fdp > 0