View Full Version : Converting 3D coordinates to 2D with MaxScript
12 December 2008, 03:20 PM
Hi guys. This is my first post and I am new to Max, so 'hello' in the first instance and please excuse errors in terminology!!!
I am trying to ...
1. use maxscript to convert 3d coordinates of objects to 2d coordinates relative to a camera (that is pointing at them).
2. I will then save the coordinates output to a text file and create hot spots on an image map later on to act as an overlay to the 3D render.
I think I've got the second part figured out, but I am struggling with point #1. I am familar with conversion matrices but would dearly love to avoid them in favour of a simpler solution.
I appreciate any help that I can offer, please let me know if I need to go into more detail.
12 December 2008, 12:38 AM
check out the "How To ... Develop a Vertex Renderer" topic. There's -a- function for converting world coordinate point3's into screen coordinate point2's in there.
also see scriptspot.com - there's a few scripts out there already that track an object in screen space and write out the coordinates to a text file
12 December 2008, 09:42 AM
This information is invaluable - thank you so much for taking the time to reply. Just what I was after!
12 December 2008, 07:39 PM
That's right, my fusionsplines script: http://scripts.subd.nl/?f=JHN_FusionSplines.ms
Is one of them, it can track points in the viewport to export them as .spl files that fusion can then read, it compensates for pixelaspect etc. You will generally be interested in the gw functions and especially how to define where [0,0] is in the 2d document, fusion and aftereffects have different approaches to that, afaik.
12 December 2008, 02:32 PM
Yes JHN - I think I get what is going on here. Thank you both once again for your help - I look forward to trying this out
02 February 2009, 03:42 PM
Well I've managed to extract the methods thanks to some help from JHN.
But I have found that by using the gw.getWinSize and getViewSize() methods I can only return the 2d coordinates of meshes relative to the stage view.
To clarify: I would like to get the coordinates relative to the camera viewpane: as it stands when I resize the 3DS IDE and run my script, the coordinates vary wildly based on how the camera view has been resized to fit in the viewing area.
Are there any functions that allow you to get these coordinates and isn't affected by the IDE size?
Many thanks for any help.
02 February 2009, 05:52 PM
well if you want 2D coordinates, you're going to have to specify a device context eventually..
JHN is using viewport context, 'How To ... Develop a Vertex Renderer' uses the render output size context, etc.
If you want it to be truly independent, just divide the result of either method by the context's dimensions.
I.e. if you're using the 'How To ... Develop a Vertex Renderer' method, your render output size is 640x480 and the coordinate you receive is [360,120], divide that by the earlier [640,480] and you get [0.5625,0.25]; which is about as indepent as it gets; you can then multiply it by whatever actual dimensions you're working with to get the pixel coordinates for that context.
Edit: Just to note.. make sure that JHN's method takes the output aspect into account as it fits within the viewport (just like the safe frames) as otherwise you would indeed get wildly varying values even when made independent; basically it's better to use the output size except where you may need to draw results in the viewport itself.
02 February 2009, 08:14 PM
I don't know if you have taken a good look at what I'm doing, but my script does calculate the viewport width by the renderWidth taking into account the aspect ratio, finally returning a float value of 0 to 1. The beauty of this is that as long as the aspect doesn't change the value scales really well. Fusion takes float values for positional data and not absolute coords.
fn get2DPoint pos yTop:false= -- takes a point3 value as input
local sX = gw.getWinSizeX() as float -- Get WinSize X
local sY = gw.getWinSizeY() as float -- Get WinSize X
local rPA = renderPixelAspect -- Get Render Pixel Aspect
local rX = RenderWidth as float -- Get Render Pixels X
local rY = RenderHeight as float -- Get Render Pixels Y
rY = rY * ( 1 / rPA ) -- Correct for aspect ratio
local rratio = ( sX / rX ) / (sY / rY) -- Get Ratio
if rratio >= 1. then ( -- If Ratio is bigger than 1 then
local ratio = sY / rY -- Use Y ratio for calculations
) else (
local ratio = sX / rX -- Else use X ratio for calculations
) -- end if
local xMin = ( sX - ( rX * ratio ) ) / 2 -- Get x minimum value
local yMin = ( sY - ( rY * ratio ) ) / 2 -- Get y minimum value
gw.setTransform (matrix3 1) -- Set gw View transform to zero
local p = gw.TransPoint ( pos ) -- Get 3D point in 2D screenspace
local x = ( p.x - xMin ) / ( sX - ( xMin * 2) ) -- Convert View space to Render space for X
local y = ( p.y - yMin ) / ( sY - ( yMin * 2 ) ) -- idem for Y
if not yTop then y = 1 - y -- if [0,0] should be at the top then set Ytop true
[x,y] -- return a floating point2 value
) -- end get2DPoint
get2DPoint $.pos yTop:true -- get values where y=0. is at the top
get2DPoint $.pos -- gets values with y=0. like fusion wants it at the bottom
Hope this excerpt is of any use to you.
02 February 2009, 08:45 PM
I thought it was odd you would've forgotten that :bowdown:
So it should definitely work exactly as one would want it to..
..midget35, time to review your code and check that it matches what JHN is doing :)
02 February 2009, 09:36 AM
JHN, ZeBoxx2 - you are absolutely right. I am sorry guys I just couldn't see this for looking yesterday.
Once again - thanks a ton!
02 February 2009, 09:36 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.