LZScene

Форк
0
/
GLTree.pas 
1419 строк · 43.3 Кб
1
//
2
// This unit is part of the GLScene Engine https://github.com/glscene
3
//
4
{
5
   Dynamic tree generation in GLScene
6

7
   This code was adapted from the nVidia Tree Demo:
8
   http://developer.nvidia.com/object/Procedural_Tree.html
9

10
   History: 
11
      10/11/12 - PW - Added CPP compatibility: changed vector arrays to records
12
      23/08/10 - Yar - Added OpenGLTokens to uses, replaced OpenGL1x functions to OpenGLAdapter
13
      30/03/07 - DaStr - Added $I GLScene.inc
14
      28/03/07 - DaStr - Renamed parameters in some methods
15
                            (thanks Burkhard Carstens) (Bugtracker ID = 1678658)
16
      13/01/07 - DaStr - Added changes proposed by Tim "Sivael" Kapuœciñski [sivael@gensys.pl]
17
                         Modified the code to create much more realistic trees -
18
                          added third branch for every node and modified constants
19
                          to make the tree look more "alive".
20
                         Also removed the "fractal effect" that ocurred, when
21
                          rendering with the older engine - the leaves and
22
                          branches were much more "in order".
23
                         Added Center* declarations, CenterBranchConstant,
24
                         Added AutoRebuild flag.
25
      02/08/04 - LR, YHC - BCB corrections: use record instead array
26
      14/04/04 - SG - Added AutoCenter property.
27
      03/03/04 - SG - Added GetExtents and AxisAlignedDimensionsUnscaled.
28
      24/11/03 - SG - Creation.
29
    
30

31
   Some info:
32
   CenterBranchConstant  -
33
    Defines, how big the central branch is. When around 50%
34
    it makes a small branch inside the tree, for higher values
35
    much more branches and leaves are created, so either use it
36
    with low depth, or set it to zero, and have two-branched tree.
37
    Default : 0.5
38
   "AutoRebuild" flag  -
39
    Rebuild tree after property change.
40
    Default: True
41
}
42
unit GLTree;
43

44
interface
45

46
{$I GLScene.inc}
47

48
uses
49
   Classes, SysUtils,
50
    
51
   GLScene, GLMaterial, GLVectorGeometry, GLVectorLists,
52
   OpenGLTokens, GLVectorFileObjects, GLApplicationFileIO, GLRenderContextInfo,
53
   XOpenGL, GLContext , GLVectorTypes;
54

55
type
56
   TGLTree = class;
57
   TGLTreeBranches = class;
58
   TGLTreeBranchNoise = class;
59

60
   // TGLTreeLeaves
61
   //
62
   TGLTreeLeaves = class
63
      private
64
          
65
         FOwner : TGLTree;
66
         FCount : Integer;
67
         FVertices : TAffineVectorList;
68
         FNormals : TAffineVectorList;
69
         FTexCoords : TAffineVectorList;
70

71
      public
72
          
73
         constructor Create(AOwner : TGLTree);
74
         destructor Destroy; override;
75

76
         procedure BuildList(var rci : TGLRenderContextInfo);
77
         procedure AddNew(matrix : TMatrix);
78
         procedure Clear;
79

80
         property Owner : TGLTree read FOwner;
81
         property Count : Integer read FCount;
82
         property Vertices : TAffineVectorList read FVertices;
83
         property Normals : TAffineVectorList read FNormals;
84
         property TexCoords : TAffineVectorList read FTexCoords;
85
   end;
86

87
   // TGLTreeBranch
88
   //
89
   TGLTreeBranch = class
90
      private
91
          
92
         FOwner : TGLTreeBranches;
93
         FLeft : TGLTreeBranch;
94
         FCenter : TGLTreeBranch;
95
         FRight : TGLTreeBranch;
96
         FParent : TGLTreeBranch;
97
         FBranchID : Integer;
98
         FParentID : Integer;
99
         FMatrix : TMatrix;
100
         FLower : TIntegerList;
101
         FUpper : TIntegerList;
102
         FCentralLeader : Boolean;
103

104
         procedure BuildBranch(branchNoise : TGLTreeBranchNoise; const Matrix : TMatrix;
105
                               TexCoordY, Twist : Single; Level : Integer);
106

107
      public
108
          
109
         constructor Create(AOwner : TGLTreeBranches; AParent : TGLTreeBranch);
110
         destructor Destroy; override;
111

112
         property Owner : TGLTreeBranches read FOwner;
113
         property Left : TGLTreeBranch read FLeft;
114
         property Center : TGLTreeBranch read FCenter;
115
         property Right : TGLTreeBranch read FRight;
116
         property Parent : TGLTreeBranch read FParent;
117
         property Matrix : TMatrix read FMatrix;
118
         property Lower : TIntegerList read FLower;
119
         property Upper : TIntegerList read FUpper;
120
   end;
121

122
   // TGLTreeBranches
123
   //
124
   TGLTreeBranches = class
125
      private
126
          
127
         FOwner : TGLTree;
128
         FSinList : TSingleList;
129
         FCosList : TSingleList;
130
         FVertices : TAffineVectorList;
131
         FNormals : TAffineVectorList;
132
         FTexCoords : TAffineVectorList;
133
         FIndices : TIntegerList;
134
         FRoot : TGLTreeBranch;
135
         FCount : Integer;
136
         FBranchCache : TList;
137
         FBranchIndices : TIntegerList;
138

139
         procedure BuildBranches;
140

141
      public
142
          
143
         constructor Create(AOwner : TGLTree);
144
         destructor Destroy; override;
145

146
         procedure BuildList(var rci : TGLRenderContextInfo);
147
         procedure Clear;
148

149
         property Owner : TGLTree read FOwner;
150
         property SinList : TSingleList read FSinList;
151
         property CosList : TSingleList read FCosList;
152
         property Vertices : TAffineVectorList read FVertices;
153
         property Normals : TAffineVectorList read FNormals;
154
         property TexCoords : TAffineVectorList read FTexCoords;
155
         property Count : Integer read FCount;
156
   end;
157

158
   // TGLTreeBranchNoise
159
   //
160
   TGLTreeBranchNoise = class
161
      private
162
          
163
         FBranchNoise : Single;
164
         FLeft, FRight, FCenter : TGLTreeBranchNoise;
165

166
         function GetLeft : TGLTreeBranchNoise;
167
         function GetCenter : TGLTreeBranchNoise;
168
         function GetRight : TGLTreeBranchNoise;
169

170
      public
171
          
172
         constructor Create;
173
         destructor Destroy; override;
174

175
         property Left : TGLTreeBranchNoise read GetLeft;
176
         property Center : TGLTreeBranchNoise read GetCenter;
177
         property Right : TGLTreeBranchNoise read GetRight;
178
         property BranchNoise : Single read FBranchNoise;
179
   end;
180

181
   // TGLTree
182
   //
183
   TGLTree = class (TGLImmaterialSceneObject)
184
      private
185
          
186
         FDepth : Integer;
187
         FBranchFacets : Integer;
188
         FLeafSize : Single;
189
         FBranchSize : Single;
190
         FBranchNoise : Single;
191
         FBranchAngleBias : Single;
192
         FBranchAngle : Single;
193
         FBranchTwist : Single;
194
         FBranchRadius : Single;
195
         FLeafThreshold : Single;
196
         FCentralLeaderBias : Single;
