ArenaZ

Форк
0
/
uSuperellipsoid.pas 
749 строк · 19.1 Кб
1
unit uSuperellipsoid;
2

3
interface
4

5
{$I GLScene.inc}
6

7
uses
8
  System.SysUtils,
9
  System.Classes,
10
  System.Math,
11
  //GLS
12
  GLVectorGeometry,
13
  GLVectorTypes,
14
  GLScene,
15
  OpenGLAdapter,
16
  OpenGLTokens,
17
  GLVectorLists,
18
  GLCrossPlatform,
19
  GLContext,
20
  GLSilhouette,
21
  GLColor,
22
  GLRenderContextInfo,
23
  GLBaseClasses,
24
  GLNodes,
25
  GLCoordinates;
26

27
type
28

29
  // TNormalSmoothing
30
  //
31
  { : Determines how and if normals are smoothed.<p>
32
    - nsFlat : facetted look<br>
33
    - nsSmooth : smooth look<br>
34
    - nsNone : unlighted rendering, usefull for decla texturing }
35
  TNormalSmoothing = (nsFlat, nsSmooth, nsNone);
36

37
  // TGLQuadricObject
38
  //
39
  { : Base class for quadric objects.<p>
40
    Introduces some basic Quadric interaction functions (the actual quadric
41
    math is part of the GLU library). }
42
  TGLQuadricObject = class(TGLSceneObject)
43
  private
44
     
45
    FNormals: TNormalSmoothing;
46
    FNormalDirection: TNormalDirection;
47

48
  protected
49
    { Protected Declarations }
50
    procedure SetNormals(aValue: TNormalSmoothing);
51
    procedure SetNormalDirection(aValue: TNormalDirection);
52
    procedure SetupQuadricParams(quadric: PGLUquadricObj);
53
    procedure SetNormalQuadricOrientation(quadric: PGLUquadricObj);
54
    procedure SetInvertedQuadricOrientation(quadric: PGLUquadricObj);
55

56
  public
57
     
58
    constructor Create(AOwner: TComponent); override;
59
    procedure Assign(Source: TPersistent); override;
60

61
  published
62
     
63
    property Normals: TNormalSmoothing read FNormals write SetNormals
64
      default nsSmooth;
65
    property NormalDirection: TNormalDirection read FNormalDirection
66
      write SetNormalDirection default ndOutside;
67
  end;
68

69
  TAngleLimit1 = -90 .. 90;
70
  TAngleLimit2 = 0 .. 360;
71
  TCapType = (ctNone, ctCenter, ctFlat);
72

73
  // TGLSuperellipsoid
74
  //
75
  { : A Superellipsoid object.<p>
76
    The Superellipsoid can have top and bottom caps,
77
    as well as being just a slice of Superellipsoid. }
78
  TGLSuperellipsoid = class(TGLQuadricObject)
79
  private
80
     
81
    FRadius, FxyCurve, FzCurve: TGLFloat;
82
    FSlices, FStacks: TGLInt;
83
    FTop: TAngleLimit1;
84
    FBottom: TAngleLimit1;
85
    FStart: TAngleLimit2;
86
    FStop: TAngleLimit2;
87
    FTopCap, FBottomCap: TCapType;
88
    procedure SetBottom(aValue: TAngleLimit1);
89
    procedure SetBottomCap(aValue: TCapType);
90
    procedure SetRadius(const aValue: TGLFloat);
91
    procedure SetxyCurve(const aValue: TGLFloat);
92
    procedure SetzCurve(const aValue: TGLFloat);
93
    procedure SetSlices(aValue: TGLInt);
94
    procedure SetStart(aValue: TAngleLimit2);
95
    procedure SetStop(aValue: TAngleLimit2);
96
    procedure SetStacks(aValue: TGLInt);
97
    procedure SetTop(aValue: TAngleLimit1);
98
    procedure SetTopCap(aValue: TCapType);
99

100
  public
101
     
102
    constructor Create(AOwner: TComponent); override;
103
    procedure Assign(Source: TPersistent); override;
104

