fBoxSphereD.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. unit fBoxSphereD;
  2. interface
  3. uses
  4. Winapi.Windows,
  5. Winapi.OpenGL,
  6. System.SysUtils,
  7. System.Classes,
  8. System.Math,
  9. Vcl.Graphics,
  10. Vcl.Controls,
  11. Vcl.Forms,
  12. Vcl.Dialogs,
  13. Vcl.ExtCtrls,
  14. Vcl.ComCtrls,
  15. Vcl.StdCtrls,
  16. Vcl.Samples.Spin,
  17. GLS.Scene,
  18. GLS.PersistentClasses,
  19. GLScene.VectorTypes,
  20. GLS.Objects,
  21. GLS.Cadencer,
  22. GLS.VectorFileObjects,
  23. GLS.SceneViewer,
  24. GLScene.VectorGeometry,
  25. GLS.Graph,
  26. GLS.GeomObjects,
  27. GLS.Coordinates,
  28. GLS.BaseClasses;
  29. type
  30. TFormBoxSphere = class(TForm)
  31. Viewer: TGLSceneViewer;
  32. GLScene: TGLScene;
  33. GLCadencer: TGLCadencer;
  34. GLCamera1: TGLCamera;
  35. GLLightSource1: TGLLightSource;
  36. GLLightSource2: TGLLightSource;
  37. DCCamTarget: TGLDummyCube;
  38. Panel2: TPanel;
  39. GLCube1: TGLCube;
  40. GLXYZGrid1: TGLXYZGrid;
  41. GLLines1: TGLLines;
  42. CheckBox06: TCheckBox;
  43. CheckBox04: TCheckBox;
  44. CheckBox05: TCheckBox;
  45. GLSphere1: TGLSphere;
  46. DCCube1: TGLDummyCube;
  47. CheckBox07: TCheckBox;
  48. Label5: TLabel;
  49. Label3: TLabel;
  50. Label4: TLabel;
  51. Edit1: TEdit;
  52. Edit2: TEdit;
  53. Edit3: TEdit;
  54. UpDown1: TUpDown;
  55. UpDown2: TUpDown;
  56. UpDown3: TUpDown;
  57. Edit4: TEdit;
  58. Edit5: TEdit;
  59. Edit6: TEdit;
  60. UpDown4: TUpDown;
  61. UpDown5: TUpDown;
  62. UpDown6: TUpDown;
  63. Edit7: TEdit;
  64. Edit8: TEdit;
  65. Edit9: TEdit;
  66. UpDown7: TUpDown;
  67. UpDown8: TUpDown;
  68. UpDown9: TUpDown;
  69. Label1: TLabel;
  70. Edit10: TEdit;
  71. UpDown10: TUpDown;
  72. Label7: TLabel;
  73. Button3: TButton;
  74. Button4: TButton;
  75. GLLines3: TGLLines;
  76. GLSphere2: TGLSphere;
  77. procedure GLCadencerProgress(Sender: TObject; const DeltaTime, newTime: Double);
  78. procedure FormCreate(Sender: TObject);
  79. procedure ViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  80. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  81. procedure FormResize(Sender: TObject);
  82. procedure FormKeyPress(Sender: TObject; var Key: Char);
  83. procedure CheckBox04Click(Sender: TObject);
  84. procedure Edit1Change(Sender: TObject);
  85. procedure ViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  86. procedure Button3Click(Sender: TObject);
  87. procedure Button4Click(Sender: TObject);
  88. private
  89. mdx, mdy: Integer;
  90. intersPoint, ResNormal, BoxScale, SpherePos: TAffineVector;
  91. BoxMatrix: TGLMatrix;
  92. SphereRadius: Single;
  93. end;
  94. // Generates random rotation for matrix. It remains a scale.
  95. function RandomRotation(const aMatrix: TGLMatrix): TGLMatrix;
  96. var
  97. FormBoxSphere: TFormBoxSphere;
  98. implementation
  99. {$R *.DFM}
  100. procedure TFormBoxSphere.FormCreate(Sender: TObject);
  101. begin
  102. Randomize;
  103. BoxScale := XYZVector;
  104. SphereRadius := 1;
  105. BoxMatrix := IdentityHmgMatrix;
  106. end;
  107. procedure TFormBoxSphere.CheckBox04Click(Sender: TObject);
  108. begin
  109. GLCube1.Visible := CheckBox04.Checked;
  110. GLLines1.Visible := CheckBox05.Checked;
  111. GLXYZGrid1.Visible := CheckBox06.Checked;
  112. GLSphere1.Visible := CheckBox07.Checked;
  113. end;
  114. procedure TFormBoxSphere.Edit1Change(Sender: TObject);
  115. const
  116. EditorsScale = 0.1;
  117. var
  118. Res1: Boolean;
  119. begin
  120. if not FormBoxSphere.Visible then
  121. Exit;
  122. GLLines3.Nodes.Clear;
  123. // Calc data.
  124. BoxMatrix.W.X := UpDown1.Position * EditorsScale;
  125. BoxMatrix.W.Y := UpDown2.Position * EditorsScale;
  126. BoxMatrix.W.Z := UpDown3.Position * EditorsScale;
  127. BoxMatrix.W.W := 1;
  128. BoxScale.X := UpDown4.Position * EditorsScale;
  129. BoxScale.Y := UpDown5.Position * EditorsScale;
  130. BoxScale.Z := UpDown6.Position * EditorsScale;
  131. SpherePos.X := UpDown7.Position * EditorsScale;
  132. SpherePos.Y := UpDown8.Position * EditorsScale;
  133. SpherePos.Z := UpDown9.Position * EditorsScale;
  134. SphereRadius := UpDown10.Position * EditorsScale;
  135. // dCollideSphereBox function !
  136. Res1 := IntersectSphereBox(VectorMake(SpherePos, 1), SphereRadius, BoxMatrix,
  137. BoxScale, @intersPoint, @ResNormal);
  138. if Res1 then
  139. begin
  140. // Intersected.
  141. Label1.Caption := 'Intersected';
  142. DCCamTarget.Position.SetPoint(intersPoint);
  143. // Draw normal
  144. GLLines3.Nodes.AddNode(intersPoint);
  145. GLLines3.Nodes.AddNode(VectorAdd(intersPoint, VectorScale(
  146. ResNormal, SphereRadius * 3)));
  147. end
  148. else
  149. begin
  150. // Not intersected.
  151. beep;
  152. Label1.Caption := '';
  153. end;
  154. DCCamTarget.Visible := Res1;
  155. // Draw GLCube1 and GLSphere1.
  156. GLCube1.SetMatrix(BoxMatrix);
  157. GLCube1.CubeWidth := BoxScale.X;
  158. GLCube1.CubeHeight := BoxScale.Y;
  159. GLCube1.CubeDepth := BoxScale.Z;
  160. DCCube1.SetMatrix(GLCube1.Matrix^);
  161. DCCube1.Scale.SetVector(BoxScale);
  162. GLSphere1.Position.SetPoint(SpherePos);
  163. GLSphere1.Radius := SphereRadius;
  164. GLSphere2.Position.SetPoint(SpherePos);
  165. GLSphere2.Radius := SphereRadius;
  166. end;
  167. // Recalc.
  168. procedure TFormBoxSphere.Button3Click(Sender: TObject);
  169. begin
  170. Edit1Change(Self);
  171. end;
  172. // Generates random rotation for matrix. It remains a scale.
  173. function RandomRotation(const aMatrix: TGLMatrix): TGLMatrix;
  174. var
  175. aScale: TAffineVector;
  176. I: Integer;
  177. begin
  178. // Save scale.
  179. for I := 0 to 2 do
  180. aScale.V[I] := VectorLength(aMatrix.V[I]);
  181. // Generate two not equal random vectors.
  182. Result.W := aMatrix.W;
  183. repeat
  184. repeat
  185. Result.X := VectorMake(Random * 2 - 1, Random * 2 - 1, Random * 2 - 1);
  186. until VectorNorm(Result.X) > 10e-6;
  187. repeat
  188. Result.Y := VectorMake(Random * 2 - 1, Random * 2 - 1, Random * 2 - 1);
  189. until VectorNorm(Result.Y) > 10e-6;
  190. until VectorNorm(VectorSubtract(Result.X, Result.Y)) > 10e-6;
  191. // Calculate two perpendicular vectors.
  192. Result.Z := VectorCrossProduct(Result.X, Result.Y);
  193. Result.Y := VectorCrossProduct(Result.X, Result.Z);
  194. // Restore scale.
  195. for I := 0 to 2 do
  196. begin
  197. NormalizeVector(Result.V[I]);
  198. ScaleVector(Result.V[I], aScale.V[I]);
  199. end;
  200. end;
  201. // Random matrix.
  202. procedure TFormBoxSphere.Button4Click(Sender: TObject);
  203. begin
  204. BoxMatrix := RandomRotation(BoxMatrix);
  205. Edit1Change(Self);
  206. end;
  207. procedure TFormBoxSphere.ViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  208. begin
  209. Viewer.SetFocus;
  210. end;
  211. procedure TFormBoxSphere.GLCadencerProgress(Sender: TObject; const DeltaTime, newTime: Double);
  212. begin
  213. if FormBoxSphere.Active then
  214. Viewer.Invalidate;
  215. end;
  216. procedure TFormBoxSphere.ViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  217. begin
  218. if Shift = [ssLeft] then
  219. GLCamera1.MoveAroundTarget(mdy - Y, mdx - X);
  220. mdx := X;
  221. mdy := Y;
  222. end;
  223. procedure TFormBoxSphere.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  224. begin
  225. if Viewer.Focused then
  226. GLCamera1.AdjustDistanceToTarget(Power(1.02, WheelDelta / 120));
  227. end;
  228. procedure TFormBoxSphere.FormResize(Sender: TObject);
  229. begin
  230. GLCamera1.FocalLength := MinInteger(Height, Width) / 10;
  231. end;
  232. procedure TFormBoxSphere.FormKeyPress(Sender: TObject; var Key: Char);
  233. begin
  234. if Key = #27 then
  235. Close;
  236. end;
  237. end.