Newbie question: Determining if a entity is visible by camera


(Niklas Thörne) #1

Hi,

Is there some functionality, that does not involve coordinate comparisons, which allows to determine whether an entity with a SpriteRenderer and a Transform is currently visible by camera?


(Joël Lupien) #2

You want to know if the entity is inside the camera rectangle or you want to know if the entity is hidden under other entities?


(Niklas Thörne) #3

Within the camera rectangle is perfectly fine, z-ordering does not really matter for my purposes.


(Nolan) #4

I’d be interested in knowing this as well. I’m using Amethyst for audio games, and knowing that something like a pile of coins is being rendered on a tilemap would let me play a clinking sound or something at their location so the player can find them. This is distinct from active sounds that an entity makes–kind of an audio icon that loops whenever the item is being rendered.


(Gray Olson) #5

I’m not sure exactly what you mean by this, as a check like this will always require coordinate comparisons. If you mean–a tool built into amethyst that does this for you? In that case, no, you’ll need to do it yourself. Thankfully it’s not that complex to implement yourself if you don’t care about perfect accuracy.

First, get the sprite’s largest dimension, either it’s width or height. This will be used as the diameter of a circle around the sprite. Then we will check if this circle intersects with the camera’s view box.

To get the view box (and you can just do this once at the beginning of the system run), we can apply that we know the camera is an orthographic camera and do this (note that this only works if the camera has no Parent; if it does then it gets a little more tricky, but not that bad; let me know and I can explain)

let ortho = nalgebra::Orthographic3::from_matrix_unchecked(camera.proj);
let translation = camera_transform.translation.vector.xy();
let bottom_left = nalgebra::Point2::new(ortho.left(), ortho.bottom()) + translation;
let top_right = nalgebra::Point2::new(ortho.right(), ortho.top()) + translation;
let camera_half_size = 0.5 * (top_right - bottom_left);
let camera_center = bottom_left + camera_half_size;

Now using these values that we’ve computed, we can check if the entity’s circle is inside the camera rect. For each entity (note that this will only work if the entity has no parent; if it does then you’ll need to compute the position from the GlobalTransform instead):

let entity_pos = naglebra::Point2::from(entity.transform.translation.vector.xy());
if (entity_pos.x - camera_center.x).abs() < camera_half_size.x + entity_radius
    || (entity_pos.y - camera_center.y).abs() < camera_half_size.y + entity_radius
{
    // The entity is inside the camera view
} else {
    // The entity is not inside the camera view
}

(Niklas Thörne) #6

Yes, that was exactly what I was hoping for, but the solution you present was indeed not too tricky, and perfect accuracy is not needed in this case.; Thanks, @termhn!