105
    procedure BuildList(var rci: TGLRenderContextInfo); override;
106
    function AxisAlignedDimensionsUnscaled: TVector; override;
107
    function RayCastIntersect(const rayStart, rayVector: TVector;
108
      intersectPoint: PVector = nil; intersectNormal: PVector = nil)
109
      : Boolean; override;
110

111
    function GenerateSilhouette(const silhouetteParameters
112
      : TGLSilhouetteParameters): TGLSilhouette; override;
113
  published
114
     
115
    property Bottom: TAngleLimit1 read FBottom write SetBottom default -90;
116
    property BottomCap: TCapType read FBottomCap write SetBottomCap
117
      default ctNone;
118
    property Radius: TGLFloat read FRadius write SetRadius;
119
    property xyCurve: TGLFloat read FxyCurve write SetxyCurve;
120
    property zCurve: TGLFloat read FzCurve write SetzCurve;
121
    property Slices: TGLInt read FSlices write SetSlices default 16;
122
    property Stacks: TGLInt read FStacks write SetStacks default 16;
123
    property Start: TAngleLimit2 read FStart write SetStart default 0;
124
    property Stop: TAngleLimit2 read FStop write SetStop default 360;
125
    property Top: TAngleLimit1 read FTop write SetTop default 90;
126
    property TopCap: TCapType read FTopCap write SetTopCap default ctNone;
127
  end;
128

129
implementation
130

131
// -------------------------------------------------------------
132
// -------------------------------------------------------------
133
// -------------------------------------------------------------
134

135
uses
136
  GLSpline,
137
  XOpenGL,
138
  GLState;
139

140
const
141
  cDefaultPointSize: Single = 1.0;
142

143
// ------------------
144
// ------------------ TGLQuadricObject ------------------
145
// ------------------
146

147
// Create
148
//
149

150
constructor TGLQuadricObject.Create(AOwner: TComponent);
151
begin
152
  inherited;
153
  FNormals := nsSmooth;
154
  FNormalDirection := ndOutside;
155
end;
156

157
// SetNormals
158
//
159

160
procedure TGLQuadricObject.SetNormals(aValue: TNormalSmoothing);
161
begin
162
  if aValue <> FNormals then
163
  begin
164
    FNormals := aValue;
165
    StructureChanged;
166
  end;
167
end;
168

169
// SetNormalDirection
170
//
171

172
procedure TGLQuadricObject.SetNormalDirection(aValue: TNormalDirection);
173
begin
174
  if aValue <> FNormalDirection then
175
  begin
176
    FNormalDirection := aValue;
177
    StructureChanged;
178
  end;
179
end;
180

181
// SetupQuadricParams
182
//
183

184
procedure TGLQuadricObject.SetupQuadricParams(quadric: PGLUquadricObj);
185
const
186
  cNormalSmoothinToEnum: array [nsFlat .. nsNone] of TGLEnum = (GLU_FLAT,
187
    GLU_SMOOTH, GLU_NONE);
188
begin
189
  gluQuadricDrawStyle(quadric, GLU_FILL);
190
  gluQuadricNormals(quadric, cNormalSmoothinToEnum[FNormals]);
191
  SetNormalQuadricOrientation(quadric);
192
  gluQuadricTexture(quadric, True);
193
end;
194

195
// SetNormalQuadricOrientation
196
//
197

198
procedure TGLQuadricObject.SetNormalQuadricOrientation(quadric: PGLUquadricObj);
199
const
200
  cNormalDirectionToEnum: array [ndInside .. ndOutside] of TGLEnum =
201
    (GLU_INSIDE, GLU_OUTSIDE);
202
begin
203
  gluQuadricOrientation(quadric, cNormalDirectionToEnum[FNormalDirection]);
204
end;
205

206
// SetInvertedQuadricOrientation
207
//
208

209
procedure TGLQuadricObject.SetInvertedQuadricOrientation
210
  (quadric: PGLUquadricObj);
211
const
212
  cNormalDirectionToEnum: array [ndInside .. ndOutside] of TGLEnum =
