fMeshGradients.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. unit fMeshGradients;
  2. interface
  3. uses
  4. {$IFDEF FPC} LCLIntf, {$ELSE} Windows, {$ENDIF}
  5. System.SysUtils,
  6. System.Classes,
  7. System.Math,
  8. Graphics,
  9. Controls,
  10. Forms,
  11. Dialogs,
  12. ExtCtrls,
  13. StdCtrls,
  14. SyncObjs,
  15. GR32,
  16. GR32_Image,
  17. GR32_ColorGradients,
  18. GR32_RangeBars;
  19. type
  20. TFrmMeshGradients = class(TForm)
  21. BtnRecall: TButton;
  22. BtnStore: TButton;
  23. CbxColoredPolygons: TCheckBox;
  24. CmbBackgroundSampler: TComboBox;
  25. ColorDialog: TColorDialog;
  26. GbrPower: TGaugeBar;
  27. LblBackgroundSampler: TLabel;
  28. LblPower: TLabel;
  29. LblVertexColor: TLabel;
  30. PaintBox32: TPaintBox32;
  31. PnlDelaunayTriangulation: TPanel;
  32. PnlSampler: TPanel;
  33. PnlSettings: TPanel;
  34. PnlVertex: TPanel;
  35. VertexColorShape: TShape;
  36. procedure FormCreate(Sender: TObject);
  37. procedure BtnStoreClick(Sender: TObject);
  38. procedure BtnRecallClick(Sender: TObject);
  39. procedure CbxAdaptiveSuperSamplerClick(Sender: TObject);
  40. procedure CmbBackgroundSamplerChange(Sender: TObject);
  41. procedure GbrPowerChange(Sender: TObject);
  42. procedure PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
  43. Shift: TShiftState; X, Y: Integer);
  44. procedure PaintBox32MouseMove(Sender: TObject; Shift: TShiftState;
  45. X, Y: Integer);
  46. procedure PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
  47. Shift: TShiftState; X, Y: Integer);
  48. procedure PaintBox32PaintBuffer(Sender: TObject);
  49. procedure SelectVertexColorClick(Sender: TObject);
  50. procedure VertexColorShapeMouseDown(Sender: TObject; Button: TMouseButton;
  51. Shift: TShiftState; X, Y: Integer);
  52. procedure CbxColoredPolygonsClick(Sender: TObject);
  53. private
  54. FColorPoints: TArrayOfColor32FloatPoint;
  55. FClipboard: TArrayOfColor32FloatPoint;
  56. FSelected: Integer;
  57. FIdwPower: TFloat;
  58. procedure SetSelected(const Value: Integer);
  59. protected
  60. procedure SelectedChanged;
  61. public
  62. property Selected: Integer read FSelected write SetSelected;
  63. end;
  64. var
  65. FrmMeshGradients: TFrmMeshGradients;
  66. implementation
  67. {$IFDEF FPC}
  68. {$R *.lfm}
  69. {$ELSE}
  70. {$R *.dfm}
  71. {$ENDIF}
  72. uses
  73. GR32_Geometry,
  74. GR32_Resamplers,
  75. GR32_Polygons,
  76. GR32_VectorUtils;
  77. procedure TFrmMeshGradients.FormCreate(Sender: TObject);
  78. var
  79. Index: Integer;
  80. begin
  81. SetLength(FColorPoints, 3);
  82. for Index := 0 to High(FColorPoints) do
  83. begin
  84. FColorPoints[Index].Point := FloatPoint(PaintBox32.Width * Random,
  85. PaintBox32.Height * Random);
  86. FColorPoints[Index].Color32 := SetAlpha(Random($FFFFFF), $FF);
  87. end;
  88. FColorPoints[0].Point := FloatPoint(274, 199);
  89. FColorPoints[1].Point := FloatPoint(134, 419);
  90. FColorPoints[2].Point := FloatPoint(46, 146);
  91. FSelected := -1;
  92. FIdwPower := 16;
  93. end;
  94. procedure TFrmMeshGradients.GbrPowerChange(Sender: TObject);
  95. begin
  96. FIdwPower := 15.9 * (Log2(1 + 0.0001 * GbrPower.Position)) + 0.1;
  97. PaintBox32.Invalidate;
  98. end;
  99. procedure TFrmMeshGradients.SelectVertexColorClick(Sender: TObject);
  100. begin
  101. if (FSelected >= 0) then
  102. begin
  103. ColorDialog.Color := WinColor(FColorPoints[FSelected].Color32);
  104. if ColorDialog.Execute then
  105. begin
  106. FColorPoints[FSelected].Color32 := Color32(ColorDialog.Color);
  107. PaintBox32.Invalidate;
  108. VertexColorShape.Brush.Color := WinColor(FColorPoints[Selected].Color32);
  109. end;
  110. end;
  111. end;
  112. procedure TFrmMeshGradients.PaintBox32MouseDown(Sender: TObject;
  113. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  114. var
  115. Index: Integer;
  116. begin
  117. Selected := -1;
  118. for Index := 0 to High(FColorPoints) do
  119. begin
  120. if (Abs(FColorPoints[Index].Point.X - X) < 4) and
  121. (Abs(FColorPoints[Index].Point.Y - Y) < 4) then
  122. begin
  123. Selected := Index;
  124. Break;
  125. end;
  126. end;
  127. if (Selected >= 0) and (Button = mbRight) then
  128. begin
  129. // do not delete last point!
  130. if Length(FColorPoints) = 1 then
  131. Exit;
  132. if Selected < Length(FColorPoints) - 1 then
  133. Move(FColorPoints[Selected + 1], FColorPoints[Selected],
  134. (Length(FColorPoints) - Selected - 1) * SizeOf(TColor32FloatPoint));
  135. SetLength(FColorPoints, Length(FColorPoints) - 1);
  136. Selected := -1;
  137. end;
  138. if (Selected < 0) and (Button = mbLeft) then
  139. begin
  140. Selected := Length(FColorPoints);
  141. SetLength(FColorPoints, Length(FColorPoints) + 1);
  142. FColorPoints[Selected].Point := FloatPoint(X, Y);
  143. FColorPoints[Selected].Color32 := SetAlpha(Random($FFFFFF), $FF);
  144. VertexColorShape.Brush.Color := WinColor(FColorPoints[Selected].Color32);
  145. if ssShift in Shift then
  146. SelectVertexColorClick(Sender);
  147. end;
  148. PaintBox32.Invalidate;
  149. end;
  150. procedure TFrmMeshGradients.PaintBox32MouseMove(Sender: TObject;
  151. Shift: TShiftState; X, Y: Integer);
  152. begin
  153. if (ssLeft in Shift) and (Selected >= 0) then
  154. begin
  155. FColorPoints[Selected].Point.X := X;
  156. FColorPoints[Selected].Point.Y := Y;
  157. PaintBox32.Invalidate;
  158. end;
  159. end;
  160. procedure TFrmMeshGradients.PaintBox32MouseUp(Sender: TObject;
  161. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  162. begin
  163. // Selected := -1;
  164. end;
  165. procedure TFrmMeshGradients.PaintBox32PaintBuffer(Sender: TObject);
  166. var
  167. Index: Integer;
  168. X, Y: Integer;
  169. FrameColor: TColor32;
  170. Renderer: TPolygonRenderer32VPR;
  171. Points: TArrayOfFloatPoint;
  172. Sampler: TCustomArbitrarySparsePointGradientSampler;
  173. Delaunay: TGourandShadedDelaunayTrianglesSampler;
  174. begin
  175. // clear paint box
  176. PaintBox32.Buffer.Clear;
  177. case CmbBackgroundSampler.ItemIndex of
  178. 1, 2:
  179. begin
  180. Sampler := TVoronoiSampler.Create;
  181. try
  182. Sampler.SetColorPoints(FColorPoints);
  183. if CmbBackgroundSampler.ItemIndex = 2 then
  184. with TAdaptiveSuperSampler.Create(Sampler) do
  185. begin
  186. Level := 4;
  187. PrepareSampling;
  188. with PaintBox32 do
  189. for Y := 0 to Height - 1 do
  190. for X := 0 to Width - 1 do
  191. begin
  192. Buffer.Pixel[X, Y] := GetSampleInt(X, Y);
  193. end;
  194. end
  195. else
  196. begin
  197. Sampler.PrepareSampling;
  198. with PaintBox32 do
  199. for Y := 0 to Height - 1 do
  200. for X := 0 to Width - 1 do
  201. begin
  202. Buffer.Pixel[X, Y] := Sampler.GetSampleInt(X, Y);
  203. end;
  204. end;
  205. finally
  206. Sampler.Free;
  207. end;
  208. end;
  209. 3, 4:
  210. begin
  211. Sampler := TInvertedDistanceWeightingSampler.Create;
  212. try
  213. if CmbBackgroundSampler.ItemIndex = 4 then
  214. TInvertedDistanceWeightingSampler(Sampler).Power := FIdwPower;
  215. Sampler.SetColorPoints(FColorPoints);
  216. Sampler.PrepareSampling;
  217. with PaintBox32 do
  218. for Y := 0 to Height - 1 do
  219. for X := 0 to Width - 1 do
  220. Buffer.Pixel[X, Y] := Sampler.GetSampleInt(X, Y);
  221. finally
  222. Sampler.Free;
  223. end;
  224. end;
  225. 5:
  226. begin
  227. Sampler := TGourandShadedDelaunayTrianglesSampler.Create;
  228. try
  229. Sampler.SetColorPoints(FColorPoints);
  230. Sampler.PrepareSampling;
  231. with PaintBox32 do
  232. for Y := 0 to Height - 1 do
  233. for X := 0 to Width - 1 do
  234. Buffer.Pixel[X, Y] := Sampler.GetSampleInt(X, Y);
  235. finally
  236. Sampler.Free;
  237. end;
  238. end;
  239. end;
  240. SetLength(Points, Length(FColorPoints));
  241. for Index := 0 to High(FColorPoints) do
  242. Points[Index] := FColorPoints[Index].Point;
  243. if CbxColoredPolygons.Checked then
  244. begin
  245. Renderer := TPolygonRenderer32VPR.Create(PaintBox32.Buffer);
  246. try
  247. Delaunay := TGourandShadedDelaunayTrianglesSampler.Create;
  248. try
  249. Renderer.FillMode := pfWinding;
  250. Renderer.Filler := TSamplerFiller.Create(Delaunay);
  251. Delaunay.SetColorPoints(FColorPoints);
  252. Renderer.PolygonFS(Points);
  253. finally
  254. Delaunay.Free;
  255. end;
  256. finally
  257. Renderer.Free;
  258. end;
  259. end;
  260. with PaintBox32.Buffer do
  261. for Index := 0 to High(FColorPoints) do
  262. with FColorPoints[Index] do
  263. begin
  264. if Index = FSelected then
  265. FrameColor := clWhite32
  266. else
  267. FrameColor := clBlack32;
  268. FillRectS(Round(Point.X - 4), Round(Point.Y - 4), Round(Point.X + 4),
  269. Round(Point.Y + 4), Color32);
  270. FrameRectTS(Round(Point.X - 5), Round(Point.Y - 5), Round(Point.X + 5),
  271. Round(Point.Y + 5), FrameColor);
  272. end;
  273. end;
  274. procedure TFrmMeshGradients.SelectedChanged;
  275. begin
  276. LblVertexColor.Visible := FSelected >= 0;
  277. VertexColorShape.Visible := FSelected >= 0;
  278. if FSelected >= 0 then
  279. VertexColorShape.Brush.Color := WinColor(FColorPoints[FSelected].Color32);
  280. end;
  281. procedure TFrmMeshGradients.SetSelected(const Value: Integer);
  282. begin
  283. if FSelected <> Value then
  284. begin
  285. FSelected := Value;
  286. SelectedChanged;
  287. end;
  288. end;
  289. procedure TFrmMeshGradients.VertexColorShapeMouseDown(Sender: TObject;
  290. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  291. begin
  292. if Button = mbLeft then
  293. SelectVertexColorClick(Sender);
  294. end;
  295. procedure TFrmMeshGradients.BtnRecallClick(Sender: TObject);
  296. begin
  297. if Length(FColorPoints) > 0 then
  298. begin
  299. FColorPoints := Copy(FClipboard, 0, Length(FColorPoints));
  300. PaintBox32.Invalidate;
  301. end;
  302. end;
  303. procedure TFrmMeshGradients.BtnStoreClick(Sender: TObject);
  304. begin
  305. FClipboard := Copy(FColorPoints, 0, Length(FColorPoints));
  306. PaintBox32.Invalidate;
  307. BtnRecall.Enabled := True;
  308. end;
  309. procedure TFrmMeshGradients.CbxAdaptiveSuperSamplerClick(Sender: TObject);
  310. begin
  311. PaintBox32.Invalidate;
  312. end;
  313. procedure TFrmMeshGradients.CbxColoredPolygonsClick(Sender: TObject);
  314. begin
  315. PaintBox32.Invalidate;
  316. end;
  317. procedure TFrmMeshGradients.CmbBackgroundSamplerChange(Sender: TObject);
  318. begin
  319. LblPower.Visible := CmbBackgroundSampler.ItemIndex = 4;
  320. GbrPower.Visible := LblPower.Visible;
  321. PaintBox32.Invalidate;
  322. end;
  323. end.