fOctreeRenderD.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. unit fOctreeRenderD;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Classes,
  7. System.Types,
  8. System.Math,
  9. Vcl.Graphics,
  10. Vcl.Controls,
  11. Vcl.Forms,
  12. Vcl.Dialogs,
  13. Vcl.ExtCtrls,
  14. Vcl.StdCtrls,
  15. Vcl.ComCtrls,
  16. GLS.Objects,
  17. GLS.Scene,
  18. GLS.Cadencer,
  19. GLS.SceneViewer,
  20. GLS.VectorGeometry,
  21. GLS.VectorTypes,
  22. GLS.GeometryBB,
  23. GLS.Texture,
  24. GLS.SpacePartition,
  25. GLS.Coordinates,
  26. GLS.RenderContextInfo,
  27. GLS.State,
  28. GLS.SimpleNavigation,
  29. GLS.Material,
  30. GLS.Context,
  31. GLS.BaseClasses;
  32. const
  33. cBOX_SIZE = 14.2;
  34. type
  35. TfrmOctreeDemo = class(TForm)
  36. GLScene1: TGLScene;
  37. GLSceneViewer1: TGLSceneViewer;
  38. GLLightSource1: TGLLightSource;
  39. GLCamera1: TGLCamera;
  40. GLDummyCube1: TGLDummyCube;
  41. GLDirectOpenGL1: TGLDirectOpenGL;
  42. GLCube1: TGLCube;
  43. GLCadencer1: TGLCadencer;
  44. GLSphere1: TGLSphere;
  45. GLPlane1: TGLPlane;
  46. GLSimpleNavigation1: TGLSimpleNavigation;
  47. GLMaterialLibrary1: TGLMaterialLibrary;
  48. Panel1: TPanel;
  49. Label3: TLabel;
  50. TrackBar_LeafThreshold: TTrackBar;
  51. Label2: TLabel;
  52. Button_ResetOctreeSize: TButton;
  53. LabelCollisions: TLabel;
  54. procedure FormCreate(Sender: TObject);
  55. procedure GLDirectOpenGL1Render(Sender: TObject;
  56. var rci: TGLRenderContextInfo);
  57. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  58. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  59. procedure GLCadencer1Progress(Sender: TObject;
  60. const deltaTime, newTime: Double);
  61. procedure TrackBar_LeafThresholdChange(Sender: TObject);
  62. procedure Button_ResetOctreeSizeClick(Sender: TObject);
  63. procedure FormDestroy(Sender: TObject);
  64. public
  65. Octree: TGLOctreeSpacePartition;
  66. procedure CreateBox;
  67. procedure VerifySpacialMisc;
  68. end;
  69. var
  70. frmOctreeDemo: TfrmOctreeDemo;
  71. //========================================================
  72. implementation
  73. //========================================================
  74. {$R *.dfm}
  75. procedure TfrmOctreeDemo.FormCreate(Sender: TObject);
  76. var
  77. i: Integer;
  78. begin
  79. randomize;
  80. Octree := TGLOctreeSpacePartition.Create;
  81. Octree.SetSize(AffineVectorMake(-15, -15, -15), AffineVectorMake(15, 15, 15));
  82. Octree.MaxTreeDepth := 6;
  83. Octree.LeafThreshold := 10;
  84. TrackBar_LeafThresholdChange(nil);
  85. for i := 0 to 300 do
  86. CreateBox;
  87. VerifySpacialMisc;
  88. end;
  89. procedure TfrmOctreeDemo.CreateBox;
  90. function randomPos: TAffineVector;
  91. const
  92. c1 = 10;
  93. begin
  94. // MakeVector(result, random*c1-c1/2, random*c1-c1/2, random*c1-c1/2);
  95. MakeVector(result, random, random, random);
  96. end;
  97. function randomSize: Single;
  98. begin
  99. result := 0.1 + random * 0.5;
  100. end;
  101. var
  102. Cube: TGLCube;
  103. begin
  104. Cube := TGLCube(GLScene1.Objects.AddNewChild(TGLCube));
  105. Cube.Position.AsAffineVector := randomPos;
  106. Cube.CubeWidth := randomSize;
  107. Cube.CubeHeight := randomSize;
  108. Cube.CubeDepth := randomSize;
  109. TGLSpacePartitionLeafS.CreateGLOwned(Octree, Cube);
  110. end;
  111. procedure TfrmOctreeDemo.GLDirectOpenGL1Render(Sender: TObject;
  112. var rci: TGLRenderContextInfo);
  113. procedure RenderAABB(AABB: TAABB; w, r, g, b: Single);
  114. begin
  115. glColor3f(r, g, b);
  116. rci.GLStates.LineWidth := w;
  117. glBegin(GL_LINE_STRIP);
  118. glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Min.Z);
  119. glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Min.Z);
  120. glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Min.Z);
  121. glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Min.Z);
  122. glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Min.Z);
  123. glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Max.Z);
  124. glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Max.Z);
  125. glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Max.Z);
  126. glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Max.Z);
  127. glVertex3f(AABB.Min.X, AABB.Min.Y, AABB.Max.Z);
  128. glEnd();
  129. glBegin(GL_LINES);
  130. glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Min.Z);
  131. glVertex3f(AABB.Min.X, AABB.Max.Y, AABB.Max.Z);
  132. glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Min.Z);
  133. glVertex3f(AABB.Max.X, AABB.Max.Y, AABB.Max.Z);
  134. glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Min.Z);
  135. glVertex3f(AABB.Max.X, AABB.Min.Y, AABB.Max.Z);
  136. glEnd;
  137. end;
  138. procedure RenderOctreeNode(Node: TGLSectorNode);
  139. var
  140. i: Integer;
  141. AABB: TAABB;
  142. begin
  143. if Node.NoChildren then
  144. begin
  145. AABB := Node.AABB;
  146. if Node.RecursiveLeafCount > 0 then
  147. RenderAABB(AABB, 1, 0, 0, 0)
  148. else
  149. RenderAABB(AABB, 1, 0.8, 0.8, 0.8) // }
  150. end
  151. else
  152. begin
  153. for i := 0 to Node.ChildCount - 1 do
  154. RenderOctreeNode(Node.Children[i]);
  155. end;
  156. end;
  157. var
  158. AABB: TAABB;
  159. begin
  160. rci.GLStates.Disable(stLighting);
  161. rci.GLStates.Enable(stColorMaterial);
  162. MakeVector(AABB.Min, -cBOX_SIZE, -cBOX_SIZE, -cBOX_SIZE);
  163. MakeVector(AABB.Max, cBOX_SIZE, cBOX_SIZE, cBOX_SIZE);
  164. RenderAABB(AABB, 2, 0, 0, 0);
  165. RenderOctreeNode(Octree.RootNode);
  166. end;
  167. procedure TfrmOctreeDemo.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  168. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  169. begin
  170. GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
  171. Handled := true
  172. end;
  173. procedure TfrmOctreeDemo.GLCadencer1Progress(Sender: TObject;
  174. const deltaTime, newTime: Double);
  175. var
  176. AABB: TAABB;
  177. BSphere: TBSphere;
  178. Leaf, TestLeaf: TGLSpacePartitionLeafS;
  179. Cube: TGLCube;
  180. i, j, CollidingLeafCount: Integer;
  181. (*sub*)function TestMove(pos: Single; var dir: Single): Single;
  182. const
  183. cSPEED = 2;
  184. begin
  185. if (abs(pos + dir * deltaTime * cSPEED) >= cBOX_SIZE) then
  186. dir := -dir;
  187. result := pos + dir * deltaTime * cSPEED;
  188. end;
  189. begin
  190. for i := 0 to Octree.Leaves.Count - 1 do
  191. begin
  192. Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
  193. Cube := TGLCube(Leaf.GLBaseSceneObject);
  194. Cube.Position.X := TestMove(Cube.Position.X, Leaf.Direction.X);
  195. Cube.Position.Y := TestMove(Cube.Position.Y, Leaf.Direction.Y);
  196. Cube.Position.Z := TestMove(Cube.Position.Z, Leaf.Direction.Z);
  197. Leaf.Changed;
  198. end; // }
  199. for i := 0 to Octree.Leaves.Count - 1 do
  200. begin
  201. Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
  202. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 0;
  203. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.
  204. Green := 0;
  205. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Blue := 0;
  206. end; // }
  207. // AABB collision
  208. AABB := GLCube1.AxisAlignedBoundingBox;
  209. AABB.Min := GLCube1.LocalToAbsolute(AABB.Min);
  210. AABB.Max := GLCube1.LocalToAbsolute(AABB.Max);
  211. Octree.QueryAABB(AABB);
  212. for i := 0 to Octree.QueryResult.Count - 1 do
  213. begin
  214. Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
  215. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
  216. end; // }
  217. // BSphere collision
  218. BSphere.Center := GLSphere1.Position.AsAffineVector;
  219. BSphere.Radius := GLSphere1.Radius;
  220. Octree.QueryBSphere(BSphere);
  221. for i := 0 to Octree.QueryResult.Count - 1 do
  222. begin
  223. Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
  224. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
  225. end; // }
  226. // Plane collision
  227. if GLPlane1.Visible then
  228. begin
  229. Octree.QueryPlane(GLPlane1.Position.AsAffineVector,
  230. GLPlane1.Direction.AsAffineVector);
  231. for i := 0 to Octree.QueryResult.Count - 1 do
  232. begin
  233. Leaf := TGLSpacePartitionLeafS(Octree.QueryResult[i]);
  234. TGLCube(Leaf.GLBaseSceneObject)
  235. .Material.FrontProperties.Emission.Blue := 1;
  236. end; // }
  237. end;
  238. // Leaf - leaf collision
  239. CollidingLeafCount := 0;
  240. for i := 0 to Octree.Leaves.Count - 1 do
  241. begin
  242. Leaf := TGLSpacePartitionLeafS(Octree.Leaves[i]);
  243. Octree.QueryAABB(Leaf.FCachedAABB);
  244. for j := 0 to Octree.QueryResult.Count - 1 do
  245. begin
  246. TestLeaf := TGLSpacePartitionLeafS(Octree.QueryResult[j]);
  247. if TestLeaf <> Leaf then
  248. begin
  249. TGLCube(TestLeaf.GLBaseSceneObject).Material.FrontProperties.Emission.
  250. Green := 1;
  251. inc(CollidingLeafCount);
  252. end;
  253. end;
  254. end; // }//*)
  255. // Cone collision
  256. { Cone.Base := GLCone1.Position.AsAffineVector;
  257. Cone.Axis := VectorScale(GLCone1.Up.AsAffineVector, -1);
  258. Cone.Length := GLCone1.Height;
  259. Cone.Angle := ArcTan(GLCone1.BottomRadius/GLCone1.Height);
  260. Octree.QueryCone(Cone);
  261. for i := 0 to Octree.QueryResult.Count-1 do
  262. begin
  263. Leaf := TGLSpacePartitionLeaf(Octree.QueryResult[i]);
  264. TGLCube(Leaf.GLBaseSceneObject).Material.FrontProperties.Emission.Red := 1;
  265. end;// }
  266. LabelCollisions.Caption := Format('Nodes = %d, Colliding Leaves = %d',
  267. [Octree.GetNodeCount, CollidingLeafCount]);
  268. end;
  269. procedure TfrmOctreeDemo.TrackBar_LeafThresholdChange(Sender: TObject);
  270. begin
  271. Label3.Caption := Format('Leaf Threshold : %d',
  272. [TrackBar_LeafThreshold.Position]);
  273. Octree.LeafThreshold := TrackBar_LeafThreshold.Position;
  274. end;
  275. procedure TfrmOctreeDemo.VerifySpacialMisc;
  276. var
  277. AABBmajor, AABBfull, AABBoff, AABBpartial: TAABB;
  278. begin
  279. MakeVector(AABBmajor.Min, 0, 0, 0);
  280. MakeVector(AABBmajor.Max, 5, 5, 5);
  281. MakeVector(AABBpartial.Min, 4, 4, 4);
  282. MakeVector(AABBpartial.Max, 6, 6, 6);
  283. MakeVector(AABBfull.Min, 1, 1, 1);
  284. MakeVector(AABBfull.Max, 2, 2, 2);
  285. MakeVector(AABBoff.Min, 7, 7, 7);
  286. MakeVector(AABBoff.Max, 8, 8, 8);
  287. Assert(AABBFitsInAABBAbsolute(AABBfull, AABBmajor),
  288. 'AABBFitsInAABBAbsolute failed!');
  289. Assert(IntersectAABBsAbsolute(AABBfull, AABBmajor),
  290. 'IntersectAABBsAbsolute failed!');
  291. Assert(AABBContainsAABB(AABBmajor, AABBfull) = scContainsFully,
  292. 'AABBContainsAABB failed!');
  293. Assert(not AABBFitsInAABBAbsolute(AABBmajor, AABBfull),
  294. 'AABBFitsInAABBAbsolute failed!');
  295. Assert(IntersectAABBsAbsolute(AABBmajor, AABBfull),
  296. 'IntersectAABBsAbsolute failed!');
  297. Assert(AABBContainsAABB(AABBfull, AABBmajor) = scContainsPartially,
  298. 'AABBContainsAABB failed!');
  299. Assert(not AABBFitsInAABBAbsolute(AABBfull, AABBoff),
  300. 'AABBFitsInAABBAbsolute failed!');
  301. Assert(not IntersectAABBsAbsolute(AABBfull, AABBoff),
  302. 'IntersectAABBsAbsolute failed!');
  303. Assert(AABBContainsAABB(AABBfull, AABBoff) = scNoOverlap,
  304. 'AABBContainsAABB failed!');
  305. Assert(not AABBFitsInAABBAbsolute(AABBoff, AABBfull),
  306. 'AABBFitsInAABBAbsolute failed!');
  307. Assert(not IntersectAABBsAbsolute(AABBoff, AABBfull),
  308. 'IntersectAABBsAbsolute failed!');
  309. Assert(AABBContainsAABB(AABBoff, AABBfull) = scNoOverlap,
  310. 'AABBContainsAABB failed!');
  311. Assert(not AABBFitsInAABBAbsolute(AABBmajor, AABBpartial),
  312. 'AABBFitsInAABBAbsolute failed!');
  313. Assert(not AABBFitsInAABBAbsolute(AABBpartial, AABBmajor),
  314. 'AABBFitsInAABBAbsolute failed!');
  315. Assert(IntersectAABBsAbsolute(AABBmajor, AABBpartial),
  316. 'IntersectAABBsAbsolute failed!');
  317. Assert(IntersectAABBsAbsolute(AABBpartial, AABBmajor),
  318. 'IntersectAABBsAbsolute failed!');
  319. Assert(AABBContainsAABB(AABBmajor, AABBpartial) = scContainsPartially,
  320. 'AABBContainsAABB failed!');
  321. Assert(AABBContainsAABB(AABBpartial, AABBmajor) = scContainsPartially,
  322. 'AABBContainsAABB failed!');
  323. end;
  324. procedure TfrmOctreeDemo.Button_ResetOctreeSizeClick(Sender: TObject);
  325. begin
  326. Octree.GrowMethod := gmBestFit;
  327. Octree.UpdateStructureSize(0.05);
  328. Octree.GrowMethod := gmIncreaseToFitAll;
  329. end;
  330. procedure TfrmOctreeDemo.FormDestroy(Sender: TObject);
  331. begin
  332. Octree.Free;
  333. end;
  334. end.