1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378 |
- //
- // The multimedia graphics platform GLScene https://github.com/glscene
- //
- unit GLS.Tree;
- (*
- Dynamic tree generation in GLScene
- This code was adapted from the nVidia Tree Demo:
- http://developer.nvidia.com/object/Procedural_Tree.html
- Some info:
- CenterBranchConstant -
- Defines, how big the central branch is. When around 50%
- it makes a small branch inside the tree, for higher values
- much more branches and leaves are created, so either use it
- with low depth, or set it to zero, and have two-branched tree.
- Default value: 0.5
- "AutoRebuild" flag - Rebuild tree after property change.
- Default: True
- *)
- interface
- {$I GLScene.inc}
- uses
- Winapi.OpenGL,
- System.Classes,
- System.SysUtils,
- System.Math,
- GLS.OpenGLTokens,
- GLS.Scene,
- GLS.State,
- GLS.Material,
- GLS.VectorGeometry,
- GLS.VectorLists,
- GLS.VectorFileObjects,
- GLS.ApplicationFileIO,
- GLS.RenderContextInfo,
- GLS.PersistentClasses,
- GLS.XOpenGL,
- GLS.Context,
- GLS.VectorTypes,
- GLS.Utils;
- type
- TGLTree = class;
- TGLTreeBranches = class;
- TGLTreeBranchNoise = class;
- TGLTreeLeaves = class
- private
- FOwner: TGLTree;
- FCount: Integer;
- FVertices: TGLAffineVectorList;
- FNormals: TGLAffineVectorList;
- FTexCoords: TGLAffineVectorList;
- public
- constructor Create(AOwner: TGLTree);
- destructor Destroy; override;
- procedure BuildList(var rci: TGLRenderContextInfo);
- procedure AddNew(matrix: TGLMatrix);
- procedure Clear;
- property Owner: TGLTree read FOwner;
- property Count: Integer read FCount;
- property Vertices: TGLAffineVectorList read FVertices;
- property Normals: TGLAffineVectorList read FNormals;
- property TexCoords: TGLAffineVectorList read FTexCoords;
- end;
- TGLTreeBranch = class
- private
- FOwner: TGLTreeBranches;
- FLeft: TGLTreeBranch;
- FCenter: TGLTreeBranch;
- FRight: TGLTreeBranch;
- FParent: TGLTreeBranch;
- FBranchID: Integer;
- FParentID: Integer;
- FMatrix: TGLMatrix;
- FLower: TGLIntegerList;
- FUpper: TGLIntegerList;
- FCentralLeader: Boolean;
- procedure BuildBranch(branchNoise: TGLTreeBranchNoise;
- const matrix: TGLMatrix; TexCoordY, Twist: Single; Level: Integer);
- public
- constructor Create(AOwner: TGLTreeBranches; AParent: TGLTreeBranch);
- destructor Destroy; override;
- property Owner: TGLTreeBranches read FOwner;
- property Left: TGLTreeBranch read FLeft;
- property Center: TGLTreeBranch read FCenter;
- property Right: TGLTreeBranch read FRight;
- property Parent: TGLTreeBranch read FParent;
- property matrix: TGLMatrix read FMatrix;
- property Lower: TGLIntegerList read FLower;
- property Upper: TGLIntegerList read FUpper;
- end;
- TGLTreeBranches = class
- private
- FOwner: TGLTree;
- FSinList: TGLSingleList;
- FCosList: TGLSingleList;
- FVertices: TGLAffineVectorList;
- FNormals: TGLAffineVectorList;
- FTexCoords: TGLAffineVectorList;
- FIndices: TGLIntegerList;
- FRoot: TGLTreeBranch;
- FCount: Integer;
- FBranchCache: TList;
- FBranchIndices: TGLIntegerList;
- procedure BuildBranches;
- public
- constructor Create(AOwner: TGLTree);
- destructor Destroy; override;
- procedure BuildList(var rci: TGLRenderContextInfo);
- procedure Clear;
- property Owner: TGLTree read FOwner;
- property SinList: TGLSingleList read FSinList;
- property CosList: TGLSingleList read FCosList;
- property Vertices: TGLAffineVectorList read FVertices;
- property Normals: TGLAffineVectorList read FNormals;
- property TexCoords: TGLAffineVectorList read FTexCoords;
- property Count: Integer read FCount;
- end;
- TGLTreeBranchNoise = class
- private
- FBranchNoise: Single;
- FLeft, FRight, FCenter: TGLTreeBranchNoise;
- function GetLeft: TGLTreeBranchNoise;
- function GetCenter: TGLTreeBranchNoise;
- function GetRight: TGLTreeBranchNoise;
- public
- constructor Create;
- destructor Destroy; override;
- property Left: TGLTreeBranchNoise read GetLeft;
- property Center: TGLTreeBranchNoise read GetCenter;
- property Right: TGLTreeBranchNoise read GetRight;
- property branchNoise: Single read FBranchNoise;
- end;
- TGLTree = class(TGLImmaterialSceneObject)
- private
- FDepth: Integer;
- FBranchFacets: Integer;
- FLeafSize: Single;
- FBranchSize: Single;
- FBranchNoise: Single;
- FBranchAngleBias: Single;
- FBranchAngle: Single;
- FBranchTwist: Single;
- FBranchRadius: Single;
- FLeafThreshold: Single;
- FCentralLeaderBias: Single;
- FCentralLeader: Boolean;
- FSeed: Integer;
- FAutoCenter: Boolean;
- FAutoRebuild: Boolean;
- FCenterBranchConstant: Single;
- FLeaves: TGLTreeLeaves;
- FBranches: TGLTreeBranches;
- FNoise: TGLTreeBranchNoise;
- FMaterialLibrary: TGLMaterialLibrary;
- FLeafMaterialName: TGLLibMaterialName;
- FLeafBackMaterialName: TGLLibMaterialName;
- FBranchMaterialName: TGLLibMaterialName;
- FRebuildTree: Boolean;
- FAxisAlignedDimensionsCache: TGLVector;
- protected
- procedure SetDepth(const Value: Integer);
- procedure SetBranchFacets(const Value: Integer);
- procedure SetLeafSize(const Value: Single);
- procedure SetBranchSize(const Value: Single);
- procedure SetBranchNoise(const Value: Single);
- procedure SetBranchAngleBias(const Value: Single);
- procedure SetBranchAngle(const Value: Single);
- procedure SetBranchTwist(const Value: Single);
- procedure SetBranchRadius(const Value: Single);
- procedure SetLeafThreshold(const Value: Single);
- procedure SetCentralLeaderBias(const Value: Single);
- procedure SetCentralLeader(const Value: Boolean);
- procedure SetSeed(const Value: Integer);
- procedure SetAutoCenter(const Value: Boolean);
- procedure SetAutoRebuild(const Value: Boolean);
- procedure SetCenterBranchConstant(const Value: Single);
- procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
- procedure SetLeafMaterialName(const Value: TGLLibMaterialName);
- procedure SetLeafBackMaterialName(const Value: TGLLibMaterialName);
- procedure SetBranchMaterialName(const Value: TGLLibMaterialName);
- procedure Loaded; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure DoRender(var ARci: TGLRenderContextInfo;
- ARenderSelf, ARenderChildren: Boolean); override;
- procedure BuildList(var rci: TGLRenderContextInfo); override;
- procedure StructureChanged; override;
- procedure BuildMesh(GLBaseMesh: TGLBaseMesh);
- procedure RebuildTree;
- procedure ForceTotalRebuild;
- procedure Clear;
- procedure GetExtents(var min, max: TAffineVector);
- function AxisAlignedDimensionsUnscaled: TGLVector; override;
- procedure LoadFromStream(aStream: TStream);
- procedure SaveToStream(aStream: TStream);
- procedure LoadFromFile(const aFileName: String);
- procedure SaveToFile(const aFileName: String);
- property Leaves: TGLTreeLeaves read FLeaves;
- property Branches: TGLTreeBranches read FBranches;
- property Noise: TGLTreeBranchNoise read FNoise;
- published
- // The depth of tree branch recursion.
- property Depth: Integer read FDepth write SetDepth;
- // The number of facets for each branch in the tree.
- property BranchFacets: Integer read FBranchFacets write SetBranchFacets;
- // Leaf size modifier. Leaf size is also influenced by branch recursion scale.
- property LeafSize: Single read FLeafSize write SetLeafSize;
- // Branch length modifier.
- property BranchSize: Single read FBranchSize write SetBranchSize;
- // Overall branch noise influence. Relates to the 'fullness' of the tree.
- property BranchNoise: Single read FBranchNoise write SetBranchNoise;
- (* Effects the habit of the tree. Values from 0 to 1 refer to Upright to
- Spreading respectively. *)
- property BranchAngleBias: Single read FBranchAngleBias write SetBranchAngleBias;
- // Effects the balance of the tree.
- property BranchAngle: Single read FBranchAngle write SetBranchAngle;
- // Effects the rotation of each sub branch in recursion.
- property BranchTwist: Single read FBranchTwist write SetBranchTwist;
- // Effects the thickness of the branches.
- property BranchRadius: Single read FBranchRadius write SetBranchRadius;
- // Determines how thin a branch can get before a leaf is substituted.
- property LeafThreshold: Single read FLeafThreshold write SetLeafThreshold;
- // Determines how BranchAngle effects the central leader (CentralLeader must = True).
- property CentralLeaderBias: Single read FCentralLeaderBias
- write SetCentralLeaderBias;
- // Does this tree have a central leader?
- property CentralLeader: Boolean read FCentralLeader write SetCentralLeader;
- property Seed: Integer read FSeed write SetSeed;
- // Automatically center the tree's vertices after building them.
- property AutoCenter: Boolean read FAutoCenter write SetAutoCenter;
- // Automatically rebuild the tree after changing the settings
- property AutoRebuild: Boolean read FAutoRebuild write SetAutoRebuild;
- (* Central branch can be thinner(lower values)/thicker(->1) depending on this constant.
- The effect also depends on the BranchAngle variable. *)
- property CenterBranchConstant: Single read FCenterBranchConstant
- write SetCenterBranchConstant;
- property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary
- write SetMaterialLibrary;
- property LeafMaterialName: TGLLibMaterialName read FLeafMaterialName
- write SetLeafMaterialName;
- property LeafBackMaterialName: TGLLibMaterialName read FLeafBackMaterialName
- write SetLeafBackMaterialName;
- property BranchMaterialName: TGLLibMaterialName read FBranchMaterialName
- write SetBranchMaterialName;
- end;
- // -----------------------------------------------------------------------------
- implementation
- // -----------------------------------------------------------------------------
- // -----------------------------------------------------------------------------
- // TGLTreeLeaves
- // -----------------------------------------------------------------------------
- constructor TGLTreeLeaves.Create(AOwner: TGLTree);
- begin
- FOwner := AOwner;
- FCount := 0;
- FVertices := TGLAffineVectorList.Create;
- FNormals := TGLAffineVectorList.Create;
- FTexCoords := TGLAffineVectorList.Create;
- end;
- destructor TGLTreeLeaves.Destroy;
- begin
- FVertices.Free;
- FNormals.Free;
- FTexCoords.Free;
- inherited;
- end;
- procedure TGLTreeLeaves.AddNew(matrix: TGLMatrix);
- var
- radius: Single;
- pos: TGLVector;
- begin
- radius := Owner.LeafSize;
- Inc(FCount);
- pos := matrix.W;
- matrix.W := NullHMGPoint;
- matrix := Roll(matrix, FCount / 10);
- NormalizeMatrix(matrix);
- matrix.W := pos;
- FVertices.Add(VectorTransform(PointMake(0, -radius, 0), matrix));
- FVertices.Add(VectorTransform(PointMake(0, radius, 0), matrix));
- FVertices.Add(VectorTransform(PointMake(0, radius, 2 * radius), matrix));
- FVertices.Add(VectorTransform(PointMake(0, -radius, 2 * radius), matrix));
- FNormals.Add(VectorTransform(XHmgVector, matrix));
- FTexCoords.Add(XVector, NullVector);
- FTexCoords.Add(YVector, XYVector);
- end;
- procedure TGLTreeLeaves.BuildList(var rci: TGLRenderContextInfo);
- var
- i: Integer;
- n: TAffineVector;
- libMat: TGLLibMaterial;
- begin
- libMat := Owner.MaterialLibrary.LibMaterialByName(Owner.LeafMaterialName);
- if Assigned(libMat) then
- libMat.Apply(rci);
- gl.EnableClientState(GL_VERTEX_ARRAY);
- xgl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
- gl.VertexPointer(3, GL_FLOAT, 0, @FVertices.List[0]);
- xgl.TexCoordPointer(3, GL_FLOAT, 0, @FTexCoords.List[0]);
- for i := 0 to (FVertices.Count div 4) - 1 do
- begin
- gl.Normal3fv(@FNormals.List[i]);
- gl.DrawArrays(GL_QUADS, 4 * i, 4);
- end;
- with Owner do
- if LeafMaterialName <> LeafBackMaterialName then
- begin
- if Assigned(libMat) then
- libMat.UnApply(rci);
- libMat := MaterialLibrary.LibMaterialByName(LeafBackMaterialName);
- if Assigned(libMat) then
- libMat.Apply(rci);
- end;
- rci.GLStates.InvertGLFrontFace;
- for i := 0 to (FVertices.Count div 4) - 1 do
- begin
- n := VectorNegate(FNormals[i]);
- gl.Normal3fv(@n);
- gl.DrawArrays(GL_QUADS, 4 * i, 4);
- end;
- rci.GLStates.InvertGLFrontFace;
- gl.DisableClientState(GL_VERTEX_ARRAY);
- xgl.DisableClientState(GL_TEXTURE_COORD_ARRAY);
- if Assigned(libMat) then
- libMat.UnApply(rci);
- end;
- procedure TGLTreeLeaves.Clear;
- begin
- FVertices.Clear;
- FNormals.Clear;
- FTexCoords.Clear;
- FCount := 0;
- end;
- // -----------------------------------------------------------------------------
- // TGLTreeBranch
- // -----------------------------------------------------------------------------
- constructor TGLTreeBranch.Create(AOwner: TGLTreeBranches;
- AParent: TGLTreeBranch);
- begin
- FOwner := AOwner;
- FParent := AParent;
- FUpper := TGLIntegerList.Create;
- FLower := TGLIntegerList.Create;
- FCentralLeader := False;
- // Skeletal construction helpers
- if Assigned(FOwner) then
- begin
- FBranchID := FOwner.Count - 1;
- FOwner.FBranchCache.Add(Self);
- end
- else
- FBranchID := -1;
- if Assigned(FParent) then
- FParentID := FParent.FBranchID
- else
- FParentID := -1;
- end;
- destructor TGLTreeBranch.Destroy;
- begin
- FUpper.Free;
- FLower.Free;
- FLeft.Free;
- FRight.Free;
- inherited;
- end;
- procedure TGLTreeBranch.BuildBranch(branchNoise: TGLTreeBranchNoise;
- const matrix: TGLMatrix; TexCoordY, Twist: Single; Level: Integer);
- var
- i: Integer;
- Tree: TGLTree;
- Branches: TGLTreeBranches;
- Facets: Integer;
- t, c, s: Single;
- radius, LeftRadius, RightRadius, CenterRadius: Single;
- BranchAngle, LeftAngle, RightAngle, CenterAngle: Single;
- BranchAngleBias, BranchTwist, Taper: Single;
- LeftBranchNoiseValue, RightBranchNoiseValue, CenterBranchNoiseValue: Single;
- LeftBranchNoise: TGLTreeBranchNoise;
- CenterBranchNoise: TGLTreeBranchNoise;
- RightBranchNoise: TGLTreeBranchNoise;
- LeftMatrix, RightMatrix, CenterMatrix: TGLMatrix;
- central_leader: Boolean;
- begin
- Assert(Assigned(FOwner), 'Incorrect use of TGLTreeBranch');
- Assert(Assigned(FOwner.FOwner), 'Incorrect use of TGLTreeBranches');
- FMatrix := matrix;
- Branches := FOwner;
- Tree := FOwner.FOwner;
- Facets := Tree.BranchFacets;
- radius := Tree.BranchRadius;
- FLower.Clear;
- FLower.Capacity := Facets + 1;
- FUpper.Clear;
- FUpper.Capacity := Facets + 1;
- BranchAngle := Tree.BranchAngle;
- BranchAngleBias := Tree.BranchAngleBias;
- BranchTwist := Twist + Tree.BranchTwist;
- LeftBranchNoise := branchNoise.Left;
- CenterBranchNoise := branchNoise.Center;
- RightBranchNoise := branchNoise.Right;
- LeftBranchNoiseValue := ((LeftBranchNoise.branchNoise * 0.4) - 0.1) *
- Tree.branchNoise;
- LeftRadius := Sqrt(1 - BranchAngle + LeftBranchNoiseValue);
- LeftRadius := ClampValue(LeftRadius, 0, 1);
- LeftAngle := BranchAngle * 90 * BranchAngleBias + 10 * LeftBranchNoiseValue;
- CenterBranchNoiseValue := ((CenterBranchNoise.branchNoise * 0.9) - 0.1) *
- Tree.branchNoise;
- CenterRadius := Sqrt(Tree.CenterBranchConstant - BranchAngle +
- CenterBranchNoiseValue);
- CenterRadius := ClampValue(CenterRadius, 0, 1);
- CenterAngle := (1 - BranchAngle) * 50 * CenterBranchNoiseValue *
- BranchAngleBias;
- RightBranchNoiseValue := ((RightBranchNoise.branchNoise * 0.6) - 0.1) *
- Tree.branchNoise;
- RightRadius := Sqrt(BranchAngle + RightBranchNoiseValue);
- RightRadius := ClampValue(RightRadius, 0, 1);
- RightAngle := (1 - BranchAngle) * -90 * BranchAngleBias + 10 *
- RightBranchNoiseValue;
- Taper := MaxFloat(LeftRadius, RightRadius, CenterRadius);
- // Build cylinder lower
- for i := 0 to Facets do
- begin
- t := 1 / Facets * i;
- c := Branches.CosList[i];
- s := Branches.SinList[i];
- Branches.Vertices.Add(VectorTransform(PointMake(c * radius, s * radius,
- radius), matrix));
- Branches.Normals.Add(VectorTransform(VectorMake(c, s, 0), matrix));
- Branches.TexCoords.Add(t, TexCoordY);
- FLower.Add(Branches.Vertices.Count - 1);
- Branches.FBranchIndices.Add(FBranchID);
- end;
- TexCoordY := TexCoordY + 1 - 2 * radius;
- // Build cylinder upper
- for i := 0 to Facets do
- begin
- t := 1 / Facets * i;
- c := Branches.CosList[i];
- s := Branches.SinList[i];
- Branches.Vertices.Add(VectorTransform(PointMake(c * radius * Taper,
- s * radius * Taper, 1 - radius), matrix));
- Branches.Normals.Add(VectorTransform(VectorMake(c, s, 0), matrix));
- Branches.TexCoords.Add(t, TexCoordY);
- FUpper.Add(Branches.Vertices.Count - 1);
- Branches.FBranchIndices.Add(FBranchID);
- end;
- TexCoordY := TexCoordY + 2 * radius;
- // BuildMatrices
- SinCos(DegToRad(BranchTwist), s, c);
- if Level = 0 then
- central_leader := FCentralLeader
- else
- central_leader := FParent.FCentralLeader;
- if central_leader then
- begin
- LeftMatrix := MatrixMultiply(CreateScaleMatrix(AffineVectorMake(LeftRadius,
- LeftRadius, LeftRadius)), CreateRotationMatrix(AffineVectorMake(s, c, 0),
- DegToRad(LeftAngle) * Tree.CentralLeaderBias));
- end
- else
- begin
- LeftMatrix := MatrixMultiply(CreateScaleMatrix(AffineVectorMake(LeftRadius,
- LeftRadius, LeftRadius)), CreateRotationMatrix(AffineVectorMake(s, c, 0),
- DegToRad(LeftAngle)));
- end;
- LeftMatrix := MatrixMultiply(LeftMatrix,
- MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0, 0,
- Tree.BranchSize * (1 - LeftBranchNoiseValue))), matrix));
- CenterMatrix := MatrixMultiply
- (CreateScaleMatrix(AffineVectorMake(CenterRadius, CenterRadius,
- CenterRadius)), CreateRotationMatrix(AffineVectorMake(s, c, 0),
- DegToRad(CenterAngle)));
- CenterMatrix := MatrixMultiply(CenterMatrix,
- MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0, 0,
- Tree.BranchSize * (1 - CenterBranchNoiseValue))), matrix));
- RightMatrix := MatrixMultiply(CreateScaleMatrix(AffineVectorMake(RightRadius,
- RightRadius, RightRadius)), CreateRotationMatrix(AffineVectorMake(s, c, 0),
- DegToRad(RightAngle)));
- RightMatrix := MatrixMultiply(RightMatrix,
- MatrixMultiply(CreateTranslationMatrix(AffineVectorMake(0, 0,
- Tree.BranchSize * (1 - RightBranchNoiseValue))), matrix));
- if (((Level + 1) >= Tree.Depth) or (LeftRadius < Tree.LeafThreshold)) then
- begin
- Tree.Leaves.AddNew(LeftMatrix);
- end
- else
- begin
- Inc(Branches.FCount);
- FLeft := TGLTreeBranch.Create(Owner, Self);
- FLeft.FCentralLeader := central_leader and (LeftRadius >= RightRadius);
- FLeft.BuildBranch(LeftBranchNoise, LeftMatrix, TexCoordY, BranchTwist,
- Level + 1);
- end;
- if (((Level + 1) >= Tree.Depth) or (CenterRadius < Tree.LeafThreshold)) then
- begin
- Tree.Leaves.AddNew(CenterMatrix);
- end
- else
- begin
- Inc(Branches.FCount);
- FCenter := TGLTreeBranch.Create(Owner, Self);
- FCenter.BuildBranch(CenterBranchNoise, CenterMatrix, TexCoordY, BranchTwist,
- Level + 1);
- end;
- if (((Level + 1) >= Tree.Depth) or (RightRadius < Tree.LeafThreshold)) then
- begin
- Tree.Leaves.AddNew(RightMatrix);
- end
- else
- begin
- Inc(Branches.FCount);
- FRight := TGLTreeBranch.Create(Owner, Self);
- FRight.BuildBranch(RightBranchNoise, RightMatrix, TexCoordY, BranchTwist,
- Level + 1);
- end;
- for i := 0 to Facets do
- begin
- Branches.FIndices.Add(Upper[i]);
- Branches.FIndices.Add(Lower[i]);
- end;
- if Assigned(FRight) then
- begin
- for i := 0 to Facets do
- begin
- Branches.FIndices.Add(Right.Lower[i]);
- Branches.FIndices.Add(Upper[i]);
- end;
- end;
- if Assigned(FCenter) then
- begin
- for i := 0 to Facets do
- begin
- Branches.FIndices.Add(Center.Lower[i]);
- Branches.FIndices.Add(Upper[i]);
- end;
- end;
- if Assigned(FLeft) then
- begin
- for i := 0 to Facets do
- begin
- Branches.FIndices.Add(Left.Lower[i]);
- Branches.FIndices.Add(Upper[i]);
- end;
- end;
- end;
- // -----------------------------------------------------------------------------
- // TGLTreeBranches
- // -----------------------------------------------------------------------------
- constructor TGLTreeBranches.Create(AOwner: TGLTree);
- begin
- FOwner := AOwner;
- FSinList := TGLSingleList.Create;
- FCosList := TGLSingleList.Create;
- FVertices := TGLAffineVectorList.Create;
- FNormals := TGLAffineVectorList.Create;
- FTexCoords := TGLAffineVectorList.Create;
- FIndices := TGLIntegerList.Create;
- FBranchCache := TList.Create;
- FBranchIndices := TGLIntegerList.Create;
- FCount := 0;
- end;
- destructor TGLTreeBranches.Destroy;
- begin
- FSinList.Free;
- FCosList.Free;
- FVertices.Free;
- FNormals.Free;
- FTexCoords.Free;
- FIndices.Free;
- FRoot.Free;
- FBranchCache.Free;
- FBranchIndices.Free;
- inherited;
- end;
- procedure TGLTreeBranches.BuildBranches;
- var
- i: Integer;
- u: Single;
- delta, min, max: TAffineVector;
- begin
- RandSeed := Owner.FSeed;
- for i := 0 to Owner.BranchFacets do
- begin
- u := 1 / Owner.BranchFacets * i;
- SinList.Add(Sin(PI * 2 * u));
- CosList.Add(Cos(PI * 2 * u));
- end;
- Inc(FCount);
- FRoot := TGLTreeBranch.Create(Self, nil);
- FRoot.FCentralLeader := Owner.CentralLeader;
- FRoot.BuildBranch(Owner.Noise, IdentityHMGMatrix, 0, 0, 0);
- delta := AffineVectorMake(0, 0, -Owner.BranchRadius);
- Vertices.Translate(delta);
- Owner.Leaves.Vertices.Translate(delta);
- if Owner.AutoCenter then
- begin
- Owner.GetExtents(min, max);
- delta := VectorCombine(min, max, -0.5, -0.5);
- Vertices.Translate(delta);
- Owner.Leaves.Vertices.Translate(delta);
- end;
- Owner.FAxisAlignedDimensionsCache.X := -1;
- end;
- procedure TGLTreeBranches.BuildList(var rci: TGLRenderContextInfo);
- var
- i, stride: Integer;
- libMat: TGLLibMaterial;
- begin
- stride := (Owner.BranchFacets + 1) * 2;
- libMat := Owner.MaterialLibrary.LibMaterialByName(Owner.BranchMaterialName);
- if Assigned(libMat) then
- libMat.Apply(rci);
- gl.VertexPointer(3, GL_FLOAT, 0, @FVertices.List[0]);
- gl.NormalPointer(GL_FLOAT, 0, @FNormals.List[0]);
- xgl.TexCoordPointer(3, GL_FLOAT, 0, @FTexCoords.List[0]);
- gl.EnableClientState(GL_VERTEX_ARRAY);
- gl.EnableClientState(GL_NORMAL_ARRAY);
- xgl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
- repeat
- for i := 0 to (FIndices.Count div stride) - 1 do
- gl.DrawElements(GL_TRIANGLE_STRIP, stride, GL_UNSIGNED_INT,
- @FIndices.List[stride * i]);
- until (not Assigned(libMat)) or (not libMat.UnApply(rci));
- xgl.DisableClientState(GL_TEXTURE_COORD_ARRAY);
- gl.DisableClientState(GL_NORMAL_ARRAY);
- gl.DisableClientState(GL_VERTEX_ARRAY);
- end;
- // Clear
- //
- procedure TGLTreeBranches.Clear;
- begin
- FSinList.Clear;
- FCosList.Clear;
- FVertices.Clear;
- FNormals.Clear;
- FTexCoords.Clear;
- FIndices.Clear;
- FBranchCache.Clear;
- FBranchIndices.Clear;
- FreeAndNil(FRoot);
- FCount := 0;
- end;
- // -----------------------------------------------------------------------------
- // TGLTreeBranchNoise
- // -----------------------------------------------------------------------------
- constructor TGLTreeBranchNoise.Create;
- begin
- FBranchNoise := Random;
- end;
- destructor TGLTreeBranchNoise.Destroy;
- begin
- FLeft.Free;
- FRight.Free;
- inherited;
- end;
- function TGLTreeBranchNoise.GetLeft: TGLTreeBranchNoise;
- begin
- if not Assigned(FLeft) then
- FLeft := TGLTreeBranchNoise.Create;
- Result := FLeft;
- end;
- function TGLTreeBranchNoise.GetRight: TGLTreeBranchNoise;
- begin
- if not Assigned(FRight) then
- FRight := TGLTreeBranchNoise.Create;
- Result := FRight;
- end;
- function TGLTreeBranchNoise.GetCenter: TGLTreeBranchNoise;
- begin
- if not Assigned(FCenter) then
- FCenter := TGLTreeBranchNoise.Create;
- Result := FCenter;
- end;
- // -----------------------------------------------------------------------------
- // TGLTree
- // -----------------------------------------------------------------------------
- constructor TGLTree.Create(AOwner: TComponent);
- begin
- inherited;
- // Default tree setting
- FDepth := 5;
- FLeafThreshold := 0.02;
- FBranchAngleBias := 0.6;
- FBranchAngle := 0.4;
- FBranchTwist := 45;
- FBranchNoise := 0.7;
- FBranchSize := 1.0;
- FLeafSize := 0.1;
- FBranchRadius := 0.12;
- FBranchFacets := 6;
- FCentralLeader := False;
- FSeed := 0;
- FAutoCenter := False;
- FAutoRebuild := True;
- FCenterBranchConstant := 0.5;
- FLeaves := TGLTreeLeaves.Create(Self);
- FBranches := TGLTreeBranches.Create(Self);
- FNoise := TGLTreeBranchNoise.Create;
- end;
- destructor TGLTree.Destroy;
- begin
- FLeaves.Free;
- FBranches.Free;
- FNoise.Free;
- inherited;
- end;
- procedure TGLTree.Loaded;
- begin
- inherited;
- FBranches.BuildBranches;
- end;
- procedure TGLTree.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- if (Operation = opRemove) and (AComponent = FMaterialLibrary) then
- MaterialLibrary := nil;
- inherited;
- end;
- procedure TGLTree.DoRender(var ARci: TGLRenderContextInfo;
- ARenderSelf, ARenderChildren: Boolean);
- begin
- MaterialLibrary.LibMaterialByName(BranchMaterialName).PrepareBuildList;
- MaterialLibrary.LibMaterialByName(LeafMaterialName).PrepareBuildList;
- MaterialLibrary.LibMaterialByName(LeafBackMaterialName).PrepareBuildList;
- inherited;
- end;
- procedure TGLTree.BuildList(var rci: TGLRenderContextInfo);
- begin
- if FRebuildTree then
- begin
- FBranches.BuildBranches;
- FRebuildTree := False;
- end;
- Branches.BuildList(rci);
- Leaves.BuildList(rci);
- end;
- procedure TGLTree.StructureChanged;
- begin
- FAxisAlignedDimensionsCache.X := -1;
- inherited;
- end;
- procedure TGLTree.BuildMesh(GLBaseMesh: TGLBaseMesh);
- procedure RecursBranches(Branch: TGLTreeBranch; bone: TGLSkeletonBone;
- Frame: TGLSkeletonFrame);
- var
- trans: TTransformations;
- mat: TGLMatrix;
- rot, pos: TAffineVector;
- begin
- bone.Name := 'Branch' + IntToStr(Branch.FBranchID);
- bone.BoneID := Branch.FBranchID;
- // Construct base frame
- if Assigned(Branch.FParent) then
- mat := Branch.FParent.FMatrix
- else
- mat := IdentityHMGMatrix;
- InvertMatrix(mat);
- NormalizeMatrix(mat);
- if MatrixDecompose(mat, trans) then
- begin
- SetVector(rot, trans[ttRotateX], trans[ttRotateY], trans[ttRotateZ]);
- SetVector(pos, mat.W);
- end
- else
- begin
- rot := NullVector;
- pos := NullVector;
- end;
- Frame.Rotation.Add(rot);
- Frame.Position.Add(pos);
- // Recurse with child branches
- if Assigned(Branch.Left) then
- RecursBranches(Branch.Left, TGLSkeletonBone.CreateOwned(bone), Frame);
- if Assigned(Branch.Right) then
- RecursBranches(Branch.Right, TGLSkeletonBone.CreateOwned(bone), Frame);
- end;
- var
- // SkelMesh : TGLSkeletonMeshObject;
- fg: TFGVertexIndexList;
- fg2: TFGVertexNormalTexIndexList;
- i, j, stride: Integer;
- // parent_id : integer;
- // bone : TGLSkeletonBone;
- begin
- if not Assigned(GLBaseMesh) then
- exit;
- if FRebuildTree then
- begin
- FBranches.BuildBranches;
- FRebuildTree := False;
- end;
- GLBaseMesh.MeshObjects.Clear;
- GLBaseMesh.Skeleton.Clear;
- // if GLBaseMesh is TGLActor then
- // TGLSkeletonMeshObject.CreateOwned(GLBaseMesh.MeshObjects)
- // else
- TGLMeshObject.CreateOwned(GLBaseMesh.MeshObjects);
- GLBaseMesh.MeshObjects[0].Mode := momFaceGroups;
- // Branches
- GLBaseMesh.MeshObjects[0].Vertices.Add(Branches.Vertices);
- GLBaseMesh.MeshObjects[0].Normals.Add(Branches.Normals);
- GLBaseMesh.MeshObjects[0].TexCoords.Add(Branches.TexCoords);
- { if GLBaseMesh is TGLActor then begin
- TGLActor(GLBaseMesh).Reference:=aarSkeleton;
- RecursBranches(Branches.FRoot,
- TGLSkeletonBone.CreateOwned(GLBaseMesh.Skeleton.RootBones),
- TGLSkeletonFrame.CreateOwned(GLBaseMesh.Skeleton.Frames));
- SkelMesh:=TGLSkeletonMeshObject(GLBaseMesh.MeshObjects[0]);
- SkelMesh.BonesPerVertex:=1;
- SkelMesh.VerticeBoneWeightCount:=Branches.FBranchIndices.Count;
- for i:=0 to Branches.FBranchIndices.Count-1 do
- SkelMesh.AddWeightedBone(Branches.FBranchIndices[i],1);
- GLBaseMesh.Skeleton.RootBones.PrepareGlobalMatrices;
- SkelMesh.PrepareBoneMatrixInvertedMeshes;
- SkelMesh.ApplyCurrentSkeletonFrame(True);
- end;// }
- stride := (BranchFacets + 1) * 2;
- for i := 0 to (FBranches.FIndices.Count div stride) - 1 do
- begin
- fg := TFGVertexIndexList.CreateOwned(GLBaseMesh.MeshObjects[0].FaceGroups);
- fg.MaterialName := BranchMaterialName;
- fg.Mode := fgmmTriangleStrip;
- for j := 0 to stride - 1 do
- fg.VertexIndices.Add(Branches.FIndices[i * stride + j]);
- end;
- // Leaves
- // if GLBaseMesh is TGLActor then
- // TGLSkeletonMeshObject.CreateOwned(GLBaseMesh.MeshObjects)
- // else
- TGLMeshObject.CreateOwned(GLBaseMesh.MeshObjects);
- GLBaseMesh.MeshObjects[1].Mode := momFaceGroups;
- GLBaseMesh.MeshObjects[1].Vertices.Add(Leaves.Vertices);
- GLBaseMesh.MeshObjects[1].Normals.Add(Leaves.FNormals);
- for i := 0 to Leaves.Normals.Count - 1 do
- GLBaseMesh.MeshObjects[1].Normals.Add(VectorNegate(Leaves.FNormals[i]));
- GLBaseMesh.MeshObjects[1].TexCoords.Add(Leaves.TexCoords);
- for i := 0 to (Leaves.FVertices.Count div 4) - 1 do
- begin
- // Leaf front
- fg2 := TFGVertexNormalTexIndexList.CreateOwned
- (GLBaseMesh.MeshObjects[1].FaceGroups);
- fg2.MaterialName := LeafMaterialName;
- fg2.Mode := fgmmTriangleStrip;
- with fg2.VertexIndices do
- begin
- Add(i * 4);
- Add(i * 4 + 1);
- Add(i * 4 + 3);
- Add(i * 4 + 2);
- end;
- for j := 0 to 3 do
- fg2.NormalIndices.Add(i);
- with fg2.TexCoordIndices do
- begin
- Add(0);
- Add(1);
- Add(3);
- Add(2);
- end;
- // Leaf back
- fg2 := TFGVertexNormalTexIndexList.CreateOwned
- (GLBaseMesh.MeshObjects[1].FaceGroups);
- fg2.MaterialName := LeafBackMaterialName;
- fg2.Mode := fgmmTriangleStrip;
- with fg2.VertexIndices do
- begin
- Add(i * 4);
- Add(i * 4 + 3);
- Add(i * 4 + 1);
- Add(i * 4 + 2);
- end;
- for j := 0 to 3 do
- fg2.NormalIndices.Add(i);
- with fg2.TexCoordIndices do
- begin
- Add(0);
- Add(3);
- Add(1);
- Add(2);
- end;
- end;
- end;
- procedure TGLTree.Clear;
- begin
- FLeaves.Clear;
- FBranches.Clear;
- end;
- procedure TGLTree.SetBranchAngle(const Value: Single);
- begin
- if Value <> FBranchAngle then
- begin
- FBranchAngle := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchAngleBias(const Value: Single);
- begin
- if Value <> FBranchAngleBias then
- begin
- FBranchAngleBias := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchNoise(const Value: Single);
- begin
- if Value <> FBranchNoise then
- begin
- FBranchNoise := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchRadius(const Value: Single);
- begin
- if Value <> FBranchRadius then
- begin
- FBranchRadius := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchSize(const Value: Single);
- begin
- if Value <> FBranchSize then
- begin
- FBranchSize := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchTwist(const Value: Single);
- begin
- if Value <> FBranchTwist then
- begin
- FBranchTwist := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetDepth(const Value: Integer);
- begin
- if Value <> FDepth then
- begin
- FDepth := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetBranchFacets(const Value: Integer);
- begin
- if Value <> FBranchFacets then
- begin
- FBranchFacets := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetLeafSize(const Value: Single);
- begin
- if Value <> FLeafSize then
- begin
- FLeafSize := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetLeafThreshold(const Value: Single);
- begin
- if Value <> FLeafThreshold then
- begin
- FLeafThreshold := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetCentralLeaderBias(const Value: Single);
- begin
- if Value <> FCentralLeaderBias then
- begin
- FCentralLeaderBias := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetCentralLeader(const Value: Boolean);
- begin
- if Value <> FCentralLeader then
- begin
- FCentralLeader := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetSeed(const Value: Integer);
- begin
- if Value <> FSeed then
- begin
- FSeed := Value;
- if (FAutoRebuild) then
- ForceTotalRebuild;
- end;
- end;
- procedure TGLTree.SetCenterBranchConstant(const Value: Single);
- begin
- if Value <> CenterBranchConstant then
- begin
- FCenterBranchConstant := Value;
- if (FAutoRebuild) then
- ForceTotalRebuild;
- end;
- end;
- procedure TGLTree.SetBranchMaterialName(const Value: TGLLibMaterialName);
- begin
- if Value <> FBranchMaterialName then
- begin
- FBranchMaterialName := Value;
- StructureChanged;
- end;
- end;
- procedure TGLTree.SetLeafBackMaterialName(const Value: TGLLibMaterialName);
- begin
- if Value <> FLeafBackMaterialName then
- begin
- FLeafBackMaterialName := Value;
- StructureChanged;
- end;
- end;
- procedure TGLTree.SetLeafMaterialName(const Value: TGLLibMaterialName);
- begin
- if Value <> FLeafMaterialName then
- begin
- FLeafMaterialName := Value;
- StructureChanged;
- end;
- end;
- procedure TGLTree.SetMaterialLibrary(const Value: TGLMaterialLibrary);
- begin
- if Value <> FMaterialLibrary then
- begin
- FMaterialLibrary := Value;
- StructureChanged;
- end;
- end;
- procedure TGLTree.RebuildTree;
- begin
- if not FRebuildTree then
- begin
- Clear;
- FRebuildTree := True;
- StructureChanged;
- end;
- end;
- procedure TGLTree.ForceTotalRebuild;
- begin
- Clear;
- FNoise.Free;
- RandSeed := FSeed;
- FNoise := TGLTreeBranchNoise.Create;
- FRebuildTree := False;
- FBranches.BuildBranches;
- StructureChanged;
- end;
- procedure TGLTree.LoadFromStream(aStream: TStream);
- var
- StrList, StrParse: TStringList;
- str: String;
- i: Integer;
- begin
- StrList := TStringList.Create;
- StrParse := TStringList.Create;
- StrList.LoadFromStream(aStream);
- try
- for i := 0 to StrList.Count - 1 do
- begin
- str := StrList[i];
- if pos('#', str) > 0 then
- str := Copy(str, 0, pos('#', str) - 1);
- StrParse.CommaText := str;
- if StrParse.Count >= 2 then
- begin
- str := LowerCase(StrParse[0]);
- if str = 'depth' then
- FDepth := StrToInt(StrParse[1])
- else if str = 'branch_facets' then
- FBranchFacets := StrToInt(StrParse[1])
- else if str = 'leaf_size' then
- FLeafSize := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_size' then
- FBranchSize := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_noise' then
- FBranchNoise := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_angle_bias' then
- FBranchAngleBias := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_angle' then
- FBranchAngle := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_twist' then
- FBranchTwist := GLStrToFloatDef(StrParse[1])
- else if str = 'branch_radius' then
- FBranchRadius := GLStrToFloatDef(StrParse[1])
- else if str = 'leaf_threshold' then
- FLeafThreshold := GLStrToFloatDef(StrParse[1])
- else if str = 'central_leader_bias' then
- FCentralLeaderBias := GLStrToFloatDef(StrParse[1])
- else if str = 'central_leader' then
- FCentralLeader := LowerCase(StrParse[1]) = 'true'
- else if str = 'seed' then
- FSeed := StrToInt(StrParse[1])
- else if str = 'leaf_front_material_name' then
- FLeafMaterialName := StrParse[1]
- else if str = 'leaf_back_material_name' then
- FLeafBackMaterialName := StrParse[1]
- else if str = 'branch_material_name' then
- FBranchMaterialName := StrParse[1];
- end;
- end;
- ForceTotalRebuild;
- finally
- StrList.Free;
- StrParse.Free;
- end;
- end;
- procedure TGLTree.SaveToStream(aStream: TStream);
- var
- StrList: TStringList;
- begin
- StrList := TStringList.Create;
- StrList.Add(Format('depth, %d', [Depth]));
- StrList.Add(Format('branch_facets, %d', [BranchFacets]));
- StrList.Add(Format('leaf_size, %f', [LeafSize]));
- StrList.Add(Format('branch_size, %f', [BranchSize]));
- StrList.Add(Format('branch_noise, %f', [branchNoise]));
- StrList.Add(Format('branch_angle_bias, %f', [BranchAngleBias]));
- StrList.Add(Format('branch_angle, %f', [BranchAngle]));
- StrList.Add(Format('branch_twist, %f', [BranchTwist]));
- StrList.Add(Format('branch_radius, %f', [BranchRadius]));
- StrList.Add(Format('leaf_threshold, %f', [LeafThreshold]));
- StrList.Add(Format('central_leader_bias, %f', [CentralLeaderBias]));
- if CentralLeader then
- StrList.Add('central_leader, true')
- else
- StrList.Add('central_leader, false');
- StrList.Add(Format('seed, %d', [Seed]));
- StrList.Add('leaf_front_material_name, "' + LeafMaterialName + '"');
- StrList.Add('leaf_back_material_name, "' + LeafBackMaterialName + '"');
- StrList.Add('branch_material_name, "' + BranchMaterialName + '"');
- StrList.SaveToStream(aStream);
- StrList.Free;
- end;
- procedure TGLTree.LoadFromFile(const aFileName: String);
- var
- stream: TStream;
- begin
- stream := TFileStream.Create(aFileName, fmOpenRead);
- try
- LoadFromStream(stream);
- finally
- stream.Free;
- end;
- end;
- procedure TGLTree.SaveToFile(const aFileName: String);
- var
- stream: TStream;
- begin
- stream := TFileStream.Create(aFileName, fmCreate);
- try
- SaveToStream(stream);
- finally
- stream.Free;
- end;
- end;
- procedure TGLTree.GetExtents(var min, max: TAffineVector);
- var
- lmin, lmax, bmin, bmax: TAffineVector;
- begin
- if Branches.Vertices.Count = 0 then
- begin
- FBranches.BuildBranches;
- FRebuildTree := False;
- end;
- if Leaves.Vertices.Count > 0 then
- Leaves.Vertices.GetExtents(lmin, lmax)
- else
- begin
- lmin := NullVector;
- lmax := NullVector;
- end;
- if Branches.Vertices.Count > 0 then
- Branches.Vertices.GetExtents(bmin, bmax)
- else
- begin
- bmin := NullVector;
- bmax := NullVector;
- end;
- min.X := MinFloat([lmin.X, lmax.X, bmin.X, bmax.X]);
- min.Y := MinFloat([lmin.Y, lmax.Y, bmin.Y, bmax.Y]);
- min.Z := MinFloat([lmin.Z, lmax.Z, bmin.Z, bmax.Z]);
- max.X := MaxFloat([lmin.X, lmax.X, bmin.X, bmax.X]);
- max.Y := MaxFloat([lmin.Y, lmax.Y, bmin.Y, bmax.Y]);
- max.Z := MaxFloat([lmin.Z, lmax.Z, bmin.Z, bmax.Z]);
- end;
- function TGLTree.AxisAlignedDimensionsUnscaled: TGLVector;
- var
- dMin, dMax: TAffineVector;
- begin
- if FAxisAlignedDimensionsCache.X < 0 then
- begin
- GetExtents(dMin, dMax);
- FAxisAlignedDimensionsCache.X := MaxFloat(Abs(dMin.X), Abs(dMax.X));
- FAxisAlignedDimensionsCache.Y := MaxFloat(Abs(dMin.Y), Abs(dMax.Y));
- FAxisAlignedDimensionsCache.Z := MaxFloat(Abs(dMin.Z), Abs(dMax.Z));
- end;
- SetVector(Result, FAxisAlignedDimensionsCache);
- end;
- procedure TGLTree.SetAutoCenter(const Value: Boolean);
- begin
- if Value <> FAutoCenter then
- begin
- FAutoCenter := Value;
- if (FAutoRebuild) then
- RebuildTree;
- end;
- end;
- procedure TGLTree.SetAutoRebuild(const Value: Boolean);
- begin
- if Value <> FAutoRebuild then
- begin
- FAutoRebuild := Value;
- end;
- end;
- initialization
- RegisterClasses([TGLTree]);
- end.
|