Forum: Poser Python Scripting


Subject: WorldToScreen() - unclear about what it returns.

3dcheapskate opened this issue on Dec 23, 2023 ยท 10 posts


3dcheapskate posted Sat, 23 December 2023 at 8:22 AM

From the WorldToScreen() scene method description on page 85 of the Poser 11 Poser Python Methods Manual it "Takes a set of (x, y, z) world coordinates (the location of a point within the 3D scene) and returns (x, y, z) screen coordinates (the location of that point relative to the screen)."

It's not clear to me what this method actually returns as "screen coordinates" are explicitly 2-dimensional (x, y) not 3-dimensional (x, y, z).

So is it

(a) just a transformation from world space to camera space, returning a true set of 3D coordinates.

(b) a calculation of the 2-dimensional x,y screen position plus the "Z-depth" 


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



shvrdavid posted Mon, 25 December 2023 at 8:54 PM Online Now!

In most programs it returns x and y only. And in an OpenGl program it may possibly return it in -1 to 1 range format on both axes. 

I have never really needed it in Poser thou.



Some things are easy to explain, other things are not........ <- Store ->   <-Freebies->


FVerbaas posted Tue, 26 December 2023 at 5:11 PM Forum Coordinator

The 3rd element in the tupel returned is some sort of inverse z-depth, positive when input (xyz) is before the camera, negative when aft of the camera.  Very close to zero when far away, larger, I have seen values close to 1000, when very near to the camera.   


3dcheapskate posted Thu, 28 December 2023 at 10:39 AM

Thanks. I was hoping it was going to be a simple world to camera space transformation.

No matter, maybe a different approach - try to do the transformation longhand in the material room... LOL !


The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



FVerbaas posted Sat, 30 December 2023 at 4:35 AM Forum Coordinator

Well, it IS a world to camera space. Just the z is scaled different from x and y. Plotted it will look like a height map. You may need to ban negative input and use log(z) for practical applications though.


3dcheapskate posted Sun, 31 December 2023 at 3:03 AM

I just nailed together a crappy bit of python to print the world space coordinates and the result of the WorldToSpace() conversion. Here's what it outputs when I have a 1PNU vertical square centred at the origin and view it via the dollycam which is positioned on the positivbe Z axis looking at the origin



So it's definitely not camera space in the way I was thinking of camera space.


Here's the 'code' (peril sensitive sunglasses recommended for viewing). I've totally given up trying to post correctly formatted code on Renderosity forums, so this is just a cut-and-paste from Notepad++


import poser,random


# I put my scripts into a class simply to avoid possible conflict with stuff in the __main__ module.

class cheapskatesTemporaryClass(object):

def main(self):

# Get Poser version for doing version-specific stuff

poserversion = '0'

posermainversion = '0'

try:

self.poserversion = poser.AppVersion()

temp = self.poserversion.split('.')

self.posermainversion = temp[0]

except:

pass

poser.DialogSimple.MessageBox("1")

scn = poser.Scene()

curact = scn.CurrentActor()

curgeom = curact.Geometry()

vcnt = curgeom.NumVertices()

wvlist = curgeom.WorldVertices()

poser.DialogSimple.MessageBox("vcnt = "+str(vcnt))

i=0

triplet=[0.0,0.0,0.0]

curcam = scn.CurrentCamera()

trp=[0.0,0.0,0.0]

trp = curcam.WorldDisplacement()

print '\nCamera position ('+str(trp[0])+', '+str(trp[1])+', '+str(trp[2])+')'

while i < vcnt:

poser.DialogSimple.MessageBox("Vertex"+str(i))

dbg ='Vertex ' + str(i) + ' World ('

curv = curgeom.WorldVertex(i)

dbg = dbg + str(curv.X()) +', '+str(curv.Y())+', '+str(curv.Z())+');'

triplet = scn.WorldToScreen(curv.X(),curv.Y(),curv.Z())

dbg = dbg + ' Screen (' +str(triplet[0]) +', '+str(triplet[1])+', '+str(triplet[2])+');'

print dbg

i = i + 1

# Inform the user that it's all done

poser.DialogSimple.MessageBox("All done")

poser.DialogSimple.MessageBox("Running 3DCheapskates XXX.py script\n\n(N.B. You should see a similar message when the script finishes. If you don't then the script has crashed!)")

cheapskatesTemporaryInstance = cheapskatesTemporaryClass()

cheapskatesTemporaryInstance.main()

poser.DialogSimple.MessageBox("3DCheapskates XXX.py script all done.")




The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).



FVerbaas posted Mon, 01 January 2024 at 12:03 PM Forum Coordinator

Why is it not a representation of camera space?

You are using 4 points effectively located on the X0Y plane and a camera looking down the Z axis. 

Let's call the three elements in the tuple returned by the method as u, v, w.

The range you get for the u coordinates is: 630-116 = 514 for the camera position z = 2. Using the same methodology for the other example positions you find 258  for z=4 and 128 for z=8. Note the figures halve when distance doubles.

If you re-do the math for the v coordinates in the first example you find a v-range of 672-158 = 514. For the other camera positions you will also find the same ranges as you found for the u-coordinate.  You thus have the 4 points arranged in a square. 

If you look at the averages, you will find that the avarages of the ranges, representing the center of the square is consistently located at u = 373, v = 415. You do not report the film (image) surface when you did the test, could it be it was sized 746x 830 pixels?

Then for the w=output: The same scaling effect is used there: a point located twice the distance gives half the signal strength. Obviously any input very close to the camera xyz would be division by zero, return an infinite number, so something will be/should have been caught and buffered there. To get a physical meaning you can scale based on some test points, simple Pythagoras.

I must have a matrix based method laying around somewhere. Let me know if you are interested.      


 


FVerbaas posted Mon, 01 January 2024 at 12:17 PM Forum Coordinator

Correction:  

Forget that last line for now. I just looked and it was not where I suspected it was. If I still have it it is dug somewhere very very deep.

 


FVerbaas posted Mon, 01 January 2024 at 12:35 PM Forum Coordinator

Correction 2: The width of your screen was probably 746 pixels. Poser just uses the width. Cannot say about height.


3dcheapskate posted Tue, 02 January 2024 at 12:18 AM

FVerbaas posted at 12:03 PM Mon, 1 January 2024 - #4479844

Why is it not a representation of camera space?

It's certainly a representation of camera space, but please note that the original question was this:

So is it

(a) just a transformation from world space to camera space, returning a true set of 3D coordinates.

(b) a calculation of the 2-dimensional x,y screen position plus the "Z-depth" 


And my comment after testing with my laughable script was "So it's definitely not camera space in the way I was thinking of camera space." since the x, y, z returned by WorldToSpace() is obviously (b), not (a) -which is what I'd expect goven the method's name.


WorldToSpace() doesn't return what I referred to, rather imprecisely, as "a true set of 3D coordinates" because it doesn't identify a single point in 3D space . You need 3 additional parameters for that - field of view, render height, and render width.






The 3Dcheapskate* occasionally posts sensible stuff. Usually by accident.
And it usually uses Poser 11, with units set to inches. Except when it's using Poser 6 or PP2014, or when its units are set to PNU.

*also available in ShareCG, DAZ, and HiveWire3D flavours (the DeviantArt and CGBytes flavour have been discontinued).