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