# Algorithm to convert screen point to ray

This topic is 380 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I used to use ScreenPointToRay function to help me do this in Unity3d. But now I use Ogre and Bullet, I have to do this on my own.

I try to dig into Bullet's example and find out this function getRayTo which convert the point on that click on screen (camera) to the 3d world point with 'farPlane' distance from the camera (that what I think). Then they create the ray (vector AB) by set the A point is the camera position, B point is the point get from the function getRayTo above. I try to re-implement this function in my project (use Ogre for graphic, so I have to use Ogre's camera and world). But I can't get it right because I don't understand the function getRayTo from Bullet.

Please explain the algorithm to convert screen point to ray. If there is a better algorithm please teach me.

Note: the scenario to use this algorithm is to find out the position to go for the character - like in the game TouchLight - a point and click game.

https://github.com/bulletphysics/bullet3/blob/d52fb7510bbe3801431cc0a431e4c1847ee3e0f1/examples/CommonInterfaces/CommonRigidBodyBase.h#L17
Edited by 123iamking

##### Share on other sites

With this code

btVector3 rayToCenter = rayFrom + rayForward;
btVector3 dHor = hor * 1.f / width;
btVector3 dVert = vertical * 1.f / height;

btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
rayTo += btScalar(x) * dHor;
rayTo -= btScalar(y) * dVert;
return rayTo;

Look like they shift the center point to the point that clicked on the camera.

Here is my attempt to convert the function, and it looks pretty ok

Ogre::Camera* m_pCam;

btVector3	EmptyProjectGameState::getRayTo(int x, int y)
{
float top = 1.f;
float bottom = -1.f;
float nearPlane = 1.f;

btVector3 camPos;

camPos.setX(m_pCam->getPosition().x);
camPos.setY(m_pCam->getPosition().y);
camPos.setZ(m_pCam->getPosition().z);

btVector3	rayFrom = camPos;
btVector3 rayForward;
rayForward.setX(m_pCam->getDirection().x);
rayForward.setY(m_pCam->getDirection().y);
rayForward.setZ(m_pCam->getDirection().z);

rayForward.normalize();
float farPlane = 10000.f;
rayForward *= farPlane;

btVector3 rightOffset;
btVector3 cameraUp = btVector3(0, 1, 0);

btVector3 vertical = cameraUp;

btVector3 hor;
hor = rayForward.cross(vertical);
hor.safeNormalize();
vertical = hor.cross(rayForward);
vertical.safeNormalize();

float tanfov = tanf(0.5f*fov);

hor *= 2.f * farPlane * tanfov;
vertical *= 2.f * farPlane * tanfov;

btScalar aspect;
float width = float(mGraphicsSystem->getRenderWindow()->getWidth());
float height = float(mGraphicsSystem->getRenderWindow()->getHeight());

aspect = width / height;

hor *= aspect;

btVector3 rayToCenter = rayFrom + rayForward;
btVector3 dHor = hor * 1.f / width;
btVector3 dVert = vertical * 1.f / height;

btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
rayTo += btScalar(x) * dHor;
rayTo -= btScalar(y) * dVert;
return rayTo;
}

Edited by 123iamking

##### Share on other sites
	vec3 dir = DirectionFromScreen(CursorX, CursorY, SCREEN_WIDTH, SCREEN_HEIGHT,90.0, 2.0, 1000.0, float(SCREEN_WIDTH) / float(SCREEN_HEIGHT));
ray_vb[1].v = FPP_CAM->pos + dir*(1000.0*depth*2.0);

vec3 DirectionFromScreen(int x, int y, int sw, int sh, float fov, float z_near, float z_far, float aspect)
{

mat4 mvm = CAM_MODEL * CAM_VIEW;
mvm.Transpose();
vec3 dirX, dirY;
dirX.x = mvm.m[0];
dirX.y = mvm.m[4];
dirX.z = mvm.m[8];

dirY.x =	mvm.m[1];
dirY.y =	mvm.m[5];
dirY.z =	mvm.m[9];

float a = fov / 2.0;
float cotangent = 1.0 / tan( a * imopi );

float ax = z_near / cotangent;

float screen_w = 2.0*ax;

float screen_h = screen_w;// * yratio;

screen_w = screen_w * aspect;

float scr_coord_x = float(x) / float(sw);
float scr_coord_y = float(sh - y) / float(sh);

vec3 dir = FPP_CAM->ReturnFrontVector();

//move to lower left corner
vec3 start_pos = (FPP_CAM->pos + dir * z_near) + (-dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));

vec3 start = start_pos + (dirX * (screen_w * scr_coord_x)) + (dirY * (screen_h * scr_coord_y));

return Normalize( vectorAB(FPP_CAM->pos, start) );
}

Assuming that you have projection and view matrices defined

You end up with point on far plane by. Camera_pos+z_far*direction

Front vector can be computed from dirx and diry

Edited by WiredCat

##### Share on other sites
const float aspect = (float)(m_renderbufferWidth) / (float)(m_renderbufferHeight);
const float fx = 2.0f * ((float)(x) / (float)(m_renderbufferWidth - 1)) - 1.0f;
const float fy = 2.0f * ((float)(y) / (float)(m_renderbufferHeight - 1)) - 1.0f;
const float tangent = tan(y_fov_radians / 2.0f);

last_click_float_x = aspect*tangent*fx;
last_click_float_y = -tangent*fy;

Here x, y is the pixel location that was clicked on by the mouse/stylus/finger user, and last_click_float_x, last_click_float_y is the location on the image plane (which is taken to be a distance of 1 from the camera). The y_fov_radians and m_renderBufferWidth, m_renderBufferHeight variables are self-explanatory (hopefully).

Edited by sjhalayka

1. 1
Rutin
40
2. 2
3. 3
4. 4
5. 5

• 18
• 19
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633362
• Total Posts
3011531
• ### Who's Online (See full list)

There are no registered users currently online

×