197
         FCentralLeader : Boolean;
198
         FSeed : Integer;
199
         FAutoCenter : Boolean;
200
         FAutoRebuild : Boolean;
201
         FCenterBranchConstant : Single;
202

203
         FLeaves : TGLTreeLeaves;
204
         FBranches : TGLTreeBranches;
205
         FNoise : TGLTreeBranchNoise;
206

207
         FMaterialLibrary : TGLMaterialLibrary;
208
         FLeafMaterialName : TGLLibMaterialName;
209
         FLeafBackMaterialName : TGLLibMaterialName;
210
         FBranchMaterialName : TGLLibMaterialName;
211

212
         FRebuildTree : Boolean;
213

214
         FAxisAlignedDimensionsCache : TVector;
215

216
      protected
217
          
218
         procedure SetDepth(const Value : Integer);
219
         procedure SetBranchFacets(const Value : Integer);
220
         procedure SetLeafSize(const Value : Single);
221
         procedure SetBranchSize(const Value : Single);
222
         procedure SetBranchNoise(const Value : Single);
223
         procedure SetBranchAngleBias(const Value : Single);
224
         procedure SetBranchAngle(const Value : Single);
225
         procedure SetBranchTwist(const Value : Single);
226
         procedure SetBranchRadius(const Value : Single);
227
         procedure SetLeafThreshold(const Value : Single);
228
         procedure SetCentralLeaderBias(const Value : Single);
229
         procedure SetCentralLeader(const Value : Boolean);
230
         procedure SetSeed(const Value : Integer);
231
         procedure SetAutoCenter(const Value : Boolean);
232
         procedure SetAutoRebuild(const Value : Boolean);
233
         procedure SetCenterBranchConstant(const Value : Single);
234

235
         procedure SetMaterialLibrary(const Value : TGLMaterialLibrary);
236
         procedure SetLeafMaterialName(const Value : TGLLibMaterialName);
237
         procedure SetLeafBackMaterialName(const Value : TGLLibMaterialName);
238
         procedure SetBranchMaterialName(const Value : TGLLibMaterialName);
239

240
         procedure Loaded; override;
241

242
      public
243
          
244
         constructor Create(AOwner : TComponent); override;
245
         destructor Destroy; override;
246

247
         procedure Notification(AComponent: TComponent; Operation: TOperation); override;
248
         procedure DoRender(var ARci : TGLRenderContextInfo;
249
                            ARenderSelf, ARenderChildren : Boolean); override;
250
         procedure BuildList(var rci : TGLRenderContextInfo); override;
251
         procedure StructureChanged; override;
252

253
         procedure BuildMesh(GLBaseMesh : TGLBaseMesh);
254
         procedure RebuildTree;
255
         procedure ForceTotalRebuild;
256
         procedure Clear;
257

258
         procedure GetExtents(var min, max : TAffineVector);
259
         function AxisAlignedDimensionsUnscaled : TVector; override;
260

261
         procedure LoadFromStream(aStream : TStream);
262
         procedure SaveToStream(aStream : TStream);
263
         procedure LoadFromFile(aFileName : String);
264
         procedure SaveToFile(aFileName : String);
265

266
         property Leaves : TGLTreeLeaves read FLeaves;
267
         property Branches : TGLTreeBranches read FBranches;
268
         property Noise : TGLTreeBranchNoise read FNoise;
269

270
      published
271
          
272
         { The depth of tree branch recursion. }
273
         property Depth : Integer read FDepth write SetDepth;
274
         { The number of facets for each branch in the tree. }
275
         property BranchFacets : Integer read FBranchFacets write SetBranchFacets;
276
         { Leaf size modifier. Leaf size is also influenced by branch recursion
277
            scale. }
278
         property LeafSize : Single read FLeafSize write SetLeafSize;
279
         { Branch length modifier. }
280
         property BranchSize : Single read FBranchSize write SetBranchSize;
281
         { Overall branch noise influence. Relates to the 'fullness' of the tree. }
282
         property BranchNoise : Single read FBranchNoise write SetBranchNoise;
283
         { Effects the habit of the tree. Values from 0 to 1 refer to Upright to
284
            Spreading respectively. }
285
         property BranchAngleBias : Single read FBranchAngleBias write SetBranchAngleBias;
286
         { Effects the balance of the tree. }
287
         property BranchAngle : Single read FBranchAngle write SetBranchAngle;
288
         { Effects the rotation of each sub branch in recursion. }
289
         property BranchTwist : Single read FBranchTwist write SetBranchTwist;
290
         { Effects the thickness of the branches. }
291
         property BranchRadius : Single read FBranchRadius write SetBranchRadius;
292
         { Determines how thin a branch can get before a leaf is substituted. }
293
         property LeafThreshold : Single read FLeafThreshold write SetLeafThreshold;
294
         { Determines how BranchAngle effects the central leader (CentralLeader must = True). }
295
         property CentralLeaderBias : Single read FCentralLeaderBias write SetCentralLeaderBias;
296
         { Does this tree have a central leader? }
297
         property CentralLeader : Boolean read FCentralLeader write SetCentralLeader;
298
         property Seed : Integer read FSeed write SetSeed;
