Get Screen Scale Factor

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.

Get Screen Scale Factor

Postby Klunk » Mon Oct 31, 2011 12:50 pm

Is there a function in irrlicht that returns the screen scale factor for a given point in world space ? I've been trolling through the api not found anything.
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby hybrid » Mon Oct 31, 2011 2:01 pm

Screen scale for point in world space? A point is a point, no matter where and how it is projected. If you have a dimension somewhere, you can transform the vertices manually and get the resulting dimension. There's no automatic method for this, AFAIK. Don't know if it's too helpful, anyway. Other way round is probably more often used.
hybrid
Admin
 
Posts: 13943
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Re: Get Screen Scale Factor

Postby Klunk » Mon Oct 31, 2011 2:20 pm

its a function from the 3dsmax sdk that I would like to replicate in irrlicht, its used in the following manner in max

cpp Code: Select all
Matrix3 tm = inode->GetObjectTM(t);    
       
        float size;
        int screenSize;
 
        pblock2->GetValue(pointobj_size, t, size, FOREVER);
        pblock2->GetValue(pointobj_screensize, t, screenSize, FOREVER);
 
        float zoom = 1.0f;
        if (screenSize)
                zoom = vpt->GetScreenScaleFactor(tm.GetTrans())*0.005f;
        if (zoom==0.0f)
                 zoom = 1.0f;
 
        size *= zoom;


it gives you the option for helper objects (dummy, point, etc) to be drawn with a constant screen size.

float GetScreenScaleFactor ( const Point3 worldPoint ) Returns the screen scale factor for a point given in world coordinates. This factor gives the width in world-space units at the point's distance of the viewport (from the sdk doc).

Am i right in saying that its the width across the camera fustrum at the world point would give me the same result ?
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby Klunk » Mon Oct 31, 2011 3:57 pm

the answer to my question was yes. So for future reference...

add the following function to your custom scene node

cpp Code: Select all
        float GetScreenScaleFactor(vector3df worldpnt,ICameraSceneNode* camera)
        {
                plane3df        near_fplane = camera->getViewFrustum()->planes[SViewFrustum::VF_NEAR_PLANE];
                vector3df       cam_z = near_fplane.Normal;
                vector3df       width_vtr = camera->getUpVector().crossProduct(cam_z);
                plane3df left_fplane = camera->getViewFrustum()->planes[SViewFrustum::VF_LEFT_PLANE];
                plane3df right_fplane = camera->getViewFrustum()->planes[SViewFrustum::VF_RIGHT_PLANE];
               
                vector3df p1,p2;
                bool i1 = left_fplane.getIntersectionWithLine(worldpnt,-width_vtr,p1);
                bool i2 = right_fplane.getIntersectionWithLine(worldpnt,width_vtr,p2);
 
                return p1.getDistanceFrom(p2);
        }


the following code in your node render function will keep it a fixed size on the screen

cpp Code: Select all
float temp = size;
float zoom = GetScreenScaleFactor(getPosition(),SceneManager->getActiveCamera()) * 0.002f; // 0.002 is a constant scalar
if(zoom == 0.0f)
        zoom = 1.0f;
temp *= zoom;
 
// example wireframe screen gizmo draw
for(u32 i = 0; i < edges.size(); i++)
     driver->draw3DLine(verts[edges[i].X] * temp,verts[edges[i].Y] * temp,colour);


obviously if theres an easier way to get the width of the view at a specific point please chip in.
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby hybrid » Mon Oct 31, 2011 5:11 pm

Ok, so you want the dimensions of a full screen plane at a certain depth. I got a completely different idea from the first description. But for this purpose your code seems ok. I guess you will also need the height at that depth, and get the maximum of both values (or both values in case of non-uniform scaling) to really fill the whole screen. If not, you can still switch to the height, as this would not need the cross product then.
hybrid
Admin
 
Posts: 13943
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Re: Get Screen Scale Factor

Postby Klunk » Mon Oct 31, 2011 5:54 pm

i'm not sure it matters which is used width or height as long as it's constant as the value can be tuned with the scalar term. slightly neater method for calculating the scalefactor

