View Full Version : Frustum culling
NecroDOME
03-10-2005, 06:26 PM
Hi there,
im working on furstum culling at the moment but i'm a little stuck with some tutorials... :(
hope anyone can help me...
i'm trying to check if a sphere is inide my frustum.
the problem is here: Distance := NormalizePlane(i, Center) )+m_plane[i].Distance(); <-- How can I get the distacne of the plane? (i got it from a tutorial, (C++ code:P)
function TFrustrum.ContainsSphere(Center: TD3DVector;
Radius: single): boolean;
var Distance : single; // various distances
i : integer;
begin
// calculate our distances to each of the planes
for i := 0 to 5 do
begin
// find the distance to this plane
Distance := NormalizePlane(i, Center) )+m_plane[i].Distance();
// if this distance is < -sphere.radius, we are outside
if Distance < -Radius then
begin
Result := FRUSTRUM_OUT;
Exit;
end else
if Abs(Distance) < Radius then
begin
Result := FRUSTRUM_INTERSECT;
Exit;
end;
end;
// otherwise we are fully in view
result := FRUSTRUM_IN;
end;
the next step is the bounding box, but that souldn't be a prob when I got this working...
Thnxz in advance!!
tutorials:
http://www.flipcode.com/articles/article_frustumculling.shtml
http://www.gamedev.net/community/forums/topic.asp?topic_id=212876&forum_id=11&gforum_id=
http://p214.ezboard.com/fmrgamemakerfrm0.showMessage?topicID=3801.topic
JSoftware
03-10-2005, 06:38 PM
ax+by+cz+d=0
(a,b,c) is the vector of the point you want to get the distance from the plane from
(x,y,z) is the normal of the plane
and d is the distance
distance := -(plane.normal.x*SUBEDcenter.x+plane.normal.y*SUBED center.y+plane.normal.z*SUBEDcenter.z);
where subedcenter is the center - position of plane
NecroDOME
03-10-2005, 07:02 PM
im using TD3DXPlane
TD3DXPlane = record
a,b,c,d : single;
end;
this I use to extract the planes from the matrices
procedure TCamera.ExtractPlanes;
var Mat : TD3DMatrix;
vecFrustum : array [0..7] of TD3DVector;
i : integer;
begin
D3DXMatrixMultiply( Mat, MatView, MatProj );
D3DXMatrixInverse( Mat, nil, Mat );
vecFrustum[0] := MakeD3DVector(-1.0, -1.0, 0.0); // xyz
vecFrustum[1] := MakeD3DVector( 1.0, -1.0, 0.0); // Xyz
vecFrustum[2] := MakeD3DVector(-1.0, 1.0, 0.0); // xYz
vecFrustum[3] := MakeD3DVector( 1.0, 1.0, 0.0); // XYz
vecFrustum[4] := MakeD3DVector(-1.0, -1.0, 1.0); // xyZ
vecFrustum[5] := MakeD3DVector( 1.0, -1.0, 1.0); // XyZ
vecFrustum[6] := MakeD3DVector(-1.0, 1.0, 1.0); // xYZ
vecFrustum[7] := MakeD3DVector( 1.0, 1.0, 1.0); // XYZ
for i := 0 to 8 do
D3DXVec3TransformCoord( vecFrustum[i], vecFrustum[i], mat );
D3DXPlaneFromPoints( Frustrum.Planes[0], vecFrustum[0],vecFrustum[1],vecFrustum[2] ); // Near
D3DXPlaneFromPoints( Frustrum.Planes[1], vecFrustum[6],vecFrustum[7],vecFrustum[5] ); // Far
D3DXPlaneFromPoints( Frustrum.Planes[2], vecFrustum[2],vecFrustum[6],vecFrustum[4] ); // Left
D3DXPlaneFromPoints( Frustrum.Planes[3], vecFrustum[7],vecFrustum[3],vecFrustum[5] ); // Right
D3DXPlaneFromPoints( Frustrum.Planes[4], vecFrustum[2],vecFrustum[3],vecFrustum[6] ); // Top
D3DXPlaneFromPoints( Frustrum.Planes[5], vecFrustum[1],vecFrustum[0],vecFrustum[4] ); // Bottom
end;
I don't realy understand the code cause there are no vectors, only singles that point to some coordinats...
JSoftware
03-10-2005, 07:06 PM
plane.normal.x in my code is essentially just a in your td3dplane
NecroDOME
03-10-2005, 08:21 PM
Sorry, but it's not working for me :(
i tried:
D3DXPlaneDotCoord
D3DXPlaneDotNormal (is somehow the same as your code)
My current code:
function TNecro3D_Frustrum.ContainsSphere(Center: TD3DVector;
Radius: single): integer;
var Distance : single; // various distances
i : integer;
begin
// calculate our distances to each of the planes
for i := 0 to 5 do
begin
// find the distance to this plane
// Distance := -D3DXPlaneDotCoord(Planes[i], Center);
Distance := -(Planes[i].a*Center.x+Planes[i].b*Center.y+Planes[i].c*Center.z);
// if this distance is < -sphere.radius, we are outside
if Distance < -Radius then
begin
Result := FRUSTRUM_OUT;
Exit;
end else
if Abs(Distance) < Radius then
begin
Result := FRUSTRUM_INTERSECT;
Exit;
end;
end;
// otherwise we are fully in view
result := FRUSTRUM_IN;
end;
I think the problem is in the D3DXPlane, but i'm not sure...
JSoftware
03-10-2005, 08:32 PM
well i can't remember it any more.. :P
i'm just using the class on this page http://www.delphigl.de/tutorials/frustumcull_de.html
NecroDOME
03-10-2005, 08:38 PM
thnxz i'll try it tomorrow :)
NecroDOME
06-10-2005, 09:54 PM
I think i'm missing something cause it's not working...
function TFrustrum.ContainsPoint(Pos: TD3DVector): boolean; always returns false :(
// Camera position and rotation
D3DXQuaternionRotationYawPitchRoll(Quat, Rotation.x, Rotation.y, Rotation.z);
D3DXMatrixRotationQuaternion( matRot, Quat );
D3DXMatrixTranslation(matPos, Position.X, Position.Y, Position.Z);
D3DXMatrixMultiply(matView, matRot, matPos);
D3DXMatrixInverse( matView, nil, matView );
Screen.Device.SetTransform(D3DTS_VIEW, matView);
// Projection matrix...
D3DXMatrixPerspectiveFovLH( matProj, DegToRad(FOV), Width / Height, NearViewPlane, FarViewPlane);
Screen.Device.SetTransform( D3DTS_PROJECTION, matProj );
matView and matProj are used in the following code:
// mat : TD3DMatrix;
Mat := mView;
D3DXMatrixMultiply( Mat, Mat, mProjection );
D3DXMatrixInverse( Mat, nil, Mat );
Frustrum.SetPlaneCoefficients(FRUSTRUM_LEFT, Mat._14+Mat._11,
Mat._24+Mat._21,
Mat._34+Mat._31,
Mat._44+Mat._41);
Frustrum.SetPlaneCoefficients(FRUSTRUM_RIGHT, Mat._14-Mat._11,
Mat._24-Mat._21,
Mat._34-Mat._31,
Mat._44-Mat._41);
Frustrum.SetPlaneCoefficients(FRUSTRUM_BOTTOM,Mat. _14+Mat._12,
Mat._24+Mat._22,
Mat._34+Mat._32,
Mat._44+Mat._42);
Frustrum.SetPlaneCoefficients(FRUSTRUM_TOP, Mat._14-Mat._12,
Mat._24-Mat._22,
Mat._34-Mat._32,
Mat._44-Mat._42);
Frustrum.SetPlaneCoefficients(FRUSTRUM_BACK, Mat._13,
Mat._23,
Mat._33,
Mat._43);
Frustrum.SetPlaneCoefficients(FRUSTRUM_FRONT, Mat._14-Mat._13,
Mat._24-Mat._23,
Mat._34-Mat._33,
Mat._44-Mat._43);
procedure TFrustrum.SetPlaneCoefficients(Index: integer; a, b, c,
d: single);
var Mag : single;
begin
Mag := Sqrt((a*a)+(b*b)+(c*c));
// Mag := Sqrt( Sqrt(a)+ Sqrt(b)+ Sqrt(c) );
Planes[Index].a := a/Mag;
Planes[Index].b := b/Mag;
Planes[Index].c := c/Mag;
Planes[Index].d := d/Mag;
// Log(FloatToStr(Mag));
end;
function TFrustrum.ContainsPoint(Pos: TD3DVector): boolean;
var i : Integer;
begin
Result := True;
for i := 0 to 5 do
with Planes[i] do
if (a*Pos.X + b*Pos.Y + c*Pos.Z + d) <= 0 then
begin
Result := False;
exit;
end;
Log('IN !!');
end;
tpascal
08-10-2005, 05:35 PM
Hi,
i am also doing a game engine using pascal + directx.
This is my code for checking if sphere is inside frustum:
function FexDX_frustumSphereInside(_c : t_Vec;
_r : single;
_f : tFrustum): single;
// _c - sphere's center
// _r - sphere's radius
// Returns 0 if it's not inside or
// the distance to the NEAR plane if it's inside.
var _i : longint;
_d : single;
begin
for _i := 0 to 5 do
begin
_d := _f[_i].a * _c[0] + _f[_i].b * _c[1] + _f[_i].c * _c[2] + _f[_i].d;
if (_d <= -_r) then
begin
Result := 0;
exit;
end;
end;
Result := _d + _r;
end;
Please revise your FRUSTUM_BACK plane extraction, mine its different:
// Extract the NEAR plane
Result[5].a := _clip._14 + _clip._13;
Result[5].b := _clip._24 + _clip._23;
Result[5].c := _clip._34 + _clip._33;
Result[5].d := _clip._44 + _clip._43;
Nice to see someone coding a pascal engine using directx, i dont known why the norm here is using opengl.
I have 5 months on in now and there is a lot things to code yet, :cry:
tp.
NecroDOME
08-10-2005, 05:45 PM
Indeed nice to see someone coding a 3D engine in DirectX too :D:D
Thnxz for your respond and welcome to PGD :P
I'll grab myself a beer, so I'll try it tomorrow... (maybe tonight when i'm drunk :shock: )
Cheers
NecroDOME
09-10-2005, 09:59 PM
Well.... it works a little better, but i'll still got a some problems. Thanx
NecroDOME
12-10-2005, 08:40 AM
EDIT:
Finnaly I'v got it working :D:D:D
I removed D3DXMatrixInverse( Mat, nil, Mat );
Thnxz guys :D:D
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.