299
         { Automatically center the tree's vertices after building them. }
300
         property AutoCenter : Boolean read FAutoCenter write SetAutoCenter;
301
         { Automatically rebuild the tree after changing the settings }
302
         property AutoRebuild : Boolean read FAutoRebuild write SetAutoRebuild;
303
         { Central branch can be thinner(lower values)/thicker(->1) depending on this constant.
304
            The effect also depends on the BranchAngle variable. }
305
         property CenterBranchConstant : Single read FCenterBranchConstant write SetCenterBranchConstant;
306

307
         property MaterialLibrary : TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
308
         property LeafMaterialName : TGLLibMaterialName read FLeafMaterialName write SetLeafMaterialName;
309
         property LeafBackMaterialName : TGLLibMaterialName read FLeafBackMaterialName write SetLeafBackMaterialName;
310
         property BranchMaterialName : TGLLibMaterialName read FBranchMaterialName write SetBranchMaterialName;
311
   end;
312

313
// -----------------------------------------------------------------------------
314
// -----------------------------------------------------------------------------
315
// -----------------------------------------------------------------------------
316
implementation
317
// -----------------------------------------------------------------------------
318
// -----------------------------------------------------------------------------
319
// -----------------------------------------------------------------------------
320

321
// -----------------------------------------------------------------------------
322
// TGLTreeLeaves
323
// -----------------------------------------------------------------------------
324

325
// Create
326
//
327
constructor TGLTreeLeaves.Create(AOwner: TGLTree);
328
begin
329
   FOwner:=AOwner;
330
   FCount:=0;
331
   FVertices:=TAffineVectorList.Create;
332
   FNormals:=TAffineVectorList.Create;
333
   FTexCoords:=TAffineVectorList.Create;
334
end;
335

336
// Destroy
337
//
338
destructor TGLTreeLeaves.Destroy;
339
begin
340
   FVertices.Free;
341
   FNormals.Free;
342
   FTexCoords.Free;
343
   inherited;
344
end;
345

346
// AddNew
347
//
348
procedure TGLTreeLeaves.AddNew(matrix : TMatrix);
349
var
350
   radius : Single;
351
   pos : TVector;
352
begin
353
   radius:=Owner.LeafSize;
354
   Inc(FCount);
355

356
   pos:=matrix.V[3];
357
   Matrix.V[3]:=NullHMGPoint;
358
   Matrix:=Roll(matrix, FCount/10);
359
   NormalizeMatrix(matrix);
360
   Matrix.V[3]:=pos;
361

362
   FVertices.Add(VectorTransform(PointMake(0, -radius, 0), matrix));
363
   FVertices.Add(VectorTransform(PointMake(0, radius, 0), matrix));
364
   FVertices.Add(VectorTransform(PointMake(0, radius, 2*radius), matrix));
365
   FVertices.Add(VectorTransform(PointMake(0, -radius, 2*radius), matrix));
366
   FNormals.Add(VectorTransform(XHmgVector, matrix));
367
   FTexCoords.Add(XVector, NullVector);
368
   FTexCoords.Add(YVector, XYVector);
369
end;
370

371
// BuildList
372
//
373
procedure TGLTreeLeaves.BuildList(var rci: TGLRenderContextInfo);
374
var
375
   i : integer;
376
   n : TAffineVector;
377
   libMat : TGLLibMaterial;
378
begin
379
   libMat:=Owner.MaterialLibrary.LibMaterialByName(Owner.LeafMaterialName);
380
   if Assigned(libMat) then
381
      libMat.Apply(rci);
382

383
   GL.EnableClientState(GL_VERTEX_ARRAY);
384
   xgl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
385

386
   GL.VertexPointer(3, GL_FLOAT, 0, @FVertices.List[0]);
387
   xgl.TexCoordPointer(3, GL_FLOAT, 0, @FTexCoords.List[0]);
388

389
   for i:=0 to (FVertices.Count div 4)-1 do begin
390
      GL.Normal3fv(@FNormals.List[i]);
391
      GL.DrawArrays(GL_QUADS, 4*i, 4);
392
   end;
393

394
   with Owner do if LeafMaterialName<>LeafBackMaterialName then begin
395
      if Assigned(libMat) then
396
         libMat.UnApply(rci);
397
      libMat:=MaterialLibrary.LibMaterialByName(LeafBackMaterialName);
398
      if Assigned(libMat) then
399
         libMat.Apply(rci);
400
   end;
401

402
   rci.GLStates.InvertGLFrontFace;
403
   for i:=0 to (FVertices.Count div 4)-1 do begin
404
      n:=VectorNegate(FNormals[i]);
405
      GL.Normal3fv(@n);
406
      GL.DrawArrays(GL_QUADS, 4*i, 4);
407
   end;
408
   rci.GLStates.InvertGLFrontFace;
409

410
   GL.DisableClientState(GL_VERTEX_ARRAY);
411
   xgl.DisableClientState(GL_TEXTURE_COORD_ARRAY);
412

413
   if Assigned(libMat) then
414
      libMat.UnApply(rci);
415
end;
416

417
// Clear
418
//
419
procedure TGLTreeLeaves.Clear;
420
begin
421
   FVertices.Clear;
422
   FNormals.Clear;
423
   FTexCoords.Clear;
424
   FCount:=0;
425
end;
426

427
// -----------------------------------------------------------------------------
428
// TGLTreeBranch
429
// -----------------------------------------------------------------------------
430

431
// Create
432
//
433
constructor TGLTreeBranch.Create(AOwner : TGLTreeBranches; AParent : TGLTreeBranch);
434
begin
435
   FOwner:=AOwner;
436
   FParent:=AParent;
437
   FUpper:=TIntegerList.Create;
438
   FLower:=TIntegerList.Create;
439
   FCentralLeader:=False;
440

441
   // Skeletal construction helpers
442
   if Assigned(FOwner) then begin
443
      FBranchID:=FOwner.Count-1;
444
      FOwner.FBranchCache.Add(Self);
445
   end else FBranchID:=-1;
446
   if Assigned(FParent) then
447
      FParentID:=FParent.FBranchID
448
   else FParentID:=-1;
449
end;
450

451
// Destroy
452
//
453
destructor TGLTreeBranch.Destroy;
454
begin
455
   FUpper.Free;
456
   FLower.Free;
457
   FLeft.Free;
458
   FRight.Free;
459
   inherited;
460
end;
461

462
// BuildBranch
463
//
464
procedure TGLTreeBranch.BuildBranch(branchNoise : TGLTreeBranchNoise; const Matrix : TMatrix;
465
                                    TexCoordY, Twist : Single; Level : Integer);
466
var
467
   i : Integer;
468
   Tree : TGLTree;
469
   Branches : TGLTreeBranches;
470
   Facets : Integer;
471
   t,c,s : Single;
472
   Radius, LeftRadius,  RightRadius, CenterRadius : Single;
473
   BranchAngle, LeftAngle, RightAngle, CenterAngle : Single;
474
   BranchAngleBias, BranchTwist, Taper : Single;
475
   LeftBranchNoiseValue, RightBranchNoiseValue, CenterBranchNoiseValue : Single;
476
   LeftBranchNoise : TGLTreeBranchNoise;
477
   CenterBranchNoise : TGLTreeBranchNoise;
478
   RightBranchNoise : TGLTreeBranchNoise;
479
   LeftMatrix, RightMatrix, CenterMatrix : TMatrix;
480
   central_leader : Boolean;
481
begin
482
   Assert(Assigned(FOwner),'Incorrect use of TGLTreeBranch');
483
   Assert(Assigned(FOwner.FOwner),'Incorrect use of TGLTreeBranches');
484

485
   FMatrix:=Matrix;
486

487
   Branches:=FOwner;
488
   Tree:=FOwner.FOwner;
489

490
   Facets:=Tree.BranchFacets;
491
   Radius:=Tree.BranchRadius;
492

493
   FLower.Clear;
494
   FLower.Capacity:=Facets+1;
495
   FUpper.Clear;
496
   FUpper.Capacity:=Facets+1;
497

498
   BranchAngle:=Tree.BranchAngle;
499
   BranchAngleBias:=Tree.BranchAngleBias;
500
   BranchTwist:=Twist+Tree.BranchTwist;
501

502
   LeftBranchNoise:=BranchNoise.Left;
503
   CenterBranchNoise:=BranchNoise.Center;
504
   RightBranchNoise:=BranchNoise.Right;
505

506
   LeftBranchNoiseValue:=((LeftBranchNoise.BranchNoise*0.4)-0.1)*Tree.BranchNoise;
507
   LeftRadius:=Sqrt(1-BranchAngle+LeftBranchNoiseValue);
508
   LeftRadius:=ClampValue(LeftRadius,0,1);
509
   LeftAngle:=BranchAngle*90*BranchAngleBias+10*LeftBranchNoiseValue;
510

511
   CenterBranchNoiseValue:=((CenterBranchNoise.BranchNoise*0.9)-0.1)*Tree.BranchNoise;
512
   CenterRadius:=Sqrt(Tree.CenterBranchConstant-BranchAngle+CenterBranchNoiseValue);
513
   CenterRadius:=ClampValue(CenterRadius,0,1);
514
   CenterAngle:=(1-BranchAngle)*50*CenterBranchNoiseValue*BranchAngleBias;
515

516
   RightBranchNoiseValue:=((RightBranchNoise.BranchNoise*0.6)-0.1)*Tree.BranchNoise;
517
   RightRadius:=Sqrt(BranchAngle+RightBranchNoiseValue);
518
   RightRadius:=ClampValue(RightRadius,0,1);
519
   RightAngle:=(1-BranchAngle)*-90*BranchAngleBias+10*RightBranchNoiseValue;
520

521
   Taper:=MaxFloat(LeftRadius, RightRadius, CenterRadius);
522

523
   // Build cylinder lower
524
   for i:=0 to Facets do begin
525
      t:=1/Facets*i;
526
      c:=Branches.CosList[i];
527
      s:=Branches.SinList[i];
528
      Branches.Vertices.Add(VectorTransform(PointMake(c*Radius,s*Radius,Radius),Matrix));
529
      Branches.Normals.Add(VectorTransform(VectorMake(c,s,0),Matrix));
530
      Branches.TexCoords.Add(t,TexCoordY);
531
      FLower.Add(Branches.Vertices.Count-1);
532
      Branches.FBranchIndices.Add(FBranchID);
533
   end;
534

535
   TexCoordY:=TexCoordY+1-2*Radius;
536

537
   // Build cylinder upper
538
   for i:=0 to Facets do begin
539
      t:=1/Facets*i;
540
      c:=Branches.CosList[i];
541
      s:=Branches.SinList[i];
542
      Branches.Vertices.Add(VectorTransform(PointMake(c*Radius*Taper,s*Radius*Taper,1-Radius),Matrix));
543
      Branches.Normals.Add(VectorTransform(VectorMake(c,s,0),Matrix));
544
      Branches.TexCoords.Add(t,TexCoordY);
545
      FUpper.Add(Branches.Vertices.Count-1);
546
      Branches.FBranchIndices.Add(FBranchID);
547
   end;
548

549
   TexCoordY:=TexCoordY+2*Radius;
550

551
   // BuildMatrices
552
   SinCos(DegToRad(BranchTwist),s,c);
553

554
   if Level=0 then
555
      central_leader:=FCentralLeader
556
   else
557
      central_leader:=FParent.FCentralLeader;
558

559
   if central_leader then begin
560
      LeftMatrix:=MatrixMultiply(
561
         CreateScaleMatrix(AffineVectorMake(LeftRadius,LeftRadius,LeftRadius)),
562
         CreateRotationMatrix(AffineVectorMake(s,c,0),DegToRad(LeftAngle)*Tree.CentralLeaderBias));
563
   end else begin
564
      LeftMatrix:=MatrixMultiply(
565
         CreateScaleMatrix(AffineVectorMake(LeftRadius,LeftRadius,LeftRadius)),
566
         CreateRotationMatrix(AffineVectorMake(s,c,0),DegToRad(LeftAngle)));
567
   end;
568
   LeftMatrix:=MatrixMultiply(
569
      LeftMatrix,
570
      MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0,0,Tree.BranchSize*(1-LeftBranchNoiseValue))),Matrix));
