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