09. november 2001 - 21:07
Der er
7 kommentarer
Skæring mellem trekant og frustum
Hvordan tjeker jeg at en trekant ligger delvis inden mit view-frustum?
Jeg har en funktion somm får fat i frustum (ExtractFrustum()) fra opengl, og en funktion som checker om et punkt er i frustum (PointInFrustum(x,y,z)).
Hvordan checker jeg at blot noget af trekanten med hjørnerne A,B,C ligger indenfor frustum (så den skal tegnes)??
10. november 2001 - 16:40
#1
Kender du en funktion som kan fortælle mig om en trekant bliver vist eller ej... Jeg mener når man anvender gl_cull_face og eksempelvis glcullface(gl_front), hvordan kan jeg så få at vide om en trekant bliver renderet eller ej... håber du forstår, hvad jeg mener (Jeg vil gerne give dig points)...
12. november 2001 - 10:12
#6
Følgende kode anvender DirectX, men jeg er sikker på der findes ekvivalente funktioner i OpenGL...
Her tjekkes ikke på hver enkelt 3-kant, men på en bounding box. Det kan være du kan bruge det til noget.
How it works, every frame I get the D3DVIEWPORT in my HeartBeat function
of my camera and store it. If I want to check if a BoundingBox is onscreen
or not, I just use my function
BoundingBoxIntersectsFrustum(D3DXVECTOR3 pMin, D3DXVECTOR3) which returns
true if partially or inside the view frustum, or false if totally
outside. I hope this helps people like it did ME!
enum POINTLOC
{
LEFT,
RIGHT,
ABOVE,
BELOW,
BACK,
FRONT,
INSIDE
};
D3DVIEWPORT8 vp;
D3DXMATRIX view, proj, world;
POINTLOC PointToScreen(D3DXVECTOR3 Point3D);
void CCamera::HeartBeat()
{
GetViewport(&vp);
GetTransform(D3DTS_VIEW, &view);
GetTransform(D3DTS_PROJECTION, &proj);
GetTransform(D3DTS_WORLD, &world);
}
POINTLOC CCamera::PointToScreen(D3DXVECTOR3 Point3D)
{
D3DXVECTOR3 Out;
D3DXVec3Project((D3DXVECTOR3*)&Out, &Point3D, &vp, &proj, &view, &world);
if (Out.x < vp.X) return LEFT;
if (Out.y < vp.Y) return ABOVE;
if (Out.x > vp.Width) return RIGHT;
if (Out.y > vp.Height) return BELOW;
if (Out.z < vp.MinZ) return FRONT;
if (Out.z > vp.MaxZ) return BACK;
else return INSIDE;
}
bool CCamera::BoundingBoxIntersectsFrustum(D3DXVECTOR3 pMin, D3DXVECTOR3
pMax)
{
POINTLOC results[8];
// Check Front Top Left
results[0] = PointToScreen(D3DXVECTOR3(pMin.x, pMin.y, pMin.z));
// Check Front Top Right
results[1] = PointToScreen(D3DXVECTOR3(pMax.x, pMin.y, pMin.z));
// Check Front Bottom Left
results[2] = PointToScreen(D3DXVECTOR3(pMin.x, pMax.y, pMin.z));
// Check From Bottom Right
results[3] = PointToScreen(D3DXVECTOR3(pMax.x, pMax.y, pMin.z));
// Check the BACK of the box now
// Check Back Top Left
results[4] = PointToScreen(D3DXVECTOR3(pMin.x, pMin.y, pMax.z));
// Check Back Top Right
results[5] = PointToScreen(D3DXVECTOR3(pMax.x, pMin.y, pMax.z));
// Check Back Bottom Left
results[6] = PointToScreen(D3DXVECTOR3(pMin.x, pMax.y, pMax.z));
// Check Back Bottom Right
results[7] = PointToScreen(D3DXVECTOR3(pMax.x, pMax.y, pMax.z));
// Check if ALL points are visible, if so, this makes it REAL easy
int Encounted = 0;
// Handle the Easiest first, any indea and draw the Bounding Box
for (int i = 0; i < 8; i++)
{
if (results[i] == INSIDE) return true;
}
// Check if everything is to the right of the screen
for (i = 0; i < 8; i++)
{
if (results[i] == RIGHT) Encounted++;
}
if (Encounted == 8) return false;
// Check if everything is to the left of the screen
Encounted = 0;
for (i = 0; i < 8; i++)
{
if (results[i] == LEFT) Encounted++;
}
if (Encounted == 8) return false;
// Check if everything is to the top of the screen
Encounted = 0;
for (i = 0; i < 8; i++)
{
if (results[i] == ABOVE) Encounted++;
}
if (Encounted == 8) return false;
// Check if everything is BELOW the screen
Encounted = 0;
for (i = 0; i < 8; i++)
{
if (results[i] == BELOW) Encounted++;
}
if (Encounted == 8) return false;
// Check if everything is BEHIND the screen
Encounted = 0;
for (i = 0; i < 8; i++)
{
if (results[i] == BACK) Encounted++;
}
if (Encounted == 8) return false;
// Check if everything is BEYOND the screen
Encounted = 0;
for (i = 0; i < 8; i++)
{
if (results[i] == FRONT) Encounted++;
}
if (Encounted == 8) return false;
return true;
}