PDA

View Full Version : 3d pos as 2D screen pos for a rollout, not just viewport 2D pos


Gravey
02-07-2008, 05:14 AM
i'm trying to figure out if there's an easy way to get the 2D position in 'desktop screen space' of a 3D point so that I could, for example, select a vertex and run a script to create a rollout that is positioned at that vertex. Any ideas ?

JHN
02-07-2008, 09:54 AM
I think gw.wTransPoint <point3> does the trick...
Look up viewport drawing methods in the manual.

-Johan

Gravey
02-07-2008, 11:22 AM
thanks but i've tried all the gw.transpoint functions and they all seem to be for drawing polylines, text etc. in the active viewport's screen space. What I am looking for is a way to take a 3D point and convert it to 2D screen space that is relative to the entire desktop for the purpose of creating a rollout at that point.
I have found functions like getMAXWindowSize, getMAXWindowPos, getViewSize, sysinfo.desktopsize and of course the gw.transpoint functions, which have given me some ideas but there's still 1 key factor that is missing in all this. It would be quite easy to find if i knew the position of the top left corner of the active viewport, relative to the MAXWindowPos or the desktopSize.
Hopefully i've missed a function somewhere in the reference and someone can point me in the right direction

JHN
02-07-2008, 01:26 PM
Then I don't think there's a way really... you indeed only need to get the upper leftcorner of the active view in "application space" the rest of the functionality seems to be there...
So no help from me, maybe someone else knows some tricks...

-Johan

PEN
02-07-2008, 04:15 PM
The script that I posted on here last week that creates viewport labels does this. Most of the code is in the help files in the tutorials section (Thanks Bobo). Have a look there an it will show you how to do it.

JHN
02-07-2008, 07:24 PM
Paul, I think your script only returns the correct position in the current viewport.
Gravey wants to spawn a dialog or rolloutfloater on the position of an object in the currentviewport... for that you'll need pixel position of the object in screen (not viewport) space... right!?

-Johan

Gräck
08-28-2008, 03:21 PM
I also need this. Bobo, can you help? :-)

JHaywood
08-28-2008, 07:34 PM
Paul, I think your script only returns the correct position in the current viewport.
Gravey wants to spawn a dialog or rolloutfloater on the position of an object in the currentviewport... for that you'll need pixel position of the object in screen (not viewport) space... right!?

-Johan

In this case, viewport space should work fine. Since the object exists in a viewport, you're just getting it's 2D position in the space of that same viewport.

ZeBoxx2
08-28-2008, 08:17 PM
In this case, viewport space should work fine. Since the object exists in a viewport, you're just getting it's 2D position in the space of that same viewport.

Except that you can only make a dialog (createDialog) pop up in screen space coordinates, and not in viewport window coordinates.

If the tool is related to interacting with the object at all, then certainly mouse.screenPos will do - but I'm guessing the mouse cursor may not be anywhere near the object of interest when the dialog needs to be popped up.

Essentially what's missing is a getPos equivalent of gw.setPos . Or just a getViewPos() etc. I'm sure it can be coded as a plugin or potentially via C# (You can get the coordinates via windows messages; MaxScript's support of the windows messaging system is too limited, however, as there's no way to allocate the Rect), but with stock MaxScript functions... haven't the foggiest.

JHaywood
08-28-2008, 08:23 PM
Here's the actual code supplied by bobo (used by Paul) that I wrapped into a function. I'm sure someone with more time that I do can modify it to return screen coordinates instead of viewport coordinates.

-- thanks to bobo for this function
fn mapWorldToScreen pos =
(
width=gw.getWinSizeX()
height=gw.getWinSizeY()

thePos = pos * viewport.getTM()
screenOrigin = mapScreenToView [0,0] (thePos.z) [width,height]

worldSize = screenOrigin*2
xAspect = width/(abs worldSize.x)
yAspect = height/(abs worldSize.y)

screenPos=point2 (xAspect *(thePos.x-screenOrigin.x)) (-(yAspect*(thePos.y-screenOrigin.y)))
if (screenPos.x) < 0 then (screenPos.x=0)
if (screenPos.y) < 0 then (screenPos.y=0)

screenPos.x = screenPos.x as integer
screenPos.y = screenPos.y as integer

screenPos
)

