# I'm trying to get a 2D screen position so I unproject a point from 3D into 2D screen coordinates by that following function:

I'm trying to get a 2D screen position so I unproject a point from 3D into 2D screen coordinates by that following function:

Ogre::Vector2 SpaceTransformHelper::convertWorldToScreenPosition( const Ogre::Vector3& worldPosition )
{
Stages::AStage* currStage = Stages::StageManager::getSingleton()->getActiveStage();
Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()->getScreenResolution();

// Get worldviewprojection from camera.
Ogre::Matrix4 worldViewProjection = currStage->getActiveCamera()->getCameraViewProjectionMatrix();

// Transform world coordinates.
Ogre::Vector3 transformedWorldPosition = worldViewProjection * worldPosition;

// Calculate screen coordinates from world coordinates.
Ogre::Vector2 screenPosition;
screenPosition.x = (int) ( ( ( transformedWorldPosition.x + 1 ) / 2.0 ) * screenRes.width + 0.5 );
screenPosition.y = (int) ( ( ( 1 - transformedWorldPosition.y ) / 2.0 ) * screenRes.height + 0.5 );

return screenPosition;
}


Now I want to convert that screenPosition into Image space to crop an image:

Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()->getScreenResolution();
float screenPositionX = (screenPosition.x / screenRes.width) * (pixelBuffer->getWidth());
float screenPositionY =  (screenPosition.y / screenRes.height) * (pixelBuffer->getHeight());


When I click on the mobile screen on the Green LED I get that cropped image.. but what I want is to only crop that green led.. Is there a problem with the transformation ?

  const Core::Resolution cameraRes = Core::EnvironmentInformation::getSingleton()->getCameraResolutionUpLoad( plane );
Ogre::HardwarePixelBufferSharedPtr pixelBuffer = mTexture[plane]->getBuffer( 0, 0 );

viewarassert( screenPosition.x < cameraRes.width || screenPosition.x >= 0 || screenPosition.y < cameraRes.height || screenPosition.y >= 0 );

Core::Resolution screenRes = Core::EnvironmentInformation::getSingleton()->getScreenResolution();
std::pair< Ogre::Vector2, Ogre::Vector2 > uvBounds = calculateSingleViewTextureCoordinates();

float screenPositionX = cameraRes.height - (screenPosition.x / screenRes.width) * ((int)pixelBuffer->getHeight());
float screenPositionY=  cameraRes.width -  (screenPosition.y / screenRes.height) * ((int)pixelBuffer->getWidth());

int  min_x = std::max( 0,(int)screenPositionX - radius);
int  min_y = std::max( 0,(int)screenPositionY - radius);
int  max_x = std::min( (int)cameraRes.width, (int) screenPositionX + radius );
int  max_y = std::min( (int)cameraRes.height, (int) screenPositionY+ radius );

// Get the pixelbox within the radius.

Ogre::Image img;
pixelBuffer->getHeight(), pixelBuffer->getFormat());
img = img.flipAroundY();

Ogre::Image *out = cropImage(img,  min_x, min_y,  max_x,  max_y);

• Didn't you ask this on SO as well? stackoverflow.com/questions/47857995/… Anyways as the guy mentioned I don't understand your transformation matrix. You said perspective projection isn't involved but you name it projection anyways? what is the space of world position after you apply the matrix? Camera space? Projection space? – gallickgunner Dec 19 '17 at 4:54

Not sure if Ogre does it implicitely, but using a 4x4 matrix to transform a 3D point to get the correct 2D coordinates (as it would be rendered with the same matrix), requires a transition from homogeneous coordinates by dividing the result by w.

In other words, you must multiply the matrix by a 4-component vector (x,y,z,1.0f) instead of a 3-component vector. And then the resulting vector will look like (X,Y,Z,W) and you need to divide by W to get the position like it would be rendered.

Like this:

// Transform world coordinates.
Ogre::Vector4 transformedWorldPosition = worldViewProjection * Ogre::Vector4(worldPosition,1.0);

//Divide by w
transformedWorldPosition = transformedWorldPosition / transformedWorldPosition.w;

// Calculate screen coordinates from world coordinates.
Ogre::Vector2 screenPosition;
screenPosition.x = (int) ( ( ( transformedWorldPosition.x + 1 ) / 2.0 ) * screenRes.width + 0.5 );
screenPosition.y = (int) ( ( ( 1 - transformedWorldPosition.y ) / 2.0 ) * screenRes.height + 0.5 );


From what I can see, it looks like screenPosition.x is in some sort of screen space and screenPositionX is in terms of the actual pixel buffer in units of pixels. My guess is that cropImage wants its inputs in units of pixels but when you calculate min_x, min_y, ... you are using screenPosition.x when you should really be using screenPositionX. Also, where does radius come from? Is it in world space, screen space, or pixel buffer space?

Regardless of whether or not that fixes your problem, try to be more explicit in the future about your variables names to keep track of which space/units you are in. Having a screenPosition.x and a screenPositionX which refer to different things is generally a bad idea.

• the radius is pixel buffer space, screenPosition.x is screenspace, and screenPositionX is in actual pixel buffer. I still gets wrong cropped rectangle. Thanks – Ahmed Saleh Dec 19 '17 at 11:52
• I have edited the post.. still I get wrong cropped image, out of bounds exception – Ahmed Saleh Dec 19 '17 at 11:59
• Which piece of code gives the out of bounds exception? – Chuck Dec 19 '17 at 18:13
• Ogre::Image *out = cropImage(img, min_x, min_y, max_x, max_y); – Ahmed Saleh Dec 19 '17 at 20:35
• This is a longshot but maybe you need to clamp the max value to cameraRes - 1 because accessing cameraRes on a zero indexed array would be out of bounds. – Chuck Dec 21 '17 at 7:09