camera.worldToScreen, frustum culling

I have made some modifications to the “follow-world-target.js” file from the tutorials, and I wanted to run it by the community to see if there’s a better way to accomplish my goal, and make the script better.

Basically, I need to find a reliable way to cull items from the screen, when their target Entity is offscreen. The sample assumes that all targets will always be visible. My use-case does not.

I noticed that camera.worldToScreen would return a vector with a negative z-coordinate when the target is behind the camera (with a perspective camera). This seems to make sense in an intuitive fashion. But, then I noticed that negative z-coordinates were commonplace when using an orthogonal camera.

So, I’ve added this conditional to the bottom of the script just ahead of setting the local position:

var proj = this.cameraEntity.camera.projection;
if( (proj === pc.PROJECTION_PERSPECTIVE && screenPos.z < 0) || 
   (proj === pc.PROJECTION_ORTHOGRAPHIC && screenPos.z < -1) ) {
    x = -1000;   // go far offscreen, instead of disable
}

I haven’t done enough testing to know if those “<” should be “<=”, in the code above.

Also, do we think this approach is reliable? Or, is it using undocumented features that may change in the future? Is there a better way to detect that the target is not within the camera frustum?

Hi @Cain_Quigley,

As a side note, is there a reason to not use the frustum culling provided by the engine?

That would take into account not only the position of the entity (model) but its size as well, to make sure that its completely hidden.

https://developer.playcanvas.com/en/api/pc.CameraComponent.html#frustumCulling

Well, actually, I am. But that only removes elements that the camera can see in 3D space, right?

The entity with the ‘follow-world-target.js’ script is in a 2D screen, in overlay space. The function ‘camera.worldToScreen’ will still compute a “screen position” for an Entity that has been frustum culled. I’m trying to find a cheap and effective way of determining whether or not to show the “following” entity (in overlay space). Using the ‘negative z-coordinate’ seems like a “cheap” way of detecting this.

Of course, I need to know if this is also “effective”. Clearly, if it’s not a reliable technique, then it fails that test.

And, to answer the other point, we are trying to maintain static size on text elements that follow the position of an object in the 3D world. The text always needs to be clear, regardless of range to target. (And, naturally, the text shouldn’t be seen when the world entity is behind the camera.)

A simple test to check if an entity is behind an object is to do a dot product with the camera forward vector and a vector from the camera position. If is less than 0, it’s behind the camera

1 Like

Right. That’s true, of course. But, simply being ‘in front of’ the camera is not the same thing as ‘in the view frustum.’

It had occurred to me that calling ‘worldToScreen’ would already need to compute whether or not something is in the view frustum, in order to be mapped correctly to the screen. And, it seems as though I am right about this. An artifact of the ‘worldToScreen’ computation is that the z-coordinate will be negative when the input vector is ‘off screen’ (not just ‘behind’ the camera).

Wasn’t the issue that with cameras with orthographic projection, it wasn’t clear if something was behind the camera or not?