Sign in to follow this  
BS-er

when targeting reticles move off-screen

Recommended Posts

Its pretty easy to calculate X Y screen coordinates to place a 2D reticle given world X Y Z coordinates: Multiply projection matrix by (view matrix multiplied by position), and the X and Y of the result are your X and Y screen coordinates (zero centered). However I'm struggling with the target position being off-screen especially directly left, right, above or below the camera. I'd like to have a reticle on the edge of the window consistent with the target's off-screen relative position. However its quite jumpy, and irregular. I'm convinced that there is an appropriate calculation because I've seen it done quite well in games. Would anyone happen to know the magic formula?

Share this post


Link to post
Share on other sites
Mmm, the best way to do this is find the position of the object in view space. Then project onto the xy-plane (assuming you look down the z-axis in view space). You can then create a vector in view space from the origin to the projected position. In screen space use this same vector from the center of the screen to find the intersection with the edge of the screen using cohen sutherland clipping or some other sort of clipping.

Share this post


Link to post
Share on other sites
Thanks a bunch for the tip. You lit a spark and sent me off in the right direction when you mentioned intersection with the edge.

I didn't need to mess with a clipping algorithm though, although its good to know about it now. The following approach works nicely :).


Vector3 EyeSpacePos = mCamera->getViewMatrix(true) * Position;
Vector3 ScreenSpacePos = mCamera->getProjectionMatrix() * EyeSpacePos;

x = ScreenSpacePos.x;
y = ScreenSpacePos.y;
float abs_x = fabs(x);
float abs_y = fabs(y);

// check if not in the forward or backward view frustum
if ((abs_x > 1) || (abs_y > 1))
{
if (abs_x > abs_y)
{
// abs_x is greater, so its either the left or right edge
x = (ScreenSpacePos.x > 0)? 1.0 : -1.0;
y = ScreenSpacePos.y / abs_x;
}
else
{
// abs_y is greater, so its either the top or bottom edge
y = (ScreenSpacePos.y > 0)? 1.0 : -1.0;
x = ScreenSpacePos.x / abs_y;
}
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this