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