fCamera.pas 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. unit fCamera;
  2. interface
  3. uses
  4. System.Classes,
  5. System.Math,
  6. System.Types,
  7. Vcl.Forms,
  8. Vcl.Controls,
  9. Vcl.StdCtrls,
  10. Vcl.ExtCtrls,
  11. GLS.Scene,
  12. GLS.VectorTypes,
  13. GLS.Objects,
  14. GLS.PersistentClasses,
  15. GLS.PipelineTransformation,
  16. GLS.GeomObjects,
  17. GLS.Coordinates,
  18. GLS.BaseClasses,
  19. GLS.VectorGeometry,
  20. GLS.Cadencer,
  21. GLS.Context,
  22. GLS.SceneViewer;
  23. type
  24. TFormCamera = class(TForm)
  25. GLScene1: TGLScene;
  26. GLSceneViewer1: TGLSceneViewer;
  27. GLCamera1: TGLCamera;
  28. Teapot1: TGLTeapot;
  29. GLLightSource1: TGLLightSource;
  30. DummyCube1: TGLDummyCube;
  31. RadioGroup1: TRadioGroup;
  32. RadioGroup2: TRadioGroup;
  33. GLCadencer1: TGLCadencer;
  34. procedure GLSceneViewer1MouseDown(Sender: TObject;
  35. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  36. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  37. X, Y: Integer);
  38. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  39. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  40. procedure FormKeyPress(Sender: TObject; var Key: Char);
  41. procedure RadioGroup1Click(Sender: TObject);
  42. procedure RadioGroup2Click(Sender: TObject);
  43. procedure GLCamera1CustomPerspective(const viewport: TRectangle; width,
  44. height, DPI: Integer; var viewPortRadius: Single);
  45. procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
  46. newTime: Double);
  47. private
  48. mdx, mdy: Integer;
  49. a: Double;
  50. public
  51. end;
  52. var
  53. FormCamera: TFormCamera;
  54. implementation
  55. {$R *.DFM}
  56. procedure TFormCamera.GLSceneViewer1MouseDown(Sender: TObject;
  57. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  58. begin
  59. // store mouse coordinates when a button went down
  60. mdx := X;
  61. mdy := Y;
  62. end;
  63. procedure TFormCamera.GLSceneViewer1MouseMove(Sender: TObject;
  64. Shift: TShiftState; X, Y: Integer);
  65. var
  66. dx, dy: Integer;
  67. v: TGLVector;
  68. begin
  69. // calculate delta since last move or last mousedown
  70. dx := mdx - X;
  71. dy := mdy - Y;
  72. mdx := X;
  73. mdy := Y;
  74. if ssLeft in Shift then
  75. begin
  76. if ssShift in Shift then
  77. begin
  78. // right button with shift rotates the teapot
  79. // (rotation happens around camera's axis)
  80. GLCamera1.RotateObject(Teapot1, dy, dx);
  81. end
  82. else
  83. begin
  84. // right button without shift changes camera angle
  85. // (we're moving around the parent and target dummycube)
  86. GLCamera1.MoveAroundTarget(dy, dx)
  87. end;
  88. end
  89. else if Shift = [ssRight] then
  90. begin
  91. // left button moves our target and parent dummycube
  92. v := GLCamera1.ScreenDeltaToVectorXY(dx, -dy,
  93. 0.12 * GLCamera1.DistanceToTarget / GLCamera1.FocalLength);
  94. DummyCube1.Position.Translate(v);
  95. // notify camera that its position/target has been changed
  96. GLCamera1.TransformationChanged;
  97. end;
  98. end;
  99. procedure TFormCamera.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  100. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  101. begin
  102. // Note that 1 wheel-step induces a WheelDelta of 120,
  103. // this code adjusts the distance to target with a 10% per wheel-step ratio
  104. GLCamera1.AdjustDistanceToTarget(Power(1.1, WheelDelta/120));
  105. end;
  106. procedure TFormCamera.FormKeyPress(Sender: TObject; var Key: Char);
  107. begin
  108. with Teapot1 do case Key of
  109. '1' : RotateAbsolute( 0, 0,-15);
  110. '3' : RotateAbsolute( 0, 0,+15);
  111. '4' : RotateAbsolute( 0,-15, 0);
  112. '6' : RotateAbsolute( 0,+15, 0);
  113. '7' : RotateAbsolute(-15, 0, 0);
  114. '9' : RotateAbsolute(+15, 0, 0);
  115. end;
  116. end;
  117. procedure TFormCamera.RadioGroup1Click(Sender: TObject);
  118. begin
  119. case RadioGroup1.ItemIndex of
  120. 0: GLCamera1.CameraStyle := csPerspective;
  121. 1: GLCamera1.CameraStyle := csInfinitePerspective;
  122. 2: GLCamera1.CameraStyle := csPerspectiveKeepFOV;
  123. 3: GLCamera1.CameraStyle := csCustom;
  124. end;
  125. end;
  126. procedure TFormCamera.RadioGroup2Click(Sender: TObject);
  127. begin
  128. GLCamera1.KeepFOVMode := TGLCameraKeepFOVMode(RadioGroup2.ItemIndex);
  129. end;
  130. procedure TFormCamera.GLCadencer1Progress(Sender: TObject; const deltaTime,
  131. newTime: Double);
  132. begin
  133. a := Pi * sin(newTime) / 18;
  134. GLSceneViewer1.Invalidate();
  135. end;
  136. procedure TFormCamera.GLCamera1CustomPerspective(const viewport: TRectangle;
  137. width, height, DPI: Integer; var viewPortRadius: Single);
  138. var
  139. Mat: TGLMatrix;
  140. begin
  141. Mat := CreatePerspectiveMatrix(GLCamera1.GetFieldOfView(Width)/4,
  142. Width / Height, GLCamera1.NearPlaneBias, GLCamera1.DepthOfView);
  143. Mat := MatrixMultiply(Mat, CreateRotationMatrixZ(a));
  144. CurrentGLContext.PipelineTransformation.ProjectionMatrix^ := Mat;
  145. end;
  146. end.