fParticleMaskingD.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. unit fParticleMaskingD;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Classes,
  7. System.Types,
  8. System.Math,
  9. Vcl.Graphics,
  10. Vcl.Controls,
  11. Vcl.Forms,
  12. Vcl.Dialogs,
  13. Vcl.ExtCtrls,
  14. Vcl.ComCtrls,
  15. Vcl.StdCtrls,
  16. GLS.Scene,
  17. GLS.Objects,
  18. GLS.BitmapFont,
  19. GLS.WindowsFont,
  20. GLS.Texture,
  21. GLS.Cadencer,
  22. GLS.SceneViewer,
  23. GLS.ParticleFX,
  24. Stage.VectorGeometry,
  25. Stage.VectorTypes,
  26. GLS.EParticleMasksManager,
  27. GLS.GeomObjects,
  28. GLS.AsyncTimer,
  29. GLS.Material,
  30. GLS.Coordinates,
  31. GLS.BaseClasses;
  32. const
  33. PlaneHeights = 5;
  34. PlaneWidths = 5;
  35. PlaneDepths = 5;
  36. PlaneOffsets = 3;
  37. type
  38. TFormParticleMasking = class(TForm)
  39. MaskBox: TGroupBox;
  40. GLScene: TGLScene;
  41. SceneViewer: TGLSceneViewer;
  42. GLCadencer: TGLCadencer;
  43. MatLib: TGLMaterialLibrary;
  44. WinFont: TGLWindowsBitmapFont;
  45. XImage: TImage;
  46. Splitter1: TSplitter;
  47. XLabel: TLabel;
  48. YLabel: TLabel;
  49. ZLabel: TLabel;
  50. YImage: TImage;
  51. ZImage: TImage;
  52. Camera: TGLCamera;
  53. Target: TGLDummyCube;
  54. XPlane: TGLPlane;
  55. YPlane: TGLPlane;
  56. ZPlane: TGLPlane;
  57. Light: TGLLightSource;
  58. PLManager: TGLPointLightPFXManager;
  59. PFXRenderer: TGLParticleFXRenderer;
  60. Button1: TButton;
  61. Button2: TButton;
  62. Button3: TButton;
  63. GLEParticleMasksManager1: TGLEParticleMasksManager;
  64. Panel1: TPanel;
  65. Label1: TLabel;
  66. Label2: TLabel;
  67. Button4: TButton;
  68. Edit1: TEdit;
  69. Edit2: TEdit;
  70. Label3: TLabel;
  71. Label4: TLabel;
  72. Label5: TLabel;
  73. Edit3: TEdit;
  74. Edit4: TEdit;
  75. Edit5: TEdit;
  76. Sphere: TGLSphere;
  77. CheckBox1: TCheckBox;
  78. GLArrowLine1: TGLArrowLine;
  79. AsyncTimer1: TGLAsyncTimer;
  80. procedure GLCadencerProgress(Sender: TObject; const DeltaTime, newTime: Double);
  81. procedure FormCreate(Sender: TObject);
  82. procedure SceneViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  83. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer;
  84. MousePos: TPoint; var Handled: Boolean);
  85. procedure PLManagerCreateParticle(Sender: TObject; aParticle: TGLParticle);
  86. procedure Button1Click(Sender: TObject);
  87. procedure Button2Click(Sender: TObject);
  88. procedure Button3Click(Sender: TObject);
  89. procedure Button4Click(Sender: TObject);
  90. procedure Edit3Change(Sender: TObject);
  91. procedure Edit4Change(Sender: TObject);
  92. procedure Edit5Change(Sender: TObject);
  93. procedure CheckBox1Click(Sender: TObject);
  94. procedure AsyncTimer1Timer(Sender: TObject);
  95. procedure Edit2Change(Sender: TObject);
  96. private
  97. public
  98. mx, my: Integer;
  99. procedure RefreshMask;
  100. end;
  101. var
  102. FormParticleMasking: TFormParticleMasking;
  103. implementation
  104. {$R *.dfm}
  105. procedure TFormParticleMasking.RefreshMask;
  106. var
  107. Rect: TRect;
  108. Mat: TGLLibMaterial;
  109. Letter: Char;
  110. Depth: Integer;
  111. begin
  112. Letter := Edit2.Text[1];
  113. Depth := StrToIntDef(Edit1.Text, 50);
  114. XPlane.Position.X := -PlaneOffSets;
  115. XPlane.Height := PlaneHeights;
  116. XPlane.Width := PlaneWidths;
  117. YPlane.Position.Y := -PlaneOffSets;
  118. YPlane.Height := PlaneHeights;
  119. YPlane.Width := PlaneWidths;
  120. ZPlane.Position.Z := -PlaneOffSets;
  121. ZPlane.Height := PlaneHeights;
  122. ZPlane.Width := PlaneWidths;
  123. Rect.Left := 0;
  124. Rect.Top := 0;
  125. Rect.Bottom := XImage.Height;
  126. Rect.Right := XImage.Width;
  127. XImage.Canvas.Font.Name := 'Arial';
  128. XImage.Canvas.Font.Size := 180;
  129. XImage.Canvas.Font.Color := clWhite;
  130. XImage.Canvas.Pen.Color := clBlack;
  131. XImage.Canvas.Pen.Style := psSolid;
  132. XImage.Canvas.Brush.Color := clBlack;
  133. XImage.Canvas.Brush.Style := bsSolid;
  134. XImage.Canvas.FillRect(Rect);
  135. XImage.Canvas.TextOut(round((XImage.Width - XImage.Canvas.TextWidth(Letter)) / 2),
  136. round((XImage.Height - XImage.Canvas.TextHeight(Letter)) / 2), Letter);
  137. Mat := MatLib.LibMaterialByName('XMask');
  138. with Mat.Material.Texture.Image as TGLPersistentImage do
  139. begin
  140. Picture.Bitmap.Height := XImage.Height;
  141. Picture.Bitmap.Width := XImage.Width;
  142. Picture.Bitmap.Canvas.Draw(0, 0, XImage.Picture.Graphic);
  143. end;
  144. // this is a very recent implementation, the ability to generate other masks from 1 mask, so it satisfies
  145. // the requirements for the particle mask manager. useful for text and making basic shapes (cylinders etc)
  146. GLEParticleMasksManager1.ParticleMaskByName('mask').GenerateMaskFromProjection(pptXMask, pptYMask, Depth);
  147. GLEParticleMasksManager1.ParticleMaskByName('mask').GenerateMaskFromProjection(pptXMask, pptZMask, Depth);
  148. Mat := MatLib.LibMaterialByName('YMask');
  149. with Mat.Material.Texture.Image as TGLPersistentImage do
  150. YImage.Canvas.Draw(0, 0, Picture.Graphic);
  151. Mat := MatLib.LibMaterialByName('ZMask');
  152. with Mat.Material.Texture.Image as TGLPersistentImage do
  153. ZImage.Canvas.Draw(0, 0, Picture.Graphic);
  154. end;
  155. // with formcreate, we are just drawing some pre-rendered masks
  156. procedure TFormParticleMasking.FormCreate(Sender: TObject);
  157. begin
  158. RefreshMask;
  159. Sphere.Visible := CheckBox1.Checked;
  160. end;
  161. procedure TFormParticleMasking.GLCadencerProgress(Sender: TObject; const DeltaTime, newTime: Double);
  162. begin
  163. Sphere.TurnAngle := -newTime * 20;
  164. Sphere.Position.X := Cos(DegToRad(newTime * 20)) * 1.5;
  165. Sphere.Position.Z := Sin(DegToRad(newTime * 20)) * 1.5;
  166. SceneViewer.Invalidate;
  167. end;
  168. procedure TFormParticleMasking.SceneViewerMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  169. begin
  170. if ssLeft in Shift then
  171. Camera.MoveAroundTarget(my - Y, mx - X);
  172. mx := X;
  173. my := Y;
  174. end;
  175. procedure TFormParticleMasking.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  176. begin
  177. Camera.FocalLength := Camera.FocalLength + (WheelDelta / 150);
  178. Handled := True;
  179. end;
  180. procedure TFormParticleMasking.PLManagerCreateParticle(Sender: TObject; aParticle: TGLParticle);
  181. var
  182. I: Integer;
  183. Particle: TGLParticle;
  184. begin
  185. // using point lights just coz it is easier to see the effect
  186. if PLManager.Particles.ItemCount > 0 then
  187. for I := 0 to PLManager.Particles.ItemCount - 1 do
  188. begin
  189. Particle := PLManager.Particles.Items[I];
  190. // first we find the particles that are tagged (since before particle creation, the position is overridden)
  191. if Particle.Tag = 1 then
  192. begin
  193. if CheckBox1.Checked then
  194. GLEParticleMasksManager1.SetParticlePositionFromMaskTarget(Particle, 'mask', Sphere)
  195. else
  196. GLEParticleMasksManager1.SetParticlePositionFromMask(Particle, 'mask');
  197. Particle.Tag := 0;
  198. end;
  199. end;
  200. // we tag the new particle for when another particle is made so we know this one needs updating aswell
  201. aParticle.Tag := 1;
  202. end;
  203. procedure TFormParticleMasking.Button1Click(Sender: TObject);
  204. begin
  205. Camera.Position.Z := 0;
  206. Camera.Position.Y := 0;
  207. Camera.Position.X := 4;
  208. end;
  209. procedure TFormParticleMasking.Button2Click(Sender: TObject);
  210. begin
  211. Camera.Position.X := 0;
  212. Camera.Position.Z := 0.01;
  213. Camera.Position.Y := 4;
  214. end;
  215. procedure TFormParticleMasking.Button3Click(Sender: TObject);
  216. begin
  217. Camera.Position.X := 0;
  218. Camera.Position.Y := 0;
  219. Camera.Position.Z := 4;
  220. end;
  221. procedure TFormParticleMasking.Button4Click(Sender: TObject);
  222. begin
  223. FormCreate(Sender);
  224. end;
  225. procedure TFormParticleMasking.Edit2Change(Sender: TObject);
  226. begin
  227. RefreshMask;
  228. end;
  229. procedure TFormParticleMasking.Edit3Change(Sender: TObject);
  230. begin
  231. GLEParticleMasksManager1.ParticleMaskByName('mask').PitchAngle := StrToFloatDef(Edit3.Text, 0);
  232. end;
  233. procedure TFormParticleMasking.Edit4Change(Sender: TObject);
  234. begin
  235. GLEParticleMasksManager1.ParticleMaskByName('mask').RollAngle := StrToFloatDef(Edit4.Text, 0);
  236. end;
  237. procedure TFormParticleMasking.Edit5Change(Sender: TObject);
  238. begin
  239. GLEParticleMasksManager1.ParticleMaskByName('mask').TurnAngle := StrToFloatDef(Edit5.Text, 0);
  240. end;
  241. procedure TFormParticleMasking.CheckBox1Click(Sender: TObject);
  242. begin
  243. Sphere.Visible := CheckBox1.Checked;
  244. end;
  245. procedure TFormParticleMasking.AsyncTimer1Timer(Sender: TObject);
  246. begin
  247. Caption := FormatFloat('Particle Masking - ' +'FPS: 0.0', SceneViewer.FramesPerSecond) +
  248. ' Particle Count: ' + IntToStr(PLManager.ParticleCount);
  249. SceneViewer.ResetPerformanceMonitor;
  250. end;
  251. end.