C2Flora.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:8k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  CAST II Engine vegetation unit
  3.  (C) 2006-2008 George "Mirage" Bakhtadze. avagames@gmail.com
  4.  Created: Mar 13, 2008
  5.  Unit contains
  6. *)
  7. {$Include GDefines.inc}
  8. {$Include C2Defines.inc}
  9. unit C2Flora;
  10. interface
  11. uses SysUtils, TextFile, Basics, BaseTypes, Base3d, Props, BaseClasses, C2Types, C2Visual, C2VisItems, CAST2;
  12. type
  13.   TTreeAdjTesselator = class(TMeshTesselator)
  14.   private
  15.     FAdjNormals, FAdjdiffuse: Boolean;
  16.     FDiffuse: TColor;
  17.     TimeElapsed: Integer;
  18.     procedure AdjustMesh;
  19.   public
  20.     procedure Init; override;
  21.     procedure AddProperties(const Result: Props.TProperties; const PropNamePrefix: TNameString); override;
  22.     procedure SetProperties(Properties: Props.TProperties; const PropNamePrefix: TNameString); override;
  23.     function Tesselate(const Params: TTesselationParameters; VBPTR: Pointer): Integer; override;
  24.   end;
  25.   TTreeAdj = class(TMesh)
  26.     function GetTesselatorClass: CTesselator; override;
  27.     procedure Process(const DeltaT: Float); override;
  28.   end;
  29.   // Procedural tree stem tesselator
  30.   TTreeStemTesselator = class(TTesselator)
  31.   public
  32.     Width, Height: Single;
  33.     Sides, Levels: Integer;
  34.     procedure Init; override;
  35.     procedure AddProperties(const Result: Props.TProperties; const PropNamePrefix: TNameString); override;
  36.     procedure SetProperties(Properties: Props.TProperties; const PropNamePrefix: TNameString); override;
  37.     function Tesselate(const Params: TTesselationParameters; VBPTR: Pointer): Integer; override;
  38.   end;
  39.   // Procedural tree stem
  40.   TTreeStem = class(TVisible)
  41.     function GetTesselatorClass: CTesselator; override;
  42.   end;
  43.   // Returns list of classes introduced by the unit
  44.   function GetUnitClassList: TClassArray;
  45. implementation
  46. function GetUnitClassList: TClassArray;
  47. begin
  48.   Result := GetClassList([TTreeAdj, TTreeStem]);
  49. end;
  50. { TTreeAdjTesselator }
  51. procedure TTreeAdjTesselator.AddProperties(const Result: Props.TProperties; const PropNamePrefix: TNameString);
  52. begin
  53.   inherited;
  54.   Result.Add(PropNamePrefix + 'Adjust normals', vtBoolean, [], OnOffStr[FAdjNormals], '');
  55.   Result.Add(PropNamePrefix + 'Adjust diffuse', vtBoolean, [], OnOffStr[FAdjdiffuse], '');
  56.   AddColorProperty(Result, PropNamePrefix + 'Diffuse', FDiffuse);
  57. end;
  58. procedure TTreeAdjTesselator.SetProperties(Properties: Props.TProperties; const PropNamePrefix: TNameString);
  59. begin
  60.   inherited;                                                                   
  61.   if Properties.Valid(PropNamePrefix + 'Adjust normals') then FAdjNormals := Properties.GetAsInteger(PropNamePrefix + 'Adjust normals') > 0;
  62.   if Properties.Valid(PropNamePrefix + 'Adjust diffuse') then FAdjdiffuse := Properties.GetAsInteger(PropNamePrefix +'Adjust diffuse') > 0;
  63.   SetColorProperty(Properties, PropNamePrefix + 'Diffuse', FDiffuse);
  64.   AdjustMesh;
  65. end;
  66. function TTreeAdjTesselator.Tesselate(const Params: TTesselationParameters; VBPTR: Pointer): Integer;
  67. const FreqK = 0.01; AmpK = 0.6;
  68. var i, i1, i2, i3, t: Integer; v1, v2, v3, n: TVector3s; Freq, Amp: Single;
  69. begin
  70.   Result := 0;
  71.   if FVertices = nil then Exit;
  72.   Move(FVertices^, VBPTR^, TotalVertices * FVertexSize);
  73.   for i := 0 to TotalPrimitives - 1 do begin
  74.     i1 := GetIndex(i*3+0, Indices);
  75.     i2 := GetIndex(i*3+1, Indices);
  76.     i3 := GetIndex(i*3+2, Indices);
  77.     v1 := GetVertexDataC(i1, Vertices);
  78.     v2 := GetVertexDataC(i2, Vertices);
  79.     v3 := GetVertexDataC(i3, Vertices);
  80. //    n := CrossProductVector3s(SubVector3s(v1, v3), SubVector3s(v2, v1));
  81.     n := AddVector3s(SubVector3s(v1, v3), SubVector3s(v2, v1));
  82.     n := NormalizeVector3s(n);
  83.     Amp := TimeElapsed*FreqK*0.5+(Params.ModelMatrix.ViewTranslate.x+Params.ModelMatrix.ViewTranslate.z)*0.0009;
  84.     t := Trunc(Amp);
  85.     if t mod 2 = 0 then begin
  86.       Amp := Amp - t;
  87.       Amp := 1+2*Sin(Amp*pi)//(Amp * Ord(Amp < 0.5) + (1 - Amp) * Ord(Amp >= 0.5));
  88.     end else Amp := 1;
  89.     Freq := FreqK * (1+i1 mod 8);
  90.     Amp := Amp * AmpK * (1+i2 mod 4);
  91.     v1 := AddVector3s(V1, ScaleVector3s(n, Sin(TimeElapsed*Freq)*Amp));
  92.     SetVertexDataC(V1, i1, VBPTR);
  93. //    v2.Y := V2.Y + Sin(TimeElapsed*K)*amp;
  94. //    SetVertexDataC(V2, i2, VBPTR);
  95. //    v3.Y := V3.Y + Sin(TimeElapsed*K)*amp;
  96. //    SetVertexDataC(V3, i3, VBPTR);
  97.   end;
  98.   TesselationStatus[tbVertex].Status := tsTesselated;
  99. //  Status := tsChanged;
  100.   LastTotalIndices := TotalIndices;
  101.   LastTotalVertices := TotalVertices;
  102.   Result := LastTotalVertices;
  103. end;
  104. procedure TTreeAdjTesselator.AdjustMesh;
  105. var i, i1, i2, i3: Integer; v1, v2, v3, e1, e2, e3: TVector3s;
  106. begin
  107.   if not Assigned(Vertices) or not Assigned(Indices) or (PrimitiveType <> ptTriangleList) then begin
  108.     Log.Log('TTreeAdjTesselator.AdjustMesh: Vertices or indices are not present or primitive type is not triangle list', lkError);
  109.     Exit;
  110.   end;
  111.   for i := 0 to TotalPrimitives - 1 do begin
  112.     i1 := GetIndex(i*3+0, Indices);
  113.     i2 := GetIndex(i*3+1, Indices);
  114.     i3 := GetIndex(i*3+2, Indices);
  115.     v1 := GetVertexDataC(i1, Vertices);
  116.     v2 := GetVertexDataC(i2, Vertices);
  117.     v3 := GetVertexDataC(i3, Vertices);
  118.     SetVertexDataD(FDiffuse, i1, Vertices);         
  119.     SetVertexDataD(FDiffuse, i2, Vertices);
  120.     SetVertexDataD(FDiffuse, i3, Vertices);
  121.     if FAdjNormals then begin
  122.       e1 := SubVector3s(v2, v1);
  123.       e2 := SubVector3s(v3, v2);
  124.       e3 := SubVector3s(v1, v3);
  125.       SetVertexDataN(NormalizeVector3s(SubVector3s(e3, e1)), i1, Vertices);
  126.       SetVertexDataN(NormalizeVector3s(SubVector3s(e1, e2)), i2, Vertices);
  127.       SetVertexDataN(NormalizeVector3s(SubVector3s(e2, e3)), i3, Vertices);
  128.     end;
  129.   end;
  130.   Inc(TimeElapsed);
  131.   Invalidate([tbVertex], False);
  132. end;
  133. procedure TTreeAdjTesselator.Init;
  134. begin
  135.   inherited;
  136.   TesselationStatus[tbVertex].TesselatorType := ttDynamic;
  137.   TesselationStatus[tbIndex].TesselatorType  := ttStatic;
  138. end;
  139. { TTreeAdj }
  140. function TTreeAdj.GetTesselatorClass: CTesselator; begin Result := TTreeAdjTesselator; end;
  141. procedure TTreeAdj.Process(const DeltaT: Float);
  142. begin
  143.   inherited;
  144.   if Assigned(CurrentTesselator) then TTreeAdjTesselator(CurrentTesselator).AdjustMesh;
  145. end;
  146. { TTreeStem }
  147. function TTreeStem.GetTesselatorClass: CTesselator; begin Result := TTreeStemTesselator; end;
  148. { TTreeStemTesselator }
  149. procedure TTreeStemTesselator.Init;
  150. begin
  151.   inherited;
  152. end;
  153. procedure TTreeStemTesselator.AddProperties(const Result: Props.TProperties; const PropNamePrefix: TNameString);
  154. begin
  155.   inherited;
  156.   Result.Add('Width',  vtSingle, [], FloatToStr(Width),  '');
  157.   Result.Add('Height', vtSingle, [], FloatToStr(Height), '');
  158.   Result.Add('Sides',  vtInt,    [], IntToStr(Sides),    '');
  159.   Result.Add('Levels', vtInt,    [], IntToStr(Levels),   '');
  160. end;
  161. procedure TTreeStemTesselator.SetProperties(Properties: Props.TProperties; const PropNamePrefix: TNameString);
  162. begin
  163.   inherited;
  164.   if Properties.Valid('Width')  then Width  := StrToFloatDef(Properties['Width'],  0);
  165.   if Properties.Valid('Height') then Height := StrToFloatDef(Properties['Height'], 0);
  166.   if Properties.Valid('Sides')  then Sides  := StrToIntDef(Properties['Sides'],    0);
  167.   if Properties.Valid('Levels') then Levels := StrToIntDef(Properties['Levels'],   0);
  168.   TotalVertices := Sides*6;
  169.   TotalPrimitives := Sides*2;
  170. end;
  171. function TTreeStemTesselator.Tesselate(const Params: TTesselationParameters; VBPTR: Pointer): Integer;
  172. var i: Integer; c1, s1, c2, s2: Single;
  173. begin
  174.   for i := 0 to Sides-1 do begin
  175.     c1 := Cos(i/180*pi*360/Sides);     s1 := Sin(i/180*pi*360/Sides);
  176.     c2 := Cos((i+1)/180*pi*360/Sides); s2 := Sin((i+1)/180*pi*360/Sides);
  177.     // First triangle of a side
  178.     SetVertexDataC(c1*Width, Height, -s1*Width, i*6, VBPTR);
  179.     SetVertexDataN(c1, 0, -s1, i*6, VBPTR);
  180.     SetVertexDataC(c1*Width, 0, -s1*Width, i*6+1, VBPTR);
  181.     SetVertexDataN(c1, 0, -s1, i*6+1, VBPTR);
  182.     SetVertexDataC(c2*Width, 0, -s2*Width, i*6+2, VBPTR);
  183.     SetVertexDataN(c2, 0, -s2, i*6+2, VBPTR);
  184.     // Second triangle of a side
  185.     SetVertexDataC(c1*Width, Height, -s1*Width, i*6+3, VBPTR);
  186.     SetVertexDataN(c1, 0, -s1, i*6+3, VBPTR);
  187.     SetVertexDataC(c2*Width, 0, -s2*Width, i*6+4, VBPTR);
  188.     SetVertexDataN(c2, 0, -s2, i*6+4, VBPTR);
  189.     SetVertexDataC(c2*Width, Height, -s2*Width, i*6+5, VBPTR);
  190.     SetVertexDataN(c2, 0, -s2, i*6+5, VBPTR);
  191.   end;
  192.   TesselationStatus[tbVertex].Status := tsTesselated;
  193.   LastTotalIndices  := TotalIndices;
  194.   LastTotalVertices := TotalVertices;
  195.   Result := LastTotalVertices;
  196. end;
  197. begin
  198.   GlobalClassList.Add('C2Flora', GetUnitClassList);
  199. end.