fQuadtreeCullingD.pas 9.2 KB

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