- Home /
Calculate distance at which an object occupies 0 pixels, given bounding sphere?
I'm working on a spawning system that will randomly spawn asteroids in the player's path as he's traveling through space. The area the asteroids can spawn should be in front of the player, but far enough away that they don't just appear to pop into existence. I need to figure out what that distance is.
I can't just use the camera's far plane, because its way too far away (I have large objects like stars that should be visible at a pretty good distance), and so the asteroids wouldn't become visible for some time, and the first asteroids spawned wouldn't show up for awhile.
So, I'm looking to find the nearest distance at which the asteroids wouldn't be visible if they appeared straight in front of the player, aka, the point at which they wouldn't occupy any pixels on screen (or 1 pixel would work fine too). This will be dependent on the size of the asteroid, which I can approximate with the diameter of the asteroid's bounding sphere.
I figure I could calculate how many pixels an asteroid occupies given its position and diameter pretty easily:
//Gets the number of pixels a given asteroid object occupies
//on screen. Assumes asteroid has a sphere collider.
public float GetOccupiedPixels(GameObject asteroid)
{
float radius = asteroid.collider.bounds.radius;
Vector3 point1 = asteroid.collider.bounds.center + Vector3.up*radius;
Vector3 point2 = asteroid.collider.bounds.center - Vector3.up*radius;
Vector2 screenPoint1 = camera.WorldToScreenPoint(point1);
Vector2 screenPoint2 = camera.WorldToScreenPoint(point2);
return (screenPoint1 - screenPoint2).magnitude;
}
(I haven't tested this code so maybe there's errors, but you get the idea)
The problem is that I can't go the other way. In order to go from screen to world points I would need to provide the distance to the object from the camera, and that is the exact value I'm trying to solve for.
I realize I could just use the above code to empirically determine a good distance for my largest asteroid size and use that. I might end up going that route. But I'd really like a more flexible solution. Can anyone think of way to do this in Unity?
I don't get what you're trying to do. If all you need is the distance from the camera, then why not place the camera at the origin? Whatever the magnitude of the position vector of your asteroid is would be the distance from the camera.
I don't really have time right now to investigate this further, but I think you should be able to calculate this distance rather easily using right triangle trigonometry. From the cameras vertical fieldofview you can get the angle of one pixel size at , fieldofview / screenHeightInPixels. Then using a right triangle where you want to find the length of the base, and you have the angle(fov/screenheight) between the hypotenusae and base, and you have the height(object diameter). Not sure if this works in practice.
sqrt((bX-aX)^2+(bY-aY)^2+(bZ-aZ)^2)
or use the distance(a,b) or Vector3.sqr$$anonymous$$agnitude(a-b) function
Answer by justinl · Sep 28, 2012 at 07:08 AM
Could you spawn the asteroid with no renderer on it at a distance, check your GetOccupiedPixels() method, and if it's still too large, then move it back by a certain factor, test again, and continue to do that until it's no longer visible? The beauty of this particular solution would be in how you check various distances without wasting a lot of CPU. Perhaps when a certain type of object for the first time at runtime figure out the distance, this can be stored in a manager class, so that future version of that object with the same size will already have this distance "cached".