Determining Object visibility quick and dirty

Started by
18 comments, last by jaymz 23 years, 10 months ago
Just running some ideas through the grinder... Any comments on if this would work or not? Say you have a fixed FOV in your engine and its 90 deg. Knowing this, wouldn''t it be easy to quickly determine if a object is in the FOV by creating a triangle with the 90 deg angle point at 0,0,0, then transforming that triangle by the view matrix (to get the proper camera position and viewing angle) and then doing a simple point/poly test to see if the center point of the object is inside the triangle? I know the center point test is not very accurate, but this is a quick and dirty test after all Keep in mind I am only thinking about this in 2d BTW, on the x and z plane, I''m not really worried about the y value.. (thinking of how this would work for terrain "patch" visibility testing)
Advertisement
You are almost right.

Create the triangle and transform it with the inverse of the view matrix (ie. the camera''s world matrix) to put it in world coordinates. Then check if your objects are inside the triangle. You shouldn''t do a single point in triangle test instead do a bounding sphere in triangle test. This will be just as fast as what you were thinking yet more accurate because if the sphere isn''t visible then nothing inside it is either.

- WitchLord

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

WitchLord, so you are working for gamedev already?
Ok, so basically, transform each point of the triangle by the inverse of the view matrix, this gives you a triangle thats lined up with the fov on the x,z plane, thats not hard. Now to determine if a point is inside this triangle or not. What steps would need to be taken to convert line segments into planes? (I''m thinking the test would be a 3 step process, by testing the point against each side of the 3 planes to see if its negitive or positive to determine if its inbetween all 3 planes or not)

If I''m making this problem harder than it needs to be PLEASE enlighten me

BTW thanks for all the help WitchLord, for this post and the others you answered for me. I will try the bounding sphere test after I make sure the simple point test works fine.. I''m not very good at collision detection at all and want to build up my skills.
Im not sure if this is faster or not, but I just check the angle of a ray from the camera to the patches center against the ZAxis, if its greater then your FOV/2 then its outside the view frustum.
Well, I tried that.. but I''m not seeing something because it doesnt work.. heres the code snip:


D3DXMATRIX matrix;
D3DXVECTOR3 view, point;
float angle;

// Get patch''s center point
int patchCenterX = m_WorldX + PATCH_SIZE / 2;
int patchCenterY = m_WorldY + PATCH_SIZE / 2;
m_lpd3ddev->GetTransform(D3DTS_VIEW, &matrix);

view.x=matrix._13;
view.y=matrix._23;
view.z=matrix._33;

point.x=patchCenterX;
point.y=0;
point.z=patchCenterY;

angle=D3DXVec3Dot(&view, &point);

if(abs(angle)>DEG2RAD(45)) m_isVisible=0;

else m_isVisible=1;



any ideas?
Ok, hmm.

1. You create two vectors, view and point.

View is created by taking the ZAxis.
Point is created by Point.x = PatchCenterX - matrix._41, Point.z = PatchCenterZ - matrix._43.

2. Find the angle between them.

If D3DXVec3Dot doesn''t normalize the vectors you''ll need to before you pass it to it.

3. If its greater then 45 degrees its outside of the view.



Another thing that is probably messing it up is the View matrix, which represents the opposite of what you would expect the camera to be. So if you had the Z axis pointing 45 degrees to the right the view matrix is going to have it pointing 45 degrees to the left, which will mess up your calculations.

What I did was create a camera class that stores all the info about where it is pointed and what not, then every frame before I render the camera takes its position, say 3,4,5, and rotation, and reverses everything, and creates the view matrix. Then for functions like this I use the values stored in the camera class.
Grr.. still having some issues... every "patch" is drawn still, even if its outside the angle.. I will try to detail the code.
Here is the guts of the function after a few fixes:


D3DXMATRIX matrix;
D3DXVECTOR3 view, point;
float angle;

// Get patch''s center point
int patchCenterX = m_WorldX + PATCH_SIZE / 2;
int patchCenterY = m_WorldY + PATCH_SIZE / 2;
m_lpd3ddev->GetTransform(D3DTS_VIEW, &matrix);

D3DXMatrixInverse(&matrix, NULL, &matrix);

view.x=matrix._13;
view.y=matrix._23;
view.z=matrix._33;

point.x=patchCenterX;
point.y=0;
point.z=patchCenterY;

D3DXVec3Normalize(&view, &view);
D3DXVec3Normalize(&point, &point);

angle=D3DXVec3Dot(&view, &point);

if(abs(angle)>DEG2RAD(45)) m_isVisible=0;

else m_isVisible=1;


Each patch is a square of the size PATCH_SIZExPATCH_SIZE on the x and z plane. This code is called 1 time per frame by each patch to determine if this patch needs to be computed or not. m_worldX and m_worldY are member variables of the patch class. These variables tell the patch where it starts from in world coords on the x and z plane. m_isVisible is just a flag that determines if this patch is visible or not. Basically the test point is in the center of the patch. The problem is NO patchs are being set to m_Visible=0... I can even set the angle to 5 and all of the patches are still drawn... my eyes refuse to see an error in the above code at this point HELP!
If you are already using D3D, just use ComputeSphereVisibility().
I think changing:

point.x=patchCenterX;
point.y=0;
point.z=patchCenterY;


To

point.x=patchCenterX - view.x;
point.y = 0;
point.z = patchCenterZ - view.z;

should work.

And if you want to speed it up somemore you can store the value for the center of each patch and save yourself the 2 additions and 2 divides per patch per frame, which comes to like 500 additions and 500 divides per frame depending on how many patches you have.

This topic is closed to new replies.

Advertisement