GBE.SphereExtend.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. unit GBE.SphereExtend;
  2. (*
  3. The TGBESphereExtend originally allows to create Mesh from a TSphere
  4. Based on code by Gregory Bersegeay
  5. *)
  6. interface
  7. uses
  8. System.SysUtils,
  9. System.Classes,
  10. FMX.Types,
  11. FMX.Controls3D,
  12. FMX.Objects3D,
  13. FMX.Types3D,
  14. System.RTLConsts,
  15. System.Math.Vectors,
  16. FMX.MaterialSources;
  17. type
  18. TCustomMeshHelper = class(TCustomMesh);
  19. TSpheroid = (capsule, dome, culbuto, sphere, apple, pot, diamond);
  20. TGBESphereExtend = class(TMesh)
  21. private
  22. fSubdivisionsAxes, fSubdivisionsHeight: integer;
  23. fSpheroid: TSpheroid;
  24. fLongueur: single;
  25. fShowlines: boolean;
  26. fMaterialLignes: TColorMaterialSource;
  27. procedure CreateGBESphere(Const aData: TMeshData;
  28. Const aForme: TSpheroid = TSpheroid.sphere; Const aLength: single = 1.0);
  29. protected
  30. procedure SetForme(Value: TSpheroid);
  31. procedure SetLongueur(Value: single);
  32. procedure SetSubdivisionsAxes(Value: integer);
  33. procedure SetSubdivisionsHeight(Value: integer);
  34. public
  35. constructor Create(AOwner: TComponent); override;
  36. destructor Destroy; override;
  37. procedure Render; override;
  38. published
  39. property SubdivisionsAxes: integer read fSubdivisionsAxes
  40. write SetSubdivisionsAxes;
  41. property SubdivisionsHeight: integer read fSubdivisionsHeight
  42. write SetSubdivisionsHeight;
  43. property ShowLines: boolean read fShowlines write fShowlines;
  44. property Forme: TSpheroid read fSpheroid write SetForme;
  45. property Longueur: single read fLongueur write SetLongueur;
  46. property MaterialLines: TColorMaterialSource read fMaterialLignes
  47. write fMaterialLignes;
  48. end;
  49. procedure Register;
  50. implementation // -------------------------------------------------------------
  51. constructor TGBESphereExtend.Create(AOwner: TComponent);
  52. begin
  53. inherited;
  54. SubdivisionsHeight := 12;
  55. SubdivisionsAxes := 16;
  56. CreateGBESphere(self.Data);
  57. end;
  58. procedure TGBESphereExtend.CreateGBESphere(Const aData: TMeshData;
  59. Const aForme: TSpheroid = TSpheroid.sphere; Const aLength: single = 1.0);
  60. var
  61. D: TMeshData;
  62. Sp: TSphere;
  63. SbA, SbH, Vw, H, A: integer;
  64. P: PPoint3d;
  65. K, Yh, L: single;
  66. begin
  67. D := TMeshData.Create;
  68. Sp := TSphere.Create(nil);
  69. Sp.SubdivisionsAxes := SubdivisionsAxes;
  70. Sp.SubdivisionsHeight := SubdivisionsHeight;
  71. SbA := Sp.SubdivisionsAxes;
  72. SbH := Sp.SubdivisionsHeight div 2;
  73. D.Assign(TCustomMeshHelper(Sp).Data);
  74. TCustomMeshHelper(Sp).Data.Clear;
  75. Sp.Free;
  76. if (aForme <> TSpheroid.sphere) and (aForme <> TSpheroid.diamond) then
  77. begin
  78. L := aLength;
  79. K := L / SbH;
  80. Yh := L;
  81. Vw := SbA + 1;
  82. for H := 0 to SbH - 1 do
  83. begin
  84. for A := 0 to SbA do
  85. begin
  86. P := D.VertexBuffer.VerticesPtr[A + (H * Vw)];
  87. if (aForme = TSpheroid.dome) or (aForme = TSpheroid.pot) then
  88. P^.Y := -L
  89. else
  90. P^.Y := P^.Y - Yh;
  91. end;
  92. if (aForme = TSpheroid.culbuto) or (aForme = TSpheroid.apple) then
  93. Yh := Yh - K;
  94. end;
  95. end;
  96. if (aForme = TSpheroid.dome) or (aForme = TSpheroid.pot) then
  97. D.CalcTangentBinormals
  98. else
  99. D.CalcSmoothNormals;
  100. aData.Clear;
  101. aData.Assign(D);
  102. D.Free;
  103. end;
  104. destructor TGBESphereExtend.Destroy;
  105. begin
  106. inherited;
  107. end;
  108. procedure TGBESphereExtend.SetLongueur(Value: single);
  109. begin
  110. if Value <> fLongueur then
  111. begin
  112. fLongueur := Value;
  113. CreateGBESphere(self.Data, fSpheroid, fLongueur);
  114. end;
  115. end;
  116. procedure TGBESphereExtend.SetForme(Value: TSpheroid);
  117. begin
  118. if Value <> fSpheroid then
  119. begin
  120. fSpheroid := Value;
  121. case fSpheroid of
  122. TSpheroid.apple:
  123. fLongueur := -0.4;
  124. TSpheroid.pot:
  125. fLongueur := -0.15;
  126. TSpheroid.diamond:
  127. begin
  128. fSubdivisionsAxes := 4;
  129. fSubdivisionsHeight := 2;
  130. end;
  131. end;
  132. CreateGBESphere(self.Data, fSpheroid, fLongueur);
  133. end;
  134. end;
  135. procedure TGBESphereExtend.SetSubdivisionsAxes(Value: integer);
  136. begin
  137. if Value <> fSubdivisionsAxes then
  138. begin
  139. fSubdivisionsAxes := Value;
  140. CreateGBESphere(self.Data, fSpheroid, fLongueur);
  141. end;
  142. end;
  143. procedure TGBESphereExtend.SetSubdivisionsHeight(Value: integer);
  144. begin
  145. if Value <> fSubdivisionsHeight then
  146. begin
  147. fSubdivisionsHeight := Value;
  148. CreateGBESphere(self.Data, fSpheroid, fLongueur);
  149. end;
  150. end;
  151. procedure TGBESphereExtend.Render;
  152. begin
  153. inherited;
  154. if ShowLines then
  155. Context.DrawLines(self.Data.VertexBuffer, self.Data.IndexBuffer,
  156. TMaterialSource.ValidMaterial(fMaterialLignes), 1);
  157. end;
  158. // ----------------------------------------------------------------------------
  159. procedure Register;
  160. begin
  161. RegisterComponents('GXScene GBE', [TGBESphereExtend]);
  162. end;
  163. end.