fCameraControllerD.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. unit fCameraControllerD;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Variants,
  7. System.Classes,
  8. System.Types,
  9. System.Math,
  10. Vcl.Graphics,
  11. Vcl.Controls,
  12. Vcl.Forms,
  13. Vcl.Dialogs,
  14. Vcl.ExtCtrls,
  15. Vcl.StdCtrls,
  16. Vcl.ComCtrls,
  17. GLS.Scene,
  18. GLS.Objects,
  19. GLS.SceneViewer,
  20. GLS.VectorFileObjects,
  21. GLS.CameraController,
  22. GLS.File3DS,
  23. GLS.GeomObjects,
  24. GLS.Texture,
  25. GLS.Cadencer,
  26. GLS.Material,
  27. GLS.Coordinates,
  28. GLS.VectorTypes,
  29. GLS.BaseClasses,
  30. GLS.VectorGeometry,
  31. GLS.Navigator,
  32. GLS.SmoothNavigator,
  33. GLS.Graph;
  34. type
  35. TForm1 = class(TForm)
  36. Panel1: TPanel;
  37. Panel2: TPanel;
  38. Label1: TLabel;
  39. Label2: TLabel;
  40. Label3: TLabel;
  41. eDestX: TEdit;
  42. eDestY: TEdit;
  43. eDestZ: TEdit;
  44. Label5: TLabel;
  45. GLScene1: TGLScene;
  46. dcSphere: TGLDummyCube;
  47. GLSphere1: TGLSphere;
  48. GLCylinder1: TGLCylinder;
  49. GLSphere2: TGLSphere;
  50. GLCamera: TGLCamera;
  51. GLLightSource1: TGLLightSource;
  52. GLMaterialLibrary1: TGLMaterialLibrary;
  53. GLCadencer1: TGLCadencer;
  54. GLSceneViewer1: TGLSceneViewer;
  55. GLSphere3: TGLSphere;
  56. Panel3: TPanel;
  57. Label6: TLabel;
  58. Label9: TLabel;
  59. eDistance: TEdit;
  60. Panel4: TPanel;
  61. Label7: TLabel;
  62. Label8: TLabel;
  63. Label10: TLabel;
  64. Label11: TLabel;
  65. eSafeDistance: TEdit;
  66. eTimeToSafePlacement: TEdit;
  67. eTimeToOrbit: TEdit;
  68. Label12: TLabel;
  69. eTimeToZoomBackIn: TEdit;
  70. Panel5: TPanel;
  71. Label13: TLabel;
  72. eTime: TEdit;
  73. Label14: TLabel;
  74. btnMoveToPos: TButton;
  75. btnZoomToDistance: TButton;
  76. btnOrbitToPos: TButton;
  77. btnSafeOrbitAndZoomToPos: TButton;
  78. pImg: TPanel;
  79. Image1: TImage;
  80. Label4: TLabel;
  81. Panel6: TPanel;
  82. Label15: TLabel;
  83. btnOrbitToPosAdv: TButton;
  84. Timer1: TTimer;
  85. GLCameraController1: TGLCameraController;
  86. Panel8: TPanel;
  87. Label20: TLabel;
  88. Panel7: TPanel;
  89. Label16: TLabel;
  90. Label17: TLabel;
  91. Label18: TLabel;
  92. Label19: TLabel;
  93. camDirX: TEdit;
  94. camDirY: TEdit;
  95. camDirZ: TEdit;
  96. Panel9: TPanel;
  97. Label21: TLabel;
  98. Label22: TLabel;
  99. Label23: TLabel;
  100. Label24: TLabel;
  101. camUpX: TEdit;
  102. camUpY: TEdit;
  103. camUpZ: TEdit;
  104. btSmoothOrbit: TButton;
  105. GLSmoothNavigator: TGLSmoothNavigator;
  106. dcDebugGUI: TGLDummyCube;
  107. ArrowLine: TGLArrowLine;
  108. XYZGrid: TGLXYZGrid;
  109. GLPlane1: TGLPlane;
  110. UpAxis: TCheckBox;
  111. btSmoothOrbitToPosAdv: TButton;
  112. btSmoothOrbitAndZoom: TButton;
  113. dcMovingParent: TGLDummyCube;
  114. cbMoveParent: TCheckBox;
  115. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  116. X, Y: Integer);
  117. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  118. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
  119. MousePos: TPoint; var Handled: Boolean);
  120. procedure btnMoveToPosClick(Sender: TObject);
  121. procedure btnZoomToDistanceClick(Sender: TObject);
  122. procedure btnOrbitToPosClick(Sender: TObject);
  123. procedure btnSafeOrbitAndZoomToPosClick(Sender: TObject);
  124. procedure GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  125. X, Y: Integer);
  126. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  127. procedure FormCreate(Sender: TObject);
  128. procedure GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
  129. procedure btnOrbitToPosAdvClick(Sender: TObject);
  130. procedure Timer1Timer(Sender: TObject);
  131. procedure btSmoothOrbitToPosAdvClick(Sender: TObject);
  132. procedure btSmoothOrbitClick(Sender: TObject);
  133. procedure btSmoothOrbitAndZoomClick(Sender: TObject);
  134. private
  135. FGLCameraController: TGLCameraController;
  136. DextX, DextY, DextZ, Time, ZoomDistance: Double;
  137. mx, my: Integer;
  138. FCameraSmoothAnimator_AbsPos: TGLNavigatorSmoothChangeVector;
  139. FCameraSmoothAnimator_RelPos: TGLNavigatorSmoothChangeVector;
  140. procedure GetInput(Sender: TButton);
  141. function OnGetCameraPosition(const ASender: TGLNavigatorSmoothChangeVector): TGLVector;
  142. procedure OnSetCameraPosition(const ASender: TGLNavigatorSmoothChangeVector;
  143. const AValue: TGLVector);
  144. public
  145. end;
  146. var
  147. Form1: TForm1;
  148. implementation
  149. {$R *.dfm}
  150. procedure TForm1.GetInput(Sender: TButton);
  151. begin
  152. FCameraSmoothAnimator_AbsPos.Enabled := False;
  153. FCameraSmoothAnimator_RelPos.Enabled := False;
  154. if (Sender = btnMoveToPos) or (Sender = btnOrbitToPos) or (Sender = btnOrbitToPosAdv) or
  155. (Sender = btnSafeOrbitAndZoomToPos) or (Sender = btSmoothOrbit) or
  156. (Sender = btSmoothOrbitAndZoom) or (Sender = btSmoothOrbitToPosAdv) then
  157. begin
  158. DextX := strtofloat(eDestX.text);
  159. DextY := strtofloat(eDestY.text);
  160. DextZ := strtofloat(eDestZ.text);
  161. end;
  162. if (Sender = btnMoveToPos) or (Sender.Name = 'btnZoomToDistance') or
  163. (Sender.Name = 'btnOrbitToPosAdv') or (Sender.Name = 'btnOrbitToPos') then
  164. begin
  165. Time := strtofloat(eTime.text);
  166. end;
  167. if (Sender.Name = 'btnZoomToDistance') then
  168. begin
  169. ZoomDistance := strtofloat(eDistance.text)
  170. end;
  171. if (Sender.Name = 'btnSafeOrbitAndZoomToPos') then
  172. begin
  173. FGLCameraController.soSafeDistance := strtofloat(eSafeDistance.text);
  174. FGLCameraController.soTimeToSafePlacement := strtofloat(eTimeToSafePlacement.text);
  175. FGLCameraController.soTimeToOrbit := strtofloat(eTimeToOrbit.text);
  176. FGLCameraController.soTimeToZoomBackIn := strtofloat(eTimeToZoomBackIn.text);
  177. end;
  178. end;
  179. function TForm1.OnGetCameraPosition(const ASender: TGLNavigatorSmoothChangeVector): TGLVector;
  180. begin
  181. if ASender = FCameraSmoothAnimator_AbsPos then
  182. Result := GLCamera.AbsolutePosition
  183. else
  184. Result := GLCamera.Position.DirectVector;
  185. end;
  186. procedure TForm1.OnSetCameraPosition(const ASender: TGLNavigatorSmoothChangeVector;
  187. const AValue: TGLVector);
  188. begin
  189. if ASender = FCameraSmoothAnimator_AbsPos then
  190. GLCamera.AbsolutePosition := AValue
  191. else
  192. GLCamera.Position.AsVector := AValue;
  193. end;
  194. procedure TForm1.FormCreate(Sender: TObject);
  195. begin
  196. FGLCameraController := GLCameraController1;
  197. FCameraSmoothAnimator_AbsPos := TGLNavigatorSmoothChangeVector.Create
  198. (GLSmoothNavigator.CustomAnimatedItems);
  199. FCameraSmoothAnimator_AbsPos.Enabled := False;
  200. FCameraSmoothAnimator_AbsPos.Inertia := 0.6;
  201. FCameraSmoothAnimator_AbsPos.Speed := 1;
  202. FCameraSmoothAnimator_AbsPos.SpeedLimit := 5000;
  203. FCameraSmoothAnimator_AbsPos.Cutoff := 0.0001;
  204. FCameraSmoothAnimator_AbsPos.OnGetCurrentValue := OnGetCameraPosition;
  205. FCameraSmoothAnimator_AbsPos.OnSetCurrentValue := OnSetCameraPosition;
  206. FCameraSmoothAnimator_RelPos := TGLNavigatorSmoothChangeVector.Create
  207. (GLSmoothNavigator.CustomAnimatedItems);
  208. FCameraSmoothAnimator_RelPos.Assign(FCameraSmoothAnimator_AbsPos);
  209. GLSmoothNavigator.MovingObject := GLCamera;
  210. GLSmoothNavigator.MoveAroundParams.TargetObject := GLCamera.TargetObject;
  211. end;
  212. // MoveToPos Usage
  213. procedure TForm1.btnMoveToPosClick(Sender: TObject);
  214. begin
  215. GetInput(TButton(Sender));
  216. FGLCameraController.MoveToPos(DextX, DextY, DextZ, Time);
  217. end;
  218. // ZoomToDistance Usage
  219. procedure TForm1.btnZoomToDistanceClick(Sender: TObject);
  220. begin
  221. GetInput(TButton(Sender));
  222. FGLCameraController.ZoomToDistance(ZoomDistance, Time);
  223. end;
  224. // OrbitToPos Usage
  225. procedure TForm1.btnOrbitToPosClick(Sender: TObject);
  226. var
  227. lTargetPosition: TGLVector;
  228. begin
  229. GetInput(TButton(Sender));
  230. lTargetPosition := dcSphere.LocalToAbsolute(PointMake(DextX, DextY, DextZ));
  231. FGLCameraController.OrbitToPos(lTargetPosition.X, lTargetPosition.Y, lTargetPosition.Z, Time);
  232. end;
  233. procedure TForm1.btnOrbitToPosAdvClick(Sender: TObject);
  234. var
  235. lTargetPosition: TGLVector;
  236. begin
  237. GetInput(TButton(Sender));
  238. lTargetPosition := dcSphere.LocalToAbsolute(PointMake(DextX, DextY, DextZ));
  239. FGLCameraController.OrbitToPosAdvanced(lTargetPosition.X, lTargetPosition.Y, lTargetPosition.Z,
  240. Time, UpAxis.Checked);
  241. end;
  242. // SafeOrbitAndZoomToPos Usage
  243. procedure TForm1.btnSafeOrbitAndZoomToPosClick(Sender: TObject);
  244. begin
  245. GetInput(TButton(Sender));
  246. FGLCameraController.SafeOrbitAndZoomToPos(DextX, DextY, DextZ);
  247. end;
  248. // GUI Implementation - Pay attention to FGLCameraController.AllowUserAction!
  249. procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
  250. MousePos: TPoint; var Handled: Boolean);
  251. begin
  252. FCameraSmoothAnimator_AbsPos.Enabled := False;
  253. FCameraSmoothAnimator_RelPos.Enabled := False;
  254. GLCamera.AdjustDistanceToTarget(Power(1.1, WheelDelta / 120));
  255. end;
  256. procedure TForm1.GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
  257. begin
  258. if cbMoveParent.Checked then
  259. begin
  260. dcMovingParent.Position.X := Sin(newTime * 1.5) * 8;
  261. end;
  262. // For btSmoothOrbitAndZoomClick Order of these commands is important.
  263. GLSmoothNavigator.AdjustDistanceToTarget(0, deltaTime);
  264. FGLCameraController.Step(deltaTime, newTime);
  265. // This component requires FixedDeltaTime higher than FMaxExpectedDeltatime.
  266. GLSmoothNavigator.AnimateCustomItems(deltaTime);
  267. end;
  268. procedure TForm1.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  269. X, Y: Integer);
  270. begin
  271. FCameraSmoothAnimator_AbsPos.Enabled := False;
  272. FCameraSmoothAnimator_RelPos.Enabled := False;
  273. FGLCameraController.StopMovement;
  274. if Shift = [ssLeft] then
  275. begin
  276. mx := X;
  277. my := Y;
  278. end;
  279. end;
  280. procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  281. begin
  282. if Shift = [ssLeft] then
  283. begin
  284. GLCamera.MoveAroundTarget(my - Y, mx - X);
  285. mx := X;
  286. my := Y;
  287. Caption := 'Camera Controller - camera position = ' + FormatFloat('0.##', GLCamera.Position.X) +
  288. '/' + FormatFloat('0.##', GLCamera.Position.Y) + '/' +
  289. FormatFloat('0.##', GLCamera.Position.Z);
  290. end;
  291. end;
  292. procedure TForm1.GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  293. X, Y: Integer);
  294. begin
  295. Caption := 'Camera Controller';
  296. end;
  297. procedure TForm1.Timer1Timer(Sender: TObject);
  298. begin
  299. camDirX.text := Format('%.4f', [GLCamera.Direction.X]);
  300. camDirY.text := Format('%.4f', [GLCamera.Direction.Y]);
  301. camDirZ.text := Format('%.4f', [GLCamera.Direction.Z]);
  302. camUpX.text := Format('%.4f', [GLCamera.Up.X]);
  303. camUpY.text := Format('%.4f', [GLCamera.Up.Y]);
  304. camUpZ.text := Format('%.4f', [GLCamera.Up.Z]);
  305. end;
  306. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  307. begin
  308. GLCadencer1.Enabled := False;
  309. end;
  310. procedure TForm1.btSmoothOrbitClick(Sender: TObject);
  311. var
  312. lAngle: Single; // In radians.
  313. lTime: Single;
  314. lNeedToRecalculateZoom: Boolean;
  315. lTargetPosition: TGLVector;
  316. begin
  317. GetInput(TButton(Sender));
  318. lTargetPosition := dcSphere.LocalToAbsolute(PointMake(DextX, DextY, DextZ));
  319. lAngle := AngleBetweenVectors(GLCamera.AbsolutePosition, lTargetPosition,
  320. GLSphere1.AbsolutePosition);
  321. // The final look and feel of smooth animation is affected by
  322. // FCameraSmoothAnimator_AbsPos's propperties and this value.
  323. lTime := lAngle * 2;
  324. FCameraSmoothAnimator_RelPos.ResetTargetValue();
  325. FCameraSmoothAnimator_RelPos.Enabled := True;
  326. if Sender = btSmoothOrbit then
  327. lNeedToRecalculateZoom := False
  328. else if Sender = btSmoothOrbitAndZoom then
  329. lNeedToRecalculateZoom := True
  330. else
  331. begin
  332. lNeedToRecalculateZoom := False;
  333. Assert(False);
  334. end;
  335. FGLCameraController.OrbitToPosSmooth(lTargetPosition, lTime, FCameraSmoothAnimator_RelPos,
  336. lNeedToRecalculateZoom, @YHmgVector);
  337. end;
  338. procedure TForm1.btSmoothOrbitAndZoomClick(Sender: TObject);
  339. begin
  340. btSmoothOrbitClick(btSmoothOrbitAndZoom);
  341. GLSmoothNavigator.AdjustDistanceParams.AddImpulse(Sign(Random - 0.5) * 10);
  342. end;
  343. procedure TForm1.btSmoothOrbitToPosAdvClick(Sender: TObject);
  344. var
  345. lAngle: Single; // In radians.
  346. lTime: Single;
  347. lTargetPosition: TGLVector;
  348. begin
  349. GetInput(TButton(Sender));
  350. lTargetPosition := dcSphere.LocalToAbsolute(PointMake(DextX, DextY, DextZ));
  351. lAngle := AngleBetweenVectors(GLCamera.AbsolutePosition, lTargetPosition,
  352. GLSphere1.AbsolutePosition);
  353. lTime := lAngle; // Speed can be controled by applying a multiplier here.
  354. FCameraSmoothAnimator_AbsPos.TargetValue.DirectVector := GLCamera.AbsolutePosition;
  355. FCameraSmoothAnimator_AbsPos.Enabled := True;
  356. FGLCameraController.OrbitToPosAdvancedSmooth(lTargetPosition.X, lTargetPosition.Y,
  357. lTargetPosition.Z, lTime, FCameraSmoothAnimator_AbsPos);
  358. end;
  359. initialization
  360. FormatSettings.DecimalSeparator := '.';
  361. end.