MathgeomGLS
618 строк · 15.8 Кб
1unit fMeshEllips;
2
3interface
4
5uses
6Winapi.OpenGL,
7
8Winapi.Windows,
9Winapi.Messages,
10System.SysUtils,
11System.Variants,
12System.Classes,
13System.Math,
14Vcl.Graphics,
15Vcl.Controls,
16Vcl.Forms,
17Vcl.Dialogs,
18Vcl.ComCtrls,
19Vcl.ExtCtrls,
20Vcl.Imaging.Jpeg,
21Vcl.StdCtrls,
22
23GLS.OpenGLTokens,
24GLS.SceneViewer,
25GLS.BaseClasses,
26GLS.Scene,
27GLS.Objects,
28GLS.Coordinates,
29GLS.State,
30GLS.Graph,
31GLS.GeomObjects,
32GLS.Mesh,
33GLS.HUDObjects,
34GLS.BitmapFont,
35GLS.WindowsFont,
36GLS.VectorGeometry,
37GLS.VectorTypes,
38GLS.Color,
39GLS.Texture;
40
41type
42TFormMesh = class(TForm)
43StatusBar: TStatusBar;
44GLScene1: TGLScene;
45GLSceneViewer1: TGLSceneViewer;
46GLDummyCube1: TGLDummyCube;
47GLCamera1: TGLCamera;
48ObjectsCube: TGLDummyCube;
49ArrowZ: TGLArrowLine;
50ArrowY: TGLArrowLine;
51ArrowX: TGLArrowLine;
52GLLightSource1: TGLLightSource;
53Panel1: TPanel;
54Label1: TLabel;
55Label2: TLabel;
56Label3: TLabel;
57Label4: TLabel;
58Label5: TLabel;
59Label6: TLabel;
60Label7: TLabel;
61Label8: TLabel;
62Label9: TLabel;
63Label10: TLabel;
64Label12: TLabel;
65xRadiusTrackBar: TTrackBar;
66yRadiusTrackBar: TTrackBar;
67zRadiusTrackBar: TTrackBar;
68xyCurveTrackBar: TTrackBar;
69zCurveTrackBar: TTrackBar;
70GridCheckBox: TCheckBox;
71ArrowsCheckBox: TCheckBox;
72SlicesTrackBar: TTrackBar;
73StacksTrackBar: TTrackBar;
74TopCapRadioGroup: TRadioGroup;
75BottomTrackBar: TTrackBar;
76TopTrackBar: TTrackBar;
77StartTrackBar: TTrackBar;
78StopTrackBar: TTrackBar;
79BottomCapRadioGroup: TRadioGroup;
80Button1: TButton;
81GLXYZGridXZ: TGLXYZGrid;
82GLMesh1: TGLMesh;
83GLWindowsBitmapFont1: TGLWindowsBitmapFont;
84GLHUDText1: TGLHUDText;
85procedure FormShow(Sender: TObject);
86procedure FormCreate(Sender: TObject);
87procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
88Shift: TShiftState; X, Y: Integer);
89procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
90X, Y: Integer);
91procedure GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
92Shift: TShiftState; X, Y: Integer);
93procedure AnyChange(Sender: TObject);
94procedure GridCheckBoxClick(Sender: TObject);
95procedure ArrowsCheckBoxClick(Sender: TObject);
96procedure Button1Click(Sender: TObject);
97procedure StartTrackBarChange(Sender: TObject);
98procedure StopTrackBarChange(Sender: TObject);
99private
100MousePoint: TPoint;
101procedure ShowCameraLocation;
102procedure ShowFocalLength;
103procedure ShowMesh;
104public
105end;
106
107var
108FormMesh: TFormMesh;
109
110implementation
111
112{$R *.dfm}
113{$R CURSORS.RES}
114
115const
116crLightxz = 1;
117crLightyz = 2;
118crLightxy = 3;
119crSlidexy = 4;
120crSlideyz = 5;
121crSlidexz = 6;
122crRotate = 7;
123crZoom = 8;
124crHandMove = 9;
125
126procedure TFormMesh.AnyChange(Sender: TObject);
127begin
128ShowMesh;
129end;
130
131procedure TFormMesh.ArrowsCheckBoxClick(Sender: TObject);
132begin
133ArrowX.Visible := not ArrowsCheckBox.Checked;
134ArrowY.Visible := ArrowX.Visible;
135ArrowZ.Visible := ArrowX.Visible;
136end;
137
138procedure TFormMesh.Button1Click(Sender: TObject);
139begin
140(* vmV, vmVN, vmVNC, vmVNCT, vmVNT, vmVT *)
141GLMesh1.VertexMode := vmVN;
142with GLMesh1.Material.Texture do
143begin
144// We need a CubeMapImage, which unlike the "regular Images" stores
145// multiple images.
146ImageClassName := TGLCubeMapImage.ClassName;
147with (Image as TGLCubeMapImage) do
148begin
149// Load all 6 texture map components of the cube map
150// The 'PX', 'NX', etc. refer to 'positive X', 'negative X', etc.
151// and follow the RenderMan specs/conventions
152Picture[cmtPX].LoadFromFile('cm_left.jpg');
153Picture[cmtNX].LoadFromFile('cm_right.jpg');
154Picture[cmtPY].LoadFromFile('cm_top.jpg');
155Picture[cmtNY].LoadFromFile('cm_bottom.jpg');
156Picture[cmtPZ].LoadFromFile('cm_back.jpg');
157Picture[cmtNZ].LoadFromFile('cm_front.jpg');
158end;
159// Select reflection cube map environment mapping
160// This is the mode you'll most commonly use with cube maps, normal cube
161// map generation is also supported (used for diffuse environment lighting)
162MappingMode := tmmCubeMapReflection;
163// That's all folks, let us see the thing!
164Disabled := False;
165end;
166Button1.Visible := False;
167end;
168
169procedure TFormMesh.FormCreate(Sender: TObject);
170begin
171Screen.Cursors[crRotate] := LoadCursor(HInstance, 'ROTATE');
172Screen.Cursors[crZoom] := LoadCursor(HInstance, 'ZOOM');
173end;
174
175procedure TFormMesh.FormShow(Sender: TObject);
176begin
177ShowCameraLocation;
178// focallength: right mouse drag up/down
179ShowFocalLength;
180ShowMesh;
181end;
182
183procedure TFormMesh.GLSceneViewer1MouseDown(Sender: TObject;
184Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
185begin
186MousePoint.X := X;
187MousePoint.Y := Y;
188if ssShift in Shift then
189begin
190if ssLeft in Shift then
191Screen.Cursor := crZoom
192else if ssRight in Shift then
193Screen.Cursor := crLightxz;
194end
195else if ssCtrl in Shift then
196begin
197if ssLeft in Shift then
198Screen.Cursor := crSlidexy
199else if ssRight in Shift then
200Screen.Cursor := crLightxy;
201end
202else // no shift or ctrl key
203begin
204if Shift = [ssLeft] then
205Screen.Cursor := crRotate
206else if Shift = [ssRight] then
207Screen.Cursor := crZoom;
208end;
209end;
210
211procedure TFormMesh.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
212X, Y: Integer);
213var
214dx, dy: Integer;
215nx, nz, d: TGLFloat;
216
217begin { refer GLScene\Demos\interface\camera\Camera.dpr }
218dx := MousePoint.X - X;
219dy := MousePoint.Y - Y;
220if ssShift in Shift then { shift key down }
221begin
222if ssLeft in Shift then { left mouse button }
223begin
224{ dy = a step which adjusts target distance by 1.25%; zoom in or out }
225with GLCamera1 do
226AdjustDistanceToTarget(Power(1.0125, dy));
227ShowCameraLocation;
228end
229end
230else // no shift key
231begin
232if Shift = [ssLeft] then
233// Left mouse button changes camera angle by moving around target
234begin
235GLCamera1.MoveAroundTarget(dy, dx);
236ShowCameraLocation;
237end;
238if Shift = [ssRight] then
239begin
240{ Right mouse button alters the camera's focal length;
241zoom out or in by moving cursor up or down }
242with GLCamera1 do
243begin
244FocalLength := FocalLength - dy;
245if FocalLength > 2000 then
246FocalLength := 2000; // max focal length
247if FocalLength < 20 then
248FocalLength := 20; // min focal length
249end;
250ShowFocalLength; // display in statusbar palel
251end;
252end;
253MousePoint.X := X; // update mouse position
254MousePoint.Y := Y;
255end;
256
257procedure TFormMesh.GLSceneViewer1MouseUp(Sender: TObject; Button: TMouseButton;
258Shift: TShiftState; X, Y: Integer);
259begin
260Screen.Cursor := crDefault;
261end;
262
263procedure TFormMesh.GridCheckBoxClick(Sender: TObject);
264begin
265GLXYZGridXZ.Visible := not GridCheckBox.Checked;
266end;
267
268procedure TFormMesh.ShowCameraLocation;
269begin
270with GLCamera1.Position do
271StatusBar.Panels[0].Text := 'Camera: ' + FloatToStrF(X, ffNumber, 5, 2) +
272', ' + FloatToStrF(Y, ffNumber, 5, 2) + ', ' +
273FloatToStrF(Z, ffNumber, 5, 2);
274end;
275
276procedure TFormMesh.ShowFocalLength;
277begin
278with GLCamera1 do
279StatusBar.Panels[1].Text := 'f = ' + FloatToStrF(FocalLength,
280ffNumber, 5, 2);
281end;
282
283procedure TFormMesh.ShowMesh;
284type
285TCapType = (ctNone, ctCenter, ctFlat);
286
287procedure AddTriangle(const p1, p2, p3: TAffineVector;
288const Color: TGLColorVector);
289begin
290with GLMesh1.Vertices do
291begin
292AddVertex(p1, NullVector, Color);
293AddVertex(p2, NullVector, Color);
294AddVertex(p3, NullVector, Color);
295end;
296end;
297
298var
299i, j, tc1, tc2: Integer;
300CosPc1, SinPc1, CosTc2, SinTc2, CosNPc1, SinNPc1, CosNTc2, SinNTc2: Double;
301
302xyCurve: extended;
303zCurve: extended;
304
305Stacks: GLInt;
306Slices: GLInt;
307
308Top: TGLAngleLimit180; // i.e. -90 .. 90
309Bottom: TGLAngleLimit180;
310Start: TGLAngleLimit360; // i.e. 0 .. 360
311Stop: TGLAngleLimit360;
312TopCap, BottomCap: TCapType;
313
314v1, v2, v3, v4: TAffineVector;
315AngTop, AngBottom, AngStart, AngStop, StepV, StepH, Phi, NextPhi, Theta,
316NextTheta, SinP, CosP, SinNP, CosNP, SinT, CosT, SinNT, CosNT: Double;
317
318begin
319xyCurve := xyCurveTrackBar.Position / 10;
320zCurve := zCurveTrackBar.Position / 10;
321
322Slices := SlicesTrackBar.Position;
323Stacks := StacksTrackBar.Position;
324
325Top := TopTrackBar.Position;
326Bottom := -BottomTrackBar.Position;
327
328Start := StartTrackBar.Position;
329Stop := StopTrackBar.Position;
330
331case TopCapRadioGroup.ItemIndex of
3320:
333TopCap := ctNone;
3341:
335TopCap := ctCenter;
3362:
337TopCap := ctFlat;
338end;
339
340case BottomCapRadioGroup.ItemIndex of
3410:
342BottomCap := ctNone;
3431:
344BottomCap := ctCenter;
3452:
346BottomCap := ctFlat;
347end;
348
349AngTop := DegToRadian(1.0 * Top);
350AngBottom := DegToRadian(1.0 * Bottom);
351AngStart := DegToRadian(1.0 * Start);
352AngStop := DegToRadian(1.0 * Stop);
353StepH := (AngStop - AngStart) / Slices;
354StepV := (AngTop - AngBottom) / Stacks;
355
356with GLMesh1 do
357begin
358Mode := mmTriangles;
359Vertices.Clear;
360Scale.SetVector(xRadiusTrackBar.Position / 10, yRadiusTrackBar.Position /
36110, zRadiusTrackBar.Position / 10);
362end;
363{ Even integer used with the Power function, only produce positive points }
364tc1 := trunc(xyCurve);
365tc2 := trunc(zCurve);
366if tc1 mod 2 = 0 then
367xyCurve := xyCurve + 1E-6;
368if tc2 mod 2 = 0 then
369zCurve := zCurve - 1E-6;
370
371// bottom cap
372if (Bottom > -90) and (BottomCap in [ctCenter, ctFlat]) then
373begin
374SinCosine(AngBottom, SinP, CosP);
375
376if (Sign(SinP) = 1) or (tc1 = xyCurve) then
377SinPc1 := Power(SinP, xyCurve)
378else
379SinPc1 := -Power(-SinP, xyCurve);
380
381if (Sign(CosP) = 1) or (tc1 = xyCurve) then
382CosPc1 := Power(CosP, xyCurve)
383else
384CosPc1 := -Power(-CosP, xyCurve);
385
386if BottomCap = ctCenter then
387begin
388v1 := NullVector;
389v3.Y := SinPc1;
390v4.Y := SinPc1;
391end
392else { BottomCap = ctFlat }
393begin
394v1.X := 0;
395v1.Y := SinPc1;
396v1.Z := 0;
397v3.Y := v1.Y;
398v4.Y := v1.Y;
399end;
400
401Theta := AngStart;
402NextTheta := Theta + StepH;
403
404for i := 0 to Slices - 1 do
405begin
406SinCosine(Theta, SinT, CosT);
407if (Sign(SinT) = 1) or (tc2 = zCurve) then
408SinTc2 := Power(SinT, zCurve)
409else
410SinTc2 := -Power(-SinT, zCurve);
411
412SinCosine(NextTheta, SinNT, CosNT);
413if (Sign(SinNT) = 1) or (tc2 = zCurve) then
414SinNTc2 := Power(SinNT, zCurve)
415else
416SinNTc2 := -Power(-SinNT, zCurve);
417
418if (Sign(CosT) = 1) or (tc2 = zCurve) then
419CosTc2 := Power(CosT, zCurve)
420else
421CosTc2 := -Power(-CosT, zCurve);
422
423if (Sign(CosNT) = 1) or (tc2 = zCurve) then
424CosNTc2 := Power(CosNT, zCurve)
425else
426CosNTc2 := -Power(-CosNT, zCurve);
427
428v3.X := CosPc1 * SinTc2;
429v3.Z := CosPc1 * CosTc2;
430v4.X := CosPc1 * SinNTc2;
431v4.Z := CosPc1 * CosNTc2;
432
433AddTriangle(v1, v4, v3, clrTurquoise);
434Theta := NextTheta;
435NextTheta := Theta + StepH;
436end;
437end;
438// main body
439Phi := AngBottom;
440NextPhi := Phi + StepV; { positive StepV; from bottom to top }
441
442for j := 0 to Stacks - 1 do
443begin
444Theta := AngStart;
445NextTheta := Theta + StepH; { positive StepH; from start to stop }
446
447SinCosine(Phi, SinP, CosP);
448if (Sign(SinP) = 1) or (tc1 = xyCurve) then
449SinPc1 := Power(SinP, xyCurve)
450else
451SinPc1 := -Power(-SinP, xyCurve);
452
453v1.Y := SinPc1;
454v2.Y := SinPc1;
455
456SinCosine(NextPhi, SinNP, CosNP);
457if (Sign(SinNP) = 1) or (tc1 = xyCurve) then
458SinNPc1 := Power(SinNP, xyCurve)
459else
460SinNPc1 := -Power(-SinNP, xyCurve);
461
462v3.Y := SinNPc1;
463v4.Y := SinNPc1;
464
465{ define CopsPvc & CosNPc1 for Slices }
466if (Sign(CosP) = 1) or (tc1 = xyCurve) then
467CosPc1 := Power(CosP, xyCurve)
468else
469CosPc1 := -Power(-CosP, xyCurve);
470
471if (Sign(CosNP) = 1) or (tc1 = xyCurve) then
472CosNPc1 := Power(CosNP, xyCurve)
473else
474CosNPc1 := -Power(-CosNP, xyCurve);
475
476for i := 0 to Slices - 1 do
477begin
478SinCosine(Theta, SinT, CosT);
479if (Sign(SinT) = 1) or (tc2 = zCurve) then
480SinTc2 := Power(SinT, zCurve)
481else
482SinTc2 := -Power(-SinT, zCurve);
483
484if (Sign(CosT) = 1) or (tc2 = zCurve) then
485CosTc2 := Power(CosT, zCurve)
486else
487CosTc2 := -Power(-CosT, zCurve);
488
489SinCosine(NextTheta, SinNT, CosNT);
490if (Sign(SinNT) = 1) or (tc2 = zCurve) then
491SinNTc2 := Power(SinNT, zCurve)
492else
493SinNTc2 := -Power(-SinNT, zCurve);
494
495if (Sign(CosNT) = 1) or (tc2 = zCurve) then
496CosNTc2 := Power(CosNT, zCurve)
497else
498CosNTc2 := -Power(-CosNT, zCurve);
499
500v1.X := CosPc1 * SinTc2;
501v2.X := CosPc1 * SinNTc2;
502v3.X := CosNPc1 * SinTc2;
503v4.X := CosNPc1 * SinNTc2;
504
505v1.Z := CosPc1 * CosTc2;
506v2.Z := CosPc1 * CosNTc2;
507v3.Z := CosNPc1 * CosTc2;
508v4.Z := CosNPc1 * CosNTc2;
509
510AddTriangle(v1, v2, v3, clrTurquoise);
511AddTriangle(v2, v4, v3, clrTurquoise);
512
513Theta := NextTheta;
514NextTheta := Theta + StepH;
515end;
516Phi := NextPhi;
517NextPhi := Phi + StepV;
518end;
519
520// top cap
521if (Top < 90) and (TopCap in [ctCenter, ctFlat]) then
522begin
523SinCosine(AngTop, SinP, CosP);
524
525if (Sign(SinP) = 1) or (tc1 = xyCurve) then
526SinPc1 := Power(SinP, xyCurve)
527else
528SinPc1 := -Power(-SinP, xyCurve);
529
530if (Sign(CosP) = 1) or (tc1 = xyCurve) then
531CosPc1 := Power(CosP, xyCurve)
532else
533CosPc1 := -Power(-CosP, xyCurve);
534
535if TopCap = ctCenter then
536begin
537v1 := NullVector;
538v3.Y := SinPc1;
539v4.Y := SinPc1;
540end
541else { FTopCap = ctFlat }
542begin
543v1.X := 0;
544v1.Y := SinPc1;
545v1.Z := 0;
546v3.Y := v1.Y;
547v4.Y := v1.Y;
548end;
549
550Theta := AngStart;
551NextTheta := Theta + StepH;
552
553for i := 0 to Slices - 1 do
554begin
555SinCosine(Theta, SinT, CosT);
556if (Sign(SinT) = 1) or (tc2 = zCurve) then
557SinTc2 := Power(SinT, zCurve)
558else
559SinTc2 := -Power(-SinT, zCurve);
560
561SinCosine(NextTheta, SinNT, CosNT);
562if (Sign(SinNT) = 1) or (tc2 = zCurve) then
563SinNTc2 := Power(SinNT, zCurve)
564else
565SinNTc2 := -Power(-SinNT, zCurve);
566
567if (Sign(CosT) = 1) or (tc2 = zCurve) then
568CosTc2 := Power(CosT, zCurve)
569else
570CosTc2 := -Power(-CosT, zCurve);
571
572if (Sign(CosNT) = 1) or (tc2 = zCurve) then
573CosNTc2 := Power(CosNT, zCurve)
574else
575CosNTc2 := -Power(-CosNT, zCurve);
576
577v3.X := CosPc1 * SinTc2;
578v3.Z := CosPc1 * CosTc2;
579v4.X := CosPc1 * SinNTc2;
580v4.Z := CosPc1 * CosNTc2;
581
582AddTriangle(v1, v3, v4, clrTurquoise);
583
584Theta := NextTheta;
585NextTheta := Theta + StepH;
586end;
587end; { Top Cap }
588
589GLMesh1.CalcNormals(fwCounterClockWise);
590GLHUDText1.Text := 'Scale:' + FloatToStrF(xRadiusTrackBar.Position / 10,
591ffNumber, 6, 2) + ', ' + FloatToStrF(yRadiusTrackBar.Position / 10,
592ffNumber, 6, 2) + ', ' + FloatToStrF(zRadiusTrackBar.Position / 10,
593ffNumber, 6, 2) + #13#10'xyCurve:' +
594FloatToStrF(xyCurveTrackBar.Position / 10, ffNumber, 6, 2) + #13#10'zCurve:'
595+ FloatToStrF(zCurveTrackBar.Position / 10, ffNumber, 6, 2) +
596#13#10'Slices:' + IntToStr(SlicesTrackBar.Position) + #13#10'Stacks:' +
597IntToStr(StacksTrackBar.Position) + #13#10'Top:' +
598IntToStr(TopTrackBar.Position) + '�' + #13#10'Bottom:' +
599IntToStr(BottomTrackBar.Position) + '�' + #13#10'Start:' +
600IntToStr(StartTrackBar.Position) + '�' + #13#10'Stop:' +
601IntToStr(StopTrackBar.Position) + '�';
602end;
603
604procedure TFormMesh.StartTrackBarChange(Sender: TObject);
605begin
606if (StartTrackBar.Position >= StopTrackBar.Position) then
607StartTrackBar.Position := StopTrackBar.Position;
608ShowMesh;
609end;
610
611procedure TFormMesh.StopTrackBarChange(Sender: TObject);
612begin
613if (StopTrackBar.Position <= StartTrackBar.Position) then
614StopTrackBar.Position := StartTrackBar.Position;
615ShowMesh;
616end;
617
618end.
619