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