213
    (GLU_OUTSIDE, GLU_INSIDE);
214
begin
215
  gluQuadricOrientation(quadric, cNormalDirectionToEnum[FNormalDirection]);
216
end;
217

218
// Assign
219
//
220

221
procedure TGLQuadricObject.Assign(Source: TPersistent);
222
begin
223
  if Assigned(Source) and (Source is TGLQuadricObject) then
224
  begin
225
    FNormals := TGLQuadricObject(Source).FNormals;
226
    FNormalDirection := TGLQuadricObject(Source).FNormalDirection;
227
  end;
228
  inherited Assign(Source);
229
end;
230

231
// ------------------
232
// ------------------ TGLSuperellipsoid ------------------
233
// ------------------
234

235
// Create
236
//
237

238
constructor TGLSuperellipsoid.Create(AOwner: TComponent);
239
begin
240
  inherited Create(AOwner);
241
  FRadius := 0.5;
242
  FxyCurve := 1.0;
243
  FzCurve := 1.0;
244
  FSlices := 16;
245
  FStacks := 16;
246
  FTop := 90;
247
  FBottom := -90;
248
  FStart := 0;
249
  FStop := 360;
250
end;
251

252
// BuildList
253
//
254

255
procedure TGLSuperellipsoid.BuildList(var rci: TGLRenderContextInfo);
256
var
257
  CosPc1, SinPc1, CosTc2, SinTc2: TGLFloat;
258

259
  tc1, tc2: TGLInt;
260
  v1, V2, N1: TAffineVector;
261
  AngTop, AngBottom, AngStart, AngStop, StepV, StepH: Extended;
262
  SinP, CosP, SinP2, CosP2, SinT, CosT, Phi, Phi2, Theta: Extended;
263
  uTexCoord, uTexFactor, vTexFactor, vTexCoord0, vTexCoord1: Single;
264
  i, j: Integer;
265
  DoReverse: Boolean;
266

267
begin
268
  DoReverse := (FNormalDirection = ndInside);
269
  rci.GLStates.PushAttrib([sttPolygon]);
270
  if DoReverse then
271
    rci.GLStates.InvertGLFrontFace;
272

273
  // common settings
274
  AngTop := DegToRadian(1.0 * FTop);
275
  AngBottom := DegToRadian(1.0 * FBottom);
276
  AngStart := DegToRadian(1.0 * FStart);
277
  AngStop := DegToRadian(1.0 * FStop);
278
  StepH := (AngStop - AngStart) / FSlices;
279
  StepV := (AngTop - AngBottom) / FStacks;
280
  GL.PushMatrix;
281
  GL.Scalef(Radius, Radius, Radius);
282

283
{ Even integer used with the Power function, only produce positive points }
284
  tc1 := trunc(xyCurve);
285
  tc2 := trunc(zCurve);
286
  if tc1 mod 2 = 0 then xyCurve := xyCurve + 1e-6;
287
  if tc2 mod 2 = 0 then  zCurve :=  zCurve - 1e-6;
288

289
  // top cap
290
  if (FTop < 90) and (FTopCap in [ctCenter, ctFlat]) then
291
  begin
292
    glBegin(GL_TRIANGLE_FAN);
293
    SinCos(AngTop, SinP, CosP);
294
    xgl.TexCoord2f(0.5, 0.5);
295
    if DoReverse then
296
      GL.Normal3f(0, -1, 0)
297
    else
298
      GL.Normal3f(0, 1, 0);
299

300
    if FTopCap = ctCenter then
301
      glVertex3f(0, 0, 0)
302
    else
303
    begin  { FTopCap = ctFlat }
304
//    glVertex3f(0, SinP, 0);
305
      if (Sign(SinP) = 1) or (tc1 = xyCurve)
306
      then SinPc1 :=   PowerSingle( SinP, xyCurve)
307
      else SinPc1 :=  -PowerSingle(-SinP, xyCurve);
308
      glVertex3f(0, SinPc1, 0);
309

310
      N1 := YVector;
311
      if DoReverse then
312
        N1.Y := -N1.Y;
