Notifications
Clear all

[Closed] Converting 3D coordinates to 2D with MaxScript

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.

9 Replies

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

Hi ZeBoxx.

This information is invaluable – thank you so much for taking the time to reply. Just what I was after!

 JHN

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.

-Johan

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

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.

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 640×480 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.

 JHN

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
  

  get2DPoint()
  [0.939249,0.017495]
  [0.939249,0.982505]
  

Hope this excerpt is of any use to you.

-Johan

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

JHN, ZeBoxx2 – you are absolutely right. I am sorry guys I just couldn’t see this for looking yesterday.

Once again – thanks a ton!