ArenaZ
393 строки · 11.2 Кб
1unit uNavCube;
2
3{$IFDEF FPC}
4{$MODE Delphi}
5{$ENDIF}
6
7interface
8
9uses
10{$ifdef Windows}windows, {$endif}lcltype, lclintf, Classes, SysUtils,
11Graphics, Forms, Controls,
12// GLS
13GLScene, GLObjects, GLHUDObjects, GLGeomObjects, GLMaterial, GLTexture,
14GLTextureFormat, GLVectorGeometry, GLKeyboard, GLContext, GLBaseClasses,
15GLLCLViewer, GLRenderContextInfo, keyboard;
16
17type
18TGLNavCube = class(TGLBaseSceneObject)
19private
20FDelta, FFps, FTimer, FInactiveTime: single;
21FCube: TGLDummyCube;
22FSel: Integer;
23FSelPos: TVector;
24FCam, FNavCam: TGLCamera;
25FHud: TGLHUDSprite;
26FMem: TGLMemoryViewer;
27FViewer: TGLSceneViewer;
28FReady, FMouse: boolean;
29FMouseRotation: boolean;
30FAutoRotate : Boolean;
31FMousePos: TPoint;
32
33FPosAnimationStart: TVector;
34FPosAnimationEnd: TVector;
35
36public
37constructor CreateAsChild(aParentOwner: TGLBaseSceneObject); reintroduce;
38procedure DoProgress(const pt: TProgressTimes); override;
39procedure DoRender(var ARci: TGLRenderContextInfo;
40ARenderSelf, ARenderChildren: boolean); override;
41
42property SceneViewer: TGLSceneViewer read FViewer write FViewer;
43property Camera: TGLCamera read FCam write FCam;
44property FPS: single read FFps write FFps;
45
46property ActiveMouse: boolean read FMouse write FMouse;
47property AutoRotate: boolean read FAutoRotate write FAutoRotate;
48property InactiveTime: single read FInactiveTime write FInactiveTime;
49end;
50
51var
52sW2, sH2: Integer;
53
54implementation
55
56// constructor
57//
58constructor TGLNavCube.CreateAsChild(aParentOwner: TGLBaseSceneObject);
59
60procedure genTex(s: string; mat: TGLMaterial);
61var
62bmp: TBitmap;
63begin
64bmp := TBitmap.Create;
65bmp.Width := 64;
66bmp.Height := 64;
67with bmp.Canvas do
68begin
69Font.Name := 'Verdana';
70Font.Size := 10;
71TextOut(32 - TextWidth(s) div 2, 24, s);
72end;
73mat.FrontProperties.Diffuse.SetColor(1, 1, 1);
74mat.Texture.Image.Assign(bmp);
75mat.Texture.Disabled := false;
76mat.Texture.FilteringQuality := tfAnisotropic;
77mat.Texture.TextureMode := tmModulate;
78bmp.Free;
79end;
80
81procedure SetColor(m: TGLMaterial; c: single);
82begin
83m.FrontProperties.Diffuse.SetColor(c, c, 1);
84end;
85
86procedure addPlane(t: Integer; ttl: string; c, x, y, z, dx, dy, dz: single);
87begin
88with TGLPlane.CreateAsChild(FCube) do
89begin
90tag := t;
91tagfloat := c;
92Position.SetPoint(x, y, z);
93Direction.SetVector(dx, dy, dz);
94genTex(ttl, Material);
95end;
96end;
97
98procedure addCube(t: Integer; c, x, y, z, sx, sy, sz: single);
99begin
100with TGLCube.CreateAsChild(FCube) do
101begin
102tag := t;
103tagfloat := c;
104Position.SetPoint(x, y, z);
105Scale.SetVector(sx, sy, sz);
106SetColor(Material, c);
107end;
108end;
109
110begin
111inherited CreateAsChild(aParentOwner);
112FDelta := 2;
113FFps := 30;
114FTimer := 10;
115FMouse := True;
116FAutoRotate := False;
117FInactiveTime := 0;
118
119FHud := TGLHUDSprite.CreateAsChild(self);
120FHud.Width := 128;
121FHud.Height := 128;
122FHud.Material.BlendingMode := bmTransparency;
123with FHud.Material.Texture do
124begin
125Disabled := false;
126ImageClassName := 'TGLBlankImage';
127MinFilter := miNearest;
128TGLBlankImage(Image).Width := 128;
129TGLBlankImage(Image).Height := 128;
130TextureMode := tmReplace;
131end;
132FHud.Position.SetPoint(-200, 50, 0);
133
134FNavCam := TGLCamera.CreateAsChild(self);
135FNavCam.FocalLength := 55;
136FNavCam.TargetObject := self;
137
138FMem := TGLMemoryViewer.Create(aParentOwner);
139FMem.Width := 128;
140FMem.Height := 128;
141FMem.Camera := FNavCam;
142with FMem.Buffer do
143begin
144BackgroundAlpha := 0;
145Antialiasing := aa6x;
146ContextOptions := [roDestinationAlpha];
147Lighting := false;
148end;
149
150FCube := TGLDummyCube.CreateAsChild(self);
151FCube.Visible := false;
152
153with TGLDisk.CreateAsChild(FCube) do
154begin
155Position.SetPoint(0, -0.805, 0);
156Direction.SetVector(0, 1, 0);
157InnerRadius := 0.9;
158OuterRadius := 1.3;
159Slices := 60;
160Loops := 1;
161SetColor(Material, 0.6);
162end;
163
164with TGLDisk.CreateAsChild(FCube) do
165begin
166Position.SetPoint(0, -0.8, 0);
167Direction.SetVector(0, 1, 0);
168InnerRadius := 0.95;
169OuterRadius := 1.25;
170Slices := 60;
171Loops := 1;
172SetColor(Material, 1);
173end;
174
175addPlane(0, 'FRONT', 1, 0, 0, 0.7, 0, 0, 1);
176addPlane(1, 'RIGHT', 1, 0.7, 0, 0, 1, 0, 0);
177addPlane(2, 'LEFT', 1, -0.7, 0, 0, -1, 0, 0);
178addPlane(3, 'BACK', 1, 0, 0, -0.7, 0, 0, -1);
179addPlane(4, 'TOP', 1, 0, 0.7, 0, 0, 1, 0);
180addPlane(5, 'BOTTOM', 1, 0, -0.7, 0, 0, -1, 0);
181
182addCube(6, 0.9, 0, 0.6, 0.6, 1, 0.2, 0.2);
183addCube(7, 0.9, 0, 0.6, -0.6, 1, 0.2, 0.2);
184addCube(8, 0.9, 0, -0.6, 0.6, 1, 0.2, 0.2);
185addCube(9, 0.9, 0, -0.6, -0.6, 1, 0.2, 0.2);
186
187addCube(10, 0.9, 0.6, 0.6, 0, 0.2, 0.2, 1);
188addCube(11, 0.9, 0.6, -0.6, 0, 0.2, 0.2, 1);
189addCube(12, 0.9, -0.6, 0.6, 0, 0.2, 0.2, 1);
190addCube(13, 0.9, -0.6, -0.6, 0, 0.2, 0.2, 1);
191
192addCube(14, 0.9, 0.6, 0, 0.6, 0.2, 1, 0.2);
193addCube(15, 0.9, 0.6, 0, -0.6, 0.2, 1, 0.2);
194addCube(16, 0.9, -0.6, 0, 0.6, 0.2, 1, 0.2);
195addCube(17, 0.9, -0.6, 0, -0.6, 0.2, 1, 0.2);
196
197addCube(18, 0.8, 0.6, 0.6, 0.6, 0.2, 0.2, 0.2);
198addCube(19, 0.8, 0.6, 0.6, -0.6, 0.2, 0.2, 0.2);
199addCube(20, 0.8, 0.6, -0.6, 0.6, 0.2, 0.2, 0.2);
200addCube(21, 0.8, -0.6, 0.6, 0.6, 0.2, 0.2, 0.2);
201addCube(22, 0.8, 0.6, -0.6, -0.6, 0.2, 0.2, 0.2);
202addCube(23, 0.8, -0.6, -0.6, 0.6, 0.2, 0.2, 0.2);
203addCube(24, 0.8, -0.6, 0.6, -0.6, 0.2, 0.2, 0.2);
204addCube(25, 0.8, -0.6, -0.6, -0.6, 0.2, 0.2, 0.2);
205
206end;
207
208// DoProgress
209//
210procedure TGLNavCube.DoProgress(const pt: TProgressTimes);
211const
212tb: array [0 .. 1] of array [0 .. 3] of TVector = (((x: 0; y: 20; z: 1;
213W: 0), (x: 1; y: 20; z: 0; W: 0), (x: 0; y: 20; z: - 1; W: 0), (x: - 1;
214y: 20; z: 0; W: 0)), ((x: 0; y: - 20; z: 1; W: 0), (x: 1; y: - 20; z: 0;
215W: 0), (x: 0; y: - 20; z: - 1; W: 0), (x: - 1; y: - 20; z: 0; W: 0)));
216var
217mp: TPoint;
218mover: boolean;
219i: Integer;
220v0, v1, v2, v: TVector;
221obj: TGLBaseSceneObject;
222
223procedure moveTo(trgv: TVector);
224begin
225FPosAnimationStart := FCam.Position.AsVector;
226FPosAnimationEnd := FCam.TargetObject.AbsoluteToLocal
227(VectorScale(VectorNormalize(trgv), FCam.DistanceToTarget));
228FDelta := 0;
229end;
230
231begin
232// if not (csloading in componentstate) then
233// begin
234mp := FViewer.ScreenToClient(mouse.CursorPos);
235mover := (mp.x > FHud.Position.x - 64) and (mp.x < FHud.Position.x + 64) and
236(mp.y > FHud.Position.y - 64) and (mp.y < FHud.Position.y + 64);
237// mouse Down/Up
238if (mp.y<FViewer.Top) or (mp.x<FViewer.Left) or (mp.y>FViewer.Top+FViewer.Height) or (mp.x>FViewer.Left+FViewer.Width) then exit;
239if FDelta > 1 then
240begin
241if iskeydown(VK_LBUTTON) and (not FMouseRotation) then
242begin
243// selection > start auto rotation
244if mover and (FSel >= 0) then
245begin
246
247v := FCam.AbsoluteVectorToTarget;
248v.y := 0;
249if v.x < 0 then
250i := -1
251else
252i := 1;
253i := round((ArcCos(VectorAngleCosine(v, ZHmgPoint)) * i + PI) / PI
254* 2) mod 4;
255if (FSel = 4) or (FSel = 5) then
256moveTo(tb[FSel - 4][i])
257else
258moveTo(FSelPos);
259FInactiveTime := 0;
260end // start manual rotation
261else if FMouse then
262begin
263
264FMouseRotation := true;
265FMousePos := mouse.CursorPos;
266//FMousePos := point(sW2, sH2);
267// mouse.CursorPos := point(sW2, sH2);
268FInactiveTime := 0;
269end;
270end;
271// stop rotation, restore cursor
272if (not iskeydown(VK_LBUTTON)) and FMouseRotation and FMouse then
273begin
274FMouseRotation := false;
275// FMousePos := mouse.CursorPos;
276// mouse.CursorPos := FMousePos;
277
278FInactiveTime := 0;
279end;
280end
281// auto rotation progress
282else
283begin
284FDelta := FDelta + pt.deltaTime * 2;
285v := VectorLerp(FPosAnimationStart, FPosAnimationEnd,
286FDelta * FDelta * (3 - 2 * FDelta));
287v := VectorScale(VectorNormalize(v), VectorLength(FPosAnimationStart));
288if FDelta < 1 then
289FCam.Position.SetPoint(v)
290else
291FCam.Position.SetPoint(FPosAnimationEnd);
292
293v := VectorScale(VectorNormalize(v), 10);
294if FDelta < 1 then
295v := VectorScale(VectorNormalize(v), 10)
296else
297v := VectorScale(VectorNormalize(FPosAnimationEnd), 10);
298FNavCam.Position.SetPoint(v);
299
300for i := 2 to FCube.Count - 1 do
301with TGLSceneObject(FCube.Children[i]) do
302Material.FrontProperties.Diffuse.SetColor(tagfloat, tagfloat, 1);
303FInactiveTime := 0;
304end;
305FSel := -1;
306// manual rotation progress
307if FMouseRotation and FMouse then
308begin
309
310mp := mouse.CursorPos;
311if FCam <> nil then
312begin
313FCam.MoveAroundTarget((FMousePos.y - mp.y) * 0.02, (FMousePos.x - mp.x) * 0.02);
314FNavCam.MoveAroundTarget((FMousePos.y - mp.y) * 0.02, (FMousePos.x - mp.x) * 0.02);
315// FCam.MoveAroundTarget((sH2 - mp.y) * 0.2, (sW2 - mp.x) * 0.2);
316// FNavCam.MoveAroundTarget((sH2 - mp.y) * 0.2, (sW2 - mp.x) * 0.2);
317end;
318
319// mouse.CursorPos := point(sW2, sH2);
320
321FInactiveTime := 0;
322end
323else if FReady then
324begin
325// selection
326if mover and (FDelta > 1) then
327begin
328v0 := FNavCam.AbsolutePosition;
329v1 := FMem.Buffer.ScreenToVector(mp.x - round(FHud.Position.x) + 64,
330round(FHud.Position.y) - mp.y + 64);
331SetVector(v2, 99999, 99999, 99999);
332
333obj := nil;
334for i := 2 to FCube.Count - 1 do
335with TGLSceneObject(FCube.Children[i]) do
336begin
337Material.FrontProperties.Diffuse.SetColor(tagfloat, tagfloat, 1);
338if RayCastIntersect(v0, v1, @v) then
339if VectorDistance2(v2, v0) > VectorDistance2(v, v0) then
340begin
341SetVector(v2, v);
342FSel := FCube.Children[i].tag;
343FSelPos := FCube.Children[i].Position.AsVector;
344obj := FCube.Children[i];
345end;
346end;
347if FSel >= 0 then
348begin
349FViewer.cursor := -21;
350TGLSceneObject(obj).Material.FrontProperties.Diffuse.SetColor
351(1, 0.6, 0);
352end
353else
354FViewer.cursor := 0;
355end;
356v := VectorScale(VectorNormalize(FCam.AbsoluteVectorToTarget), 10);
357FNavCam.Position.SetPoint(VectorNegate(v));
358FInactiveTime := FInactiveTime + pt.deltaTime;
359end;
360// rendering
361FTimer := FTimer + pt.deltaTime;
362if FTimer > 1 / FFps then
363begin
364FTimer := FTimer - floor(FTimer * FFps) / FFps;
365FMem.Render(FCube);
366FMem.CopyToTexture(FHud.Material.Texture);
367FReady := true;
368end;
369// end;
370end;
371
372// DoRender (setup)
373//
374procedure TGLNavCube.DoRender(var ARci: TGLRenderContextInfo;
375ARenderSelf, ARenderChildren: boolean);
376begin
377inherited;
378if (FCam = nil) and (scene.CurrentGLCamera <> nil) then
379begin
380FCam := scene.CurrentGLCamera;
381FNavCam.Position.SetPoint
382(VectorScale(VectorNormalize(FCam.Position.AsVector), 10));
383end;
384if FViewer <> nil then
385FHud.Position.SetPoint(FViewer.Width - 80, 50, 0);
386end;
387
388initialization
389
390sW2 := screen.Width div 2;
391sH2 := screen.Height div 2;
392
393end.
394
395