313
    end;  { FTopCap = ctFlat }
314

315
//  v1[1] := SinP;
316
    if (Sign(SinP) = 1) or (tc1 = xyCurve)
317
    then SinPc1 :=   Power( SinP, xyCurve)
318
    else SinPc1 :=  -Power(-SinP, xyCurve);
319
    v1.Y := SinPc1;
320

321
    Theta := AngStart;
322

323
    for i := 0 to FSlices do
324
    begin
325
      SinCos(Theta, SinT, CosT);
326
//    v1[0] := CosP * SinT;
327
      if (Sign(CosP) = 1) or (tc1 = xyCurve)
328
      then CosPc1 :=  Power( CosP, xyCurve)
329
      else CosPc1 := -Power(-CosP, xyCurve);
330

331
      if (Sign(SinT) = 1) or (tc2 = zCurve)
332
      then SinTc2 :=  Power( SinT, zCurve)
333
      else SinTc2 := -Power(-SinT, zCurve);
334
      v1.X := CosPc1 * SinTc2;
335

336
//    v1[2] := CosP * CosT;
337
      if (Sign(CosT) = 1) or (tc2 = zCurve)
338
      then CosTc2 :=  Power( CosT, zCurve)
339
      else CosTc2 := -Power(-CosT, zCurve);
340
      v1.Z := CosPc1 * CosTc2;
341

342
      if FTopCap = ctCenter then
343
      begin
344
        N1 := VectorPerpendicular(YVector, v1);
345
        if DoReverse then
346
          NegateVector(N1);
347
      end;
348
//    xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
349
      xgl.TexCoord2f(SinTc2 * 0.5 + 0.5, CosTc2 * 0.5 + 0.5);
350
      GL.Normal3fv(@N1);
351
      glVertex3fv(@v1);
352
      Theta := Theta + StepH;
353
    end;
354
    GL.End_;
355
  end;
356

357
  // main body
358
  Phi := AngTop;
359
  Phi2 := Phi - StepV;
360
  uTexFactor := 1 / FSlices;
361
  vTexFactor := 1 / FStacks;
362

363
  for j := 0 to FStacks - 1 do
364
  begin
365
    Theta := AngStart;
366
    SinCos(Phi, SinP, CosP);
367
    SinCos(Phi2, SinP2, CosP2);
368

369
    if (Sign(SinP) = 1) or (tc1 = xyCurve)
370
    then SinPc1 :=   Power( SinP, xyCurve)
371
    else SinPc1 :=  -Power(-SinP, xyCurve);
372
    v1.Y := SinPc1;
373

374
    if (Sign(SinP2) = 1) or (tc1 = xyCurve)
375
    then SinPc1 :=  Power( SinP2, xyCurve)
376
    else SinPc1 := -Power(-SinP2, xyCurve);
377
    v2.Y := SinPc1;
378

379
    vTexCoord0 := 1 - j * vTexFactor;
380
    vTexCoord1 := 1 - (j + 1) * vTexFactor;
381

382
    glBegin(GL_TRIANGLE_STRIP);
383
    for i := 0 to FSlices do
384
    begin
385
      SinCos(Theta, SinT, CosT);
386

387
      if (Sign(CosP) = 1) or (tc1 = xyCurve)
388
      then CosPc1 :=  Power( CosP, xyCurve)
389
      else CosPc1 := -Power(-CosP, xyCurve);
390

391
      if (Sign(SinT) = 1) or (tc2 = zCurve)
392
      then SinTc2 :=  Power( SinT, zCurve)
393
      else SinTc2 := -Power(-SinT, zCurve);
394
      v1.X := CosPc1 * SinTc2;
395

396
      if (Sign(CosP2) = 1) or (tc1 = xyCurve)
397
      then CosPc1 :=  Power( CosP2, xyCurve)
398
      else CosPc1 := -Power(-CosP2, xyCurve);
399
      V2.X := CosPc1 * SinTc2;
400

401
      if (Sign(CosP) = 1) or (tc1 = xyCurve)
402
      then CosPc1 :=  Power( CosP, xyCurve)
