|
@@ -1,7 +1,6 @@
|
|
//
|
|
//
|
|
// The graphics rendering engine GLScene http://glscene.org
|
|
// The graphics rendering engine GLScene http://glscene.org
|
|
//
|
|
//
|
|
-
|
|
|
|
unit GLS.SpacePartition;
|
|
unit GLS.SpacePartition;
|
|
|
|
|
|
(*
|
|
(*
|
|
@@ -58,7 +57,7 @@ type
|
|
TBaseSpacePartition = class;
|
|
TBaseSpacePartition = class;
|
|
|
|
|
|
// Describes a cone, and is used for cone collision
|
|
// Describes a cone, and is used for cone collision
|
|
- TSPCone = record
|
|
|
|
|
|
+ TGLConeSP = record
|
|
// The base of the cone
|
|
// The base of the cone
|
|
Base: TAffineVector;
|
|
Base: TAffineVector;
|
|
// The axis of the cone
|
|
// The axis of the cone
|
|
@@ -70,7 +69,7 @@ type
|
|
end;
|
|
end;
|
|
|
|
|
|
// Extended frustum, used for fast intersection testing
|
|
// Extended frustum, used for fast intersection testing
|
|
- TExtendedFrustum = record
|
|
|
|
|
|
+ TGLExtendedFrustum = record
|
|
Frustum: TFrustum;
|
|
Frustum: TFrustum;
|
|
BSphere: TBSphere;
|
|
BSphere: TBSphere;
|
|
// SPCone : TSPCone;
|
|
// SPCone : TSPCone;
|
|
@@ -126,7 +125,7 @@ type
|
|
private
|
|
private
|
|
FCullingMode: TCullingMode;
|
|
FCullingMode: TCullingMode;
|
|
// Query space for Leaves that intersect a cone, result is returned through QueryResult
|
|
// Query space for Leaves that intersect a cone, result is returned through QueryResult
|
|
- function QueryCone(const ACone: TSPCone): Integer; virtual;
|
|
|
|
|
|
+ function QueryCone(const ACone: TGLConeSP): Integer; virtual;
|
|
protected
|
|
protected
|
|
FQueryResult: TSpacePartitionLeafList;
|
|
FQueryResult: TSpacePartitionLeafList;
|
|
FQueryInterObjectTests: Integer;
|
|
FQueryInterObjectTests: Integer;
|
|
@@ -163,7 +162,7 @@ type
|
|
(* Query space for Leaves that intersect an extended frustum. Result is
|
|
(* Query space for Leaves that intersect an extended frustum. Result is
|
|
returned through QueryResult. Extended frustum is slightly faster than the
|
|
returned through QueryResult. Extended frustum is slightly faster than the
|
|
regular frustum because it uses a bounding sphere for the frustum *)
|
|
regular frustum because it uses a bounding sphere for the frustum *)
|
|
- function QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum): Integer; virtual;
|
|
|
|
|
|
+ function QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum): Integer; virtual;
|
|
(* Once a query has been run, this number tells of how many inter object
|
|
(* Once a query has been run, this number tells of how many inter object
|
|
tests that were run. This value must be set by all that override the queries *)
|
|
tests that were run. This value must be set by all that override the queries *)
|
|
property QueryInterObjectTests: Integer read FQueryInterObjectTests;
|
|
property QueryInterObjectTests: Integer read FQueryInterObjectTests;
|
|
@@ -183,7 +182,7 @@ type
|
|
private
|
|
private
|
|
FLeaves: TSpacePartitionLeafList;
|
|
FLeaves: TSpacePartitionLeafList;
|
|
// Query space for Leaves that intersect a cone, result is returned through QueryResult
|
|
// Query space for Leaves that intersect a cone, result is returned through QueryResult
|
|
- function QueryCone(const ACone: TSPCone): Integer; override;
|
|
|
|
|
|
+ function QueryCone(const ACone: TGLConeSP): Integer; override;
|
|
public
|
|
public
|
|
// Clear all internal storage Leaves
|
|
// Clear all internal storage Leaves
|
|
procedure Clear; override;
|
|
procedure Clear; override;
|
|
@@ -305,7 +304,7 @@ type
|
|
// Query the node and its children for leaves that match the Frustum
|
|
// Query the node and its children for leaves that match the Frustum
|
|
procedure QueryFrustum(const Frustum: TFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
procedure QueryFrustum(const Frustum: TFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
// Query the node and its children for leaves that match the extended frustum
|
|
// Query the node and its children for leaves that match the extended frustum
|
|
- procedure QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
|
|
|
|
+ procedure QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
(* Adds all leaves to query result without testing if they intersect, and
|
|
(* Adds all leaves to query result without testing if they intersect, and
|
|
then do the same for all children. This is used when QueryAABB or
|
|
then do the same for all children. This is used when QueryAABB or
|
|
QueryBSphere determines that a node fits completely in the searched space *)
|
|
QueryBSphere determines that a node fits completely in the searched space *)
|
|
@@ -367,7 +366,7 @@ type
|
|
function QueryFrustum(const Frustum: TFrustum): Integer; override;
|
|
function QueryFrustum(const Frustum: TFrustum): Integer; override;
|
|
(* Query space for Leaves that intersect an extended frustum. Result is
|
|
(* Query space for Leaves that intersect an extended frustum. Result is
|
|
returned through QueryResult *)
|
|
returned through QueryResult *)
|
|
- function QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum): Integer; override;
|
|
|
|
|
|
+ function QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum): Integer; override;
|
|
(* After a query has been run, this value will contain the number of nodes
|
|
(* After a query has been run, this value will contain the number of nodes
|
|
that were checked during the query *)
|
|
that were checked during the query *)
|
|
property QueryNodeTests: Integer read FQueryNodeTests;
|
|
property QueryNodeTests: Integer read FQueryNodeTests;
|
|
@@ -479,10 +478,10 @@ procedure RenderSpatialPartitioning(var rci: TGLRenderContextInfo;
|
|
(*Create an extended frustum from a GLSceneViewer - this makes the unit
|
|
(*Create an extended frustum from a GLSceneViewer - this makes the unit
|
|
specific to the windows platform!*)
|
|
specific to the windows platform!*)
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
- const vWidth, vHeight: integer; AGLCamera: TGLCamera): TExtendedFrustum; overload;
|
|
|
|
|
|
+ const vWidth, vHeight: integer; AGLCamera: TGLCamera): TGLExtendedFrustum; overload;
|
|
|
|
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
- const AGLSceneViewer: TGLSceneViewer): TExtendedFrustum; overload;
|
|
|
|
|
|
+ const AGLSceneViewer: TGLSceneViewer): TGLExtendedFrustum; overload;
|
|
|
|
|
|
// Renders an AABB as a line
|
|
// Renders an AABB as a line
|
|
procedure RenderAABB(var rci: TGLRenderContextInfo; const AABB: TAABB; w, r, g, b: single); overload;
|
|
procedure RenderAABB(var rci: TGLRenderContextInfo; const AABB: TAABB; w, r, g, b: single); overload;
|
|
@@ -490,13 +489,13 @@ procedure RenderAABB(var rci: TGLRenderContextInfo; const AABB: TAABB); overload
|
|
|
|
|
|
|
|
|
|
// Determines to which extent one Cone contains an BSphere
|
|
// Determines to which extent one Cone contains an BSphere
|
|
-function ConeContainsBSphere(const Cone: TSPCone; const BSphere: TBSphere): TSpaceContains;
|
|
|
|
|
|
+function ConeContainsBSphere(const Cone: TGLConeSP; const BSphere: TBSphere): TSpaceContains;
|
|
// Determines if a extended frustum intersects an BSphere
|
|
// Determines if a extended frustum intersects an BSphere
|
|
-function ExtendedFrustumIntersectsBSphere(const AExtendedFrustum: TExtendedFrustum; const ABSphere: TBSphere): Boolean;
|
|
|
|
|
|
+function ExtendedFrustumIntersectsBSphere(const AExtendedFrustum: TGLExtendedFrustum; const ABSphere: TBSphere): Boolean;
|
|
// Create an extended frustum from a number of values
|
|
// Create an extended frustum from a number of values
|
|
function ExtendedFrustumMake(const AFrustum: TFrustum; const ANearDist, AFarDist, AFieldOfViewRadians: Single;
|
|
function ExtendedFrustumMake(const AFrustum: TFrustum; const ANearDist, AFarDist, AFieldOfViewRadians: Single;
|
|
const ACameraPosition, ALookVector: TAffineVector { ;
|
|
const ACameraPosition, ALookVector: TAffineVector { ;
|
|
- const AScreenWidth, AScreenHeight : integer { } ): TExtendedFrustum;
|
|
|
|
|
|
+ const AScreenWidth, AScreenHeight : integer { } ): TGLExtendedFrustum;
|
|
|
|
|
|
//---------------------------------------------------
|
|
//---------------------------------------------------
|
|
implementation
|
|
implementation
|
|
@@ -531,7 +530,7 @@ const
|
|
(CMAX, CMID, CMID) // Lower Back Right
|
|
(CMAX, CMID, CMID) // Lower Back Right
|
|
);
|
|
);
|
|
|
|
|
|
-function ConeContainsBSphere(const Cone: TSPCone; const BSphere: TBSphere): TSpaceContains;
|
|
|
|
|
|
+function ConeContainsBSphere(const Cone: TGLConeSP; const BSphere: TBSphere): TSpaceContains;
|
|
var
|
|
var
|
|
U, D: TAffineVector;
|
|
U, D: TAffineVector;
|
|
E, Dsqr: Single;
|
|
E, Dsqr: Single;
|
|
@@ -575,7 +574,7 @@ begin
|
|
Result := ScNoOverlap;
|
|
Result := ScNoOverlap;
|
|
end; // }
|
|
end; // }
|
|
|
|
|
|
-function ExtendedFrustumIntersectsBSphere(const AExtendedFrustum: TExtendedFrustum; const ABSphere: TBSphere): Boolean;
|
|
|
|
|
|
+function ExtendedFrustumIntersectsBSphere(const AExtendedFrustum: TGLExtendedFrustum; const ABSphere: TBSphere): Boolean;
|
|
begin
|
|
begin
|
|
// Test if the bounding sphere of the node intersect the bounding sphere of the
|
|
// Test if the bounding sphere of the node intersect the bounding sphere of the
|
|
// frustum? This test is exremely fast
|
|
// frustum? This test is exremely fast
|
|
@@ -592,7 +591,7 @@ end;
|
|
|
|
|
|
function ExtendedFrustumMake(const AFrustum: TFrustum; const ANearDist, AFarDist, AFieldOfViewRadians: Single;
|
|
function ExtendedFrustumMake(const AFrustum: TFrustum; const ANearDist, AFarDist, AFieldOfViewRadians: Single;
|
|
const ACameraPosition, ALookVector: TAffineVector { ;
|
|
const ACameraPosition, ALookVector: TAffineVector { ;
|
|
- const AScreenWidth, AScreenHeight : integer{ } ): TExtendedFrustum;
|
|
|
|
|
|
+ const AScreenWidth, AScreenHeight : integer{ } ): TGLExtendedFrustum;
|
|
var
|
|
var
|
|
ViewLen: Single;
|
|
ViewLen: Single;
|
|
Height, Width: Single;
|
|
Height, Width: Single;
|
|
@@ -762,7 +761,7 @@ begin
|
|
Result := 0;
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TBaseSpacePartition.QueryCone(const ACone: TSPCone): Integer;
|
|
|
|
|
|
+function TBaseSpacePartition.QueryCone(const ACone: TGLConeSP): Integer;
|
|
begin
|
|
begin
|
|
// Virtual
|
|
// Virtual
|
|
Result := 0;
|
|
Result := 0;
|
|
@@ -793,7 +792,7 @@ begin
|
|
Result := 0;
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TBaseSpacePartition.QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum): Integer;
|
|
|
|
|
|
+function TBaseSpacePartition.QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum): Integer;
|
|
begin
|
|
begin
|
|
// Virtual
|
|
// Virtual
|
|
Result := 0;
|
|
Result := 0;
|
|
@@ -880,11 +879,10 @@ begin
|
|
if Distance2 < Sqr(Leaf.FCachedBSphere.Radius + ABSphere.Radius) then
|
|
if Distance2 < Sqr(Leaf.FCachedBSphere.Radius + ABSphere.Radius) then
|
|
FQueryResult.Add(Leaf);
|
|
FQueryResult.Add(Leaf);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
Result := FQueryResult.Count;
|
|
Result := FQueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TLeavedSpacePartition.QueryCone(const ACone: TSPCone): Integer;
|
|
|
|
|
|
+function TLeavedSpacePartition.QueryCone(const ACone: TGLConeSP): Integer;
|
|
var
|
|
var
|
|
I: Integer;
|
|
I: Integer;
|
|
begin
|
|
begin
|
|
@@ -898,7 +896,6 @@ begin
|
|
if ConeContainsBSphere(ACone, Leaves[I].FCachedBSphere) <> ScNoOverlap then
|
|
if ConeContainsBSphere(ACone, Leaves[I].FCachedBSphere) <> ScNoOverlap then
|
|
FQueryResult.Add(Leaves[I]);
|
|
FQueryResult.Add(Leaves[I]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
Result := FQueryResult.Count;
|
|
Result := FQueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -910,26 +907,22 @@ var
|
|
begin
|
|
begin
|
|
// Very brute force!
|
|
// Very brute force!
|
|
FlushQueryResult;
|
|
FlushQueryResult;
|
|
-
|
|
|
|
for I := 0 to Leaves.Count - 1 do
|
|
for I := 0 to Leaves.Count - 1 do
|
|
begin
|
|
begin
|
|
Inc(FQueryInterObjectTests);
|
|
Inc(FQueryInterObjectTests);
|
|
-
|
|
|
|
Leaf := Leaves[I];
|
|
Leaf := Leaves[I];
|
|
-
|
|
|
|
CurrentPenetrationDepth := -(PointPlaneDistance(Leaf.FCachedBSphere.Center, FLocation, FNormal) -
|
|
CurrentPenetrationDepth := -(PointPlaneDistance(Leaf.FCachedBSphere.Center, FLocation, FNormal) -
|
|
Leaf.FCachedBSphere.Radius);
|
|
Leaf.FCachedBSphere.Radius);
|
|
-
|
|
|
|
// Correct the node location
|
|
// Correct the node location
|
|
if CurrentPenetrationDepth > 0 then
|
|
if CurrentPenetrationDepth > 0 then
|
|
FQueryResult.Add(Leaves[I]);
|
|
FQueryResult.Add(Leaves[I]);
|
|
end; // }
|
|
end; // }
|
|
-
|
|
|
|
Result := FQueryResult.Count;
|
|
Result := FQueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
-{ TSectorNode }
|
|
|
|
-
|
|
|
|
|
|
+//-------------------------------------
|
|
|
|
+// TSectorNode
|
|
|
|
+//-------------------------------------
|
|
function TSectorNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
function TSectorNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
begin
|
|
begin
|
|
Result := ContainsAABB(AAABB) in [ScContainsFully];
|
|
Result := ContainsAABB(AAABB) in [ScContainsFully];
|
|
@@ -1048,18 +1041,14 @@ begin
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
begin
|
|
begin
|
|
FChildren[I].CollapseNode;
|
|
FChildren[I].CollapseNode;
|
|
-
|
|
|
|
for J := 0 to FChildren[I].FLeaves.Count - 1 do
|
|
for J := 0 to FChildren[I].FLeaves.Count - 1 do
|
|
begin
|
|
begin
|
|
FChildren[I].FLeaves[J].FPartitionTag := Self;
|
|
FChildren[I].FLeaves[J].FPartitionTag := Self;
|
|
FLeaves.Add(FChildren[I].FLeaves[J]);
|
|
FLeaves.Add(FChildren[I].FLeaves[J]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
FChildren[I].FLeaves.Clear;
|
|
FChildren[I].FLeaves.Clear;
|
|
-
|
|
|
|
FreeAndNil(FChildren[I]);
|
|
FreeAndNil(FChildren[I]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
FChildCount := 0;
|
|
FChildCount := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1080,7 +1069,6 @@ var
|
|
I: Integer;
|
|
I: Integer;
|
|
begin
|
|
begin
|
|
Result := 1;
|
|
Result := 1;
|
|
-
|
|
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
Result := Result + FChildren[I].GetNodeCount;
|
|
Result := Result + FChildren[I].GetNodeCount;
|
|
end;
|
|
end;
|
|
@@ -1091,13 +1079,11 @@ var
|
|
begin
|
|
begin
|
|
// Which child does it fit in?
|
|
// Which child does it fit in?
|
|
ChildNode := GetChildForAABB(ALeaf.FCachedAABB);
|
|
ChildNode := GetChildForAABB(ALeaf.FCachedAABB);
|
|
-
|
|
|
|
if ChildNode <> nil then
|
|
if ChildNode <> nil then
|
|
begin
|
|
begin
|
|
Result := ChildNode.AddLeaf(ALeaf);
|
|
Result := ChildNode.AddLeaf(ALeaf);
|
|
Exit;
|
|
Exit;
|
|
end; // }
|
|
end; // }
|
|
-
|
|
|
|
// Doesn't fit the any child
|
|
// Doesn't fit the any child
|
|
ALeaf.FPartitionTag := Self;
|
|
ALeaf.FPartitionTag := Self;
|
|
FLeaves.Add(ALeaf);
|
|
FLeaves.Add(ALeaf);
|
|
@@ -1126,7 +1112,6 @@ begin
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
begin
|
|
begin
|
|
Inc(FSectoredSpacePartition.FQueryInterObjectTests);
|
|
Inc(FSectoredSpacePartition.FQueryInterObjectTests);
|
|
-
|
|
|
|
if IntersectAABBsAbsolute(FLeaves[I].FCachedAABB, AAABB) then
|
|
if IntersectAABBsAbsolute(FLeaves[I].FCachedAABB, AAABB) then
|
|
QueryResult.Add(FLeaves[I]);
|
|
QueryResult.Add(FLeaves[I]);
|
|
end;
|
|
end;
|
|
@@ -1136,7 +1121,6 @@ begin
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
QueryResult.Add(FLeaves[I]);
|
|
QueryResult.Add(FLeaves[I]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
// Recursively let the children add their leaves
|
|
// Recursively let the children add their leaves
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
FChildren[I].QueryAABB(AAABB, QueryResult);
|
|
FChildren[I].QueryAABB(AAABB, QueryResult);
|
|
@@ -1149,9 +1133,7 @@ var
|
|
SpaceContains: TSpaceContains;
|
|
SpaceContains: TSpaceContains;
|
|
begin
|
|
begin
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
-
|
|
|
|
SpaceContains := BSphereContainsSector(ABSphere);
|
|
SpaceContains := BSphereContainsSector(ABSphere);
|
|
-
|
|
|
|
if SpaceContains = ScContainsFully then
|
|
if SpaceContains = ScContainsFully then
|
|
begin
|
|
begin
|
|
AddAllLeavesRecursive(QueryResult);
|
|
AddAllLeavesRecursive(QueryResult);
|
|
@@ -1171,7 +1153,6 @@ begin
|
|
else
|
|
else
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
for I := 0 to FLeaves.Count - 1 do
|
|
QueryResult.Add(FLeaves[I]);
|
|
QueryResult.Add(FLeaves[I]);
|
|
-
|
|
|
|
// Recursively let the children add their leaves
|
|
// Recursively let the children add their leaves
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
FChildren[I].QueryBSphere(ABSphere, QueryResult);
|
|
FChildren[I].QueryBSphere(ABSphere, QueryResult);
|
|
@@ -1184,9 +1165,7 @@ var
|
|
SpaceContains: TSpaceContains;
|
|
SpaceContains: TSpaceContains;
|
|
begin
|
|
begin
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
-
|
|
|
|
SpaceContains := PlaneContainsBSphere(Location, Normal, FBSphere);
|
|
SpaceContains := PlaneContainsBSphere(Location, Normal, FBSphere);
|
|
-
|
|
|
|
if SpaceContains = ScContainsFully then
|
|
if SpaceContains = ScContainsFully then
|
|
begin
|
|
begin
|
|
AddAllLeavesRecursive(QueryResult);
|
|
AddAllLeavesRecursive(QueryResult);
|
|
@@ -1211,7 +1190,8 @@ begin
|
|
|
|
|
|
FChildren[I].QueryPlane(Location, Normal, QueryResult);
|
|
FChildren[I].QueryPlane(Location, Normal, QueryResult);
|
|
end;
|
|
end;
|
|
- end; // }
|
|
|
|
|
|
+ end;
|
|
|
|
+ // *)
|
|
end;
|
|
end;
|
|
|
|
|
|
function TSectorNode.RemoveLeaf(ALeaf: TSpacePartitionLeaf; OwnerByThis: Boolean): Boolean;
|
|
function TSectorNode.RemoveLeaf(ALeaf: TSpacePartitionLeaf; OwnerByThis: Boolean): Boolean;
|
|
@@ -1232,7 +1212,6 @@ begin
|
|
CollapseNode;
|
|
CollapseNode;
|
|
Result := True;
|
|
Result := True;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
if Parent <> nil then
|
|
if Parent <> nil then
|
|
Parent.RemoveLeaf(ALeaf, False);
|
|
Parent.RemoveLeaf(ALeaf, False);
|
|
end;
|
|
end;
|
|
@@ -1246,7 +1225,6 @@ begin
|
|
Result := Format('Node at depth %d mismatches, %d<>%d!', [FNodeDepth, FRecursiveLeafCount, CalcRecursiveLeafCount]);
|
|
Result := Format('Node at depth %d mismatches, %d<>%d!', [FNodeDepth, FRecursiveLeafCount, CalcRecursiveLeafCount]);
|
|
Exit;
|
|
Exit;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
begin
|
|
begin
|
|
Result := FChildren[I].VerifyRecursiveLeafCount;
|
|
Result := FChildren[I].VerifyRecursiveLeafCount;
|
|
@@ -1283,7 +1261,6 @@ end;
|
|
procedure TSectorNode.SetAABB(const Value: TAABB);
|
|
procedure TSectorNode.SetAABB(const Value: TAABB);
|
|
begin
|
|
begin
|
|
FAABB := Value;
|
|
FAABB := Value;
|
|
-
|
|
|
|
AABBToBSphere(FAABB, FBSphere);
|
|
AABBToBSphere(FAABB, FBSphere);
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1297,27 +1274,19 @@ begin
|
|
// Instead of looping through all children, we simply determine on which
|
|
// Instead of looping through all children, we simply determine on which
|
|
// side of the center node the child is located
|
|
// side of the center node the child is located
|
|
ChildNodeIndex := 0;
|
|
ChildNodeIndex := 0;
|
|
-
|
|
|
|
Location := AABB.Min;
|
|
Location := AABB.Min;
|
|
-
|
|
|
|
// Upper / Lower
|
|
// Upper / Lower
|
|
if Location.Y < FBSphere.Center.Y then
|
|
if Location.Y < FBSphere.Center.Y then
|
|
ChildNodeIndex := 4;
|
|
ChildNodeIndex := 4;
|
|
-
|
|
|
|
// Left / Right
|
|
// Left / Right
|
|
if Location.Z < FBSphere.Center.Z then
|
|
if Location.Z < FBSphere.Center.Z then
|
|
ChildNodeIndex := ChildNodeIndex or 2;
|
|
ChildNodeIndex := ChildNodeIndex or 2;
|
|
-
|
|
|
|
// Fore / Back
|
|
// Fore / Back
|
|
if Location.X > FBSphere.Center.X then
|
|
if Location.X > FBSphere.Center.X then
|
|
ChildNodeIndex := ChildNodeIndex or 1;
|
|
ChildNodeIndex := ChildNodeIndex or 1;
|
|
-
|
|
|
|
Assert((ChildNodeIndex >= 0) and (ChildNodeIndex <= 8), Format('ChildNodeIndex is out of range (%d)!', [ChildNodeIndex]));
|
|
Assert((ChildNodeIndex >= 0) and (ChildNodeIndex <= 8), Format('ChildNodeIndex is out of range (%d)!', [ChildNodeIndex]));
|
|
-
|
|
|
|
ChildNode := FChildren[ChildNodeIndex];
|
|
ChildNode := FChildren[ChildNodeIndex];
|
|
-
|
|
|
|
Assert(Assigned(ChildNode), 'ChildNode not assigned');
|
|
Assert(Assigned(ChildNode), 'ChildNode not assigned');
|
|
-
|
|
|
|
if ChildNode.AABBFitsInNode(AABB) then
|
|
if ChildNode.AABBFitsInNode(AABB) then
|
|
Result := ChildNode
|
|
Result := ChildNode
|
|
else
|
|
else
|
|
@@ -1341,7 +1310,6 @@ begin
|
|
SpaceContains := FrustumContainsAABB(Frustum, AABB)
|
|
SpaceContains := FrustumContainsAABB(Frustum, AABB)
|
|
else
|
|
else
|
|
SpaceContains := ScNoOverlap;
|
|
SpaceContains := ScNoOverlap;
|
|
-
|
|
|
|
// If the frustum fully contains the leaf, then we need not check every piece,
|
|
// If the frustum fully contains the leaf, then we need not check every piece,
|
|
// just add them all
|
|
// just add them all
|
|
if SpaceContains = ScContainsFully then
|
|
if SpaceContains = ScContainsFully then
|
|
@@ -1349,7 +1317,6 @@ begin
|
|
AddAllLeavesRecursive(QueryResult);
|
|
AddAllLeavesRecursive(QueryResult);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
-
|
|
|
|
// If the frustum partiall contains the leaf, then we should add the leaves
|
|
// If the frustum partiall contains the leaf, then we should add the leaves
|
|
// that intersect the frustum and recurse for all children
|
|
// that intersect the frustum and recurse for all children
|
|
if SpaceContains = ScContainsPartially then
|
|
if SpaceContains = ScContainsPartially then
|
|
@@ -1361,7 +1328,6 @@ begin
|
|
if not IsVolumeClipped(FLeaves[I].FCachedBSphere.Center, FLeaves[I].FCachedBSphere.Radius, Frustum) then
|
|
if not IsVolumeClipped(FLeaves[I].FCachedBSphere.Center, FLeaves[I].FCachedBSphere.Radius, Frustum) then
|
|
QueryResult.Add(FLeaves[I]);
|
|
QueryResult.Add(FLeaves[I]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
// Recursively let the children add their leaves
|
|
// Recursively let the children add their leaves
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
FChildren[I].QueryFrustum(Frustum, QueryResult);
|
|
FChildren[I].QueryFrustum(Frustum, QueryResult);
|
|
@@ -1373,21 +1339,18 @@ begin
|
|
// Do nothing in the basic case
|
|
// Do nothing in the basic case
|
|
end;
|
|
end;
|
|
|
|
|
|
-procedure TSectorNode.QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
|
|
|
|
+procedure TSectorNode.QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum; const QueryResult: TSpacePartitionLeafList);
|
|
var
|
|
var
|
|
SpaceContains: TSpaceContains;
|
|
SpaceContains: TSpaceContains;
|
|
I: Integer;
|
|
I: Integer;
|
|
begin
|
|
begin
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
Inc(FSectoredSpacePartition.FQueryNodeTests);
|
|
-
|
|
|
|
// Does the extended frustum intersect the bsphere at all?
|
|
// Does the extended frustum intersect the bsphere at all?
|
|
if not ExtendedFrustumIntersectsBSphere(ExtendedFrustum, BSphere) then
|
|
if not ExtendedFrustumIntersectsBSphere(ExtendedFrustum, BSphere) then
|
|
SpaceContains := ScNoOverlap
|
|
SpaceContains := ScNoOverlap
|
|
-
|
|
|
|
else
|
|
else
|
|
// Test if the bounding frustum intersects the AABB of the node
|
|
// Test if the bounding frustum intersects the AABB of the node
|
|
SpaceContains := FrustumContainsAABB(ExtendedFrustum.Frustum, AABB); // }
|
|
SpaceContains := FrustumContainsAABB(ExtendedFrustum.Frustum, AABB); // }
|
|
-
|
|
|
|
// If the frustum fully contains the leaf, then we need not check every piece,
|
|
// If the frustum fully contains the leaf, then we need not check every piece,
|
|
// just add them all
|
|
// just add them all
|
|
if SpaceContains = ScContainsFully then
|
|
if SpaceContains = ScContainsFully then
|
|
@@ -1395,7 +1358,6 @@ begin
|
|
AddAllLeavesRecursive(QueryResult);
|
|
AddAllLeavesRecursive(QueryResult);
|
|
end
|
|
end
|
|
else
|
|
else
|
|
-
|
|
|
|
// If the frustum partially contains the leaf, then we should add the leaves
|
|
// If the frustum partially contains the leaf, then we should add the leaves
|
|
// that intersect the frustum and recurse for all children
|
|
// that intersect the frustum and recurse for all children
|
|
if SpaceContains = ScContainsPartially then
|
|
if SpaceContains = ScContainsPartially then
|
|
@@ -1405,21 +1367,19 @@ begin
|
|
// Early out 1
|
|
// Early out 1
|
|
if not BSphereIntersectsBSphere(FLeaves[I].FCachedBSphere, ExtendedFrustum.BSphere) then
|
|
if not BSphereIntersectsBSphere(FLeaves[I].FCachedBSphere, ExtendedFrustum.BSphere) then
|
|
Continue;
|
|
Continue;
|
|
-
|
|
|
|
Inc(FSectoredSpacePartition.FQueryInterObjectTests);
|
|
Inc(FSectoredSpacePartition.FQueryInterObjectTests);
|
|
-
|
|
|
|
if not IsVolumeClipped(FLeaves[I].FCachedBSphere.Center, FLeaves[I].FCachedBSphere.Radius, ExtendedFrustum.Frustum) then
|
|
if not IsVolumeClipped(FLeaves[I].FCachedBSphere.Center, FLeaves[I].FCachedBSphere.Radius, ExtendedFrustum.Frustum) then
|
|
QueryResult.Add(FLeaves[I]);
|
|
QueryResult.Add(FLeaves[I]);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
// Recursively let the children add their leaves
|
|
// Recursively let the children add their leaves
|
|
for I := 0 to FChildCount - 1 do
|
|
for I := 0 to FChildCount - 1 do
|
|
FChildren[I].QueryFrustumEx(ExtendedFrustum, QueryResult);
|
|
FChildren[I].QueryFrustumEx(ExtendedFrustum, QueryResult);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
-{ TSectoredSpacePartition }
|
|
|
|
-
|
|
|
|
|
|
+//-------------------------------------
|
|
|
|
+// TSectoredSpacePartition
|
|
|
|
+//-------------------------------------
|
|
procedure TSectoredSpacePartition.AddLeaf(ALeaf: TSpacePartitionLeaf);
|
|
procedure TSectoredSpacePartition.AddLeaf(ALeaf: TSpacePartitionLeaf);
|
|
begin
|
|
begin
|
|
inherited;
|
|
inherited;
|
|
@@ -1448,9 +1408,7 @@ begin
|
|
|
|
|
|
FRootNode := CreateNewNode(nil);
|
|
FRootNode := CreateNewNode(nil);
|
|
FGrowMethod := gmIncreaseToFitAll;
|
|
FGrowMethod := gmIncreaseToFitAll;
|
|
-
|
|
|
|
FGrowGravy := COctree_GROW_GRAVY;
|
|
FGrowGravy := COctree_GROW_GRAVY;
|
|
-
|
|
|
|
inherited Create;
|
|
inherited Create;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1495,9 +1453,7 @@ begin
|
|
// If the leaf still fits in the old node, leave it there - or in one of the
|
|
// If the leaf still fits in the old node, leave it there - or in one of the
|
|
// children
|
|
// children
|
|
Node := TSectorNode(ALeaf.FPartitionTag);
|
|
Node := TSectorNode(ALeaf.FPartitionTag);
|
|
-
|
|
|
|
Assert(Node <> nil, 'No leaf node could be found!');
|
|
Assert(Node <> nil, 'No leaf node could be found!');
|
|
-
|
|
|
|
if Node.AABBFitsInNode(ALeaf.FCachedAABB) then
|
|
if Node.AABBFitsInNode(ALeaf.FCachedAABB) then
|
|
begin
|
|
begin
|
|
// If the node has children, try to add the leaf to them - otherwise just
|
|
// If the node has children, try to add the leaf to them - otherwise just
|
|
@@ -1512,7 +1468,6 @@ begin
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
Node.RemoveLeaf(ALeaf, True);
|
|
Node.RemoveLeaf(ALeaf, True);
|
|
-
|
|
|
|
// Does this leaf still fit in the Octree?
|
|
// Does this leaf still fit in the Octree?
|
|
if not FRootNode.AABBFitsInNode(ALeaf.FCachedAABB) then
|
|
if not FRootNode.AABBFitsInNode(ALeaf.FCachedAABB) then
|
|
begin
|
|
begin
|
|
@@ -1559,17 +1514,13 @@ begin
|
|
|
|
|
|
Node := TSectorNode(ALeaf.FPartitionTag);
|
|
Node := TSectorNode(ALeaf.FPartitionTag);
|
|
FlushQueryResult;
|
|
FlushQueryResult;
|
|
-
|
|
|
|
// First, query downwards!
|
|
// First, query downwards!
|
|
Node.QueryAABB(ALeaf.FCachedAABB, QueryResult);
|
|
Node.QueryAABB(ALeaf.FCachedAABB, QueryResult);
|
|
-
|
|
|
|
// Now, query parents and upwards!
|
|
// Now, query parents and upwards!
|
|
Node := Node.Parent;
|
|
Node := Node.Parent;
|
|
-
|
|
|
|
while Node <> nil do
|
|
while Node <> nil do
|
|
begin
|
|
begin
|
|
Inc(FQueryNodeTests);
|
|
Inc(FQueryNodeTests);
|
|
-
|
|
|
|
// Add all leaves that overlap
|
|
// Add all leaves that overlap
|
|
for I := 0 to Node.FLeaves.Count - 1 do
|
|
for I := 0 to Node.FLeaves.Count - 1 do
|
|
begin
|
|
begin
|
|
@@ -1578,13 +1529,10 @@ begin
|
|
if IntersectAABBsAbsolute(TestLeaf.FCachedAABB, ALeaf.FCachedAABB) then
|
|
if IntersectAABBsAbsolute(TestLeaf.FCachedAABB, ALeaf.FCachedAABB) then
|
|
QueryResult.Add(TestLeaf);
|
|
QueryResult.Add(TestLeaf);
|
|
end;
|
|
end;
|
|
-
|
|
|
|
// Try the parent
|
|
// Try the parent
|
|
Node := Node.Parent;
|
|
Node := Node.Parent;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
QueryResult.Remove(ALeaf);
|
|
QueryResult.Remove(ALeaf);
|
|
-
|
|
|
|
Result := QueryResult.Count;
|
|
Result := QueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1626,7 +1574,6 @@ begin
|
|
|
|
|
|
for I := 0 to OldLeaves.Count - 1 do
|
|
for I := 0 to OldLeaves.Count - 1 do
|
|
AddLeaf(OldLeaves[I]);
|
|
AddLeaf(OldLeaves[I]);
|
|
-
|
|
|
|
OldLeaves.Free;
|
|
OldLeaves.Free;
|
|
FGrowMethod := TempGrowMethod;
|
|
FGrowMethod := TempGrowMethod;
|
|
end;
|
|
end;
|
|
@@ -1639,7 +1586,6 @@ begin
|
|
// Creates the new extents for the Octree
|
|
// Creates the new extents for the Octree
|
|
MaxAABB := GetAABB;
|
|
MaxAABB := GetAABB;
|
|
AABBSize := VectorSubtract(MaxAABB.Max, MaxAABB.Min);
|
|
AABBSize := VectorSubtract(MaxAABB.Max, MaxAABB.Min);
|
|
-
|
|
|
|
if FGrowMethod = gmBestFit then
|
|
if FGrowMethod = gmBestFit then
|
|
begin
|
|
begin
|
|
NewAABB.Min := VectorSubtract(MaxAABB.Min, VectorScale(AABBSize, Gravy));
|
|
NewAABB.Min := VectorSubtract(MaxAABB.Min, VectorScale(AABBSize, Gravy));
|
|
@@ -1659,7 +1605,6 @@ end;
|
|
procedure TSectoredSpacePartition.FlushQueryResult;
|
|
procedure TSectoredSpacePartition.FlushQueryResult;
|
|
begin
|
|
begin
|
|
inherited;
|
|
inherited;
|
|
-
|
|
|
|
FQueryNodeTests := 0;
|
|
FQueryNodeTests := 0;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1670,15 +1615,16 @@ begin
|
|
Result := FQueryResult.Count;
|
|
Result := FQueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TSectoredSpacePartition.QueryFrustumEx(const ExtendedFrustum: TExtendedFrustum): Integer;
|
|
|
|
|
|
+function TSectoredSpacePartition.QueryFrustumEx(const ExtendedFrustum: TGLExtendedFrustum): Integer;
|
|
begin
|
|
begin
|
|
FlushQueryResult;
|
|
FlushQueryResult;
|
|
FRootNode.QueryFrustumEx(ExtendedFrustum, FQueryResult);
|
|
FRootNode.QueryFrustumEx(ExtendedFrustum, FQueryResult);
|
|
Result := FQueryResult.Count;
|
|
Result := FQueryResult.Count;
|
|
end;
|
|
end;
|
|
|
|
|
|
-{ TSPOctreeNode }
|
|
|
|
-
|
|
|
|
|
|
+//-------------------------------------
|
|
|
|
+// TSPOctreeNode
|
|
|
|
+//-------------------------------------
|
|
function TSPOctreeNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
function TSPOctreeNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
begin
|
|
begin
|
|
// Faster than inherited method
|
|
// Faster than inherited method
|
|
@@ -1736,18 +1682,17 @@ begin
|
|
for I := 0 to 7 do
|
|
for I := 0 to 7 do
|
|
begin
|
|
begin
|
|
FChildren[I] := FSectoredSpacePartition.CreateNewNode(Self);
|
|
FChildren[I] := FSectoredSpacePartition.CreateNewNode(Self);
|
|
-
|
|
|
|
// Generate new extents based on parent's extents
|
|
// Generate new extents based on parent's extents
|
|
AABB.Min := GetExtent(COctFlagMIN[I]);
|
|
AABB.Min := GetExtent(COctFlagMIN[I]);
|
|
AABB.Max := GetExtent(COctFlagMax[I]);
|
|
AABB.Max := GetExtent(COctFlagMax[I]);
|
|
FChildren[I].AABB := AABB;
|
|
FChildren[I].AABB := AABB;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
FChildCount := 8;
|
|
FChildCount := 8;
|
|
end;
|
|
end;
|
|
|
|
|
|
-{ TOctreeSpacePartition }
|
|
|
|
-
|
|
|
|
|
|
+//-------------------------------------
|
|
|
|
+// TOctreeSpacePartition
|
|
|
|
+//-------------------------------------
|
|
function TOctreeSpacePartition.CreateNewNode(AParent: TSectorNode): TSectorNode;
|
|
function TOctreeSpacePartition.CreateNewNode(AParent: TSectorNode): TSectorNode;
|
|
begin
|
|
begin
|
|
Result := TSPOctreeNode.Create(Self, AParent);
|
|
Result := TSPOctreeNode.Create(Self, AParent);
|
|
@@ -1759,12 +1704,12 @@ var
|
|
begin
|
|
begin
|
|
AABB.Min := Min;
|
|
AABB.Min := Min;
|
|
AABB.Max := Max;
|
|
AABB.Max := Max;
|
|
-
|
|
|
|
RebuildTree(AABB);
|
|
RebuildTree(AABB);
|
|
end;
|
|
end;
|
|
|
|
|
|
-{ TSPQuadtreeNode }
|
|
|
|
-
|
|
|
|
|
|
+//-------------------------------------
|
|
|
|
+// TSPQuadtreeNode
|
|
|
|
+//-------------------------------------
|
|
function TSPQuadtreeNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
function TSPQuadtreeNode.AABBFitsInNode(const AAABB: TAABB): Boolean;
|
|
begin
|
|
begin
|
|
Result := (AAABB.Min.X >= FAABB.Min.X) and
|
|
Result := (AAABB.Min.X >= FAABB.Min.X) and
|
|
@@ -1797,7 +1742,6 @@ var
|
|
NewMin, NewMax: Single;
|
|
NewMin, NewMax: Single;
|
|
begin
|
|
begin
|
|
inherited;
|
|
inherited;
|
|
-
|
|
|
|
// Establish a baseline
|
|
// Establish a baseline
|
|
if Leaves.Count > 0 then
|
|
if Leaves.Count > 0 then
|
|
begin
|
|
begin
|
|
@@ -1805,7 +1749,6 @@ begin
|
|
NewMax := Leaves[0].FCachedAABB.Max.Y;
|
|
NewMax := Leaves[0].FCachedAABB.Max.Y;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
-
|
|
|
|
if FChildCount > 0 then
|
|
if FChildCount > 0 then
|
|
begin
|
|
begin
|
|
NewMin := FChildren[0].AABB.Min.Y;
|
|
NewMin := FChildren[0].AABB.Min.Y;
|
|
@@ -1817,7 +1760,6 @@ begin
|
|
NewMin := 1E9;
|
|
NewMin := 1E9;
|
|
NewMax := -1E9;
|
|
NewMax := -1E9;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
for I := 0 to Leaves.Count - 1 do
|
|
for I := 0 to Leaves.Count - 1 do
|
|
begin
|
|
begin
|
|
NewMin := Min(NewMin, Leaves[I].FCachedAABB.Min.Y);
|
|
NewMin := Min(NewMin, Leaves[I].FCachedAABB.Min.Y);
|
|
@@ -1834,7 +1776,6 @@ begin
|
|
begin
|
|
begin
|
|
FAABB.Max.Y := NewMax;
|
|
FAABB.Max.Y := NewMax;
|
|
FAABB.Min.Y := NewMin;
|
|
FAABB.Min.Y := NewMin;
|
|
-
|
|
|
|
// Make sure the parent updates it's bounds as well
|
|
// Make sure the parent updates it's bounds as well
|
|
if Assigned(Parent) then
|
|
if Assigned(Parent) then
|
|
Parent.ChildrenChanged; // }
|
|
Parent.ChildrenChanged; // }
|
|
@@ -1850,11 +1791,9 @@ begin
|
|
for ChildNodeIndex := 0 to 3 do
|
|
for ChildNodeIndex := 0 to 3 do
|
|
begin
|
|
begin
|
|
FChildren[ChildNodeIndex] := FSectoredSpacePartition.CreateNewNode(Self);
|
|
FChildren[ChildNodeIndex] := FSectoredSpacePartition.CreateNewNode(Self);
|
|
-
|
|
|
|
// Y is ignored so it's set to a very large number
|
|
// Y is ignored so it's set to a very large number
|
|
AABB.Min.Y := FAABB.Min.Y;
|
|
AABB.Min.Y := FAABB.Min.Y;
|
|
AABB.Max.Y := FAABB.Max.Y;
|
|
AABB.Max.Y := FAABB.Max.Y;
|
|
-
|
|
|
|
// Generate new extents based on parent's extents
|
|
// Generate new extents based on parent's extents
|
|
if ((ChildNodeIndex and 1) > 0) then
|
|
if ((ChildNodeIndex and 1) > 0) then
|
|
X := 1
|
|
X := 1
|
|
@@ -1864,7 +1803,6 @@ begin
|
|
Z := 1
|
|
Z := 1
|
|
else
|
|
else
|
|
Z := 0;
|
|
Z := 0;
|
|
-
|
|
|
|
if X = 0 then
|
|
if X = 0 then
|
|
begin
|
|
begin
|
|
AABB.Min.X := FAABB.Min.X + (FAABB.Max.X + FAABB.Min.X) / 2 * X;
|
|
AABB.Min.X := FAABB.Min.X + (FAABB.Max.X + FAABB.Min.X) / 2 * X;
|
|
@@ -1875,7 +1813,6 @@ begin
|
|
AABB.Min.X := (FAABB.Max.X + FAABB.Min.X) / 2;
|
|
AABB.Min.X := (FAABB.Max.X + FAABB.Min.X) / 2;
|
|
AABB.Max.X := FAABB.Max.X;
|
|
AABB.Max.X := FAABB.Max.X;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
if Z = 0 then
|
|
if Z = 0 then
|
|
begin
|
|
begin
|
|
AABB.Min.Z := FAABB.Min.Z;
|
|
AABB.Min.Z := FAABB.Min.Z;
|
|
@@ -1886,10 +1823,8 @@ begin
|
|
AABB.Min.Z := (FAABB.Max.Z + FAABB.Min.Z) / 2;
|
|
AABB.Min.Z := (FAABB.Max.Z + FAABB.Min.Z) / 2;
|
|
AABB.Max.Z := FAABB.Max.Z;
|
|
AABB.Max.Z := FAABB.Max.Z;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
FChildren[ChildNodeIndex].AABB := AABB;
|
|
FChildren[ChildNodeIndex].AABB := AABB;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
FChildCount := 4;
|
|
FChildCount := 4;
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1902,33 +1837,26 @@ begin
|
|
// Instead of looping through all children, we simply determine on which
|
|
// Instead of looping through all children, we simply determine on which
|
|
// side of the center node the child is located
|
|
// side of the center node the child is located
|
|
ChildNodeIndex := 0;
|
|
ChildNodeIndex := 0;
|
|
-
|
|
|
|
Location := AABB.Min;
|
|
Location := AABB.Min;
|
|
-
|
|
|
|
// Fore / Back
|
|
// Fore / Back
|
|
if Location.X > FBSphere.Center.X then
|
|
if Location.X > FBSphere.Center.X then
|
|
ChildNodeIndex := ChildNodeIndex or 1;
|
|
ChildNodeIndex := ChildNodeIndex or 1;
|
|
-
|
|
|
|
// Left / Right
|
|
// Left / Right
|
|
if Location.Z > FBSphere.Center.Z then
|
|
if Location.Z > FBSphere.Center.Z then
|
|
ChildNodeIndex := ChildNodeIndex or 2;
|
|
ChildNodeIndex := ChildNodeIndex or 2;
|
|
-
|
|
|
|
Assert(ChildNodeIndex < ChildCount, 'Bad ChildNodeIndex!');
|
|
Assert(ChildNodeIndex < ChildCount, 'Bad ChildNodeIndex!');
|
|
ChildNode := FChildren[ChildNodeIndex];
|
|
ChildNode := FChildren[ChildNodeIndex];
|
|
-
|
|
|
|
if ChildNode.AABBFitsInNode(AABB) then
|
|
if ChildNode.AABBFitsInNode(AABB) then
|
|
begin
|
|
begin
|
|
Result := ChildNode;
|
|
Result := ChildNode;
|
|
Exit;
|
|
Exit;
|
|
end;
|
|
end;
|
|
-
|
|
|
|
Result := nil;
|
|
Result := nil;
|
|
end;
|
|
end;
|
|
|
|
|
|
//-----------------------------------
|
|
//-----------------------------------
|
|
// TQuadtreeSpacePartition
|
|
// TQuadtreeSpacePartition
|
|
//-----------------------------------
|
|
//-----------------------------------
|
|
-
|
|
|
|
function TQuadtreeSpacePartition.CreateNewNode(AParent: TSectorNode): TSectorNode;
|
|
function TQuadtreeSpacePartition.CreateNewNode(AParent: TSectorNode): TSectorNode;
|
|
begin
|
|
begin
|
|
Result := TSPQuadtreeNode.Create(Self, AParent);
|
|
Result := TSPQuadtreeNode.Create(Self, AParent);
|
|
@@ -1940,7 +1868,6 @@ var
|
|
begin
|
|
begin
|
|
AABB.Min := Min;
|
|
AABB.Min := Min;
|
|
AABB.Max := Max;
|
|
AABB.Max := Max;
|
|
-
|
|
|
|
RebuildTree(AABB);
|
|
RebuildTree(AABB);
|
|
end;
|
|
end;
|
|
|
|
|
|
@@ -1960,7 +1887,6 @@ begin
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.min.Y, AABB.min.Z);
|
|
-
|
|
|
|
gl.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.min.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
|
|
@@ -1971,10 +1897,8 @@ begin
|
|
gl.Begin_(GL_LINES);
|
|
gl.Begin_(GL_LINES);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.min.X, AABB.max.Y, AABB.max.Z);
|
|
-
|
|
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.max.Y, AABB.max.Z);
|
|
-
|
|
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.min.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
|
|
gl.Vertex3f(AABB.max.X, AABB.min.Y, AABB.max.Z);
|
|
gl.End_;
|
|
gl.End_;
|
|
@@ -1996,7 +1920,6 @@ procedure RenderSpatialPartitioning(var rci: TGLRenderContextInfo;
|
|
RenderAABB(rci, AABB, 1, 0, 0, 0)
|
|
RenderAABB(rci, AABB, 1, 0, 0, 0)
|
|
else
|
|
else
|
|
RenderAABB(rci, AABB, 1, 0.8, 0.8, 0.8) //}
|
|
RenderAABB(rci, AABB, 1, 0.8, 0.8, 0.8) //}
|
|
-
|
|
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
@@ -2010,7 +1933,7 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
- const AGLSceneViewer: TGLSceneViewer): TExtendedFrustum; //old version
|
|
|
|
|
|
+ const AGLSceneViewer: TGLSceneViewer): TGLExtendedFrustum; //old version
|
|
begin
|
|
begin
|
|
Assert(Assigned(AGLSceneViewer.Camera), 'GLSceneViewer must have camera specified!');
|
|
Assert(Assigned(AGLSceneViewer.Camera), 'GLSceneViewer must have camera specified!');
|
|
result := ExtendedFrustumMake(AFrustum,
|
|
result := ExtendedFrustumMake(AFrustum,
|
|
@@ -2022,7 +1945,7 @@ begin
|
|
end;
|
|
end;
|
|
|
|
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
function ExtendedFrustumMakeFromSceneViewer(const AFrustum: TFrustum;
|
|
- const vWidth, vHeight: integer; AGLCamera: TGLCamera): TExtendedFrustum; //changed version
|
|
|
|
|
|
+ const vWidth, vHeight: integer; AGLCamera: TGLCamera): TGLExtendedFrustum; //changed version
|
|
var
|
|
var
|
|
buffov: single;
|
|
buffov: single;
|
|
begin
|
|
begin
|
|
@@ -2061,5 +1984,4 @@ begin
|
|
FCachedBSphere.Center := AffineVectorMake(Obj.AbsolutePosition);
|
|
FCachedBSphere.Center := AffineVectorMake(Obj.AbsolutePosition);
|
|
end;
|
|
end;
|
|
|
|
|
|
-
|
|
|
|
end.
|
|
end.
|