ZeBoxx2
08-28-2008, 08:28 PM
well... I can get the viewport's position; problem is that I'm not spotting how to get there automatically (might be some UIAccessor magic possible here)...

1. register a dialog (any) as a viewport dialog
2. select it as the viewport view (this is the manual part)
3. getDialogPos on that dialog. That now essentially returns the position of the viewport's top-left corner.

Step 2. being the problem. Also, I'm guessing this would cause a noticeable flicker ;)

Gravey
08-29-2008, 11:03 AM
I never finished the script i was working on at the time I asked this because i couldn't find a solution but ZeBoxx2 just sparked an idea that lead me to the solution!

Turns out its really simple too. To get the top left corner of the active viewport you simply say: mouse.screenpos - mouse.pos since mouse.pos is the mouse position relative to the top left of the active viewport and mouse.screenpos is the mouse position relative to the top left of your screen(s), its just simple math.

From here you can easily use gw.wTransPoint etc and there's your result!

EDIT: so use(mouse.screenpos - mouse.pos + (gw.wTransPoint $.pos))to get the screen position of the currently selected object.

JHN
08-29-2008, 11:16 AM
Hahaha, it's so simple it's almost embarrassing... great find! It's going to be really usefull!

-Johan

Gräck
08-29-2008, 12:33 PM
Gravey, I don't think your method works correctly.

Indeed Bobo's function already works.

Here is a script that displays all names of the currently visible objects in the center of each object selection:

(
fn mapWorldToScreen pos =
(
width=gw.getWinSizeX()
height=gw.getWinSizeY()

thePos = pos * viewport.getTM()
screenOrigin = mapScreenToView [0,0] (thePos.z) [width,height]

worldSize = screenOrigin*2
xAspect = width/(abs worldSize.x)
yAspect = height/(abs worldSize.y)

screenPos=point2 (xAspect *(thePos.x-screenOrigin.x)) (-(yAspect*(thePos.y-screenOrigin.y)))
if (screenPos.x) < 0 then (screenPos.x=0)
if (screenPos.y) < 0 then (screenPos.y=0)

screenPos.x = screenPos.x as integer
screenPos.y = screenPos.y as integer

screenPos
)

for i in $** where i.isHidden == false do
(

objPos = mapWorldToScreen i.center

posX = objPos.x - ((gw.getTextExtent i.name).x/2)
posY = objPos.y
posZ = 0

gw.wtext [posX, posY, posZ] i.name color:[255,255,255]
gw.enlargeUpdateRect #whole
gw.updateScreen()
)
)
This is useful for creating a snapshot of a rig with all bone names included for the programmer to work with it.

Gravey
08-29-2008, 01:21 PM
Gravey, I don't think your method works correctly.Hi Gräck. You must not have read through my posts correctly because you seem to have misunderstood what i wanted to achieve. Johan pointed this out in an earlier post: Paul, I think your script only returns the correct position in the current viewport.
Gravey wants to spawn a dialog or rolloutfloater on the position of an object in the currentviewport... for that you'll need pixel position of the object in screen (not viewport) space... right!?My method does exactly what i want it to do. :)

Gräck
08-29-2008, 01:25 PM
Oh, sorry, I thought you had a nicer method than Bobo. ;-) I didn't read correctly, my fault.

JHN
08-29-2008, 01:52 PM
I made a hybrid best of both worlds so to say


-- Position a rollout on the objects pivot.
global myrollout

