Determine whenever box is visible in frustum

Started by
10 comments, last by _WeirdCat_ 8 years, 2 months ago

Is this for graphics (e.g. culling) or for physics (e.g. collision)?

How are you storing the frustum and the box in the memory? Is the box an AABB or an OBB?

Do you need only an intersection test, or you do need information such as the intersection points?

For intersection tests with convexes one approach is to use GJK as Randy mentioned and check if the distance is zero, or you can use SAT to find a separating axis. You could use a generic SAT I guess. If you only need a simple test such as in your example I would query for a separating axis only with the *faces* of the frustum and the *faces* of the box (e.g. skipping edge-edge tests). This would be really handfull if you're storing the frustum as a plane set. For the box, just build the planes using the canonical axes.

Off-topic Note: If you plan to use GJK, don't use Casey Muratori's video as an implementation basis. In his examples there are situations in which skipping certain voronoi regions might fail. In addition, you would be checking if you're really getting close to the origin also for adding reliability (I think Erin doesn't do that in the source code Randy sent.). I would recommend reading Box2D b2Distance.cpp for more info on that.

Hope that helps.

Advertisement

im using first suggestion to test if all points are outside of one frustum plane.

liek that (didint check it though)

[spoiler]


#ifndef frustumH
#define frustumH
#include "DxcMath.h"
#include "DxcMatrix.h"


const int F_LEFT 	= 0;
const int F_RIGHT 	= 1;
const int F_TOP 	= 2;
const int F_BOTTOM 	= 3;
const int F_NEAR 	= 4;
const int F_FAR 	= 5;

struct TFrustumPlane
{
	vec3  n;
	float d;
};

struct TFrustum
{
TFrustumPlane F[6];

void CalcFrustum(TSpecCamera * FPP_CAM, mat4 CAM_VIEW, int sw, int sh, float fovy, float z_near, float z_far, float aspect)
{
mat4 CAM_MODEL;
mat4 mvm =  CAM_MODEL * CAM_VIEW;
mvm.Transpose();
vec3 dirX, dirY;
	dirX.x = mvm.m[0];
	dirX.y = mvm.m[4];
	dirX.z = mvm.m[8];

	dirY.x =	mvm.m[1];
	dirY.y =	mvm.m[5];
	dirY.z =	mvm.m[9];


	float a = fovy / 2.0;
float cotangent = 1.0 / tan( a * imopi );

float ax = z_near / cotangent;

float screen_w = 2.0*ax;

float screen_h = screen_w;

screen_w = screen_w * aspect;


vec3 dir = FPP_CAM->ReturnFrontVector();

//move to lower left corner
vec3 A = FPP_CAM->pos;


vec3 NEAR_BOTTOM_LEFT  = (FPP_CAM->pos + dir * z_near) + (-dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));
vec3 NEAR_BOTTOM_RIGHT = (FPP_CAM->pos + dir * z_near) + (dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));
vec3 NEAR_TOP_LEFT  = (FPP_CAM->pos + dir * z_near) + (-dirX * (screen_w / 2.0)) + (dirY * (screen_h/2.0));
vec3 NEAR_TOP_RIGHT = (FPP_CAM->pos + dir * z_near) + (dirX * (screen_w / 2.0)) + (dirY * (screen_h/2.0));



ax = z_far / cotangent;
screen_w = 2.0*ax;
screen_h = screen_w;
screen_w = screen_w * aspect;


vec3 FAR_BOTTOM_LEFT  = (FPP_CAM->pos + dir * z_far) + (-dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));
vec3 FAR_BOTTOM_RIGHT = (FPP_CAM->pos + dir * z_far) + (dirX * (screen_w / 2.0)) + (-dirY * (screen_h/2.0));
vec3 FAR_TOP_LEFT  = (FPP_CAM->pos + dir * z_far) + (-dirX * (screen_w / 2.0)) + (dirY * (screen_h/2.0));
vec3 FAR_TOP_RIGHT = (FPP_CAM->pos + dir * z_far) + (dirX * (screen_w / 2.0)) + (dirY * (screen_h/2.0));

F[F_LEFT].n 	= Normal(A, FAR_BOTTOM_LEFT, FAR_TOP_LEFT, true);
F[F_RIGHT].n 	= Normal(A, FAR_BOTTOM_RIGHT, FAR_TOP_RIGHT, true);

F[F_TOP].n 		= Normal(A, FAR_TOP_LEFT, FAR_TOP_RIGHT, true);
F[F_BOTTOM].n 	= Normal(A, FAR_BOTTOM_LEFT, FAR_BOTTOM_RIGHT, true);

F[F_NEAR].n 	= Normal(NEAR_BOTTOM_LEFT, NEAR_TOP_LEFT, NEAR_TOP_RIGHT, true);
F[F_FAR].n 		= Normal(FAR_BOTTOM_LEFT, FAR_TOP_LEFT, FAR_TOP_RIGHT, true);

F[F_LEFT].d 	= getplaneD(F[F_LEFT].n, A);
F[F_RIGHT].n 	= getplaneD(F[F_RIGHT].n, A);

F[F_TOP].n 		= getplaneD(F[F_TOP].n, A);
F[F_BOTTOM].n 	= getplaneD(F[F_BOTTOM].n, A);

F[F_NEAR].n 	= getplaneD(F[F_NEAR].n, NEAR_BOTTOM_LEFT);
F[F_FAR].n 		= getplaneD(F[F_FAR].n, FAR_BOTTOM_LEFT);

vec3 cp = A + dir * (z_far / 2.0);

for (int i=0; i < 4; i++)
if (classifyapointagainstaplane(cp, F[i].n, F[i].d) != isBack)
{
F[i].n = -F[i].n;
F[i].d = getplaneD(F[i].n, A);
}


if (classifyapointagainstaplane(cp, F[F_NEAR].n, F[F_NEAR].d) != isBack)
{
F[F_NEAR].n = -F[F_NEAR].n;
F[F_NEAR].d = getplaneD(F[F_NEAR].n, NEAR_BOTTOM_LEFT);
}

if (classifyapointagainstaplane(cp, F[F_FAR].n, F[F_FAR].d) != isBack)
{
F[F_FAR].n = -F[F_FAR].n;
F[F_FAR].d = getplaneD(F[F_FAR].n, FAR_BOTTOM_LEFT);
}


}



bool BoxIsVisible(vec3 * verts, int len)
{
for (int i=0; i < 6; i++) //through all frustum planes, check if all points are outside that plane if yes then its invisible
{
	bool all_one_side = true;

for (int j=0; j < len; j++)
if ( classifyapointagainstaplane(verts[j], F[i].n, F[i].d) != isFront ) {all_one_side = false; break; }

if (all_one_side) return false;
}

return true;
}

};

#endif
 

[/spoiler]

This topic is closed to new replies.

Advertisement