| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379 |
- //
- // The graphics rendering engine GLScene http://glscene.org
- //
- 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 : 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;
- type
- TGLTree = class;
- TGLTreeBranches = class;
- TGLTreeBranchNoise = class;
- TGLTreeLeaves = class
- private
- FOwner: TGLTree;
- FCount: Integer;
- FVertices: TAffineVectorList;
- FNormals: TAffineVectorList;
- FTexCoords: TAffineVectorList;
- 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: TAffineVectorList read FVertices;
- property Normals: TAffineVectorList read FNormals;
- property TexCoords: TAffineVectorList read FTexCoords;
- end;
- TGLTreeBranch = class
- private
- FOwner: TGLTreeBranches;
- FLeft: TGLTreeBranch;
- FCenter: TGLTreeBranch;
- FRight: TGLTreeBranch;
- FParent: TGLTreeBranch;
- FBranchID: Integer;
- FParentID: Integer;
- FMatrix: TGLMatrix;
- FLower: TIntegerList;
- FUpper: TIntegerList;
- 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: TIntegerList read FLower;
- property Upper: TIntegerList read FUpper;
- end;
- TGLTreeBranches = class
- private
- FOwner: TGLTree;
- FSinList: TSingleList;
- FCosList: TSingleList;
- FVertices: TAffineVectorList;
- FNormals: TAffineVectorList;
- FTexCoords: TAffineVectorList;
- FIndices: TIntegerList;
- FRoot: TGLTreeBranch;
- FCount: Integer;
- FBranchCache: TList;
- FBranchIndices: TIntegerList;
- procedure BuildBranches;
- public
- constructor Create(AOwner: TGLTree);
- destructor Destroy; override;
- procedure BuildList(var rci: TGLRenderContextInfo);
- procedure Clear;
- property Owner: TGLTree read FOwner;
- property SinList: TSingleList read FSinList;
- property CosList: TSingleList read FCosList;
- property Vertices: TAffineVectorList read FVertices;
- property Normals: TAffineVectorList read FNormals;
- property TexCoords: TAffineVectorList 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 := TAffineVectorList.Create;
- FNormals := TAffineVectorList.Create;
- FTexCoords := TAffineVectorList.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 := TIntegerList.Create;
- FLower := TIntegerList.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 := TSingleList.Create;
- FCosList := TSingleList.Create;
- FVertices := TAffineVectorList.Create;
- FNormals := TAffineVectorList.Create;
- FTexCoords := TAffineVectorList.Create;
- FIndices := TIntegerList.Create;
- FBranchCache := TList.Create;
- FBranchIndices := TIntegerList.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
- TMeshObject.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
- TMeshObject.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 := StrToFloat(StrParse[1])
- else if str = 'branch_size' then
- FBranchSize := StrToFloat(StrParse[1])
- else if str = 'branch_noise' then
- FBranchNoise := StrToFloat(StrParse[1])
- else if str = 'branch_angle_bias' then
- FBranchAngleBias := StrToFloat(StrParse[1])
- else if str = 'branch_angle' then
- FBranchAngle := StrToFloat(StrParse[1])
- else if str = 'branch_twist' then
- FBranchTwist := StrToFloat(StrParse[1])
- else if str = 'branch_radius' then
- FBranchRadius := StrToFloat(StrParse[1])
- else if str = 'leaf_threshold' then
- FLeafThreshold := StrToFloat(StrParse[1])
- else if str = 'central_leader_bias' then
- FCentralLeaderBias := StrToFloat(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.
|