403
      else CosPc1 := -Power(-CosP, xyCurve);
404

405
      if (Sign(CosT) = 1) or (tc2 = zCurve)
406
      then CosTc2 :=  Power( CosT, zCurve)
407
      else CosTc2 := -Power(-CosT, zCurve);
408
      v1.Z := CosPc1 * CosTc2;
409

410
      if (Sign(CosP2) = 1) or (tc1 = xyCurve)
411
      then CosPc1 :=  Power( CosP2, xyCurve)
412
      else CosPc1 := -Power(-CosP2, xyCurve);
413
      V2.Z := CosPc1 * CosTc2;
414

415
      uTexCoord := i * uTexFactor;
416
      xgl.TexCoord2f(uTexCoord, vTexCoord0);
417
      if DoReverse then
418
      begin
419
        N1 := VectorNegate(v1);
420
        GL.Normal3fv(@N1);
421
      end
422
      else
423
        GL.Normal3fv(@v1);
424
      glVertex3fv(@v1);
425

426
      xgl.TexCoord2f(uTexCoord, vTexCoord1);
427
      if DoReverse then
428
      begin
429
        N1 := VectorNegate(V2);
430
        GL.Normal3fv(@N1);
431
      end
432
      else
433
        GL.Normal3fv(@V2);
434
      glVertex3fv(@V2);
435

436
      Theta := Theta + StepH;
437
    end;
438
    GL.End_;
439
    Phi := Phi2;
440
    Phi2 := Phi2 - StepV;
441
  end;
442

443
  // bottom cap
444
  if (FBottom > -90) and (FBottomCap in [ctCenter, ctFlat]) then
445
  begin
446
    glBegin(GL_TRIANGLE_FAN);
447
    SinCos(AngBottom, SinP, CosP);
448
    xgl.TexCoord2f(0.5, 0.5);
449
    if DoReverse then
450
      GL.Normal3f(0, 1, 0)
451
    else
452
      GL.Normal3f(0, -1, 0);
453
    if FBottomCap = ctCenter then
454
      glVertex3f(0, 0, 0)
455
    else
456
    begin   { FTopCap = ctFlat }
457
//    glVertex3f(0, SinP, 0);
458
      if (Sign(SinP) = 1) or (tc1 = xyCurve)
459
      then SinPc1 :=   Power( SinP, xyCurve)
460
      else SinPc1 :=  -Power(-SinP, xyCurve);
461
      glVertex3f(0, SinPc1, 0);
462

463
      if DoReverse then
464
        MakeVector(N1, 0, -1, 0)
465
      else
466
        N1 := YVector;
467
    end;
468
//  v1[1] := SinP;
469
    if (Sign(SinP) = 1) or (tc1 = xyCurve)
470
    then SinPc1 :=   Power( SinP, xyCurve)
471
    else SinPc1 :=  -Power(-SinP, xyCurve);
472
    v1.Y := SinPc1;
473

474
    Theta := AngStop;
475
    for i := 0 to FSlices do
476
    begin
477
      SinCos(Theta, SinT, CosT);
478
//    v1[0] := CosP * SinT;
479
      if (Sign(CosP) = 1) or (tc1 = xyCurve)
480
      then CosPc1 :=  Power( CosP, xyCurve)
481
      else CosPc1 := -Power(-CosP, xyCurve);
482

483
      if (Sign(SinT) = 1) or (tc2 = zCurve)
484
      then SinTc2 :=  Power( SinT, zCurve)
485
      else SinTc2 := -Power(-SinT, zCurve);
486
      v1.X := CosPc1 * SinTc2;
487

488
//    v1[2] := CosP * CosT;
489
      if (Sign(CosT) = 1) or (tc2 = zCurve)
490
      then CosTc2 :=  Power( CosT, zCurve)
491
      else CosTc2 := -Power(-CosT, zCurve);
492
      v1.Z := CosPc1 * CosTc2;
493

494
      if FBottomCap = ctCenter then
495
      begin
496
        N1 := VectorPerpendicular(AffineVectorMake(0, -1, 0), v1);
