Jump to content

[SOLVED] Detect if a vertex or mesh is visible for camera


photo

Recommended Posts

Hello,

 

We are setting up a system to automate taking screenshots of certain meshes of varying sizes. The images should have all images roughly the same size so we need to zoom the camera in or out depending on how the mesh fits into the viewport. So we need to check if all parts of the mesh are visible within the viewport or within an arbitrary x/y rect inside the viewport.

 

What is the best way to do this? We don't see any obvious functions for getting the screenspace coordinates of a vertex or a mesh, do they exist? Our other ideas all involve complex and expensive math checks so please advise!

 

Thanks,

Taylor

Link to comment

Hi Taylor,

 

If you just need to know, if node is inside camera's viewing frustum, use the following method:

- create BoundFrustum (or WorldboundFrustum) class, using player's projection and modelview

- check if your node is inside it by calling BoundFrustum::inside with node's boundBox or boundSphere.

Link to comment

Hi Maxi,

 

Thanks for the response, unfortunately BoundFrustum::inside is always returning 1, no matter where the node/boundbox is (say, above the camera/frustum). I can upload a sample project if necessary but here is the full script I am using...

 

 

#include <core/unigine.h>

 
PlayerDummy cam;
BoundFrustum frust;
 
Node nod;
BoundBox bbox;
 
int init() 
{
Node camNode = engine.editor.getNodeByName("camPos");
cam = new PlayerDummy();
cam.setTransform(camNode.getTransform());
engine.game.setPlayer(cam);
 
mat4 proj = mat4(cam.getProjection());
mat4 mview = mat4(cam.getModelview());
frust = new BoundFrustum(proj, mview);
 
 
nod = engine.editor.getNodeByName("cube");
bbox = nod.getBoundBox();
 
return 1;
}
 
int shutdown() 
{
return 1;
}
 
int update() 
{
int result = frust.inside(bbox);
log.message("result is " + result + "\n");
 
return 1;
}

 

In the scene, I have the camNode position at (0,0,5) and "cube" at (10,10,10) and inside and insideAll still return 1.

 

As an aside, I tried using WorldboundFrustum but got an error that WorldboundFrustum::inside does not take a BoundBox argument

Link to comment

You are right, use WorldBoundFrustum and WorldBoundBox:

mat4 proj = cam.getProjection();
mat4 mview = cam.getModelview();
WorldBoundFrustum frust = new WorldBoundFrustum(proj, mview);

int result = frust.inside(nod.getWorldBoundBox());
Link to comment

Hi Maxi,

 

Thanks for the correction, that helped us get further with this issue. Unfortunately we've found that neither BoundBox or BoundSphere are much of a help in getting the mesh to take up as much of the screen as possible. So we have switched to detecting if all the vertices of the mesh are on screen. 

 

We ran into some problem with the models we have tried, where the number of vertices on-screen is still rising while the entire model is clearly visible on screen. I've created a sample project contrasting one of our meshes with a primitive. Here's a gif of what happens:

 

 

post-1631-0-74002900-1454364625_thumb.gif

Link to comment

OK, I've uploaded the scene to the ftp. The expected behavior is that the count of vertices on screen (displayed text) will reach its limit when the mesh is fully visible (this also stops the camera from moving) but it keeps counting up for some time after the mesh is fully visible.

Link to comment

Hello, have you found anything with the test scene? This is a very important feature for us right now and we can't proceed until we have a solution to get a "best fit" for the mesh on screen

Link to comment
  • 2 weeks later...

Hi Taylor,

 

Sorry for the late reply.

 

How do you think, is it possible that width and height for your screenshots might be equal (1024x1024 px for example)?

 

If you will set following engine start-up parameters for your test project:

-video_mode -1 -video_width 1024 -video_height 1024

camera will stop exactly when full model become visible. With that startup arguments you can see how the WorldBoundFrustom detects objects.

 

You also can get non-squared screenshot. For that you need to pass corrected projection matrix (multiplied to inverse screen aspect or divided by screen aspect). In your code where you set the projections:

dmat4 proj = cam.getProjection();

//aspect correction
width = engine.app.getWidth();
height = engine.app.getHeight();
proj.m00 /= width / height;
//end of aspect correction

dmat4 mview = cam.getModelview();
frust = new WorldBoundFrustum(proj, mview);

Thanks!

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to comment
×
×
  • Create New...