Converting world to screen coords

Howdy again

i try to convert world to screen coordinates … my guess was to use View.getProjView( canvas ) to get the view projection matrix (or transform3d) and then Transform3D.transform ( point3f ) with some of my world coordinates which should move them to screen space … but given a simple example:

camera position: (1,1,0) looking at (0,0,0)
and two points: p=(0,0,0) and q=(0,0,1)

gives the following result:

q (after transformation): (-0.70,-0.70,0)
p (after transformation): (-3.41,-3.41,0)
camera position: (0,0,1) looking at (0,0,0)
and two points: p=(0,0,0) and q=(0,0,1)

gives the following result:

p (after transformation): (0,0,-1)
q (after transformation): (0,0,-4.002001)

i have no idea how to interpret those values … is there another step needed to get screen coordinates? (and will they be ‘pixel-perfect’ -> one unit per pixel ? )

Greetz Goliat

Well, I don’t know where is mistake in your approach, but I can share my :). Working fine for me.


public Point2f getOnScreen(Point3f point3D, View view, Canvas3D canvas) {
        Point2f pointOnScreen = null;
        //------------------------------------------------------------
        float scW = (float)canvas.getWidth();
        float scH = (float)canvas.getHeight();
        //--- "on screen" refference frame for further calculations --
        Transform3D viewTF = view.getTransform();
        Vector3f Vx  = new Vector3f(1, 0, 0);  viewTF.transform( Vx);
        Vector3f Vy  = new Vector3f(0, 1, 0);  viewTF.transform( Vy);
        Vector3f nVz = new Vector3f(0, 0,-1);  viewTF.transform(nVz);
        //------- w0 - vector from camera location to point3D -------
        Vector3f viewLoc = new Vector3f();  viewTF.getTranslation(viewLoc);
        Vector3f w0 = new Vector3f(point3D);
        w0.sub(viewLoc);
        if (view.getProjectionPolicy() == View.PARALLEL_PROJECTION) {
            float k = scW/view.getScreenScale()/2;
            //-------------------------------------
            float sc_dX = k*(w0.x*Vx.x + w0.y*Vx.y + w0.z*Vx.z);
            float sc_dY = k*(w0.x*Vy.x + w0.y*Vy.y + w0.z*Vy.z);
            //-------------------------------------
            pointOnScreen = new Point2f(scW/2 + sc_dX, scH/2 - sc_dY);
        } else {
            w0.normalize();
            //-----------------------------------------------------------
            float m = (w0.x*nVz.x + w0.y*nVz.y + w0.z*nVz.z);
            if (m != 0) {
                //otherwise 90 degree and no single point on screen
                //corresponds to point3D (well - line would corresponds)
                //(only need to be considered for perspective view)

                w0.scale(1/m);
                Vector3f rV = VecLib.subVV(w0, nVz);                  
                //-------------------------------------
                float normH = (float)Math.tan(view.getFieldOfView()); 
                float k = scH/normH/2;
                //-------------------------------------
                float sc_dX = k*(rV.x*Vx.x + rV.y*Vx.y + rV.z*Vx.z);
                float sc_dY = k*(rV.x*Vy.x + rV.y*Vy.y + rV.z*Vy.z);
                //-------------------------------------
                pointOnScreen = new Point2f(scW/2 + sc_dX, scH/2 - sc_dY);
            }
        }
        return pointOnScreen;
    } 

Edit: just be aware, for perspective projection method might return null (if specified point3D is on same plane (front clip…) where your scene is projected onto, and if this point is on “infinity” at the same time…)

Bohdan.

you’re using a libary called VecLib … as it seems this is a mac libary
is this just a simple rV = w0 - nVz ?

Vector3f rV = VecLib.subVV(w0, nVz);

EDIT: i changed it to

Vector3f rV = new Vector3f();
rV.sub( w0, nVz );

and it works fine :slight_smile:
(i just believe there are too many 'new’s in there to get the best performance … or am i wrong ??? )

yes, correct! :slight_smile: It is my subsidirary math lib, it was few calls there, I just missed one change when was preparing it for you.

Well, not that many really, as for me. Well it depend what you are looking to use it for… The approach is there, and you can easy optimize/modify it the way you want. But I think it is fast enough :wink:

i believe there are some points that can be optimized … but that’ll be low priority for me …
OTOH i believe this should go to the core (or the toolkit) somewhere

I’ll be happy to contribute :slight_smile: