Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

272 rader
9.8 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. procedure Render;
  52. constructor Create;
  53. end;
  54. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  55. TglcCamera = class(TglcFrustum)
  56. private
  57. fPosition: TgluMatrix4f;
  58. public
  59. property Position: TgluMatrix4f read fPosition write fPosition;
  60. procedure Move(const aVec: TgluVector3f);
  61. procedure Tilt(const aAngle: Single);
  62. procedure Turn(const aAngle: Single);
  63. procedure Roll(const aAngle: Single);
  64. procedure Activate;
  65. function GetRay(const aPos: TgluVector2f): TgluRayf;
  66. constructor Create;
  67. end;
  68. implementation
  69. uses
  70. Math, dglOpenGL;
  71. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. //TglcFrustum///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74. function TglcFrustum.GetWidth: Single;
  75. begin
  76. result := (fRight - fLeft);
  77. end;
  78. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  79. function TglcFrustum.GetHeight: Single;
  80. begin
  81. result := (fTop - fBottom);
  82. end;
  83. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  84. function TglcFrustum.GetFOVAngle: Single;
  85. begin
  86. result := arctan2(Height/2, fNear)/Pi*360;
  87. end;
  88. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  89. function TglcFrustum.GetAspectRatio: Single;
  90. begin
  91. result := Height / Width;
  92. end;
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. procedure TglcFrustum.Frustum(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  95. begin
  96. fIsOrthogonal := false;
  97. fTop := aRight;
  98. fBottom := aLeft;
  99. fLeft := aBottom;
  100. fRight := aTop;
  101. fNear := aNear;
  102. fFar := aFar;
  103. end;
  104. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  105. procedure TglcFrustum.Perspective(const aFOVAngle, aAspectRatio, aNear, aFar: Single);
  106. begin
  107. fIsOrthogonal := false;
  108. fNear := aNear;
  109. fFar := aFar;
  110. fTop := fNear * tan(aFOVAngle / 360 * Pi);
  111. fBottom := -fTop;
  112. fRight := aAspectRatio * fTop;
  113. fLeft := -fRight;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. procedure TglcFrustum.Ortho(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single);
  117. begin
  118. fIsOrthogonal := true;
  119. fLeft := aLeft;
  120. fRight := aRight;
  121. fTop := aTop;
  122. fBottom := aBottom;
  123. fNear := aNear;
  124. fFar := aFar;
  125. end;
  126. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  127. procedure TglcFrustum.Activate;
  128. begin
  129. glMatrixMode(GL_PROJECTION);
  130. glLoadIdentity;
  131. if fIsOrthogonal then
  132. glOrtho(fLeft, fRight, fBottom, fTop, fNear, fFar)
  133. else
  134. glFrustum(fLeft, fRight, fBottom, fTop, fNear, fFar);
  135. glMatrixMode(GL_MODELVIEW);
  136. end;
  137. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  138. procedure TglcFrustum.Render;
  139. var
  140. min, max: TgluVector2f;
  141. begin
  142. min[0] := fLeft / fNear * fFar;
  143. min[1] := fBottom / fNear * fFar;
  144. max[0] := fRight / fNear * fFar;
  145. max[1] := fTop / fNear * fFar;
  146. glBegin(GL_LINE_LOOP);
  147. glVertex3f(fLeft, fTop, -fNear);
  148. glVertex3f(fLeft, fBottom, -fNear);
  149. glVertex3f(fRight, fBottom, -fNear);
  150. glVertex3f(fRight, fTop, -fNear);
  151. glEnd;
  152. glBegin(GL_LINE_LOOP);
  153. glVertex3f(min[0], min[0], -fFar);
  154. glVertex3f(min[0], max[0], -fFar);
  155. glVertex3f(max[0], max[0], -fFar);
  156. glVertex3f(max[0], min[0], -fFar);
  157. glEnd;
  158. glBegin(GL_LINES);
  159. glVertex3f(0, 0, 0); glVertex3f(min[0], min[0], -fFar);
  160. glVertex3f(0, 0, 0); glVertex3f(min[0], max[0], -fFar);
  161. glVertex3f(0, 0, 0); glVertex3f(max[0], max[0], -fFar);
  162. glVertex3f(0, 0, 0); glVertex3f(max[0], min[0], -fFar);
  163. glEnd;
  164. end;
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  166. constructor TglcFrustum.Create;
  167. begin
  168. inherited Create;
  169. fTop := 0;
  170. fBottom := 0;
  171. fLeft := 0;
  172. fRight := 0;
  173. fNear := 0;
  174. fFar := 0;
  175. end;
  176. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  177. //TglcCamera////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  178. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. procedure TglcCamera.Move(const aVec: TgluVector3f);
  180. begin
  181. fPosition := gluMatrixMult(gluMatrixTranslate(aVec), fPosition);
  182. end;
  183. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  184. procedure TglcCamera.Tilt(const aAngle: Single);
  185. begin
  186. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(1,0,0), aAngle), fPosition);
  187. end;
  188. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. procedure TglcCamera.Turn(const aAngle: Single);
  190. begin
  191. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,1,0), aAngle), fPosition);
  192. end;
  193. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  194. procedure TglcCamera.Roll(const aAngle: Single);
  195. begin
  196. fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,0,1), aAngle), fPosition);
  197. end;
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. procedure TglcCamera.Activate;
  200. begin
  201. inherited Activate;
  202. glLoadMatrixf(@fPosition[0, 0]);
  203. end;
  204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  205. function TglcCamera.GetRay(const aPos: TgluVector2f): TgluRayf;
  206. var
  207. p: TgluVector3f;
  208. begin
  209. if (aPos[0] < 0) then
  210. p[0] := -aPos[0] * fLeft
  211. else
  212. p[0] := aPos[0] * fRight;
  213. if (aPos[1] < 0) then
  214. p[1] := -aPos[1] * fBottom
  215. else
  216. p[1] := aPos[1] * fTop;
  217. if (fIsOrthogonal) then begin
  218. p[2] := 0;
  219. result.p := fPosition * p;
  220. result.v := fPosition * gluVector3f(0, 0, -1);
  221. end else begin
  222. p[2] := -fNear;
  223. result.p := gluVector3f(0, 0, 0);
  224. result.v := fPosition * p;
  225. end;
  226. result := gluRayNormalize(result);
  227. end;
  228. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  229. constructor TglcCamera.Create;
  230. begin
  231. inherited Create;
  232. fPosition := gluMatrixIdentity;
  233. end;
  234. end.