| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- unit fQuadtreeCullingD;
- interface
- uses
- Winapi.Windows,
- System.SysUtils,
- System.Classes,
- Vcl.Graphics,
- Vcl.Controls,
- Vcl.Forms,
- Vcl.Dialogs,
- Vcl.Imaging.Jpeg,
- Vcl.ExtCtrls,
- Vcl.StdCtrls,
- Vcl.ComCtrls,
- GLS.Scene,
- Scena.VectorTypes,
- GLS.PersistentClasses,
- GLS.SceneViewer,
- GLS.SkyDome,
- GLS.Objects,
- Scena.Keyboard,
- GLS.HeightData,
- GLS.TerrainRenderer,
- GLS.Texture,
- GLS.Cadencer,
- GLS.Navigator,
- GLS.SpacePartition,
- Scena.VectorGeometry,
- GLS.BitmapFont,
- GLS.GeometryBB,
- GLS.WindowsFont,
- GLS.HUDObjects,
- GLS.Material,
- GLS.Coordinates,
- GLS.BaseClasses,
- GLS.RenderContextInfo,
- GLS.Utils;
- type
- TfrmQuadtreeVisCulling = class(TForm)
- GLScene1: TGLScene;
- trees: TGLDummyCube;
- GLSkyDome1: TGLSkyDome;
- GLSceneViewer1: TGLSceneViewer;
- GLCamera1: TGLCamera;
- GLTerrainRenderer1: TGLTerrainRenderer;
- GLBitmapHDS1: TGLBitmapHDS;
- GLMaterialLibrary1: TGLMaterialLibrary;
- GLCadencer1: TGLCadencer;
- GLNavigator1: TGLNavigator;
- GLUserInterface1: TGLUserInterface;
- queryVisible: TGLDirectOpenGL;
- Timer1: TTimer;
- GLHUDText1: TGLHUDText;
- GLWindowsBitmapFont1: TGLWindowsBitmapFont;
- GLDirectOpenGL1: TGLDirectOpenGL;
- Panel1: TPanel;
- Label1: TLabel;
- ProgressBar1: TProgressBar;
- GLDirectOpenGL2: TGLDirectOpenGL;
- tree: TGLSprite;
- GLSphere1: TGLSphere;
- Panel2: TPanel;
- cbUseQuadtree: TCheckBox;
- cbUseExtendedFrustum: TCheckBox;
- cbShowQuadtree: TCheckBox;
- Label2: TLabel;
- procedure GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure queryVisibleRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure Timer1Timer(Sender: TObject);
- procedure FormKeyPress(Sender: TObject; var Key: Char);
- procedure cbShowQuadtreeClick(Sender: TObject);
- procedure GLDirectOpenGL2Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- procedure Button1Click(Sender: TObject);
- private
- cullingMode: string;
- visiblecount, treecount: integer;
- SpacePartition: TGLSectoredSpacePartition;
- FCamHeight: single;
- procedure CreateTrees;
- public
- end;
- var
- frmQuadtreeVisCulling: TfrmQuadtreeVisCulling;
- implementation
- {$R *.dfm}
- procedure TfrmQuadtreeVisCulling.GLCadencer1Progress(Sender: TObject;
- const deltaTime, newTime: Double);
- var
- speed: single;
- begin
- GLUserInterface1.MouseLook;
- GLUserInterface1.MouseUpdate;
- if IsKeyDown(VK_SHIFT) then
- speed := 6000 * deltaTime
- else
- speed := 1000 * deltaTime;
- with GLCamera1.Position do
- begin
- if IsKeyDown(87) then
- GLNavigator1.MoveForward(speed);
- if IsKeyDown(83) then
- GLNavigator1.MoveForward(-speed);
- if IsKeyDown(65) then
- GLNavigator1.StrafeHorizontal(-speed);
- if IsKeyDown(68) then
- GLNavigator1.StrafeHorizontal(speed);
- if IsKeyDown('e') then
- FCamHeight := FCamHeight + 5;
- if IsKeyDown('c') then
- FCamHeight := FCamHeight - 5;
- if IsKeyDown(VK_ESCAPE) then
- Close;
- end;
- with GLCamera1.Position do
- Y := GLTerrainRenderer1.InterpolatedHeight(AsVector) + 80 + FCamHeight;
- GLHUDText1.Text := cullingMode + 'visible tree count: ' +
- inttostr(visiblecount) + ' / Total:' + inttostr(treecount) + #13#10 +
- ' Press ''W A S D'' to navigate, ''E'' - up, ''C'' - down' + #13#10 +
- ' Press ''Q'' to Show Quadtree, ''X'' - Advanced frustum' + #13#10 +
- ' Press ''V'' to Change quadtree query visible or visiblity culling' +
- #13#10 + ' Press ''Esc'' to quit';
- end;
- procedure TfrmQuadtreeVisCulling.FormCreate(Sender: TObject);
- begin
- var Path: TFileName := GetCurrentAssetPath();
- SetCurrentDir(Path + '\texture');
- SpacePartition := TGLQuadtreeSpacePartition.Create;
- SpacePartition.LeafThreshold := 50;
- SpacePartition.MaxTreeDepth := 10;
- SpacePartition.GrowGravy := 0.01;
- tree.visible := false;
- trees.ObjectsSorting := osRenderFarthestFirst;
- GLBitmapHDS1.Picture.LoadFromFile('terrain.bmp');
- GLMaterialLibrary1.Materials[0].Material.Texture.Image.LoadFromFile
- ('snow512.jpg');
- GLMaterialLibrary1.Materials[1].Material.Texture.Image.LoadFromFile
- ('detailmap.jpg');
- tree.Material.Texture.Image.LoadFromFile('tree1.bmp');
- Show;
- CreateTrees;
- cullingMode := 'Quadtree ';
- GLUserInterface1.MouseLookActivate;
- end;
- procedure TfrmQuadtreeVisCulling.CreateTrees;
- const
- cRange = 40; // 40
- var
- i, j: integer;
- obj: TGLProxyObject;
- begin
- GLScene1.BeginUpdate;
- ProgressBar1.Max := (cRange * 2) * (cRange * 2);
- Label1.Refresh;
- for i := -cRange to cRange do
- for j := -cRange to cRange do
- begin
- inc(treecount);
- ProgressBar1.Position := treecount;
- obj := TGLProxyObject(trees.AddNewChild(TGLProxyObject));
- obj.MasterObject := tree;
- obj.Position.AsAffineVector := AffineVectorMake(i * 500 + random(200), 0,
- j * 500 + random(200));
- with obj.Position do
- Y := GLTerrainRenderer1.InterpolatedHeight(obj.AbsolutePosition) + 150;
- TGLSceneObj.CreateObj(SpacePartition, obj);
- Label2.Caption := Format('Leaves = %d, Nodes = %d, NodesInRoot = %d ',
- [SpacePartition.Leaves.Count, SpacePartition.GetNodeCount,
- SpacePartition.RootNode.Leaves.Count]);
- Label2.Refresh;
- end;
- Panel1.Free;
- GLScene1.EndUpdate;
- end;
- procedure TfrmQuadtreeVisCulling.FormDestroy(Sender: TObject);
- begin
- SpacePartition.Free;
- end;
- procedure TfrmQuadtreeVisCulling.queryVisibleRender(Sender: TObject;
- var rci: TGLRenderContextInfo);
- function PlaneToStr(const APlane: THmgPlane): string;
- begin
- result := Format('(%2.1f, %2.1f, %2.1f, %2.1f)',
- [APlane.X, APlane.Y, APlane.Z, APlane.W]);
- end;
- var
- i: integer;
- begin
- if not cbUseQuadtree.Checked then
- exit;
- GLScene1.BeginUpdate;
- for i := 0 to trees.Count - 1 do
- trees.Children[i].visible := false;
- // Query the Quadtree for objects that intersect the frustum
- if cbUseExtendedFrustum.Checked then
- SpacePartition.QueryFrustumEx(ExtendedFrustumMakeFromSceneViewer
- (rci.rcci.frustum, GLSceneViewer1))
- else
- SpacePartition.QueryFrustum(rci.rcci.frustum);
- visiblecount := SpacePartition.QueryResult.Count;
- Label2.Caption :=
- Format('NodeTests = %d (of %d), ObjTests = %d (of %d), Visible = %d',
- [SpacePartition.QueryNodeTests, SpacePartition.GetNodeCount,
- SpacePartition.QueryInterObjectTests, SpacePartition.Leaves.Count,
- SpacePartition.QueryResult.Count]); // }
- (* if rci.rcci.frustum.pNear[3]>=0 then
- Label3.Caption := 'OK'
- else
- Label3.Caption := 'BAD';// *)
- (* Label3.Caption :=
- Format('%s, %s, %s, %s, %s, %s',[
- PlaneToStr(rci.rcci.frustum.pNear),
- PlaneToStr(rci.rcci.frustum.pFar),
- PlaneToStr(rci.rcci.frustum.pTop),
- PlaneToStr(rci.rcci.frustum.pBottom),
- PlaneToStr(rci.rcci.frustum.pLeft),
- PlaneToStr(rci.rcci.frustum.pRight)]);// *)
- for i := 0 to SpacePartition.QueryResult.Count - 1 do
- begin
- TGLSceneObj(SpacePartition.QueryResult[i]).obj.visible := true;
- if cbShowQuadtree.Checked then
- RenderAABB(rci, TGLSceneObj(SpacePartition.QueryResult[i]).FCachedAABB);
- end;
- GLScene1.EndUpdate;
- end;
- procedure TfrmQuadtreeVisCulling.Timer1Timer(Sender: TObject);
- begin
- Caption := 'Quardtree Visibility Culling - ' +
- GLSceneViewer1.FramesPerSecondText;
- GLSceneViewer1.ResetPerformanceMonitor;
- end;
- procedure TfrmQuadtreeVisCulling.FormKeyPress(Sender: TObject; var Key: Char);
- var
- i: integer;
- begin
- if Key = 'v' then
- begin
- cbUseQuadtree.Checked := not cbUseQuadtree.Checked;
- if cbUseQuadtree.Checked then
- begin
- cullingMode := ' Quadtree ';
- for i := 0 to trees.Count - 1 do
- trees.Children[i].visible := true;
- trees.VisibilityCulling := vcNone;
- end
- else
- begin
- cullingMode := 'visibility culling ';
- for i := 0 to trees.Count - 1 do
- trees.Children[i].visible := true;
- trees.VisibilityCulling := vcObjectBased;
- end;
- end;
- end;
- procedure TfrmQuadtreeVisCulling.cbShowQuadtreeClick(Sender: TObject);
- begin
- GLDirectOpenGL2.visible := cbShowQuadtree.Checked;
- end;
- procedure TfrmQuadtreeVisCulling.GLDirectOpenGL2Render(Sender: TObject;
- var rci: TGLRenderContextInfo);
- (*
- var
- ExtendendFrustum : TGLExtendedFrustum;
- *)
- begin
- RenderSpatialPartitioning(rci, SpacePartition);
- (*
- ExtendendFrustum := ExtendedFrustumMake(rci.rcci.frustum,
- GLCamera1.NearPlane,
- GLCamera1.DepthOfView,
- GLSceneViewer1.FieldOfView,
- GLCamera1.Position.AsAffineVector,
- GLCamera1.Direction.AsAffineVector);//
- *)
- (*
- ExtendendFrustum := ExtendedFrustumMakeFromSceneViewer(
- rci.rcci.frustum, GLSceneViewer1);
- GLSphere1.Position.AsAffineVector :=
- VectorCombine(ExtendendFrustum.SPCone.Base, ExtendendFrustum.SPCone.Axis, 1, GLCamera1.DepthOfView * 0.05);
- GLSphere1.Radius := sin(ExtendendFrustum.SPCone.Angle) * GLCamera1.DepthOfView * 0.05;
- GLSphere1.Position.AsAffineVector := ExtendendFrustum.BSphere.Center;
- GLSphere1.Radius := ExtendendFrustum.BSphere.Radius / 1.42;//
- *)
- end;
- procedure TfrmQuadtreeVisCulling.Button1Click(Sender: TObject);
- begin
- GLSphere1.Position.AsVector := VectorCombine(GLCamera1.Position.AsVector,
- GLCamera1.Direction.AsVector, 1, GLCamera1.NearPlane)
- end;
- end.
|