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