fQuadtreeCullingD.pas 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. unit fQuadtreeCullingD;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. System.SysUtils,
  6. System.Classes,
  7. Vcl.Graphics,
  8. Vcl.Controls,
  9. Vcl.Forms,
  10. Vcl.Dialogs,
  11. Vcl.Imaging.Jpeg,
  12. Vcl.ExtCtrls,
  13. Vcl.StdCtrls,
  14. Vcl.ComCtrls,
  15. GLS.Scene,
  16. Scena.VectorTypes,
  17. GLS.PersistentClasses,
  18. GLS.SceneViewer,
  19. GLS.SkyDome,
  20. GLS.Objects,
  21. Scena.Keyboard,
  22. GLS.HeightData,
  23. GLS.TerrainRenderer,
  24. GLS.Texture,
  25. GLS.Cadencer,
  26. GLS.Navigator,
  27. GLS.SpacePartition,
  28. Scena.VectorGeometry,
  29. GLS.BitmapFont,
  30. GLS.GeometryBB,
  31. GLS.WindowsFont,
  32. GLS.HUDObjects,
  33. GLS.Material,
  34. GLS.Coordinates,
  35. GLS.BaseClasses,
  36. GLS.RenderContextInfo,
  37. GLS.Utils;
  38. type
  39. TfrmQuadtreeVisCulling = class(TForm)
  40. GLScene1: TGLScene;
  41. trees: TGLDummyCube;
  42. GLSkyDome1: TGLSkyDome;
  43. GLSceneViewer1: TGLSceneViewer;
  44. GLCamera1: TGLCamera;
  45. GLTerrainRenderer1: TGLTerrainRenderer;
  46. GLBitmapHDS1: TGLBitmapHDS;
  47. GLMaterialLibrary1: TGLMaterialLibrary;
  48. GLCadencer1: TGLCadencer;
  49. GLNavigator1: TGLNavigator;
  50. GLUserInterface1: TGLUserInterface;
  51. queryVisible: TGLDirectOpenGL;
  52. Timer1: TTimer;
  53. GLHUDText1: TGLHUDText;
  54. GLWindowsBitmapFont1: TGLWindowsBitmapFont;
  55. GLDirectOpenGL1: TGLDirectOpenGL;
  56. Panel1: TPanel;
  57. Label1: TLabel;
  58. ProgressBar1: TProgressBar;
  59. GLDirectOpenGL2: TGLDirectOpenGL;
  60. tree: TGLSprite;
  61. GLSphere1: TGLSphere;
  62. Panel2: TPanel;
  63. cbUseQuadtree: TCheckBox;
  64. cbUseExtendedFrustum: TCheckBox;
  65. cbShowQuadtree: TCheckBox;
  66. Label2: TLabel;
  67. procedure GLCadencer1Progress(Sender: TObject;
  68. const deltaTime, newTime: Double);
  69. procedure FormCreate(Sender: TObject);
  70. procedure FormDestroy(Sender: TObject);
  71. procedure queryVisibleRender(Sender: TObject;
  72. var rci: TGLRenderContextInfo);
  73. procedure Timer1Timer(Sender: TObject);
  74. procedure FormKeyPress(Sender: TObject; var Key: Char);
  75. procedure cbShowQuadtreeClick(Sender: TObject);
  76. procedure GLDirectOpenGL2Render(Sender: TObject;
  77. var rci: TGLRenderContextInfo);
  78. procedure Button1Click(Sender: TObject);
  79. private
  80. cullingMode: string;
  81. visiblecount, treecount: integer;
  82. SpacePartition: TGLSectoredSpacePartition;
  83. FCamHeight: single;
  84. procedure CreateTrees;
  85. public
  86. end;
  87. var
  88. frmQuadtreeVisCulling: TfrmQuadtreeVisCulling;
  89. implementation
  90. {$R *.dfm}
  91. procedure TfrmQuadtreeVisCulling.GLCadencer1Progress(Sender: TObject;
  92. const deltaTime, newTime: Double);
  93. var
  94. speed: single;
  95. begin
  96. GLUserInterface1.MouseLook;
  97. GLUserInterface1.MouseUpdate;
  98. if IsKeyDown(VK_SHIFT) then
  99. speed := 6000 * deltaTime
  100. else
  101. speed := 1000 * deltaTime;
  102. with GLCamera1.Position do
  103. begin
  104. if IsKeyDown(87) then
  105. GLNavigator1.MoveForward(speed);
  106. if IsKeyDown(83) then
  107. GLNavigator1.MoveForward(-speed);
  108. if IsKeyDown(65) then
  109. GLNavigator1.StrafeHorizontal(-speed);
  110. if IsKeyDown(68) then
  111. GLNavigator1.StrafeHorizontal(speed);
  112. if IsKeyDown('e') then
  113. FCamHeight := FCamHeight + 5;
  114. if IsKeyDown('c') then
  115. FCamHeight := FCamHeight - 5;
  116. if IsKeyDown(VK_ESCAPE) then
  117. Close;
  118. end;
  119. with GLCamera1.Position do
  120. Y := GLTerrainRenderer1.InterpolatedHeight(AsVector) + 80 + FCamHeight;
  121. GLHUDText1.Text := cullingMode + 'visible tree count: ' +
  122. inttostr(visiblecount) + ' / Total:' + inttostr(treecount) + #13#10 +
  123. ' Press ''W A S D'' to navigate, ''E'' - up, ''C'' - down' + #13#10 +
  124. ' Press ''Q'' to Show Quadtree, ''X'' - Advanced frustum' + #13#10 +
  125. ' Press ''V'' to Change quadtree query visible or visiblity culling' +
  126. #13#10 + ' Press ''Esc'' to quit';
  127. end;
  128. procedure TfrmQuadtreeVisCulling.FormCreate(Sender: TObject);
  129. begin
  130. var Path: TFileName := GetCurrentAssetPath();
  131. SetCurrentDir(Path + '\texture');
  132. SpacePartition := TGLQuadtreeSpacePartition.Create;
  133. SpacePartition.LeafThreshold := 50;
  134. SpacePartition.MaxTreeDepth := 10;
  135. SpacePartition.GrowGravy := 0.01;
  136. tree.visible := false;
  137. trees.ObjectsSorting := osRenderFarthestFirst;
  138. GLBitmapHDS1.Picture.LoadFromFile('terrain.bmp');
  139. GLMaterialLibrary1.Materials[0].Material.Texture.Image.LoadFromFile
  140. ('snow512.jpg');
  141. GLMaterialLibrary1.Materials[1].Material.Texture.Image.LoadFromFile
  142. ('detailmap.jpg');
  143. tree.Material.Texture.Image.LoadFromFile('tree1.bmp');
  144. Show;
  145. CreateTrees;
  146. cullingMode := 'Quadtree ';
  147. GLUserInterface1.MouseLookActivate;
  148. end;
  149. procedure TfrmQuadtreeVisCulling.CreateTrees;
  150. const
  151. cRange = 40; // 40
  152. var
  153. i, j: integer;
  154. obj: TGLProxyObject;
  155. begin
  156. GLScene1.BeginUpdate;
  157. ProgressBar1.Max := (cRange * 2) * (cRange * 2);
  158. Label1.Refresh;
  159. for i := -cRange to cRange do
  160. for j := -cRange to cRange do
  161. begin
  162. inc(treecount);
  163. ProgressBar1.Position := treecount;
  164. obj := TGLProxyObject(trees.AddNewChild(TGLProxyObject));
  165. obj.MasterObject := tree;
  166. obj.Position.AsAffineVector := AffineVectorMake(i * 500 + random(200), 0,
  167. j * 500 + random(200));
  168. with obj.Position do
  169. Y := GLTerrainRenderer1.InterpolatedHeight(obj.AbsolutePosition) + 150;
  170. TGLSceneObj.CreateObj(SpacePartition, obj);
  171. Label2.Caption := Format('Leaves = %d, Nodes = %d, NodesInRoot = %d ',
  172. [SpacePartition.Leaves.Count, SpacePartition.GetNodeCount,
  173. SpacePartition.RootNode.Leaves.Count]);
  174. Label2.Refresh;
  175. end;
  176. Panel1.Free;
  177. GLScene1.EndUpdate;
  178. end;
  179. procedure TfrmQuadtreeVisCulling.FormDestroy(Sender: TObject);
  180. begin
  181. SpacePartition.Free;
  182. end;
  183. procedure TfrmQuadtreeVisCulling.queryVisibleRender(Sender: TObject;
  184. var rci: TGLRenderContextInfo);
  185. function PlaneToStr(const APlane: THmgPlane): string;
  186. begin
  187. result := Format('(%2.1f, %2.1f, %2.1f, %2.1f)',
  188. [APlane.X, APlane.Y, APlane.Z, APlane.W]);
  189. end;
  190. var
  191. i: integer;
  192. begin
  193. if not cbUseQuadtree.Checked then
  194. exit;
  195. GLScene1.BeginUpdate;
  196. for i := 0 to trees.Count - 1 do
  197. trees.Children[i].visible := false;
  198. // Query the Quadtree for objects that intersect the frustum
  199. if cbUseExtendedFrustum.Checked then
  200. SpacePartition.QueryFrustumEx(ExtendedFrustumMakeFromSceneViewer
  201. (rci.rcci.frustum, GLSceneViewer1))
  202. else
  203. SpacePartition.QueryFrustum(rci.rcci.frustum);
  204. visiblecount := SpacePartition.QueryResult.Count;
  205. Label2.Caption :=
  206. Format('NodeTests = %d (of %d), ObjTests = %d (of %d), Visible = %d',
  207. [SpacePartition.QueryNodeTests, SpacePartition.GetNodeCount,
  208. SpacePartition.QueryInterObjectTests, SpacePartition.Leaves.Count,
  209. SpacePartition.QueryResult.Count]); // }
  210. (* if rci.rcci.frustum.pNear[3]>=0 then
  211. Label3.Caption := 'OK'
  212. else
  213. Label3.Caption := 'BAD';// *)
  214. (* Label3.Caption :=
  215. Format('%s, %s, %s, %s, %s, %s',[
  216. PlaneToStr(rci.rcci.frustum.pNear),
  217. PlaneToStr(rci.rcci.frustum.pFar),
  218. PlaneToStr(rci.rcci.frustum.pTop),
  219. PlaneToStr(rci.rcci.frustum.pBottom),
  220. PlaneToStr(rci.rcci.frustum.pLeft),
  221. PlaneToStr(rci.rcci.frustum.pRight)]);// *)
  222. for i := 0 to SpacePartition.QueryResult.Count - 1 do
  223. begin
  224. TGLSceneObj(SpacePartition.QueryResult[i]).obj.visible := true;
  225. if cbShowQuadtree.Checked then
  226. RenderAABB(rci, TGLSceneObj(SpacePartition.QueryResult[i]).FCachedAABB);
  227. end;
  228. GLScene1.EndUpdate;
  229. end;
  230. procedure TfrmQuadtreeVisCulling.Timer1Timer(Sender: TObject);
  231. begin
  232. Caption := 'Quardtree Visibility Culling - ' +
  233. GLSceneViewer1.FramesPerSecondText;
  234. GLSceneViewer1.ResetPerformanceMonitor;
  235. end;
  236. procedure TfrmQuadtreeVisCulling.FormKeyPress(Sender: TObject; var Key: Char);
  237. var
  238. i: integer;
  239. begin
  240. if Key = 'v' then
  241. begin
  242. cbUseQuadtree.Checked := not cbUseQuadtree.Checked;
  243. if cbUseQuadtree.Checked then
  244. begin
  245. cullingMode := ' Quadtree ';
  246. for i := 0 to trees.Count - 1 do
  247. trees.Children[i].visible := true;
  248. trees.VisibilityCulling := vcNone;
  249. end
  250. else
  251. begin
  252. cullingMode := 'visibility culling ';
  253. for i := 0 to trees.Count - 1 do
  254. trees.Children[i].visible := true;
  255. trees.VisibilityCulling := vcObjectBased;
  256. end;
  257. end;
  258. end;
  259. procedure TfrmQuadtreeVisCulling.cbShowQuadtreeClick(Sender: TObject);
  260. begin
  261. GLDirectOpenGL2.visible := cbShowQuadtree.Checked;
  262. end;
  263. procedure TfrmQuadtreeVisCulling.GLDirectOpenGL2Render(Sender: TObject;
  264. var rci: TGLRenderContextInfo);
  265. (*
  266. var
  267. ExtendendFrustum : TGLExtendedFrustum;
  268. *)
  269. begin
  270. RenderSpatialPartitioning(rci, SpacePartition);
  271. (*
  272. ExtendendFrustum := ExtendedFrustumMake(rci.rcci.frustum,
  273. GLCamera1.NearPlane,
  274. GLCamera1.DepthOfView,
  275. GLSceneViewer1.FieldOfView,
  276. GLCamera1.Position.AsAffineVector,
  277. GLCamera1.Direction.AsAffineVector);//
  278. *)
  279. (*
  280. ExtendendFrustum := ExtendedFrustumMakeFromSceneViewer(
  281. rci.rcci.frustum, GLSceneViewer1);
  282. GLSphere1.Position.AsAffineVector :=
  283. VectorCombine(ExtendendFrustum.SPCone.Base, ExtendendFrustum.SPCone.Axis, 1, GLCamera1.DepthOfView * 0.05);
  284. GLSphere1.Radius := sin(ExtendendFrustum.SPCone.Angle) * GLCamera1.DepthOfView * 0.05;
  285. GLSphere1.Position.AsAffineVector := ExtendendFrustum.BSphere.Center;
  286. GLSphere1.Radius := ExtendendFrustum.BSphere.Radius / 1.42;//
  287. *)
  288. end;
  289. procedure TfrmQuadtreeVisCulling.Button1Click(Sender: TObject);
  290. begin
  291. GLSphere1.Position.AsVector := VectorCombine(GLCamera1.Position.AsVector,
  292. GLCamera1.Direction.AsVector, 1, GLCamera1.NearPlane)
  293. end;
  294. end.