571

572
   CenterMatrix:=MatrixMultiply(
573
      CreateScaleMatrix(AffineVectorMake(CenterRadius,CenterRadius,CenterRadius)),
574
      CreateRotationMatrix(AffineVectorMake(s,c,0),DegToRad(CenterAngle)));
575
   CenterMatrix:=MatrixMultiply(
576
      CenterMatrix,
577
      MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0,0,Tree.BranchSize*(1-CenterBranchNoiseValue))),Matrix));
578

579
   RightMatrix:=MatrixMultiply(
580
      CreateScaleMatrix(AffineVectorMake(RightRadius,RightRadius,RightRadius)),
581
      CreateRotationMatrix(AffineVectorMake(s,c,0),DegToRad(RightAngle)));
582
   RightMatrix:=MatrixMultiply(
583
      RightMatrix,
584
      MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0,0,Tree.BranchSize*(1-RightBranchNoiseValue))),Matrix));
585

586
   if (((Level+1)>=Tree.Depth) or (LeftRadius<Tree.LeafThreshold)) then begin
587
      Tree.Leaves.AddNew(LeftMatrix);
588
   end else begin
589
      Inc(Branches.FCount);
590
      FLeft:=TGLTreeBranch.Create(Owner,Self);
591
      FLeft.FCentralLeader:=central_leader and (LeftRadius>=RightRadius);
592
      FLeft.BuildBranch(LeftBranchNoise,LeftMatrix,TexCoordY,BranchTwist,Level+1);
593
   end;
594

595
   if (((Level+1)>=Tree.Depth) or (CenterRadius<Tree.LeafThreshold)) then begin
596
      Tree.Leaves.AddNew(CenterMatrix);
597
   end else begin
598
      Inc(Branches.FCount);
599
      FCenter:=TGLTreeBranch.Create(Owner,Self);
600
      FCenter.BuildBranch(CenterBranchNoise,CenterMatrix,TexCoordY,BranchTwist,Level+1);
601
   end;
602

603
   if (((Level+1)>=Tree.Depth) or (RightRadius<Tree.LeafThreshold)) then begin
604
      Tree.Leaves.AddNew(RightMatrix);
605
   end else begin
606
      Inc(Branches.FCount);
607
      FRight:=TGLTreeBranch.Create(Owner,Self);
608
      FRight.BuildBranch(RightBranchNoise,RightMatrix,TexCoordY,BranchTwist,Level+1);
609
   end;
610

611
   for i:=0 to Facets do begin
612
      Branches.FIndices.Add(Upper[i]);
613
      Branches.FIndices.Add(Lower[i]);
614
   end;
615

616
   if Assigned(FRight) then begin
617
      for i:=0 to Facets do begin
618
         Branches.FIndices.Add(Right.Lower[i]);
619
         Branches.FIndices.Add(Upper[i]);
620
      end;
621
   end;
622

623
   if Assigned(FCenter) then begin
624
      for i:=0 to Facets do begin
625
         Branches.FIndices.Add(Center.Lower[i]);
626
         Branches.FIndices.Add(Upper[i]);
627
      end;
628
   end;
629

630
   if Assigned(FLeft) then begin
631
      for i:=0 to Facets do begin
632
         Branches.FIndices.Add(Left.Lower[i]);
633
         Branches.FIndices.Add(Upper[i]);
634
      end;
635
   end;
636

637
end;
638

639
// -----------------------------------------------------------------------------
640
// TGLTreeBranches
641
// -----------------------------------------------------------------------------
642

643
// Create
644
//
645
constructor TGLTreeBranches.Create(AOwner: TGLTree);
646
begin
647
   FOwner:=AOwner;
648
   FSinList:=TSingleList.Create;
649
   FCosList:=TSingleList.Create;
650
   FVertices:=TAffineVectorList.Create;
651
   FNormals:=TAffineVectorList.Create;
652
   FTexCoords:=TAffineVectorList.Create;
653
   FIndices:=TIntegerList.Create;
654
   FBranchCache:=TList.Create;
655
   FBranchIndices:=TIntegerList.Create;
656
   FCount:=0;
657
end;
658

659
// Destroy
660
//
661
destructor TGLTreeBranches.Destroy;
662
begin
663
   FSinList.Free;
664
   FCosList.Free;
665
   FVertices.Free;
666
   FNormals.Free;
667
   FTexCoords.Free;
668
   FIndices.Free;
669
   FRoot.Free;
670
   FBranchCache.Free;
671
   FBranchIndices.Free;
672
   inherited;
673
end;
674

675
// BuildBranches
676
//
677
procedure TGLTreeBranches.BuildBranches;
678
var
679
   i : Integer;
680
   u : Single;
