Get Screen Scale Factor
Get Screen Scale Factor
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.
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Get Screen Scale Factor
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.
Re: Get Screen Scale Factor
its a function from the 3dsmax sdk that I would like to replicate in irrlicht, its used in the following manner in max
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 ?
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;
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 ?
Re: Get Screen Scale Factor
the answer to my question was yes. So for future reference...
add the following function to your custom scene node
the following code in your node render function will keep it a fixed size on the screen
obviously if theres an easier way to get the width of the view at a specific point please chip in.
add the following function to your custom scene node
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);
}
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);
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Get Screen Scale Factor
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.
Re: Get Screen Scale Factor
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
my only concern would be what happens with an orthographic camera
Code: Select all
float GetScreenScaleFactor(const vector3df& worldpnt,ICameraSceneNode* camera)
{
vector3df viewpnt = worldpnt;
camera->getViewMatrix().transformVect(viewpnt);
return 2 * viewpnt.Z / camera->getProjectionMatrix()[0];
}
-
- Posts: 758
- Joined: Mon Mar 31, 2008 3:32 pm
- Location: Bulgaria
Re: Get Screen Scale Factor
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?Klunk wrote:my only concern would be what happens with an orthographic camera
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
Re: Get Screen Scale Factor
interestingly or not, it provides a similar method of getting screen coordinates from a 3d position.
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);
}
Re: Get Screen Scale Factor
could this thread be moved to code snippets please.
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Re: Get Screen Scale Factor
I think the latter two are pretty close to getScreenCoordinatesFrom3DPosition, aren't they?
Re: Get Screen Scale Factor
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.
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.
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);
}
Re: Get Screen Scale Factor
as a quick addendum, you can use the following to draw something more complicated in a fixed screensize
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);
Re: Get Screen Scale Factor
updated to handle orthogonal camera
Code: Select all
float GetScreenScaleFactor(const vector3df& worldpnt,ICameraSceneNode* camera)
{
if(camera->isOrthogonal())
return 2.0f/camera->getProjectionMatrix()[0];
vector3df viewpnt = worldpnt;
camera->getViewMatrix().transformVect(viewpnt);
return 2.0f * viewpnt.Z / camera->getProjectionMatrix()[0];
}