You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 line
10 KiB

  1. unit uglcCamera;
  2. { Package: OpenGLCore
  3. Prefix: glc - OpenGL Core
  4. Beschreibung: diese Unit enthält eine Klassen-Kapselung für OpenGL Frustum und Kamera
  5. Beispiel:
  6. var
  7. camera: TglcCamera;
  8. camera := TglcCamera.Create;
  9. try
  10. camera.Perspective(45, 0.01, 100, 800/600); // define perspective view
  11. camera.Move(gluVector(2, 3, -5)); // move 2 right, 3 up and 5 back
  12. camera.Tilt(-25); // turn 25 degrees down
  13. camera.Turn(-10); // turn 10 degrees left
  14. camera.Activate; // activate camera
  15. // do normal rendering
  16. finally
  17. FreeAndNil(camera);
  18. end; }
  19. {$mode objfpc}{$H+}
  20. interface
  21. uses
  22. Classes, SysUtils,
  23. ugluVector, ugluMatrix;
  24. type
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  26. TglcFrustum = class(TObject)
  27. private
  28. function GetWidth: Single;
  29. function GetHeight: Single;
  30. function GetFOVAngle: Single;
  31. function GetAspectRatio: Single;
  32. protected
  33. fIsOrthogonal: Boolean;
  34. fTop, fBottom, fLeft, fRight, fNear, fFar: Single;
  35. public
  36. property Top : Single read fTop;
  37. property Bottom : Single read fBottom;
  38. property Left : Single read fLeft;
  39. property Right : Single read fRight;
  40. property Near : Single read fNear;
  41. property Far : Single read fFar;
  42. property Width : Single read GetWidth;
  43. property Height : Single read GetHeight;
  44. property FOVAngle : Single read GetFOVAngle;
  45. property AspectRatio : Single read GetAspectRatio;
  46. property IsOrthogonal: Boolean read fIsOrthogonal;
  47. procedure Frustum(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  48. procedure Perspective(const aFOVAngle, aAspectRatio, aNear, aFar: Single);
  49. procedure Ortho(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  50. procedure Activate;
  51. {$IFNDEF OPENGL_ES}
  52. procedure Render;
  53. {$ENDIF}
  54. constructor Create;
  55. end;
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. TglcCamera = class(TglcFrustum)
  58. private
  59. fPosition: TgluMatrix4f;
  60. public
  61. property Position: TgluMatrix4f read fPosition write fPosition;
  62. procedure Move(const aVec: TgluVector3f);
  63. procedure Tilt(const aAngle: Single);
  64. procedure Turn(const aAngle: Single);
  65. procedure Roll(const aAngle: Single);
  66. procedure Activate;
  67. function GetRay(const aPos: TgluVector2f): TgluRayf;
  68. constructor Create;
  69. end;
  70. implementation
  71. uses
  72. Math, {$IFNDEF OPENGL_ES}dglOpenGL{$ELSE}dglOpenGLES{$ENDIF};
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. //TglcFrustum///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  75. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  76. function TglcFrustum.GetWidth: Single;
  77. begin
  78. result := (fRight - fLeft);
  79. end;
  80. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  81. function TglcFrustum.GetHeight: Single;
  82. begin
  83. result := (fTop - fBottom);
  84. end;
  85. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. function TglcFrustum.GetFOVAngle: Single;
  87. begin
  88. result := arctan2(Height/2, fNear)/Pi*360;
  89. end;
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  91. function TglcFrustum.GetAspectRatio: Single;
  92. begin
  93. result := Height / Width;
  94. end;
  95. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  96. procedure TglcFrustum.Frustum(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  97. begin
  98. fIsOrthogonal := false;
  99. fTop := aRight;
  100. fBottom := aLeft;
  101. fLeft := aBottom;
  102. fRight := aTop;
  103. fNear := aNear;
  104. fFar := aFar;
  105. end;
  106. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  107. procedure TglcFrustum.Perspective(const aFOVAngle, aAspectRatio, aNear, aFar: Single);
  108. begin
  109. fIsOrthogonal := false;
  110. fNear := aNear;
  111. fFar := aFar;
  112. fTop := fNear * tan(aFOVAngle / 360 * Pi);
  113. fBottom := -fTop;
  114. fRight := aAspectRatio * fTop;
  115. fLeft := -fRight;
  116. end;
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. procedure TglcFrustum.Ortho(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  119. begin
  120. fIsOrthogonal := true;
  121. fLeft := aLeft;
  122. fRight := aRight;
  123. fTop := aTop;
  124. fBottom := aBottom;
  125. fNear := aNear;
  126. fFar := aFar;
  127. end;
  128. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. procedure TglcFrustum.Activate;
  130. begin
  131. glMatrixMode(GL_PROJECTION);
  132. glLoadIdentity;
  133. if fIsOrthogonal then
  134. {$IFNDEF OPENGL_ES}glOrtho{$ELSE}glOrthof{$ENDIF}(fLeft, fRight, fBottom, fTop, fNear, fFar)
  135. else
  136. {$IFNDEF OPENGL_ES}glFrustum{$ELSE}glFrustumf{$ENDIF}(fLeft, fRight, fBottom, fTop, fNear, fFar);
  137. glMatrixMode(GL_MODELVIEW);
  138. end;
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. {$IFNDEF OPENGL_ES}
  141. procedure TglcFrustum.Render;
  142. var
  143. min, max: TgluVector2f;
  144. begin
  145. min[0] := fLeft / fNear * fFar;
  146. min[1] := fBottom / fNear * fFar;
  147. max[0] := fRight / fNear * fFar;
  148. max[1] := fTop / fNear * fFar;
  149. glBegin(GL_LINE_LOOP);
  150. glVertex3f(fLeft, fTop, -fNear);
  151. glVertex3f(fLeft, fBottom, -fNear);
  152. glVertex3f(fRight, fBottom, -fNear);
  153. glVertex3f(fRight, fTop, -fNear);
  154. glEnd;
  155. glBegin(GL_LINE_LOOP);
  156. glVertex3f(min[0], min[0], -fFar);
  157. glVertex3f(min[0], max[0], -fFar);
  158. glVertex3f(max[0], max[0], -fFar);
  159. glVertex3f(max[0], min[0], -fFar);
  160. glEnd;
  161. glBegin(GL_LINES);
  162. glVertex3f(0, 0, 0); glVertex3f(min[0], min[0], -fFar);
  163. glVertex3f(0, 0, 0); glVertex3f(min[0], max[0], -fFar);
  164. glVertex3f(0, 0, 0); glVertex3f(max[0], max[0], -fFar);
  165. glVertex3f(0, 0, 0); glVertex3f(max[0], min[0], -fFar);
  166. glEnd;
  167. end;
  168. {$ENDIF}
  169. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170. constructor TglcFrustum.Create;
  171. begin
  172. inherited Create;
  173. fTop := 0;
  174. fBottom := 0;
  175. fLeft := 0;
  176. fRight := 0;
  177. fNear := 0;
  178. fFar := 0;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. //TglcCamera////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. procedure TglcCamera.Move(const aVec: TgluVector3f);
  184. begin
  185. fPosition := gluMatrixMult(gluMatrixTranslate(aVec), fPosition);
  186. end;
  187. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  188. procedure TglcCamera.Tilt(const aAngle: Single);
  189. begin
  190. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(1,0,0), aAngle), fPosition);
  191. end;
  192. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  193. procedure TglcCamera.Turn(const aAngle: Single);
  194. begin
  195. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,1,0), aAngle), fPosition);
  196. end;
  197. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  198. procedure TglcCamera.Roll(const aAngle: Single);
  199. begin
  200. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,0,1), aAngle), fPosition);
  201. end;
  202. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203. procedure TglcCamera.Activate;
  204. begin
  205. inherited Activate;
  206. glLoadMatrixf(@fPosition[0, 0]);
  207. end;
  208. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  209. function TglcCamera.GetRay(const aPos: TgluVector2f): TgluRayf;
  210. var
  211. p: TgluVector3f;
  212. begin
  213. if (aPos[0] < 0) then
  214. p[0] := -aPos[0] * fLeft
  215. else
  216. p[0] := aPos[0] * fRight;
  217. if (aPos[1] < 0) then
  218. p[1] := -aPos[1] * fBottom
  219. else
  220. p[1] := aPos[1] * fTop;
  221. if (fIsOrthogonal) then begin
  222. p[2] := 0;
  223. result.p := fPosition * p;
  224. result.v := fPosition * gluVector3f(0, 0, -1);
  225. end else begin
  226. p[2] := -fNear;
  227. result.p := gluVector3f(0, 0, 0);
  228. result.v := fPosition * p;
  229. end;
  230. result := gluRayNormalize(result);
  231. end;
  232. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  233. constructor TglcCamera.Create;
  234. begin
  235. inherited Create;
  236. fPosition := gluMatrixIdentity;
  237. end;
  238. end.