681
   delta, min, max : TAffineVector;
682
begin
683
   RandSeed:=Owner.FSeed;
684

685
   for i:=0 to Owner.BranchFacets do begin
686
      u:=1/Owner.BranchFacets*i;
687
      SinList.Add(Sin(PI*2*u));
688
      CosList.Add(Cos(PI*2*u));
689
   end;
690

691
   Inc(FCount);
692
   FRoot:=TGLTreeBranch.Create(Self,nil);
693
   FRoot.FCentralLeader:=Owner.CentralLeader;
694
   FRoot.BuildBranch(Owner.Noise,IdentityHMGMatrix,0,0,0);
695

696
   delta:=AffineVectorMake(0,0,-Owner.BranchRadius);
697
   Vertices.Translate(delta);
698
   Owner.Leaves.Vertices.Translate(delta);
699

700
   if Owner.AutoCenter then begin
701
      Owner.GetExtents(min, max);
702
      delta:=VectorCombine(min,max,-0.5,-0.5);
703
      Vertices.Translate(delta);
704
      Owner.Leaves.Vertices.Translate(delta);
705
   end;
706

707
   Owner.FAxisAlignedDimensionsCache.V[0]:=-1;
708
end;
709

710
// BuildList
711
//
712
procedure TGLTreeBranches.BuildList(var rci: TGLRenderContextInfo);
713
var
714
   i, stride : Integer;
715
   libMat : TGLLibMaterial;
716
begin
717
   stride:=(Owner.BranchFacets+1)*2;
718

719
   libMat:=Owner.MaterialLibrary.LibMaterialByName(Owner.BranchMaterialName);
720
   if Assigned(libMat) then
721
      libMat.Apply(rci);
722

723
   GL.VertexPointer(3, GL_FLOAT, 0, @FVertices.List[0]);
724
   GL.NormalPointer(GL_FLOAT, 0, @FNormals.List[0]);
725
   xgl.TexCoordPointer(3, GL_FLOAT, 0, @FTexCoords.List[0]);
726

727
   GL.EnableClientState(GL_VERTEX_ARRAY);
728
   GL.EnableClientState(GL_NORMAL_ARRAY);
729
   xgl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
730

731
   repeat
732
      for i:=0 to (FIndices.Count div stride)-1 do
733
         GL.DrawElements(GL_TRIANGLE_STRIP, stride, GL_UNSIGNED_INT, @FIndices.List[stride*i]);
734
   until (not Assigned(libMat)) or (not libMat.UnApply(rci));
735

736
   xgl.DisableClientState(GL_TEXTURE_COORD_ARRAY);
737
   GL.DisableClientState(GL_NORMAL_ARRAY);
738
   GL.DisableClientState(GL_VERTEX_ARRAY);
739
end;
740

741
// Clear
742
//
743
procedure TGLTreeBranches.Clear;
744
begin
745
   FSinList.Clear;
746
   FCosList.Clear;
747
   FVertices.Clear;
748
   FNormals.Clear;
749
   FTexCoords.Clear;
750
   FIndices.Clear;
751
   FBranchCache.Clear;
752
   FBranchIndices.Clear;
753
   FreeAndNil(FRoot);
754
   FCount:=0;
755
end;
756

757
// -----------------------------------------------------------------------------
758
// TGLTreeBranchNoise
759
// -----------------------------------------------------------------------------
760

761
// Create
762
//
763
constructor TGLTreeBranchNoise.Create;
764
begin
765
   FBranchNoise:=Random;
766
end;
767

768
// Destroy
769
//
770
destructor TGLTreeBranchNoise.Destroy;
771
begin
772
   FLeft.Free;
773
   FRight.Free;
774
   inherited;
775
end;
776

777
// GetLeft
778
//
779
function TGLTreeBranchNoise.GetLeft: TGLTreeBranchNoise;
780
begin
781
   if not Assigned(FLeft) then
782
      FLeft:=TGLTreeBranchNoise.Create;
783
   Result:=FLeft;
784
end;
785

786
// GetRight
787
//
788
function TGLTreeBranchNoise.GetRight: TGLTreeBranchNoise;
789
begin
790
   if not Assigned(FRight) then
791
      FRight:=TGLTreeBranchNoise.Create;
792
   Result:=FRight;
793
end;
794

795
function TGLTreeBranchNoise.GetCenter: TGLTreeBranchNoise;
796
begin
797
   if not Assigned(FCenter) then
798
      FCenter:=TGLTreeBranchNoise.Create;
799
   Result:=FCenter;
800
end;
801

802
// -----------------------------------------------------------------------------
803
// TGLTree
804
// -----------------------------------------------------------------------------
805

806
// Create
807
//
808
constructor TGLTree.Create(AOwner: TComponent);
809
begin
810
   inherited;
811
   // Default tree setting
812
   FDepth:=5;
813
   FLeafThreshold:=0.02;
814
   FBranchAngleBias:=0.6;
815
   FBranchAngle:=0.4;
816
   FBranchTwist:=45;
817
   FBranchNoise:=0.7;
818
   FBranchSize:=1.0;
819
   FLeafSize:=0.1;
820
   FBranchRadius:=0.12;
821
   FBranchFacets:=6;
822
   FCentralLeader:=False;
823
   FSeed:=0;
824
   FAutoCenter:=False;
825
   FAutoRebuild:=True;
826
   FCenterBranchConstant:=0.5;
827

828
   FLeaves:=TGLTreeLeaves.Create(Self);
829
   FBranches:=TGLTreeBranches.Create(Self);
830
   FNoise:=TGLTreeBranchNoise.Create;
831
end;
832

833
// Destroy
834
//
835
destructor TGLTree.Destroy;
836
begin
837
   FLeaves.Free;
838
   FBranches.Free;
839
   FNoise.Free;
840
   inherited;
841
end;
842

843
// Loaded
844
//
845
procedure TGLTree.Loaded;
846
begin
847
   inherited;
848
   FBranches.BuildBranches;
849
end;
850

851
// Notification
852
//
853
procedure TGLTree.Notification(AComponent: TComponent; Operation: TOperation);
854
begin
855
   if (Operation=opRemove) and (AComponent=FMaterialLibrary) then
856
      MaterialLibrary:=nil;
857
   inherited;
858
end;
859

860
// DoRender
861
//
862
procedure TGLTree.DoRender(var ARci : TGLRenderContextInfo;
863
                           ARenderSelf, ARenderChildren : Boolean);
864
begin
865
   MaterialLibrary.LibMaterialByName(BranchMaterialName).PrepareBuildList;
866
   MaterialLibrary.LibMaterialByName(LeafMaterialName).PrepareBuildList;
867
   MaterialLibrary.LibMaterialByName(LeafBackMaterialName).PrepareBuildList;
868
   inherited;
869
end;
870

871
// BuildList
872
//
873
procedure TGLTree.BuildList(var rci: TGLRenderContextInfo);
874
begin
875
   if FRebuildTree then begin
876
      FBranches.BuildBranches;
877
      FRebuildTree:=False;
878
   end;
879
   Branches.BuildList(rci);
880
   Leaves.BuildList(rci);
881
end;
882

883
// StructureChanged
884
//
885
procedure TGLTree.StructureChanged;
886
begin
887
  FAxisAlignedDimensionsCache.V[0]:=-1;
888
  inherited;
889
end;
890

