MainUnit.pas 9.6 KB

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