PDA

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&#40;_c &#58; t_Vec;
_r &#58; single;
_f &#58; tFrustum&#41;&#58; 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 &#58; longint;
_d &#58; single;

begin
for _i &#58;= 0 to 5 do
begin
_d &#58;= _f&#91;_i&#93;.a * _c&#91;0&#93; + _f&#91;_i&#93;.b * _c&#91;1&#93; + _f&#91;_i&#93;.c * _c&#91;2&#93; + _f&#91;_i&#93;.d;
if &#40;_d <= -_r&#41; then
begin
Result &#58;= 0;
exit;
end;
end;
Result &#58;= _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