891
// BuildMesh
892
//
893
procedure TGLTree.BuildMesh(GLBaseMesh : TGLBaseMesh);
894

895
   procedure RecursBranches(Branch : TGLTreeBranch; bone : TGLSkeletonBone; Frame : TGLSkeletonFrame);
896
   var
897
      trans : TTransformations;
898
      mat : TMatrix;
899
      rot, pos : TAffineVector;
900
   begin
901
      bone.Name:='Branch'+IntToStr(Branch.FBranchID);
902
      bone.BoneID:=Branch.FBranchID;
903

904
      // Construct base frame
905
      if Assigned(Branch.FParent) then
906
         mat:=Branch.FParent.FMatrix
907
      else
908
         mat:=IdentityHMGMatrix;
909
      InvertMatrix(mat);
910
      NormalizeMatrix(mat);
911
      if MatrixDecompose(mat,trans) then begin
912
         SetVector(rot,trans[ttRotateX],trans[ttRotateY],trans[ttRotateZ]);
913
         SetVector(pos,mat.V[3]);
914
      end else begin
915
         rot:=NullVector;
916
        pos:=NullVector;
917
      end;
918
      Frame.Rotation.Add(rot);
919
      Frame.Position.Add(pos);
920

921
      // Recurse with child branches
922
      if Assigned(Branch.Left) then
923
         RecursBranches(Branch.Left, TGLSkeletonBone.CreateOwned(bone), Frame);
924
      if Assigned(Branch.Right) then
925
         RecursBranches(Branch.Right, TGLSkeletonBone.CreateOwned(bone), Frame);
926
   end;
927

928
var
929
   //SkelMesh : TGLSkeletonMeshObject;
930
   fg : TFGVertexIndexList;
931
   fg2 : TFGVertexNormalTexIndexList;
932
   i,j,stride : integer;
933
   //parent_id : integer;
934
   //bone : TGLSkeletonBone;
935
begin
936
   if not Assigned(GLBaseMesh) then exit;
937

938
   if FRebuildTree then begin
939
      FBranches.BuildBranches;
940
      FRebuildTree:=False;
941
   end;
942

943
   GLBaseMesh.MeshObjects.Clear;
944
   GLBaseMesh.Skeleton.Clear;
945

946
   //if GLBaseMesh is TGLActor then
947
   //   TGLSkeletonMeshObject.CreateOwned(GLBaseMesh.MeshObjects)
948
   //else
949
      TGLMeshObject.CreateOwned(GLBaseMesh.MeshObjects);
950
   GLBaseMesh.MeshObjects[0].Mode:=momFaceGroups;
951

952
   // Branches
953
   GLBaseMesh.MeshObjects[0].Vertices.Add(Branches.Vertices);
954
   GLBaseMesh.MeshObjects[0].Normals.Add(Branches.Normals);
955
   GLBaseMesh.MeshObjects[0].TexCoords.Add(Branches.TexCoords);