rollout myrollout "myRollOut"
(
fn mapWorldToScreen pos =
(
width=gw.getWinSizeX()
height=gw.getWinSizeY()

thePos = pos * viewport.getTM()
screenOrigin = mapScreenToView [0,0] (thePos.z) [width,height]

worldSize = screenOrigin*2
xAspect = width/(abs worldSize.x)
yAspect = height/(abs worldSize.y)

screenPos=point2 (xAspect *(thePos.x-screenOrigin.x)) (-(yAspect*(thePos.y-screenOrigin.y)))
if (screenPos.x) < 0 then (screenPos.x=0)
if (screenPos.y) < 0 then (screenPos.y=0)

screenPos.x = screenPos.x as integer
screenPos.y = screenPos.y as integer

screenPos
)

fn setpos =
if selection[1] != undefined then
setDialogPos myrollout (mouse.screenpos - mouse.pos + (mapWorldToScreen selection[1].pos))

fn createCallback =
registerRedrawViewsCallback myrollout.setpos

fn killCallback =
unRegisterRedrawViewsCallback myrollout.setpos

button mybutton0 "Reposition"
button mybutton1 "Create Callback"
button mybutton2 "Kill Callback"

on mybutton0 pressed do setpos()
on mybutton1 pressed do createCallback()
on mybutton2 pressed do killCallback()
on myrollout open do setpos()

)
createDialog myrollout



With gw.wTransPoint() I don't get the right pos back with bobo's function I do...

-Johan

ZeBoxx2
08-29-2008, 01:54 PM
Hahaha, it's so simple it's almost embarrassing
You can skip the almost... can't believe I overlooked that while poking at those things left and right; despite the fact that I use that very same concept in getting the mouse cursor position in a dialog over any control. Now where's that blushing smiley - ah yes :blush:

JHN
08-29-2008, 02:09 PM
ROFLOL (sorry cluttering the thread!)

Gravey
08-29-2008, 02:31 PM
Oh, sorry, I thought you had a nicer method than Bobo. ;-) I didn't read correctly, my fault.to have a nicer method than Bobo would be quite an achievement! If only...

Gravey
08-29-2008, 03:00 PM
I made a hybrid best of both worlds so to say

With gw.wTransPoint() I don't get the right pos back with bobo's function I do...

-JohanWhen i first discovered this it worked perfectly all the time but i just tried it again with your script and it wasn't working for me either - but i've found the solution... again!

I forgot about gw.setTransform (matrix3 1) which you need to call before you use gw.wTranspoint() otherwise it doesn't return the correct result. So your script can be simplified to:
-- Position a rollout on the objects pivot.
global myrollout
try(destroyDialog myRollout)catch()
rollout myrollout "myRollOut"
(
fn setpos =
if selection[1] != undefined then
(
gw.setTransform (matrix3 1)
setDialogPos myrollout (mouse.screenpos - mouse.pos + (gw.wTranspoint selection[1].pos))
)

fn createCallback =
registerRedrawViewsCallback myrollout.setpos

fn killCallback =
unRegisterRedrawViewsCallback myrollout.setpos

button mybutton0 "Reposition"
button mybutton1 "Create Callback"
button mybutton2 "Kill Callback"

on mybutton0 pressed do setpos()
on mybutton1 pressed do createCallback()
on mybutton2 pressed do killCallback()
on myrollout open do setpos()
on myrollout close do killCallback()
)
createDialog myrollout
I know its just for demo purposes but i added the try/catch destroyDialog and the rollout close event handler too just to keep it tidy :)

JHN
08-29-2008, 03:13 PM
Joel, I have seen no errors or hickups with bobo's function as I implemented it, what excactly wasn't working for you?
Your solution now is working fine for me aswell, and is much more compact, that's great!

Bobo's function is only truly usefull when you want to take pixel aspect into account, for lets say a tracking tool, which has to output non square pixel tracking values. I used that same approach for my max to fusion tracker tool.

-Johan

Gravey
08-30-2008, 01:43 AM
Joel, I have seen no errors or hickups with bobo's function as I implemented it, what excactly wasn't working for you?Ah sorry I wasn't clear in my post. What I meant was that I tried my original method (without gw.setTransform) in combination with your script and it wasn't working for me either.
Bobo's function is only truly usefull when you want to take pixel aspect into account, for lets say a tracking tool, which has to output non square pixel tracking values. I used that same approach for my max to fusion tracker tool.Thanks, good to know.

CGTalk Moderation
08-30-2008, 01:43 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.