fSubdivideD.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. unit fSubdivideD;
  2. interface
  3. uses
  4. System.SysUtils,
  5. System.Classes,
  6. Vcl.Graphics,
  7. Vcl.Controls,
  8. Vcl.Forms,
  9. Vcl.Dialogs,
  10. Vcl.StdCtrls,
  11. Vcl.ComCtrls,
  12. Vcl.ExtCtrls,
  13. GLS.Scene,
  14. GLS.VectorFileObjects,
  15. GLS.PersistentClasses,
  16. GLS.Objects,
  17. GLS.Texture,
  18. GLS.SceneViewer,
  19. GLS.MeshUtils,
  20. GLScene.VectorGeometry,
  21. GLS.VectorLists,
  22. GLS.Cadencer,
  23. GLS.Material,
  24. GLS.Coordinates,
  25. GLS.State,
  26. GLS.BaseClasses,
  27. GLScene.Utils,
  28. GLS.File3DS,
  29. GLS.FileMD2,
  30. GLS.FileSMD;
  31. type
  32. TFormSubdivide = class(TForm)
  33. GLScene1: TGLScene;
  34. GLSceneViewer1: TGLSceneViewer;
  35. GLCamera1: TGLCamera;
  36. GLMaterialLibrary1: TGLMaterialLibrary;
  37. Timer1: TTimer;
  38. GLCadencer1: TGLCadencer;
  39. Panel1: TPanel;
  40. BULoad: TButton;
  41. BUSubdivide: TButton;
  42. TrackBar1: TTrackBar;
  43. RBWireFrame: TRadioButton;
  44. RBSolid: TRadioButton;
  45. CBAnimate: TCheckBox;
  46. GLActor1: TGLActor;
  47. Label1: TLabel;
  48. LASubdivideTime: TLabel;
  49. GLLightSource1: TGLLightSource;
  50. procedure BULoadClick(Sender: TObject);
  51. procedure GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
  52. X, Y: Integer);
  53. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  54. procedure BUSubdivideClick(Sender: TObject);
  55. procedure Timer1Timer(Sender: TObject);
  56. procedure GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
  57. procedure RBWireFrameClick(Sender: TObject);
  58. procedure RBSolidClick(Sender: TObject);
  59. procedure CBAnimateClick(Sender: TObject);
  60. public
  61. mx, my: Integer;
  62. end;
  63. var
  64. FormSubdivide: TFormSubdivide;
  65. implementation
  66. {$R *.dfm}
  67. procedure TFormSubdivide.BULoadClick(Sender: TObject);
  68. begin
  69. var Path: TFileName := GetCurrentAssetPath();
  70. SetCurrentDir(Path + '\modelext');
  71. BUSubdivide.Enabled := True;
  72. // GLFreeForm1.LoadFromFile('polyhedron.3ds');
  73. // GLFreeForm1.LoadFromFile('mushroom.3ds');
  74. // GLFreeForm1.LoadFromFile('trinityrage.smd');
  75. // GLFreeForm1.LoadFromFile('HighPolyObject.3ds');
  76. (*
  77. GLActor1.LoadFromFile('trinityrage.smd');
  78. GLActor1.AddDataFromFile('run.smd');
  79. GLActor1.Animations[1].MakeSkeletalTranslationStatic;
  80. GLActor1.SwitchToAnimation(GLActor1.Animations[1]);
  81. *)
  82. GLActor1.LoadFromFile('waste.md2');
  83. GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');
  84. GLActor1.Material.Texture.Enabled := True;
  85. GLActor1.SwitchToAnimation(GLActor1.Animations[0]);
  86. CBAnimateClick(Self);
  87. end;
  88. procedure TFormSubdivide.BUSubdivideClick(Sender: TObject);
  89. var
  90. i, j: Integer;
  91. tris, norms, tex, buf, morphTris, morphNorms: TGLAffineVectorList;
  92. indices, texIndices: TGLIntegerList;
  93. firstRemap, subdivideRemap, bufRemap: TGLIntegerList;
  94. t: Int64;
  95. begin
  96. BUSubdivide.Enabled := False;
  97. Screen.Cursor := crHourGlass;
  98. t := StartPrecisionTimer;
  99. for i := 0 to GLActor1.MeshObjects.Count - 1 do
  100. begin
  101. tex := TGLAffineVectorList.Create;
  102. with GLActor1.MeshObjects[i] do
  103. tris := ExtractTriangles(tex);
  104. indices := BuildVectorCountOptimizedIndices(tris);
  105. firstRemap := TGLIntegerList(indices.CreateClone);
  106. RemapAndCleanupReferences(tris, indices);
  107. norms := BuildNormals(tris, indices);
  108. // subdivide geometry
  109. SubdivideTriangles(TrackBar1.Position * 0.1, tris, indices, norms);
  110. texIndices := BuildVectorCountOptimizedIndices(tex);
  111. RemapAndCleanupReferences(tex, texIndices);
  112. // subdivide texture space
  113. SubdivideTriangles(0, tex, texIndices);
  114. // Re-expand everything
  115. buf := TGLAffineVectorList.Create;
  116. try
  117. ConvertIndexedListToList(tris, indices, buf);
  118. tris.Assign(buf);
  119. buf.Count := 0;
  120. ConvertIndexedListToList(norms, indices, buf);
  121. norms.Assign(buf);
  122. buf.Count := 0;
  123. ConvertIndexedListToList(tex, texIndices, buf);
  124. tex.Assign(buf);
  125. finally
  126. buf.Free;
  127. end;
  128. // Pack & Optimize the expanded stuff
  129. indices.Free;
  130. indices := BuildVectorCountOptimizedIndices(tris, norms, tex);
  131. subdivideRemap := TGLIntegerList(indices.CreateClone);
  132. RemapReferences(norms, indices);
  133. RemapReferences(tex, indices);
  134. RemapAndCleanupReferences(tris, indices);
  135. IncreaseCoherency(indices, 13);
  136. with GLActor1.MeshObjects[i] as TGLMorphableMeshObject do
  137. begin
  138. bufRemap := TGLIntegerList.Create;
  139. for j := 0 to MorphTargets.Count - 1 do
  140. begin
  141. MorphTo(j);
  142. morphTris := ExtractTriangles;
  143. bufRemap.Assign(firstRemap);
  144. RemapAndCleanupReferences(morphTris, bufRemap);
  145. morphNorms := GLS.MeshUtils.BuildNormals(morphTris, bufRemap);
  146. SubdivideTriangles(TrackBar1.Position * 0.1, morphTris, bufRemap, morphNorms);
  147. buf := TGLAffineVectorList.Create;
  148. try
  149. ConvertIndexedListToList(morphTris, bufRemap, buf);
  150. morphTris.Assign(buf);
  151. ConvertIndexedListToList(morphNorms, bufRemap, buf);
  152. morphNorms.Assign(buf);
  153. finally
  154. buf.Free;
  155. end;
  156. RemapReferences(morphTris, subdivideRemap);
  157. RemapReferences(morphNorms, subdivideRemap);
  158. MorphTargets[j].Vertices := morphTris;
  159. MorphTargets[j].Normals := morphNorms;
  160. morphTris.Free;
  161. morphNorms.Free;
  162. end;
  163. bufRemap.Free;
  164. Vertices := tris;
  165. Normals := norms;
  166. TexCoords := tex;
  167. FaceGroups.Clear;
  168. with TFGVertexIndexList.CreateOwned(FaceGroups) do
  169. begin
  170. VertexIndices := indices;
  171. Mode := fgmmTriangles;
  172. end;
  173. end;
  174. texIndices.Free;
  175. subdivideRemap.Free;
  176. firstRemap.Free;
  177. tex.Free;
  178. indices.Free;
  179. norms.Free;
  180. tris.Free;
  181. end;
  182. // (GLActor1.MeshObjects[0] as TGLSkeletonMeshObject).PrepareBoneMatrixInvertedMeshes;
  183. LASubdivideTime.Caption := Format('%.1f ms', [StopPrecisionTimer(t) * 1000]);
  184. // Initial perf: 1412 ms
  185. // Basic Edges Hash: 464 ms
  186. // Several transfer optims: 377 ms
  187. // morph & subdivide normals too : 527 ms
  188. Screen.Cursor := crDefault;
  189. GLActor1.StructureChanged;
  190. end;
  191. procedure TFormSubdivide.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  192. Shift: TShiftState; X, Y: Integer);
  193. begin
  194. mx := X;
  195. my := Y;
  196. end;
  197. procedure TFormSubdivide.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  198. X, Y: Integer);
  199. begin
  200. if Shift = [ssLeft] then
  201. begin
  202. GLCamera1.MoveAroundTarget(my - Y, mx - X);
  203. end
  204. else if Shift = [ssRight] then
  205. begin
  206. GLCamera1.RotateTarget(my - Y, mx - X);
  207. end;
  208. mx := X;
  209. my := Y;
  210. end;
  211. procedure TFormSubdivide.RBWireFrameClick(Sender: TObject);
  212. begin
  213. GLActor1.Material.PolygonMode := pmLines;
  214. end;
  215. procedure TFormSubdivide.RBSolidClick(Sender: TObject);
  216. begin
  217. GLActor1.Material.PolygonMode := pmFill;
  218. end;
  219. procedure TFormSubdivide.Timer1Timer(Sender: TObject);
  220. begin
  221. Caption := Format('%.1f FPS - %d Triangles', [GLSceneViewer1.FramesPerSecond,
  222. GLActor1.MeshObjects.TriangleCount]);
  223. GLSceneViewer1.ResetPerformanceMonitor;
  224. end;
  225. procedure TFormSubdivide.GLCadencer1Progress(Sender: TObject; const deltaTime, newTime: Double);
  226. begin
  227. GLSceneViewer1.Invalidate;
  228. end;
  229. procedure TFormSubdivide.CBAnimateClick(Sender: TObject);
  230. begin
  231. // not only turns on/off animation, but also forces the TGLActor
  232. // to generate a display list when animation is off
  233. if CBAnimate.Checked then
  234. begin
  235. GLActor1.AnimationMode := aamLoop;
  236. GLActor1.ObjectStyle := GLActor1.ObjectStyle + [osDirectDraw];
  237. GLActor1.Reference := aarMorph;
  238. end
  239. else
  240. begin
  241. GLActor1.AnimationMode := aamNone;
  242. GLActor1.MeshObjects.MorphTo(0);
  243. GLActor1.Reference := aarNone;
  244. GLActor1.StructureChanged;
  245. GLActor1.ObjectStyle := GLActor1.ObjectStyle - [osDirectDraw];
  246. end;
  247. end;
  248. end.