497
        if DoReverse then
498
          NegateVector(N1);
499
      end;
500
//    xgl.TexCoord2f(SinT * 0.5 + 0.5, CosT * 0.5 + 0.5);
501
      xgl.TexCoord2f(SinTc2 * 0.5 + 0.5, CosTc2 * 0.5 + 0.5);
502
      GL.Normal3fv(@N1);
503
      glVertex3fv(@v1);
504
      Theta := Theta - StepH;
505
    end;
506
    GL.End_;
507
  end;
508
  if DoReverse then
509
    rci.GLStates.InvertGLFrontFace;
510
  GL.PopMatrix;
511
  rci.GLStates.PopAttrib;
512
end;
513

514
// RayCastIntersect
515
// This will probably not work;
516
// RayCastSphereIntersect -> RayCastSuperellipsoidIntersect ??????
517

518
function TGLSuperellipsoid.RayCastIntersect(const rayStart, rayVector: TVector;
519
  intersectPoint: PVector = nil; intersectNormal: PVector = nil): Boolean;
520
var
521
  i1, i2: TVector;
522
  localStart, localVector: TVector;
523
begin
524
  // compute coefficients of quartic polynomial
525
  SetVector(localStart, AbsoluteToLocal(rayStart));
526
  SetVector(localVector, AbsoluteToLocal(rayVector));
527
  NormalizeVector(localVector);
528
  if RayCastSphereIntersect(localStart, localVector, NullHmgVector, Radius, i1,
529
    i2) > 0 then
530
  begin
531
    Result := True;
532
    if Assigned(intersectPoint) then
533
      SetVector(intersectPoint^, LocalToAbsolute(i1));
534
    if Assigned(intersectNormal) then
535
    begin
536
      i1.W := 0; // vector transform
537
      SetVector(intersectNormal^, LocalToAbsolute(i1));
538
    end;
539
  end
540
  else
541
    Result := False;
542
end;
543

544
// GenerateSilhouette
545
// This will probably not work;
546

547
function TGLSuperellipsoid.GenerateSilhouette(const silhouetteParameters
548
  : TGLSilhouetteParameters): TGLSilhouette;
549
var
550
  i, j: Integer;
551
  s, C, angleFactor: Single;
552
  sVec, tVec: TAffineVector;
553
  Segments: Integer;
554
begin
555
  Segments := MaxInteger(FStacks, FSlices);
556

557
  // determine a local orthonormal matrix, viewer-oriented
558
  sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, XVector);
559
  if VectorLength(sVec) < 1E-3 then
560
    sVec := VectorCrossProduct(silhouetteParameters.SeenFrom, YVector);
561
  tVec := VectorCrossProduct(silhouetteParameters.SeenFrom, sVec);
562
  NormalizeVector(sVec);
563
  NormalizeVector(tVec);
564
  // generate the silhouette (outline and capping)
565
  Result := TGLSilhouette.Create;
566
  angleFactor := (2 * PI) / Segments;
567
  for i := 0 to Segments - 1 do
568
  begin
569
    SinCosine(i * angleFactor, FRadius, s, C);
570
    Result.vertices.AddPoint(VectorCombine(sVec, tVec, s, C));
571
    j := (i + 1) mod Segments;
572
    Result.Indices.Add(i, j);
573
    if silhouetteParameters.CappingRequired then
574
      Result.CapIndices.Add(Segments, i, j)
575
  end;
576
  if silhouetteParameters.CappingRequired then
577
    Result.vertices.Add(NullHmgPoint);
578
end;
579

580
// SetBottom
581
//
582

583
procedure TGLSuperellipsoid.SetBottom(aValue: TAngleLimit1);
584
begin
585
  if FBottom <> aValue then
586
  begin
587
    FBottom := aValue;
588
    StructureChanged;
589
  end;
590
end;
591

592
// SetBottomCap
593
//
594

595
procedure TGLSuperellipsoid.SetBottomCap(aValue: TCapType);
596
begin
597
  if FBottomCap <> aValue then
598
  begin
