2
0

GBE.Viewport3D.pas 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. unit GBE.Viewport3D;
  2. (*
  3. The TGBEViewport3D inherits from TViewport3D. It adds the ability to retrieve in TBitmap form the images
  4. from each of the cameras placed in the 3D scene. This then allows to display these images in other
  5. areas of the interface without having to duplicate the TViewport3D or the 3D scenes to calculate.
  6. Based on code by Gregory Bersegeay
  7. *)
  8. interface
  9. uses
  10. System.SysUtils,
  11. System.Classes,
  12. System.Generics.Collections,
  13. System.Types,
  14. System.Math.Vectors,
  15. System.DateUtils,
  16. System.UITypes,
  17. FMX.Types,
  18. FMX.Controls,
  19. FMX.Viewport3D,
  20. FMX.Graphics,
  21. FMX.Types3D,
  22. FMX.Controls3D,
  23. FMX.Layouts;
  24. type
  25. THelpOpenControl3D = class(TControl3D);
  26. TGBEViewport3D = class(TViewport3D)
  27. private
  28. FDrawing, fActiveFPS: boolean;
  29. fFPS, fComputeFPS: integer;
  30. FMyBitmap: TBitmap;
  31. FMyTexture: TTexture;
  32. fMyContext: TContext3D;
  33. fBackgroundColor: cardinal;
  34. protected
  35. FMyRenderingList: TList<TControl3D>; // List of 3D objects to display
  36. FMyViewList: TDictionary<TCamera, TBitmap>;
  37. // List of views (one view per camera)
  38. fheureDebut: TTime;
  39. procedure RebuildRenderingList;
  40. procedure Paint; override;
  41. procedure Resize; override;
  42. procedure DoAddObject(const AObject: TFmxObject); override;
  43. procedure DoRemoveObject(const AObject: TFmxObject); override;
  44. public
  45. constructor Create(AOwner: TComponent); override;
  46. destructor Destroy; override;
  47. function getBitmapFromView(camera: TCamera): TBitmap;
  48. procedure DoAddView(camera: TCamera);
  49. procedure DoRemoveView(camera: TCamera);
  50. procedure DoClearListView;
  51. property MyContext: TContext3D read fMyContext write fMyContext;
  52. property BackgroundColor: cardinal read fBackgroundColor
  53. write fBackgroundColor;
  54. published
  55. property ActiveFPS: boolean read fActiveFPS write fActiveFPS;
  56. property FPS: integer read fFPS;
  57. end;
  58. procedure Register;
  59. implementation // --------------------------------------------------------------
  60. // TGBEViewport3D1
  61. constructor TGBEViewport3D.Create(AOwner: TComponent);
  62. begin
  63. inherited;
  64. FMyViewList := TDictionary<TCamera, TBitmap>.Create;
  65. BackgroundColor := TAlphaColorRec.Null;
  66. fFPS := 0;
  67. fComputeFPS := 0;
  68. fActiveFPS := false;
  69. fheureDebut := now;
  70. end;
  71. destructor TGBEViewport3D.Destroy;
  72. begin
  73. FreeAndNil(fMyContext);
  74. FreeAndNil(FMyBitmap);
  75. FreeAndNil(FMyTexture);
  76. FreeAndNil(FMyRenderingList);
  77. FreeAndNil(FMyViewList);
  78. inherited;
  79. end;
  80. procedure TGBEViewport3D.DoAddView(camera: TCamera);
  81. begin
  82. FMyViewList.Add(camera, TBitmap.Create);
  83. end;
  84. procedure TGBEViewport3D.DoAddObject(const AObject: TFmxObject);
  85. begin
  86. inherited;
  87. if AObject is TControl3D then
  88. RebuildRenderingList;
  89. end;
  90. procedure TGBEViewport3D.DoRemoveView(camera: TCamera);
  91. begin
  92. FMyViewList.Remove(camera);
  93. end;
  94. procedure TGBEViewport3D.DoClearListView;
  95. begin
  96. FMyViewList.Clear;
  97. end;
  98. function TGBEViewport3D.getBitmapFromView(camera: TCamera): TBitmap;
  99. begin
  100. result := TBitmap.Create;
  101. if not(FDrawing) then
  102. FMyViewList.TryGetValue(camera, result);
  103. end;
  104. procedure TGBEViewport3D.DoRemoveObject(const AObject: TFmxObject);
  105. begin
  106. inherited;
  107. if AObject is TControl3D then
  108. begin
  109. RebuildRenderingList;
  110. Repaint;
  111. end;
  112. end;
  113. procedure TGBEViewport3D.Paint;
  114. var
  115. i: integer;
  116. Control: TControl3D;
  117. New: TMatrix3D;
  118. theCamera: TCamera;
  119. duree: int64;
  120. begin
  121. inherited;
  122. if FDrawing then
  123. exit;
  124. FDrawing := true;
  125. try
  126. if fActiveFPS then
  127. begin
  128. inc(fComputeFPS);
  129. duree := SecondsBetween(now, fheureDebut);
  130. if duree > 0 then
  131. begin
  132. fFPS := fComputeFPS div duree;
  133. fComputeFPS := 0;
  134. fheureDebut := now;
  135. end;
  136. end;
  137. for theCamera in FMyViewList.Keys do
  138. begin
  139. if Assigned(fMyContext) then
  140. begin
  141. if fMyContext.BeginScene then
  142. begin
  143. try
  144. New := theCamera.CameraMatrix;
  145. fMyContext.Clear([TClearTarget.Color, TClearTarget.Depth],
  146. BackgroundColor, 1.0, 0);
  147. fMyContext.SetCameraMatrix(theCamera.CameraMatrix);
  148. if Assigned(FMyRenderingList) and (FMyRenderingList.Count > 0) then
  149. begin
  150. for i := 0 to FMyRenderingList.Count - 1 do
  151. begin
  152. if FMyRenderingList[i].Visible or (FMyRenderingList[i].Tag <> 2)
  153. or (not FMyRenderingList[i].Visible and
  154. (csDesigning in ComponentState) and not FMyRenderingList[i]
  155. .Locked) then
  156. begin
  157. Control := TControl3D(FMyRenderingList[i]);
  158. Control.Context.SetCameraMatrix(New);
  159. if (csDesigning in ComponentState) and (not Control.Visible)
  160. then
  161. continue;
  162. THelpOpenControl3D(Control).RenderInternal;
  163. end;
  164. end;
  165. end;
  166. finally
  167. fMyContext.EndScene;
  168. end;
  169. end;
  170. end;
  171. fMyContext.CopyToBitmap(FMyBitmap, Rect(0, 0, FMyBitmap.Width,
  172. FMyBitmap.Height));
  173. FMyViewList.Items[theCamera].Width := FMyBitmap.Width;
  174. FMyViewList.Items[theCamera].Height := FMyBitmap.Height;
  175. FMyViewList.Items[theCamera].CopyFromBitmap(FMyBitmap);
  176. end;
  177. finally
  178. FDrawing := false;
  179. end;
  180. end;
  181. procedure TGBEViewport3D.RebuildRenderingList;
  182. var
  183. i: integer;
  184. begin
  185. if Assigned(children) and (FUpdating = 0) then
  186. begin
  187. if not Assigned(FMyRenderingList) then
  188. FMyRenderingList := TList<TControl3D>.Create;
  189. FMyRenderingList.Clear;
  190. for i := 0 to children.Count - 1 do
  191. begin
  192. if children[i] is TControl3D then
  193. begin
  194. FMyRenderingList.Add((children[i] as TControl3D));
  195. end;
  196. end;
  197. end;
  198. end;
  199. procedure TGBEViewport3D.Resize;
  200. begin
  201. inherited;
  202. FreeAndNil(FMyBitmap);
  203. FreeAndNil(FMyTexture);
  204. FreeAndNil(fMyContext);
  205. FMyTexture := TTexture.Create;
  206. FMyTexture.Style := [TTextureStyle.RenderTarget];
  207. FMyTexture.SetSize(Round(Width), Round(Height));
  208. fMyContext := TContextManager.CreateFromTexture(FMyTexture,
  209. TMultisample.FourSamples, true);
  210. FMyBitmap := TBitmap.Create; // old TBitmap.Create(fMyContext.Width, fMyContext.Height);
  211. end;
  212. // ----------------------------------------------------------------------------
  213. procedure Register;
  214. begin
  215. RegisterComponents('GXScene GBE', [TGBEViewport3D]);
  216. end;
  217. end.