2
0

fSubdivide.pas 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. unit fSubdivide;
  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. GLS.VectorGeometry,
  21. GLS.VectorLists,
  22. GLS.Cadencer,
  23. GLS.Material,
  24. GLS.Coordinates,
  25. GLS.State,
  26. GLS.BaseClasses,
  27. GLS.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;
  52. Shift: TShiftState; X, Y: Integer);
  53. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  54. X, Y: Integer);
  55. procedure BUSubdivideClick(Sender: TObject);
  56. procedure Timer1Timer(Sender: TObject);
  57. procedure GLCadencer1Progress(Sender: TObject;
  58. const deltaTime, newTime: Double);
  59. procedure RBWireFrameClick(Sender: TObject);
  60. procedure RBSolidClick(Sender: TObject);
  61. procedure CBAnimateClick(Sender: TObject);
  62. public
  63. mx, my: Integer;
  64. end;
  65. var
  66. FormSubdivide: TFormSubdivide;
  67. implementation
  68. {$R *.dfm}
  69. procedure TFormSubdivide.BULoadClick(Sender: TObject);
  70. begin
  71. SetGLSceneMediaDir();
  72. BUSubdivide.Enabled := True;
  73. // GLFreeForm1.LoadFromFile('polyhedron.3ds');
  74. // GLFreeForm1.LoadFromFile('mushroom.3ds');
  75. // GLFreeForm1.LoadFromFile('trinityrage.smd');
  76. // GLFreeForm1.LoadFromFile('HighPolyObject.3ds');
  77. {
  78. GLActor1.LoadFromFile('trinityrage.smd');
  79. GLActor1.AddDataFromFile('run.smd');
  80. GLActor1.Animations[1].MakeSkeletalTranslationStatic;
  81. GLActor1.SwitchToAnimation(GLActor1.Animations[1]);
  82. }
  83. GLActor1.LoadFromFile('waste.md2');
  84. GLActor1.Material.Texture.Image.LoadFromFile('waste.jpg');
  85. GLActor1.Material.Texture.Enabled := True;
  86. GLActor1.SwitchToAnimation(GLActor1.Animations[0]);
  87. CBAnimateClick(Self);
  88. end;
  89. procedure TFormSubdivide.BUSubdivideClick(Sender: TObject);
  90. var
  91. i, j: Integer;
  92. tris, norms, tex, buf, morphTris, morphNorms: TAffineVectorList;
  93. indices, texIndices: TIntegerlist;
  94. firstRemap, subdivideRemap, bufRemap: TIntegerlist;
  95. t: Int64;
  96. begin
  97. BUSubdivide.Enabled := False;
  98. Screen.Cursor := crHourGlass;
  99. t := StartPrecisionTimer;
  100. for i := 0 to GLActor1.MeshObjects.Count - 1 do
  101. begin
  102. tex := TAffineVectorList.Create;
  103. with GLActor1.MeshObjects[i] do
  104. tris := ExtractTriangles(tex);
  105. indices := BuildVectorCountOptimizedIndices(tris);
  106. firstRemap := TIntegerlist(indices.CreateClone);
  107. RemapAndCleanupReferences(tris, indices);
  108. norms := BuildNormals(tris, indices);
  109. // subdivide geometry
  110. SubdivideTriangles(TrackBar1.Position * 0.1, tris, indices, norms);
  111. texIndices := BuildVectorCountOptimizedIndices(tex);
  112. RemapAndCleanupReferences(tex, texIndices);
  113. // subdivide texture space
  114. SubdivideTriangles(0, tex, texIndices);
  115. // Re-expand everything
  116. buf := TAffineVectorList.Create;
  117. try
  118. ConvertIndexedListToList(tris, indices, buf);
  119. tris.Assign(buf);
  120. buf.Count := 0;
  121. ConvertIndexedListToList(norms, indices, buf);
  122. norms.Assign(buf);
  123. buf.Count := 0;
  124. ConvertIndexedListToList(tex, texIndices, buf);
  125. tex.Assign(buf);
  126. finally
  127. buf.Free;
  128. end;
  129. // Pack & Optimize the expanded stuff
  130. indices.Free;
  131. indices := BuildVectorCountOptimizedIndices(tris, norms, tex);
  132. subdivideRemap := TIntegerlist(indices.CreateClone);
  133. RemapReferences(norms, indices);
  134. RemapReferences(tex, indices);
  135. RemapAndCleanupReferences(tris, indices);
  136. IncreaseCoherency(indices, 13);
  137. with GLActor1.MeshObjects[i] as TGLMorphableMeshObject do
  138. begin
  139. bufRemap := TIntegerlist.Create;
  140. for j := 0 to MorphTargets.Count - 1 do
  141. begin
  142. MorphTo(j);
  143. morphTris := ExtractTriangles;
  144. bufRemap.Assign(firstRemap);
  145. RemapAndCleanupReferences(morphTris, bufRemap);
  146. morphNorms := GLS.MeshUtils.BuildNormals(morphTris, bufRemap);
  147. SubdivideTriangles(TrackBar1.Position * 0.1, morphTris, bufRemap,
  148. morphNorms);
  149. buf := TAffineVectorList.Create;
  150. try
  151. ConvertIndexedListToList(morphTris, bufRemap, buf);
  152. morphTris.Assign(buf);
  153. ConvertIndexedListToList(morphNorms, bufRemap, buf);
  154. morphNorms.Assign(buf);
  155. finally
  156. buf.Free;
  157. end;
  158. RemapReferences(morphTris, subdivideRemap);
  159. RemapReferences(morphNorms, subdivideRemap);
  160. MorphTargets[j].Vertices := morphTris;
  161. MorphTargets[j].Normals := morphNorms;
  162. morphTris.Free;
  163. morphNorms.Free;
  164. end;
  165. bufRemap.Free;
  166. Vertices := tris;
  167. Normals := norms;
  168. TexCoords := tex;
  169. FaceGroups.Clear;
  170. with TFGVertexIndexList.CreateOwned(FaceGroups) do
  171. begin
  172. VertexIndices := indices;
  173. Mode := fgmmTriangles;
  174. end;
  175. end;
  176. texIndices.Free;
  177. subdivideRemap.Free;
  178. firstRemap.Free;
  179. tex.Free;
  180. indices.Free;
  181. norms.Free;
  182. tris.Free;
  183. end;
  184. // (GLActor1.MeshObjects[0] as TGLSkeletonMeshObject).PrepareBoneMatrixInvertedMeshes;
  185. LASubdivideTime.Caption := Format('%.1f ms', [StopPrecisionTimer(t) * 1000]);
  186. // Initial perf: 1412 ms
  187. // Basic Edges Hash: 464 ms
  188. // Several transfer optims: 377 ms
  189. // morph & subdivide normals too : 527 ms
  190. Screen.Cursor := crDefault;
  191. GLActor1.StructureChanged;
  192. end;
  193. procedure TFormSubdivide.GLSceneViewer1MouseDown(Sender: TObject; Button: TMouseButton;
  194. Shift: TShiftState; X, Y: Integer);
  195. begin
  196. mx := X;
  197. my := Y;
  198. end;
  199. procedure TFormSubdivide.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  200. X, Y: Integer);
  201. begin
  202. if Shift = [ssLeft] then
  203. begin
  204. GLCamera1.MoveAroundTarget(my - Y, mx - X);
  205. end
  206. else if Shift = [ssRight] then
  207. begin
  208. GLCamera1.RotateTarget(my - Y, mx - X);
  209. end;
  210. mx := X;
  211. my := Y;
  212. end;
  213. procedure TFormSubdivide.RBWireFrameClick(Sender: TObject);
  214. begin
  215. GLActor1.Material.PolygonMode := pmLines;
  216. end;
  217. procedure TFormSubdivide.RBSolidClick(Sender: TObject);
  218. begin
  219. GLActor1.Material.PolygonMode := pmFill;
  220. end;
  221. procedure TFormSubdivide.Timer1Timer(Sender: TObject);
  222. begin
  223. Caption := Format('%.1f FPS - %d Triangles', [GLSceneViewer1.FramesPerSecond,
  224. GLActor1.MeshObjects.TriangleCount]);
  225. GLSceneViewer1.ResetPerformanceMonitor;
  226. end;
  227. procedure TFormSubdivide.GLCadencer1Progress(Sender: TObject;
  228. const deltaTime, newTime: Double);
  229. begin
  230. GLSceneViewer1.Invalidate;
  231. end;
  232. procedure TFormSubdivide.CBAnimateClick(Sender: TObject);
  233. begin
  234. // not only turns on/off animation, but also forces the TGLActor
  235. // to generate a display list when animation is off
  236. if CBAnimate.Checked then
  237. begin
  238. GLActor1.AnimationMode := aamLoop;
  239. GLActor1.ObjectStyle := GLActor1.ObjectStyle + [osDirectDraw];
  240. GLActor1.Reference := aarMorph;
  241. end
  242. else
  243. begin
  244. GLActor1.AnimationMode := aamNone;
  245. GLActor1.MeshObjects.MorphTo(0);
  246. GLActor1.Reference := aarNone;
  247. GLActor1.StructureChanged;
  248. GLActor1.ObjectStyle := GLActor1.ObjectStyle - [osDirectDraw];
  249. end;
  250. end;
  251. end.