599
    FBottomCap := aValue;
600
    StructureChanged;
601
  end;
602
end;
603

604
// SetRadius
605
//
606

607
procedure TGLSuperellipsoid.SetRadius(const aValue: TGLFloat);
608
begin
609
  if aValue <> FRadius then
610
  begin
611
    FRadius := aValue;
612
    StructureChanged;
613
  end;
614
end;
615

616
// SetxyCurve
617
//
618

619
procedure TGLSuperellipsoid.SetxyCurve(const aValue: TGLFloat);
620
begin
621
  if aValue <> FxyCurve then
622
  begin
623
    FxyCurve := aValue;
624
    StructureChanged;
625
  end;
626
end;
627

628
// SetzCurve
629
//
630

631
procedure TGLSuperellipsoid.SetzCurve(const aValue: TGLFloat);
632
begin
633
  if aValue <> FzCurve then
634
  begin
635
    FzCurve := aValue;
636
    StructureChanged;
637
  end;
638
end;
639

640
// SetSlices
641
//
642

643
procedure TGLSuperellipsoid.SetSlices(aValue: Integer);
644
begin
645
  if aValue <> FSlices then
646
  begin
647
    if aValue <= 0 then
648
      FSlices := 1
649
    else
650
      FSlices := aValue;
651
    StructureChanged;
652
  end;
653
end;
654

655
// SetStacks
656
//
657

658
procedure TGLSuperellipsoid.SetStacks(aValue: TGLInt);
659
begin
660
  if aValue <> FStacks then
661
  begin
662
    if aValue <= 0 then
663
      FStacks := 1
664
    else
665
      FStacks := aValue;
666
    StructureChanged;
667
  end;
668
end;
669

670
// SetStart
671
//
672

673
procedure TGLSuperellipsoid.SetStart(aValue: TAngleLimit2);
674
begin
675
  if FStart <> aValue then
676
  begin
677
    Assert(aValue <= FStop);
678
    FStart := aValue;
679
    StructureChanged;
680
  end;
681
end;
682

683
// SetStop
684
//
685

686
procedure TGLSuperellipsoid.SetStop(aValue: TAngleLimit2);
687
begin
688
  if FStop <> aValue then
689
  begin
690
    Assert(aValue >= FStart);
691
    FStop := aValue;
692
    StructureChanged;
693
  end;
694
end;
695

696
// SetTop
697
//
698

699
procedure TGLSuperellipsoid.SetTop(aValue: TAngleLimit1);
700
begin
701
  if FTop <> aValue then
702
  begin
703
    FTop := aValue;
704
    StructureChanged;
705
  end;
706
end;
707

708
// SetTopCap
709
//
710

711
procedure TGLSuperellipsoid.SetTopCap(aValue: TCapType);
712
begin
713
  if FTopCap <> aValue then
714
  begin
715
    FTopCap := aValue;
716
    StructureChanged;
717
  end;
718
end;
719

720
// Assign
721
//
722

723
procedure TGLSuperellipsoid.Assign(Source: TPersistent);
724
begin
725
  if Assigned(Source) and (Source is TGLSuperellipsoid) then
726
  begin
727
    FRadius := TGLSuperellipsoid(Source).FRadius;
728
    FSlices := TGLSuperellipsoid(Source).FSlices;
729
    FStacks := TGLSuperellipsoid(Source).FStacks;
730
    FBottom := TGLSuperellipsoid(Source).FBottom;
731
    FTop := TGLSuperellipsoid(Source).FTop;
732
    FStart := TGLSuperellipsoid(Source).FStart;
733
    FStop := TGLSuperellipsoid(Source).FStop;
734
  end;
735
  inherited Assign(Source);
736
end;
737

738
// AxisAlignedDimensions
739
//
740

741
function TGLSuperellipsoid.AxisAlignedDimensionsUnscaled: TVector;
742
begin
743
  Result.X := Abs(FRadius);
744
  Result.Y := Result.X;
745
  Result.Z := Result.X;
746
  Result.W := 0;
747
end;
748

749
end.
750

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.