Testing if a Spatial is within a viewport

Hi again :slight_smile:



I was wondering how you would go about testing if a Spatial in your game was within your current viewport, i.e. if the Spatial is currently visible anywhere on your screen.



Thanks!

[java]

screenCoords = activeCamera.getScreenCoordinates(SomeVector3fGoesHere);

int sX1 = (int)Math.floor(screenCoords.getX());

int sY1 = (int)Math.floor(screenCoords.getY());

[/java]



Then just make sure it is within the confines of the screen 0, 0, width, height… Make sure it is a possitive value as well or you’ll be including thing behind the camera.

There might be a way to do it by looking at the culling information as well.



Do you want to know if its actually visible or just inside the screen area? (For example something behind a wall would be inside the screen area but not visible).

the easiest way would be to check if the spatial is not being culled, but depends on your actual requirements

@t0neg0d said:
[java]
screenCoords = activeCamera.getScreenCoordinates(SomeVector3fGoesHere);
int sX1 = (int)Math.floor(screenCoords.getX());
int sY1 = (int)Math.floor(screenCoords.getY());
[/java]

Then just make sure it is within the confines of the screen 0, 0, width, height... Make sure it is a possitive value as well or you'll be including thing behind the camera.

Could you elaborate on this slightly? What vector do I pass into get screen coordinates? And how do I use sX1 and sY1.

It would be ideal to check if you can actually see the Spatial (ie, if it is behind a wall you can't see him). How would I check if the spatial is culled?
@t0neg0d said:
[java]
screenCoords = activeCamera.getScreenCoordinates(SomeVector3fGoesHere);
int sX1 = (int)Math.floor(screenCoords.getX());
int sY1 = (int)Math.floor(screenCoords.getY());
[/java]

Then just make sure it is within the confines of the screen 0, 0, width, height... Make sure it is a possitive value as well or you'll be including thing behind the camera.

Could you elaborate on this slightly? What vector do I pass into get screen coordinates? And how do I use sX1 and sY1.

It would be ideal to check if you can actually see the Spatial (ie, if it is behind a wall you can't see him). How would I check if the spatial is culled?

you have a camera.contains(boundingVolume) method.

However before calling it make sure you call camera.setPlaneState(0);

@nehon said:
you have a camera.contains(boundingVolume) method.
However before calling it make sure you call camera.setPlaneState(0);


This method seemed to work great, thanks!
[java]BoundingVolume bv = character.getWorldBound();
int planeState = playerCam.getPlaneState();
playerCam.setPlaneState(0);
Camera.FrustumIntersect result = playerCam.contains(bv);
playerCam.setPlaneState(planeState);
return result == Camera.FrustumIntersect.Inside;[/java]
1 Like

The current method is good, but does anyone know how to check if the Spatial is being culled?

@ollie said:
The current method is good, but does anyone know how to check if the Spatial is being culled?


When do you want to check it and why? The best you'd be able to do is detect it for the previous frame since culling happens post-update.
@pspeed said:
When do you want to check it and why? The best you'd be able to do is detect it for the previous frame since culling happens post-update.

I'm not fussed about that degree of accuracy so checking the previous frame would work fine. The reason I need to check it is because the Spatial I am detecting will be detected even if it is behind an obstacle which I don't want to happen. It should only be detected if the player can directly see it, so combining the method above with checking if it is culled should work great.

If the camera doesn’t cull it, it woun’t be culled… and you’re already making that check. That is unless you have some weird alternative culling mode, in which case you have to check the culling mode of the actual object.



Being hidden doesn’t automatically cull the object. It’s still gonna be rendered, only none of its pixels will be put into the frame buffer.



If you want to test if a player can see something, for example, I think you’d have to do a ray-cast and check manually if there are objects in the way, then perhaps do a bounding volume check or something on each object, with perspective taken into account. Lots of work.

1 Like
@androlo said:
If the camera doesn't cull it, it woun't be culled.. and you're already making that check. That is unless you have some weird alternative culling mode, in which case you have to check the culling mode of the actual object.

Being hidden doesn't automatically cull the object. It's still gonna be rendered, only none of its pixels will be put into the frame buffer.

If you want to test if a player can see something, for example, I think you'd have to do a ray-cast and check manually if there are objects in the way, then perhaps do a bounding volume check or something on each object, with perspective taken into account. Lots of work.

Oh I see, thanks for the advice :)

There are a range of methods which all depend on how accurate you need to be vs how much time you want the computer to spend working this out.



At its simplest you send one ray from the camera to the object, next step up would be using multiple rays (for example to the 4 corners of the object + the center) etc. You then run into complications about the difference between the bounding box and the actual shape as well…



I guess at its most complex you could hijack the rendering process and record what object is associated with each pixel into a texture or similar. That would be a lot of complication in the code and potentially a big drain on frame rate though.

1 Like
@zarch said:
There are a range of methods which all depend on how accurate you need to be vs how much time you want the computer to spend working this out.

At its simplest you send one ray from the camera to the object, next step up would be using multiple rays (for example to the 4 corners of the object + the center) etc. You then run into complications about the difference between the bounding box and the actual shape as well...

I guess at its most complex you could hijack the rendering process and record what object is associated with each pixel into a texture or similar. That would be a lot of complication in the code and potentially a big drain on frame rate though.


Thanks for the suggestion, but I don't plan to go that deep into making this work. It's the kind of thing that I will just have to figure out another method for. Having said that, I have just thought of one: I could cast a Ray from the Spatial to your location and just see if anything gets in the way.

That was my “at the simplest” suggestion above :slight_smile:



It does mean that your view could be “blocked” by even very tiny things if they happened to be at just the right place.