| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- unit fOctreeRenderD;
- interface
- uses
- Winapi.OpenGL,
- System.SysUtils,
- System.Classes,
- System.Types,
- System.Math,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.Dialogs,
- Vcl.ExtCtrls,
- Vcl.StdCtrls,
- Vcl.ComCtrls,
- GLS.Objects,
- GLS.Scene,
- GLS.Cadencer,
- GLS.SceneViewer,
- GLScene.VectorGeometry,
- GLScene.VectorTypes,
- GLS.GeometryBB,
- GLS.Texture,
- GLS.SpacePartition,
- GLS.Coordinates,
- GLS.RenderContextInfo,
- GLS.State,
- GLS.SimpleNavigation,
- GLS.Material,
- GLS.Context,
- GLS.BaseClasses;
- const
- cBOX_SIZE = 14.2;
- type
- TfrmOctreeDemo = class(TForm)
- GLScene1: TGLScene;
- GLSceneViewer1: TGLSceneViewer;
- GLLightSource1: TGLLightSource;
- GLCamera1: TGLCamera;
- GLDummyCube1: TGLDummyCube;
- GLDirectOpenGL1: TGLDirectOpenGL;
- GLCube1: TGLCube;
- GLCadencer1: TGLCadencer;
- GLSphere1: TGLSphere;
- GLPlane1: TGLPlane;
- GLSimpleNavigation1: TGLSimpleNavigation;
- GLMaterialLibrary1: TGLMaterialLibrary;
- Panel1: TPanel;
- Label3: TLabel;
- TrackBar_LeafThreshold: TTrackBar;
- Label2: TLabel;
- Button_ResetOctreeSize: TButton;
- LabelCollisions: TLabel;
- procedure FormCreate(Sender: TObject);
- procedure GLDirectOpenGL1Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
- WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
- procedure GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- procedure TrackBar_LeafThresholdChange(Sender: TObject);
- procedure Button_ResetOctreeSizeClick(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- public
- Octree: TGLOctreeSpacePartition;
- procedure CreateBox;
- procedure VerifySpacialMisc;
- end;
- var
- frmOctreeDemo: TfrmOctreeDemo;
- //========================================================
- implementation
- //========================================================
- {$R *.dfm}
- procedure TfrmOctreeDemo.FormCreate(Sender: TObject);
- var
- i: Integer;
- begin
- randomize;
- Octree := TGLOctreeSpacePartition.Create;
- Octree.SetSize(AffineVectorMake(-15, -15, -15), AffineVectorMake(15, 15, 15));
- Octree.MaxTreeDepth := 6;
- Octree.LeafThreshold := 10;
- TrackBar_LeafThresholdChange(nil);
- for i := 0 to 300 do
- CreateBox;
- VerifySpacialMisc;
- end;
- procedure TfrmOctreeDemo.CreateBox;
- function randomPos: TAffineVector;
- const
- c1 = 10;
- begin
- // MakeVector(result, random*c1-c1/2, random*c1-c1/2, random*c1-c1/2);
- MakeVector(result, random, random, random);
- end;
- function randomSize: Single;
- begin
- result := 0.1 + random * 0.5;
- end;
- var
- Cube: TGLCube;
- begin
- Cube := TGLCube(GLScene1.Objects.AddNewChild(TGLCube));
- Cube.Position.AsAffineVector := randomPos;
- Cube.CubeWidth := randomSize;
- Cube.CubeHeight := randomSize;
- Cube.CubeDepth := randomSize;
- TGLSpacePartitionLeafS.CreateGLOwned(Octree, Cube);
- end;
- procedure TfrmOctreeDemo.GLDirectOpenGL1Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure RenderAABB(AABB: TAABB; w, r, g, b: Single);
- begin
- glColor3f(r, g, b);
- rci.GLStates.LineWidth := w;
- glBegin(GL_LINE_STRIP);
- glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Min.Z);
- glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Min.Z);
- glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Min.Z);
- glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Min.Z);
- glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Min.Z);
- glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Max.Z);
- glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Max.Z);
- glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Max.Z);
- glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Max.Z);
- glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Max.Z);
- glEnd();
- glBegin(GL_LINES);
- glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Min.Z);
- glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Max.Z);
- glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Min.Z);
- glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Max.Z);
- glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Min.Z);
- glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Max.Z);
- glEnd;
- end;
- procedure RenderOctreeNode(Node: TGLSectorNode);
- var
- i: Integer;
- AABB: TAABB;
- begin
- if Node.NoChildren then
- begin
- AABB := Node.AABB;
- if Node.RecursiveLeafCount > 0 then
- RenderAABB(AABB, 1, 0, 0, 0)
- else
- RenderAABB(AABB, 1, 0.8, 0.8, 0.8) // }
- end
- else
- begin
- for i := 0 to Node.ChildCount - 1 do
- RenderOctreeNode(Node.Children[i]);
- end;
- end;
- var
- AABB: TAABB;
- begin
- rci.GLStates.Disable(stLighting);
- rci.GLStates.Enable(stColorMaterial);
- MakeVector(AABB.Min, -cBOX_SIZE, -cBOX_SIZE, -cBOX_SIZE);
- MakeVector(AABB.Max, cBOX_SIZE, cBOX_SIZE, cBOX_SIZE);
- RenderAABB(AABB, 2, 0, 0, 0);
- RenderOctreeNode(Octree.RootNode);
- end;
- procedure TfrmOctreeDemo.FormMouseWheel(Sender: TObject; Shift: TShiftState;
- WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
- begin
- GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
- Handled := true
- end;
- procedure TfrmOctreeDemo.GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- var
- AABB: TAABB;
- BSphere: TBSphere;
- Leaf, TestLeaf: TGLSpacePartitionLeafS;
- Cube: TGLCube;
- i, j, CollidingLeafCount: Integer;
- (*sub*)function TestMove(pos: Single; var dir: Single): Single;
- const
- cSPEED = 2;
- begin
- if (abs(pos + dir * deltaTime * cSPEED) >= cBOX_SIZE) then
- dir := -dir;
- result := pos + dir * deltaTime * cSPEED;
- end;
- begin
- for i := 0 to Octree.Leaves.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
- Cube := TGLCube(Leaf.GLBaseSceneObject);
- Cube.Position.X := TestMove(Cube.Position.X, Leaf.Direction.X);
- Cube.Position.Y := TestMove(Cube.Position.Y, Leaf.Direction.Y);
- Cube.Position.Z := TestMove(Cube.Position.Z, Leaf.Direction.Z);
- Leaf.Changed;
- end; // }
- for i := 0 to Octree.Leaves.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 0;
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.
- Green := 0;
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Blue := 0;
- end; // }
- // AABB collision
- AABB := GLCube1.AxisAlignedBoundingBox;
- AABB.Min := GLCube1.LocalToAbsolute(AABB.Min);
- AABB.Max := GLCube1.LocalToAbsolute(AABB.Max);
- Octree.QueryAABB(AABB);
- for i := 0 to Octree.QueryResult.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
- end; // }
- // BSphere collision
- BSphere.Center := GLSphere1.Position.AsAffineVector;
- BSphere.Radius := GLSphere1.Radius;
- Octree.QueryBSphere(BSphere);
- for i := 0 to Octree.QueryResult.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
- end; // }
- // Plane collision
- if GLPlane1.Visible then
- begin
- Octree.QueryPlane(GLPlane1.Position.AsAffineVector,
- GLPlane1.Direction.AsAffineVector);
- for i := 0 to Octree.QueryResult.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
- TGLCube(Leaf.GLBaseSceneObject)
- .Material.FrontProperties.Emission.Blue := 1;
- end; // }
- end;
- // Leaf - leaf collision
- CollidingLeafCount := 0;
- for i := 0 to Octree.Leaves.Count - 1 do
- begin
- Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
- Octree.QueryAABB(Leaf.FCachedAABB);
- for j := 0 to Octree.QueryResult.Count - 1 do
- begin
- TestLeaf := TGLSpacePartitionLeafS(Octree.QueryResult[j]);
- if TestLeaf <> Leaf then
- begin
- TGLCube(TestLeaf.GLBaseSceneObject).Material.FrontProperties.Emission.
- Green := 1;
- inc(CollidingLeafCount);
- end;
- end;
- end; // }//*)
- // Cone collision
- { Cone.Base := GLCone1.Position.AsAffineVector;
- Cone.Axis := VectorScale(GLCone1.Up.AsAffineVector, -1);
- Cone.Length := GLCone1.Height;
- Cone.Angle := ArcTan(GLCone1.BottomRadius/GLCone1.Height);
- Octree.QueryCone(Cone);
- for i := 0 to Octree.QueryResult.Count-1 do
- begin
- Leaf := TGLSpacePartitionLeaf(Octree.QueryResult[i]);
- TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
- end;// }
- LabelCollisions.Caption := Format('Nodes = %d, Colliding Leaves = %d',
- [Octree.GetNodeCount, CollidingLeafCount]);
- end;
- procedure TfrmOctreeDemo.TrackBar_LeafThresholdChange(Sender: TObject);
- begin
- Label3.Caption := Format('Leaf Threshold : %d',
- [TrackBar_LeafThreshold.Position]);
- Octree.LeafThreshold := TrackBar_LeafThreshold.Position;
- end;
- procedure TfrmOctreeDemo.VerifySpacialMisc;
- var
- AABBmajor, AABBfull, AABBoff, AABBpartial: TAABB;
- begin
- MakeVector(AABBmajor.Min, 0, 0, 0);
- MakeVector(AABBmajor.Max, 5, 5, 5);
- MakeVector(AABBpartial.Min, 4, 4, 4);
- MakeVector(AABBpartial.Max, 6, 6, 6);
- MakeVector(AABBfull.Min, 1, 1, 1);
- MakeVector(AABBfull.Max, 2, 2, 2);
- MakeVector(AABBoff.Min, 7, 7, 7);
- MakeVector(AABBoff.Max, 8, 8, 8);
- Assert(AABBFitsInAABBAbsolute(AABBfull, AABBmajor),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(IntersectAABBsAbsolute(AABBfull, AABBmajor),
- 'IntersectAABBsAbsolute failed!');
- Assert(AABBContainsAABB(AABBmajor, AABBfull) = scContainsFully,
- 'AABBContainsAABB failed!');
- Assert(not AABBFitsInAABBAbsolute(AABBmajor, AABBfull),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(IntersectAABBsAbsolute(AABBmajor, AABBfull),
- 'IntersectAABBsAbsolute failed!');
- Assert(AABBContainsAABB(AABBfull, AABBmajor) = scContainsPartially,
- 'AABBContainsAABB failed!');
- Assert(not AABBFitsInAABBAbsolute(AABBfull, AABBoff),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(not IntersectAABBsAbsolute(AABBfull, AABBoff),
- 'IntersectAABBsAbsolute failed!');
- Assert(AABBContainsAABB(AABBfull, AABBoff) = scNoOverlap,
- 'AABBContainsAABB failed!');
- Assert(not AABBFitsInAABBAbsolute(AABBoff, AABBfull),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(not IntersectAABBsAbsolute(AABBoff, AABBfull),
- 'IntersectAABBsAbsolute failed!');
- Assert(AABBContainsAABB(AABBoff, AABBfull) = scNoOverlap,
- 'AABBContainsAABB failed!');
- Assert(not AABBFitsInAABBAbsolute(AABBmajor, AABBpartial),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(not AABBFitsInAABBAbsolute(AABBpartial, AABBmajor),
- 'AABBFitsInAABBAbsolute failed!');
- Assert(IntersectAABBsAbsolute(AABBmajor, AABBpartial),
- 'IntersectAABBsAbsolute failed!');
- Assert(IntersectAABBsAbsolute(AABBpartial, AABBmajor),
- 'IntersectAABBsAbsolute failed!');
- Assert(AABBContainsAABB(AABBmajor, AABBpartial) = scContainsPartially,
- 'AABBContainsAABB failed!');
- Assert(AABBContainsAABB(AABBpartial, AABBmajor) = scContainsPartially,
- 'AABBContainsAABB failed!');
- end;
- procedure TfrmOctreeDemo.Button_ResetOctreeSizeClick(Sender: TObject);
- begin
- Octree.GrowMethod := gmBestFit;
- Octree.UpdateStructureSize(0.05);
- Octree.GrowMethod := gmIncreaseToFitAll;
- end;
- procedure TfrmOctreeDemo.FormDestroy(Sender: TObject);
- begin
- Octree.Free;
- end;
- end.
|