when targeting reticles move off-screen

Started by
1 comment, last by BS-er 16 years, 4 months ago
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?
Value of good ideas: 10 cents per dozen.Implementation of the good ideas: Priceless.Machines, Anarchy and Destruction - A 3D action sim with a hint of strategy
Advertisement
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.
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;		}	}
Value of good ideas: 10 cents per dozen.Implementation of the good ideas: Priceless.Machines, Anarchy and Destruction - A 3D action sim with a hint of strategy

This topic is closed to new replies.

Advertisement