956
   {if GLBaseMesh is TGLActor then begin
957
      TGLActor(GLBaseMesh).Reference:=aarSkeleton;
958
      RecursBranches(Branches.FRoot,
959
                     TGLSkeletonBone.CreateOwned(GLBaseMesh.Skeleton.RootBones),
960
                     TGLSkeletonFrame.CreateOwned(GLBaseMesh.Skeleton.Frames));
961
      SkelMesh:=TGLSkeletonMeshObject(GLBaseMesh.MeshObjects[0]);
962
      SkelMesh.BonesPerVertex:=1;
963
      SkelMesh.VerticeBoneWeightCount:=Branches.FBranchIndices.Count;
964
      for i:=0 to Branches.FBranchIndices.Count-1 do
965
         SkelMesh.AddWeightedBone(Branches.FBranchIndices[i],1);
966
      GLBaseMesh.Skeleton.RootBones.PrepareGlobalMatrices;
967
      SkelMesh.PrepareBoneMatrixInvertedMeshes;
968

969
      SkelMesh.ApplyCurrentSkeletonFrame(True);
970
   end;//}
971
   stride:=(BranchFacets+1)*2;
972
   for i:=0 to (FBranches.FIndices.Count div stride)-1 do begin
973
      fg:=TFGVertexIndexList.CreateOwned(GLBaseMesh.MeshObjects[0].FaceGroups);
974
      fg.MaterialName:=BranchMaterialName;
975
      fg.Mode:=fgmmTriangleStrip;
976
      for j:=0 to stride-1 do
977
         fg.VertexIndices.Add(Branches.FIndices[i*stride+j]);
978
   end;
979

980
   // Leaves
981
   //if GLBaseMesh is TGLActor then
982
   //   TGLSkeletonMeshObject.CreateOwned(GLBaseMesh.MeshObjects)
983
   //else
984
      TGLMeshObject.CreateOwned(GLBaseMesh.MeshObjects);
985
   GLBaseMesh.MeshObjects[1].Mode:=momFaceGroups;
986

987
   GLBaseMesh.MeshObjects[1].Vertices.Add(Leaves.Vertices);
988
   GLBaseMesh.MeshObjects[1].Normals.Add(Leaves.FNormals);
989
   for i:=0 to Leaves.Normals.Count-1 do
990
      GLBaseMesh.MeshObjects[1].Normals.Add(VectorNegate(Leaves.FNormals[i]));
991
   GLBaseMesh.MeshObjects[1].TexCoords.Add(Leaves.TexCoords);
992

993
   for i:=0 to (Leaves.FVertices.Count div 4)-1 do begin
994

995
      // Leaf front
996
      fg2:=TFGVertexNormalTexIndexList.CreateOwned(GLBaseMesh.MeshObjects[1].FaceGroups);
997
      fg2.MaterialName:=LeafMaterialName;
998
      fg2.Mode:=fgmmTriangleStrip;
999
      with fg2.VertexIndices do begin
1000
         Add(i*4);
1001
         Add(i*4+1);
1002
         Add(i*4+3);
1003
         Add(i*4+2);
1004
      end;
1005
      for j:=0 to 3 do
1006
         fg2.NormalIndices.Add(i);
1007
      with fg2.TexCoordIndices do begin
1008
         Add(0);
1009
         Add(1);
1010
         Add(3);
1011
         Add(2);
1012
      end;
1013

1014
      // Leaf back
1015
      fg2:=TFGVertexNormalTexIndexList.CreateOwned(GLBaseMesh.MeshObjects[1].FaceGroups);
1016
      fg2.MaterialName:=LeafBackMaterialName;
1017
      fg2.Mode:=fgmmTriangleStrip;
1018
      with fg2.VertexIndices do begin
1019
         Add(i*4);
1020
         Add(i*4+3);
1021
         Add(i*4+1);
1022
         Add(i*4+2);
1023
      end;
1024
      for j:=0 to 3 do
1025
         fg2.NormalIndices.Add(i);
1026
      with fg2.TexCoordIndices do begin
1027
         Add(0);
1028
         Add(3);
1029
         Add(1);
1030
         Add(2);
1031
      end;
1032
   end;
1033
end;
1034

1035
// Clear
1036
//
1037
procedure TGLTree.Clear;
1038
begin
1039
   FLeaves.Clear;
1040
   FBranches.Clear;
1041
end;
1042

1043
// SetBranchAngle
1044
//
1045
procedure TGLTree.SetBranchAngle(const Value: Single);
1046
begin
1047
   if Value<>FBranchAngle then begin
1048
      FBranchAngle:=Value;
1049
      if (FAutoRebuild) then RebuildTree;
1050
   end;
1051
end;
1052

1053
// SetBranchAngleBias
1054
//
1055
procedure TGLTree.SetBranchAngleBias(const Value: Single);
1056
begin
1057
   if Value<>FBranchAngleBias then begin
1058
      FBranchAngleBias:=Value;
1059
      if (FAutoRebuild) then RebuildTree;
1060
   end;
1061
end;
1062

1063
// SetBranchNoise
1064
//
1065
procedure TGLTree.SetBranchNoise(const Value: Single);
1066
begin
1067
   if Value<>FBranchNoise then begin
1068
      FBranchNoise:=Value;
1069
      if (FAutoRebuild) then RebuildTree;
1070
   end;
1071
end;
1072

1073
// SetBranchRadius
1074
//
1075
procedure TGLTree.SetBranchRadius(const Value: Single);
1076
begin
1077
   if Value<>FBranchRadius then begin
1078
      FBranchRadius:=Value;
1079
      if (FAutoRebuild) then RebuildTree;
1080
   end;
1081
end;
1082

1083
// SetBranchSize
1084
//
1085
procedure TGLTree.SetBranchSize(const Value: Single);
1086
begin
1087
   if Value<>FBranchSize then begin
1088
      FBranchSize:=Value;
1089
      if (FAutoRebuild) then RebuildTree;
1090
   end;
1091
end;
1092

1093
// SetBranchTwist
1094
//
1095
procedure TGLTree.SetBranchTwist(const Value: Single);
1096
begin
1097
   if Value<>FBranchTwist then begin
1098
      FBranchTwist:=Value;
1099
      if (FAutoRebuild) then RebuildTree;
1100
   end;
1101
end;
1102

1103
// SetDepth
1104
//
1105
procedure TGLTree.SetDepth(const Value: Integer);
1106
begin
1107
   if Value<>FDepth then begin
1108
      FDepth:=Value;
1109
      if (FAutoRebuild) then RebuildTree;
1110
   end;
1111
end;
1112

1113
// SetBranchFacets
1114
//
1115
procedure TGLTree.SetBranchFacets(const Value: Integer);
1116
begin
1117
   if Value<>FBranchFacets then begin
1118
      FBranchFacets:=Value;
1119
      if (FAutoRebuild) then RebuildTree;
1120
   end;
1121
end;
1122

1123
// SetLeafSize
1124
//
1125
procedure TGLTree.SetLeafSize(const Value: Single);
1126
begin
1127
   if Value<>FLeafSize then begin
1128
      FLeafSize:=Value;
1129
      if (FAutoRebuild) then RebuildTree;
1130
   end;
1131
end;
1132

1133
// SetLeafThreshold
1134
//
1135
procedure TGLTree.SetLeafThreshold(const Value: Single);
1136
begin
1137
   if Value<>FLeafThreshold then begin
1138
      FLeafThreshold:=Value;
1139
      if (FAutoRebuild) then RebuildTree;
1140
   end;
1141
end;
1142

1143
// SetCentralLeaderBias
1144
//
1145
procedure TGLTree.SetCentralLeaderBias(const Value: Single);
1146
begin
1147
   if Value<>FCentralLeaderBias then begin
1148
      FCentralLeaderBias:=Value;
1149
      if (FAutoRebuild) then RebuildTree;
1150
   end;
1151
end;
1152

1153
// SetCentralLeader
1154
//
1155
procedure TGLTree.SetCentralLeader(const Value: Boolean);
1156
begin
1157
   if Value<>FCentralLeader then begin
1158
      FCentralLeader:=Value;
1159
      if (FAutoRebuild) then RebuildTree;
1160
   end;
1161
end;
1162

1163
// SetSeed
1164
//
1165
procedure TGLTree.SetSeed(const Value: Integer);
1166
begin
1167
   if Value<>FSeed then begin
1168
      FSeed:=Value;
1169
      if (FAutoRebuild) then ForceTotalRebuild;
1170
   end;
1171
end;
1172

1173
// SetCenterBranchConstant
1174
//
1175
procedure TGLTree.SetCenterBranchConstant(const Value : Single);
1176
begin
1177
   if Value<>CenterBranchConstant then begin
1178
      FCenterBranchConstant:=Value;
1179
      if (FAutoRebuild) then ForceTotalRebuild;
1180
   end;
1181
end;
1182

1183
// SetBranchMaterialName
1184
//
1185
procedure TGLTree.SetBranchMaterialName(const Value: TGLLibMaterialName);
1186
begin
1187
   if Value<>FBranchMaterialName then begin
1188
      FBranchMaterialName:=Value;
1189
      StructureChanged;
1190
   end;
1191
end;
1192

1193
// SetLeafBackMaterialName
1194
//
1195
procedure TGLTree.SetLeafBackMaterialName(const Value: TGLLibMaterialName);
1196
begin
1197
   if Value<>FLeafBackMaterialName then begin
1198
      FLeafBackMaterialName:=Value;
1199
      StructureChanged;
1200
   end;
1201
end;
1202

1203
// SetLeafMaterialName
1204
//
1205
procedure TGLTree.SetLeafMaterialName(const Value: TGLLibMaterialName);
1206
begin
1207
   if Value<>FLeafMaterialName then begin
1208
      FLeafMaterialName:=Value;
1209
      StructureChanged;
1210
   end;
1211
end;
1212

1213
// SetMaterialLibrary
1214
//
1215
procedure TGLTree.SetMaterialLibrary(const Value: TGLMaterialLibrary);
1216
begin
1217
   if Value<>FMaterialLibrary then begin
1218
      FMaterialLibrary:=Value;
1219
      StructureChanged;
1220
   end;
1221
end;
1222

1223
// RebuildTree
1224
//
1225
procedure TGLTree.RebuildTree;
1226
begin
1227
   if not FRebuildTree then begin
1228
      Clear;
1229
      FRebuildTree:=True;
1230
      StructureChanged;
1231
   end;
1232
end;
1233

1234
// ForceTotalRebuild
1235
//
1236
procedure TGLTree.ForceTotalRebuild;
1237
begin
1238
   Clear;
1239
   FNoise.Free;
1240
   RandSeed:=FSeed;
1241
   FNoise:=TGLTreeBranchNoise.Create;
1242
   FRebuildTree:=False;
1243
   FBranches.BuildBranches;
1244
   StructureChanged;
1245
end;
1246

1247
// LoadFromStream
1248
//
1249
procedure TGLTree.LoadFromStream(aStream: TStream);
1250
var
1251
   StrList, StrParse : TStringList;
1252
   str : String;
1253
   i : integer;
1254
begin
1255
   StrList:=TStringList.Create;
1256
   StrParse:=TStringList.Create;
1257

1258
   StrList.LoadFromStream(aStream);
1259
   try
1260
      for i:=0 to StrList.Count-1 do begin
1261
         str:=StrList[i];
1262
         if Pos('#',str)>0 then
1263
            str:=Copy(str,0,Pos('#',str)-1);
1264
         StrParse.CommaText:=str;
1265
         if StrParse.Count>=2 then begin
1266
            str:=LowerCase(StrParse[0]);
1267
            if      str = 'depth' then FDepth:=StrToInt(StrParse[1])
1268
            else if str = 'branch_facets' then FBranchFacets:=StrToInt(StrParse[1])
1269
            else if str = 'leaf_size' then FLeafSize:=StrToFloat(StrParse[1])
1270
            else if str = 'branch_size' then FBranchSize:=StrToFloat(StrParse[1])
1271
            else if str = 'branch_noise' then FBranchNoise:=StrToFloat(StrParse[1])
1272
            else if str = 'branch_angle_bias' then FBranchAngleBias:=StrToFloat(StrParse[1])
1273
            else if str = 'branch_angle' then FBranchAngle:=StrToFloat(StrParse[1])
1274
            else if str = 'branch_twist' then FBranchTwist:=StrToFloat(StrParse[1])
1275
            else if str = 'branch_radius' then FBranchRadius:=StrToFloat(StrParse[1])
1276
            else if str = 'leaf_threshold' then FLeafThreshold:=StrToFloat(StrParse[1])
1277
            else if str = 'central_leader_bias' then FCentralLeaderBias:=StrToFloat(StrParse[1])
1278
            else if str = 'central_leader' then FCentralLeader:=LowerCase(StrParse[1])='true'
1279
            else if str = 'seed' then FSeed:=StrToInt(StrParse[1])
1280
            else if str = 'leaf_front_material_name' then FLeafMaterialName:=StrParse[1]
1281
            else if str = 'leaf_back_material_name' then FLeafBackMaterialName:=StrParse[1]
1282
            else if str = 'branch_material_name' then FBranchMaterialName:=StrParse[1];
1283
         end;
1284
      end;
1285
      ForceTotalRebuild;
1286
   finally
1287
      StrList.Free;
1288
      StrParse.Free;
1289
   end;
1290
end;
1291

1292
// SaveToStream
1293
procedure TGLTree.SaveToStream(aStream: TStream);
1294
var
1295
   StrList : TStringList;
1296
begin
1297
   StrList:=TStringList.Create;
1298
   StrList.Add(Format('depth, %d',[Depth]));
1299
   StrList.Add(Format('branch_facets, %d',[BranchFacets]));
1300
   StrList.Add(Format('leaf_size, %f',[LeafSize]));
1301
   StrList.Add(Format('branch_size, %f',[BranchSize]));
1302
   StrList.Add(Format('branch_noise, %f',[BranchNoise]));
1303
   StrList.Add(Format('branch_angle_bias, %f',[BranchAngleBias]));
1304
   StrList.Add(Format('branch_angle, %f',[BranchAngle]));
1305
   StrList.Add(Format('branch_twist, %f',[BranchTwist]));
1306
   StrList.Add(Format('branch_radius, %f',[BranchRadius]));
1307
   StrList.Add(Format('leaf_threshold, %f',[LeafThreshold]));
1308
   StrList.Add(Format('central_leader_bias, %f',[CentralLeaderBias]));
1309
   if CentralLeader then
1310
      StrList.Add('central_leader, true')
1311
   else
1312
      StrList.Add('central_leader, false');
1313
   StrList.Add(Format('seed, %d',[Seed]));
1314
   StrList.Add('leaf_front_material_name, "'+LeafMaterialName+'"');
1315
   StrList.Add('leaf_back_material_name, "'+LeafBackMaterialName+'"');
1316
   StrList.Add('branch_material_name, "'+BranchMaterialName+'"');
1317
   StrList.SaveToStream(aStream);
1318
   StrList.Free;
1319
end;
1320

1321
 
1322
//
1323
procedure TGLTree.LoadFromFile(aFileName: String);
1324
var
1325
   stream : TStream;
1326
begin
1327
   stream:=CreateFileStream(aFileName);
1328
   try
1329
      LoadFromStream(stream);
1330
   finally
1331
      stream.Free;
1332
   end;
1333
end;
1334

1335
// SaveToFile
1336
//
1337
procedure TGLTree.SaveToFile(aFileName: String);
1338
var
1339
   stream : TStream;
1340
begin
1341
   stream:=CreateFileStream(aFileName,fmCreate);
1342
   try
1343
      SaveToStream(stream);
1344
   finally
1345
      stream.Free;
1346
   end;
1347
end;
1348

1349
// GetExtents
1350
procedure TGLTree.GetExtents(var min, max : TAffineVector);
1351
var
1352
  lmin, lmax,
1353
  bmin, bmax : TAffineVector;
1354
begin
1355
   if Branches.Vertices.Count = 0 then begin
1356
      FBranches.BuildBranches;
1357
      FRebuildTree:=False;
1358
   end;
1359
   if Leaves.Vertices.Count>0 then
1360
     Leaves.Vertices.GetExtents(lmin, lmax)
1361
   else begin
1362
     lmin:=NullVector;
1363
     lmax:=NullVector;
1364
   end;
1365
   if Branches.Vertices.Count>0 then
1366
     Branches.Vertices.GetExtents(bmin, bmax)
1367
   else begin
1368
     bmin:=NullVector;
1369
     bmax:=NullVector;
1370
   end;
1371

1372
   min.V[0]:=MinFloat([lmin.V[0], lmax.V[0], bmin.V[0], bmax.V[0]]);
1373
   min.V[1]:=MinFloat([lmin.V[1], lmax.V[1], bmin.V[1], bmax.V[1]]);
1374
   min.V[2]:=MinFloat([lmin.V[2], lmax.V[2], bmin.V[2], bmax.V[2]]);
1375

1376
   max.V[0]:=MaxFloat([lmin.V[0], lmax.V[0], bmin.V[0], bmax.V[0]]);
1377
   max.V[1]:=MaxFloat([lmin.V[1], lmax.V[1], bmin.V[1], bmax.V[1]]);
1378
   max.V[2]:=MaxFloat([lmin.V[2], lmax.V[2], bmin.V[2], bmax.V[2]]);
1379
end;
1380

1381
// AxisAlignedDimensionsUnscaled
1382
//
1383
function TGLTree.AxisAlignedDimensionsUnscaled : TVector;
1384
var
1385
   dMin, dMax : TAffineVector;
1386
begin
1387
   if FAxisAlignedDimensionsCache.V[0]<0 then begin
1388
      GetExtents(dMin, dMax);
1389
      FAxisAlignedDimensionsCache.V[0]:=MaxFloat(Abs(dMin.V[0]), Abs(dMax.V[0]));
1390
      FAxisAlignedDimensionsCache.V[1]:=MaxFloat(Abs(dMin.V[1]), Abs(dMax.V[1]));
1391
      FAxisAlignedDimensionsCache.V[2]:=MaxFloat(Abs(dMin.V[2]), Abs(dMax.V[2]));
1392
   end;
1393
   SetVector(Result, FAxisAlignedDimensionsCache);
1394
end;
1395

1396
// SetAutoCenter
1397
//
1398
procedure TGLTree.SetAutoCenter(const Value: Boolean);
1399
begin
1400
   if Value<>FAutoCenter then begin
1401
      FAutoCenter:=Value;
1402
      if (FAutoRebuild) then RebuildTree;
1403
   end;
1404
end;
1405

1406
// SetAutoRebuild
1407
//
1408
procedure TGLTree.SetAutoRebuild(const Value: Boolean);
1409
begin
1410
   if Value<>FAutoRebuild then begin
1411
      FAutoRebuild:=Value;
1412
   end;
1413
end;
1414

1415
initialization
1416

1417
   RegisterClasses([TGLTree]);
1418

1419
end.
1420

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

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

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

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