cpp Code: Select all
float GetScreenScaleFactor(const vector3df& worldpnt,ICameraSceneNode* camera)
{
        vector3df viewpnt = worldpnt;
        camera->getViewMatrix().transformVect(viewpnt);
        return  2 * viewpnt.Z / camera->getProjectionMatrix()[0];
}
 


my only concern would be what happens with an orthographic camera
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby shadowslair » Mon Oct 31, 2011 6:30 pm

Klunk wrote:my only concern would be what happens with an orthographic camera
Nothing. You check if your camera is ortho and if so, you simply return 1.0f. With ortho projection all nodes will always keep their original scales, right?
Image
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
User avatar
shadowslair
 
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Re: Get Screen Scale Factor

Postby Klunk » Mon Oct 31, 2011 11:34 pm

interestingly or not, it provides a similar method of getting screen coordinates from a 3d position.

cpp Code: Select all
        void GetScreenCoords(const vector3df& worldpnt,ICameraSceneNode* camera, position2di& screenCoords)
        {
// get the viewport
 
                const recti& viewPort = SceneManager->getVideoDriver()->getViewPort();
 
// transform world point into view space
 
                vector3df viewpnt = worldpnt;
                camera->getViewMatrix().transformVect(viewpnt);
 
// get half the view port size at the point
 
                float hwidth = viewpnt.Z / camera->getProjectionMatrix()[0];
                float hheight = viewpnt.Z / camera->getProjectionMatrix()[5];
 
// get the equivalent screen coords
 
                screenCoords.X = round32((hwidth + viewpnt.X) * viewPort.getWidth()/ hwidth * 0.5f);
                screenCoords.Y = round32((hheight - viewpnt.Y) * viewPort.getHeight()/ hheight * 0.5f);
        }
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby Klunk » Tue Nov 01, 2011 7:53 am

could this thread be moved to code snippets please.
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby hybrid » Tue Nov 01, 2011 8:07 am

I think the latter two are pretty close to getScreenCoordinatesFrom3DPosition, aren't they?
hybrid
Admin
 
Posts: 13943
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany

Re: Get Screen Scale Factor

Postby Klunk » Tue Nov 01, 2011 8:24 am

similar, though not by design :)

you can remove one of the divisions at the expense of a check for div by zero, though i doubt you would use it enough for it to be a performance gain.

cpp Code: Select all
void GetScreenCoords(const vector3df& worldpnt,ICameraSceneNode* camera, position2di& screenCoords)
        {
// get the viewport size
 
                const recti& viewPort = SceneManager->getVideoDriver()->getViewPort();
 
// transform world point into view space
 
                vector3df viewpnt = worldpnt;
                camera->getViewMatrix().transformVect(viewpnt);
 
                if(viewpnt.Z == 0.0f) viewpnt.Z = FLT_EPSILON;
 
// get half the view port size at the point
 
                float hwidth = camera->getProjectionMatrix()[0]/viewpnt.Z;
                float hheight = camera->getProjectionMatrix()[5]/viewpnt.Z;
 
// get the equivalent screen coords
 
                screenCoords.X = round32((1.0f + hwidth * viewpnt.X) * viewPort.getWidth() * 0.5f);
                screenCoords.Y = round32((1.0f - hheight * viewpnt.Y) * viewPort.getHeight() * 0.5f);
        }
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm

Re: Get Screen Scale Factor

Postby Klunk » Wed Nov 09, 2011 11:15 am

as a quick addendum, you can use the following to draw something more complicated in a fixed screensize

cpp Code: Select all
float zoom = 1.0f;
if(fixedsize)
        zoom = GetScreenScaleFactor(getPosition(),SceneManager->getActiveCamera()) * screenscale;
if(zoom == 0.0f)
        zoom = 1.0f;
 
matrix4 scalar;
scalar.setScale(zoom);
driver->setTransform(ETS_WORLD,AbsoluteTransformation * scalar);
driver->setMaterial(mbuf->setMaterial());
driver->drawMeshBuffer(mbuf);
Klunk
 
Posts: 226
Joined: Mon Jan 10, 2011 5:21 pm


Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 1 guest