How to do gluProject in gum

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
User avatar
hardhat
Posts: 17
Joined: Thu Mar 02, 2006 9:42 am
Contact:

How to do gluProject in gum

Post by hardhat »

Hi,

I've been working on a program where I want to know where something will appear in screen coordinates to decide which camera angle is the best. So, after peeking at the Mesa source code, I've come up with the following:

Code: Select all

/** Project a point from object coordinates to screen coordinates.
 * \param object point in object coordinates.
 * \param view view transformation matrix.
 * \param projection projection transformation matrix (for example from gumPerspective).
 * \param model model transformation matrix (for example from gumLookAt).
 * \param viewport the left, top, width and height of the viewport.
 * \param screen on success, the result of the point projected into screen coordinates.
 * \returns 1 on success, or 0 if it is a degenerate projection.
 */
s32 gumProject(const ScePspFVector3 *object,const ScePspFMatrix4 *view,const ScePspFMatrix4 *projection,const ScePspFMatrix4 *model,const s32 viewport[4],ScePspFVector3 *screen) {
    ScePspFMatrix4 m;
    float w;
    gumMultMatrix(&m,view,projection);
    gumMultMatrix(&m,&m,model);
    screen->x=object->x*m.x.x+object->y*m.y.x+object->z*m.z.x+m.w.x;
    screen->y=object->x*m.x.y+object->y*m.y.y+object->z*m.z.y+m.w.y;
    screen->z=object->x*m.x.z+object->y*m.y.z+object->z*m.z.z+m.w.z;
    w=object->x*m.x.w+object->y*m.y.w+object->z*m.z.w+m.w.w;

    if(w==0) return FALSE;
    screen->x/=w;
    screen->y/=w;
    screen->z/=w;

    // Now map x,y to the range 0-1
    screen->x=screen->x*0.5f+0.5f;
    screen->y=screen->y*0.5f+0.5f;
    // Scale/translate to the viewport size
    screen->x=screen->x*viewport[2]+viewport[0]; // *width + left
    screen->y=(1.0f-screen->y)*viewport[3]+viewport[1]; // *height+top
    return TRUE;
}
which can be initialized and called via:

ScePspFMatrix4 view,projection,mode;
ScePspFVector3 from={-20,-10,-20},to={0,0,0},up={0,0,1}; // For example
ScePspFVector3 obj={2,1,0},screen;
s32 viewport[4]={0,0,480,272};

gumLoadIdentity(&view);
gumLoadIdentity(&projection);
gumPerspective(&projection,45.0f,16.0f/9.0f,1.5f,2048.0f);
gumLoadIdentity(&model);
gumLookAt(&model,&from,&to,&up);
// Now project a point obj -> screen
gumProject(&obj,&view,&projection,&model,viewport,&screen);

which should correspond to a point drawn with:

sceGumMatrixMode(GU_VIEW);
sceGumLoadIdentity();
sceGumMatrixMode(GU_PROJECTION);
sceGumLoadIdentity();
sceGumPerspective(45.0f,16.0f/9,0f,1.5f,2048.0f);
sceGumMatrixMode(GU_MODEL);
sceGumLoadIdentity();
sceGumLookAt(&from,&to,&up);

From testing it, I find that all of my projected values seem to be in the range:
x in 238 to 242 for on screen values. I just don't get it. Any ideas?

Edit: updated sample to fix cut and paste errors. Now works perfectly. :-) Enjoy.
Last edited by hardhat on Fri Feb 22, 2008 5:38 am, edited 1 time in total.
User avatar
hardhat
Posts: 17
Joined: Thu Mar 02, 2006 9:42 am
Contact:

Post by hardhat »

Okay, so I found one last bug. For those of us who like the screen origin at the top left corner, the line:

Code: Select all

screen->y=screen->y*viewport[3]+viewport[1]; // *height+top
should be:

Code: Select all

screen->y=(1.0f-screen->y)*viewport[3]+viewport[1]; // *height+top
Post Reply