fFacevsFaceD.pas 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. unit fFacevsFaceD;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.Classes,
  6. System.SysUtils,
  7. System.Math,
  8. System.Types,
  9. Vcl.Forms,
  10. Vcl.Controls,
  11. Vcl.Graphics,
  12. Vcl.StdCtrls,
  13. Vcl.ExtCtrls,
  14. Vcl.ComCtrls,
  15. Vcl.Grids,
  16. GLS.VectorTypes,
  17. GLS.Scene,
  18. GLS.Objects,
  19. GLS.SceneViewer,
  20. GLS.VectorGeometry,
  21. GLS.SpaceText,
  22. GLS.Collision,
  23. GLS.VectorFileObjects,
  24. GLS.VectorLists,
  25. GLS.File3DS,
  26. GLS.Coordinates,
  27. GLS.Utils,
  28. GLS.BaseClasses;
  29. type
  30. TFormFacevsFace = class(TForm)
  31. GLScene1: TGLScene;
  32. GLSceneViewer1: TGLSceneViewer;
  33. GLLightSource1: TGLLightSource;
  34. DummyCube1: TGLDummyCube;
  35. Timer1: TTimer;
  36. GLCamera2: TGLCamera;
  37. Panel1: TPanel;
  38. txtX: TGLSpaceText;
  39. txtY: TGLSpaceText;
  40. txtZ: TGLSpaceText;
  41. CollisionManager1: TGLCollisionManager;
  42. cbCollisionMode: TRadioGroup;
  43. Bar: TGLCube;
  44. Teapot1: TGLFreeForm;
  45. Teapot2: TGLFreeForm;
  46. Shape1: TShape;
  47. Cube2: TGLCube;
  48. Label1: TLabel;
  49. LATime: TLabel;
  50. Label2: TLabel;
  51. GLSphere1: TGLSphere;
  52. CubePoint1: TGLCube;
  53. GLSphere2: TGLSphere;
  54. Panel2: TPanel;
  55. StringGrid1: TStringGrid;
  56. Memo1: TMemo;
  57. GLSphereEllipsoid1: TGLSphere;
  58. GLSphereEllipsoid2: TGLSphere;
  59. CubePoint2: TGLCube;
  60. GLLightSource2: TGLLightSource;
  61. GLCube1: TGLCube;
  62. GLCamera1: TGLCamera;
  63. GLCamera3: TGLCamera;
  64. Splitter1: TSplitter;
  65. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  66. X, Y: Integer);
  67. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  68. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
  69. MousePos: TPoint; var Handled: Boolean);
  70. procedure Timer1Timer(Sender: TObject);
  71. procedure FormShow(Sender: TObject);
  72. procedure CollisionManager1Collision(Sender: TObject; object1, object2: TGLBaseSceneObject);
  73. procedure cbCollisionModeClick(Sender: TObject);
  74. procedure FormCreate(Sender: TObject);
  75. private
  76. mdx, mdy: Integer;
  77. CollisionDetected: Boolean;
  78. public
  79. CurrSO: TGLCustomSceneObject;
  80. end;
  81. var
  82. FormFacevsFace: TFormFacevsFace;
  83. const
  84. StringNames: array [0 .. Ord(cbmFaces)] of String = ('Point', 'Sphere', 'Ellipsoid',
  85. 'Cube', 'Faces');
  86. implementation
  87. {$R *.DFM}
  88. procedure TFormFacevsFace.FormCreate(Sender: TObject);
  89. var
  90. i: Integer;
  91. begin
  92. var Path: TFileName := GetCurrentAssetPath();
  93. SetCurrentDir(Path + '\model');
  94. Teapot1.LoadFromFile('TeaPot.3ds');
  95. Teapot1.BuildOctree;
  96. Teapot2.LoadFromFile('TeaPot.3ds');
  97. Teapot2.BuildOctree;
  98. // rgObjectsClick(nil);
  99. // Fill StringGrid1 with current state of collisions
  100. for i := 0 to Ord(cbmFaces) do
  101. begin
  102. StringGrid1.Cells[0, i + 1] := StringNames[i];
  103. StringGrid1.Cells[i + 1, 0] := StringNames[i];
  104. end;
  105. // point
  106. StringGrid1.Cells[1, 1] := 'complete'; // Point-Point
  107. StringGrid1.Cells[1, 2] := 'complete'; // Sphere-Point
  108. StringGrid1.Cells[1, 3] := 'complete'; // Ellipsoid-Point
  109. StringGrid1.Cells[1, 4] := 'complete'; // Cube-Point
  110. StringGrid1.Cells[1, 5] := 'Cube-Point'; // Faces-Point
  111. // sphere
  112. StringGrid1.Cells[2, 1] := 'complete'; // Point-Sphere
  113. StringGrid1.Cells[2, 2] := 'complete'; // Sphere-Sphere
  114. StringGrid1.Cells[2, 3] := 'complete'; // Ellipsoid-Sphere
  115. StringGrid1.Cells[2, 4] := 'complete'; // Cube-Sphere
  116. StringGrid1.Cells[2, 5] := 'Cube-Sphere'; // Faces-Sphere
  117. // ellipsoid
  118. StringGrid1.Cells[3, 1] := 'complete'; // Point-Ellipsoid
  119. StringGrid1.Cells[3, 2] := 'complete'; // Sphere-Ellipsoid
  120. StringGrid1.Cells[3, 3] := 'incorrect'; // Ellipsoid-Ellipsoid
  121. StringGrid1.Cells[3, 4] := 'Cube-Sphere'; // Cube-Ellipsoid
  122. StringGrid1.Cells[3, 5] := 'Cube-Ellipsoid'; // Faces-Ellipsoid
  123. // cube
  124. StringGrid1.Cells[4, 1] := 'complete'; // Point-Cube
  125. StringGrid1.Cells[4, 2] := 'complete'; // Sphere-Cube
  126. StringGrid1.Cells[4, 3] := 'Sphere-Cube'; // Ellipsoid-Cube
  127. StringGrid1.Cells[4, 4] := 'complete'; // Cube-Cube
  128. StringGrid1.Cells[4, 5] := 'experimental'; // Faces-Cube
  129. // Faces
  130. StringGrid1.Cells[5, 1] := 'Point-Cube'; // Point-Faces
  131. StringGrid1.Cells[5, 2] := 'Sphere-Cube'; // Sphere-Faces
  132. StringGrid1.Cells[5, 3] := 'Ellipsoid-Cube'; // Ellipsoid-Faces
  133. StringGrid1.Cells[5, 4] := 'experimental'; // Cube-Faces
  134. StringGrid1.Cells[5, 5] := 'complete'; // Faces-Faces
  135. end;
  136. procedure TFormFacevsFace.cbCollisionModeClick(Sender: TObject);
  137. begin
  138. TGLBCollision(Teapot1.Behaviours[0]).BoundingMode :=
  139. TCollisionBoundingMode(cbCollisionMode.ItemIndex);
  140. TGLBCollision(Teapot2.Behaviours[0]).BoundingMode :=
  141. TCollisionBoundingMode(cbCollisionMode.ItemIndex);
  142. TGLBCollision(Bar.Behaviours[0]).BoundingMode := cbmCube;
  143. end;
  144. procedure TFormFacevsFace.FormShow(Sender: TObject);
  145. begin
  146. // initialize
  147. CurrSO := Teapot1;
  148. cbCollisionModeClick(nil);
  149. end;
  150. procedure TFormFacevsFace.Timer1Timer(Sender: TObject);
  151. const
  152. cColor: array [False .. True] of TColor = (clLime, clRed);
  153. var
  154. t: Int64;
  155. begin
  156. Timer1.Enabled := False;
  157. CollisionDetected := False;
  158. t := StartPrecisionTimer;
  159. Memo1.Lines.Clear;
  160. Memo1.Lines.BeginUpdate;
  161. CollisionManager1.CheckCollisions;
  162. Memo1.Lines.EndUpdate;
  163. LATime.Caption := Format('%.1f ms', [StopPrecisionTimer(t) * 1000]);
  164. Shape1.Brush.Color := cColor[CollisionDetected];
  165. Timer1.Enabled := True;
  166. end;
  167. procedure TFormFacevsFace.CollisionManager1Collision(Sender: TObject;
  168. object1, object2: TGLBaseSceneObject);
  169. begin
  170. if Sender = CollisionManager1 then
  171. begin
  172. CollisionDetected := True;
  173. Memo1.Lines.Add(object1.Name + '(' + StringNames
  174. [Ord(TGLBCollision(object1.Behaviours.GetByClass(TGLBCollision)).BoundingMode)] + ')' +
  175. ' - ' + object2.Name + '(' + StringNames
  176. [Ord(TGLBCollision(object2.Behaviours.GetByClass(TGLBCollision)).BoundingMode)] + ')');
  177. end
  178. else
  179. begin
  180. Memo1.Lines.Add(object1.Name + '(' + StringNames
  181. [Ord(TGLBCollision(object1.Behaviours.GetByClass(TGLBCollision)).BoundingMode)] + ')' +
  182. ' - ' + object2.Name + '(' + StringNames
  183. [Ord(TGLBCollision(object2.Behaviours.GetByClass(TGLBCollision)).BoundingMode)] +
  184. ') ** BB collision **');
  185. end;
  186. end;
  187. procedure TFormFacevsFace.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  188. Shift: TShiftState; X, Y: Integer);
  189. var
  190. pick: TGLCustomSceneObject;
  191. begin
  192. pick := (GLSceneViewer1.Buffer.GetPickedObject(X, Y) as TGLCustomSceneObject);
  193. if Assigned(pick) then
  194. CurrSO := pick;
  195. // store mouse coordinates when a button went down
  196. mdx := X;
  197. mdy := Y;
  198. end;
  199. procedure TFormFacevsFace.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  200. X, Y: Integer);
  201. var
  202. dx, dy: Integer;
  203. VX, VY: TGLVector;
  204. Camera: TGLCamera;
  205. begin
  206. Camera := GLSceneViewer1.Camera;
  207. // calculate delta since last move or last mousedown
  208. dx := mdx - X;
  209. dy := mdy - Y;
  210. mdx := X;
  211. mdy := Y;
  212. if ssLeft in Shift then
  213. begin
  214. if ssShift in Shift then
  215. begin
  216. // left button with shift rotates the object
  217. // (rotation happens around camera's axis)
  218. Camera.RotateObject(CurrSO, dy, dx);
  219. end
  220. else
  221. begin
  222. // left button without shift changes camera angle
  223. // (we're moving around the parent and target dummycube)
  224. Camera.MoveAroundTarget(dy, dx)
  225. end;
  226. end
  227. else if Shift = [ssRight] then
  228. begin
  229. // Moving the objects
  230. // Description:
  231. // 1. via VectorPerpendicular we create a vector that is 90° to camera view and points to Y (Up)
  232. // this is Y-direction of moving
  233. // 2. now using VectorCrossProduct we create the vector that is 90° to camera view and to the other
  234. // vector (VY), this is X-direction of moving
  235. VY := VectorMake(VectorPerpendicular(YVector,
  236. VectorNormalize(GLCamera2.Position.AsAffineVector)));
  237. VX := VectorCrossProduct(VY, VectorNormalize(GLCamera2.Position.AsVector));
  238. NormalizeVector(VY);
  239. NormalizeVector(VX);
  240. CurrSO.Position.Translate(VectorCombine(VX, VY, -dx * 0.132 * Camera.DistanceToTarget /
  241. Camera.FocalLength, dy * 0.132 * Camera.DistanceToTarget / Camera.FocalLength));
  242. end;
  243. end;
  244. procedure TFormFacevsFace.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
  245. MousePos: TPoint; var Handled: Boolean);
  246. var
  247. Camera: TGLCamera;
  248. begin
  249. Camera := GLSceneViewer1.Camera;
  250. // Note that 1 wheel-step induces a WheelDelta of 120,
  251. // this code adjusts the distance to target with a 10% per wheel-step ratio
  252. Camera.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
  253. end;
  254. end.