fIntensityMeshD.pas 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. unit fIntensityMeshD;
  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.ComCtrls,
  13. Vcl.StdCtrls,
  14. Vcl.ExtCtrls,
  15. GLS.Scene,
  16. GLScene.VectorTypes,
  17. GLS.VectorFileObjects,
  18. GLS.VectorLists,
  19. GLS.SceneViewer,
  20. GLS.Mesh,
  21. GLS.Texture,
  22. GLSL.UserShader,
  23. GLS.HUDObjects,
  24. GLScene.VectorGeometry,
  25. GLS.Context,
  26. GLS.Objects,
  27. GLS.BitmapFont,
  28. GLS.WindowsFont,
  29. GLScene.Utils,
  30. GLS.Material,
  31. GLS.Coordinates,
  32. GLS.BaseClasses,
  33. GLS.RenderContextInfo,
  34. GLS.Graphics,
  35. GLS.State,
  36. GLS.TextureFormat;
  37. type
  38. TFormIntensutyMesh = class(TForm)
  39. GLScene1: TGLScene;
  40. GLSceneViewer1: TGLSceneViewer;
  41. GLCamera: TGLCamera;
  42. DCTarget: TGLDummyCube;
  43. GLFreeForm: TGLFreeForm;
  44. GLMaterialLibrary1: TGLMaterialLibrary;
  45. GLUserShader: TGLUserShader;
  46. HSPalette: TGLHUDSprite;
  47. GLWindowsBitmapFont: TGLWindowsBitmapFont;
  48. HTPaletteLeft: TGLHUDText;
  49. HTPaletteRight: TGLHUDText;
  50. Panel1: TPanel;
  51. CBWireFrame: TCheckBox;
  52. CBSmooth: TCheckBox;
  53. TBScale: TTrackBar;
  54. Label1: TLabel;
  55. procedure FormCreate(Sender: TObject);
  56. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  57. Shift: TShiftState; X, Y: Integer);
  58. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  59. X, Y: Integer);
  60. procedure GLUserShaderDoUnApply(Sender: TObject; Pass: Integer;
  61. var rci: TGLRenderContextInfo; var Continue: Boolean);
  62. procedure CBSmoothClick(Sender: TObject);
  63. procedure CBWireFrameClick(Sender: TObject);
  64. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  65. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  66. procedure TBScaleChange(Sender: TObject);
  67. private
  68. mx, my: Integer;
  69. public
  70. end;
  71. var
  72. FormIntensutyMesh: TFormIntensutyMesh;
  73. implementation
  74. {$R *.dfm}
  75. type
  76. // Structures used in our binary file
  77. // The structure is quite simplified here, original data came from a FEM
  78. // package and was in (huge) text files, and parsing text files is not the
  79. // purpose of this demo, so data was simplified ;)
  80. TDataNode = record
  81. X, Y, Z: Single;
  82. Intensity: Single;
  83. end;
  84. TDataPrimitive = record
  85. Node1, Node2, Node3, Node4: Word; // if Node4 is $FFFF, codes a triangle
  86. end;
  87. var
  88. DataNodes: array of TDataNode;
  89. DataPrimitives: array of TDataPrimitive;
  90. procedure TFormIntensutyMesh.FormCreate(Sender: TObject);
  91. var
  92. mo: TGLMeshObject;
  93. fgQuads, fgTris: TFGVertexIndexList;
  94. i: Integer;
  95. str: TFileStream;
  96. begin
  97. // load our raw data
  98. str := TFileStream.Create('IntensityMesh.data', fmOpenRead);
  99. str.Read(i, 4);
  100. SetLength(DataNodes, i);
  101. str.Read(i, 4);
  102. SetLength(DataPrimitives, i);
  103. str.Read(DataNodes[0], Length(DataNodes) * SizeOf(TDataNode));
  104. str.Read(DataPrimitives[0], Length(DataPrimitives) * SizeOf(TDataPrimitive));
  105. str.Free;
  106. // fill the freeform with our data
  107. // first create a mesh object
  108. mo := TGLMeshObject.CreateOwned(GLFreeForm.MeshObjects);
  109. mo.Mode := momFaceGroups;
  110. // Specify vertex and texcoords data (intensity is stored a texcoord)
  111. for i := 0 to High(DataNodes) do
  112. begin
  113. mo.Vertices.Add(DataNodes[i].X, DataNodes[i].Y, DataNodes[i].Z);
  114. mo.TexCoords.Add(DataNodes[i].Intensity * 0.001, 0);
  115. end;
  116. // Then create the facegroups that will hold our quads and triangles
  117. fgQuads := TFGVertexIndexList.CreateOwned(mo.FaceGroups);
  118. fgQuads.Mode := fgmmQuads;
  119. fgTris := TFGVertexIndexList.CreateOwned(mo.FaceGroups);
  120. fgTris.Mode := fgmmTriangles;
  121. // and fill them with our primitives
  122. for i := 1 to High(DataPrimitives) do
  123. with DataPrimitives[i] do
  124. begin
  125. if Node4 <> $FFFF then
  126. begin
  127. fgQuads.VertexIndices.Add(Node1, Node2);
  128. fgQuads.VertexIndices.Add(Node4, Node3);
  129. end
  130. else
  131. begin
  132. fgTris.VertexIndices.Add(Node1, Node2, Node3);
  133. end;
  134. end;
  135. // auto center
  136. GLFreeForm.PerformAutoCentering;
  137. // and initialize scale
  138. TBScaleChange(Self);
  139. end;
  140. procedure TFormIntensutyMesh.GLUserShaderDoUnApply(Sender: TObject; Pass: Integer;
  141. var rci: TGLRenderContextInfo; var Continue: Boolean);
  142. begin
  143. if not CBWireFrame.Checked then
  144. Pass := 2; // skip wireframe pass
  145. case Pass of
  146. 1:
  147. begin
  148. // 2nd pass is a wireframe pass (two-sided)
  149. rci.GLStates.ActiveTextureEnabled[ttTexture2D] := False;
  150. rci.GLStates.Enable(stLineSmooth);
  151. rci.GLStates.Enable(stBlend);
  152. rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  153. rci.GLStates.LineWidth := 0.5;
  154. rci.GLStates.PolygonMode := pmLines;
  155. rci.GLStates.PolygonOffsetFactor := -1;
  156. rci.GLStates.PolygonOffsetUnits := -1;
  157. rci.GLStates.Enable(stPolygonOffsetLine);
  158. gl.Color3f(0, 0, 0);
  159. Continue := True;
  160. end;
  161. else
  162. // restore states or mark them dirty
  163. if CBWireFrame.Checked then
  164. begin
  165. rci.GLStates.Disable(stPolygonOffsetLine);
  166. end;
  167. Continue := False;
  168. end;
  169. end;
  170. procedure TFormIntensutyMesh.CBSmoothClick(Sender: TObject);
  171. var
  172. tex: TGLTexture;
  173. begin
  174. // switch between linear and nearest filtering
  175. tex := GLMaterialLibrary1.Materials[0].Material.Texture;
  176. if CBSmooth.Checked then
  177. begin
  178. tex.MagFilter := maLinear;
  179. tex.MinFilter := miLinear;
  180. end
  181. else
  182. begin
  183. tex.MagFilter := maNearest;
  184. tex.MinFilter := miNearest;
  185. end;
  186. end;
  187. procedure TFormIntensutyMesh.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  188. Shift: TShiftState; X, Y: Integer);
  189. begin
  190. mx := X;
  191. my := Y;
  192. GLSceneViewer1.SetFocus;
  193. end;
  194. procedure TFormIntensutyMesh.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  195. X, Y: Integer);
  196. begin
  197. if ssLeft in Shift then
  198. GLCamera.MoveAroundTarget(my - Y, mx - X);
  199. if ssRight in Shift then
  200. begin
  201. DCTarget.Position.AddScaledVector((mx - X) / 30,
  202. GLCamera.AbsoluteRightVectorToTarget);
  203. DCTarget.Position.AddScaledVector((Y - my) / 30,
  204. GLCamera.AbsoluteUpVectorToTarget);
  205. end;
  206. mx := X;
  207. my := Y;
  208. end;
  209. procedure TFormIntensutyMesh.TBScaleChange(Sender: TObject);
  210. begin
  211. with GLMaterialLibrary1.Materials[0] do
  212. TextureScale.X := TBScale.Position / 100;
  213. HTPaletteRight.Text := Format('%d', [TBScale.Position * 10]);
  214. GLSceneViewer1.Invalidate;
  215. end;
  216. procedure TFormIntensutyMesh.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  217. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  218. begin
  219. GLCamera.AdjustDistanceToTarget(Power(1.03, WheelDelta / 120));
  220. end;
  221. procedure TFormIntensutyMesh.CBWireFrameClick(Sender: TObject);
  222. begin
  223. GLSceneViewer1.Invalidate;
  224. end;
  225. end.