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