GLX.BaseMeshSilhouette.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. //
  2. // The graphics platform GLXcene https://github.com/glscene
  3. //
  4. unit GLX.BaseMeshSilhouette;
  5. (* Silhouette classes for BaseMesh and FaceGroups *)
  6. interface
  7. {$I Scene.inc}
  8. uses
  9. System.Classes,
  10. GLX.VectorGeometry,
  11. GLX.VectorLists,
  12. GLX.VectorFileObjects,
  13. GLX.Silhouette;
  14. type
  15. TgxFaceGroupConnectivity = class(TConnectivity)
  16. private
  17. FMeshObject: TgxMeshObject;
  18. FOwnsVertices: boolean;
  19. procedure SetMeshObject(const Value: TgxMeshObject);
  20. public
  21. procedure Clear; override;
  22. // Builds the connectivity information.
  23. procedure RebuildEdgeList;
  24. property MeshObject: TgxMeshObject read FMeshObject write SetMeshObject;
  25. constructor Create(APrecomputeFaceNormal: boolean); override;
  26. constructor CreateFromMesh(aMeshObject: TgxMeshObject; APrecomputeFaceNormal: boolean);
  27. destructor Destroy; override;
  28. end;
  29. TgxBaseMeshConnectivity = class(TBaseConnectivity)
  30. private
  31. FBaseMesh: TgxBaseMesh;
  32. FFaceGroupConnectivityList: TList;
  33. function GetFaceGroupConnectivity(i: integer): TgxFaceGroupConnectivity;
  34. function GetConnectivityCount: integer;
  35. procedure SetBaseMesh(const Value: TgxBaseMesh);
  36. protected
  37. function GetEdgeCount: integer; override;
  38. function GetFaceCount: integer; override;
  39. public
  40. property ConnectivityCount: integer read GetConnectivityCount;
  41. property FaceGroupConnectivity[i: integer]: TgxFaceGroupConnectivity read GetFaceGroupConnectivity;
  42. property BaseMesh: TgxBaseMesh read FBaseMesh write SetBaseMesh;
  43. procedure Clear(SaveFaceGroupConnectivity: boolean);
  44. // Builds the connectivity information.
  45. procedure RebuildEdgeList;
  46. procedure CreateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters; var aSilhouette: TgxSilhouette;
  47. AddToSilhouette: boolean);
  48. constructor Create(APrecomputeFaceNormal: boolean); override;
  49. constructor CreateFromMesh(aBaseMesh: TgxBaseMesh);
  50. destructor Destroy; override;
  51. end;
  52. //==================================================================
  53. implementation
  54. //==================================================================
  55. // ------------------
  56. // ------------------ TgxFaceGroupConnectivity ------------------
  57. // ------------------
  58. procedure TgxFaceGroupConnectivity.Clear;
  59. begin
  60. if Assigned(FVertices) then
  61. begin
  62. if FOwnsVertices then
  63. FVertices.Clear
  64. else
  65. FVertices := nil;
  66. inherited;
  67. if not FOwnsVertices and Assigned(FMeshObject) then
  68. FVertices := FMeshObject.Vertices;
  69. end
  70. else
  71. inherited;
  72. end;
  73. constructor TgxFaceGroupConnectivity.Create(APrecomputeFaceNormal: boolean);
  74. begin
  75. inherited;
  76. FOwnsVertices := true;
  77. end;
  78. procedure TgxFaceGroupConnectivity.SetMeshObject(const Value: TgxMeshObject);
  79. begin
  80. Clear;
  81. FMeshObject := Value;
  82. if FOwnsVertices then
  83. FVertices.Free;
  84. FVertices := FMeshObject.Vertices;
  85. FOwnsVertices := false;
  86. RebuildEdgeList;
  87. end;
  88. constructor TgxFaceGroupConnectivity.CreateFromMesh(aMeshObject: TgxMeshObject; APrecomputeFaceNormal: boolean);
  89. begin
  90. Create(APrecomputeFaceNormal);
  91. MeshObject := aMeshObject;
  92. end;
  93. destructor TgxFaceGroupConnectivity.Destroy;
  94. begin
  95. if FOwnsVertices then
  96. FVertices.Free;
  97. FVertices := nil;
  98. inherited;
  99. end;
  100. procedure TgxFaceGroupConnectivity.RebuildEdgeList;
  101. var
  102. iFaceGroup, iFace, iVertex: integer;
  103. FaceGroup: TfgxVertexIndexList;
  104. List: PIntegerArray;
  105. begin
  106. // Make sure that the connectivity information is empty
  107. Clear;
  108. // Create a list of edges for the meshobject
  109. for iFaceGroup := 0 to FMeshObject.FaceGroups.Count - 1 do
  110. begin
  111. Assert(FMeshObject.FaceGroups[iFaceGroup] is TfgxVertexIndexList, 'Method only works for descendants of TfgxVertexIndexList.');
  112. FaceGroup := TfgxVertexIndexList(FMeshObject.FaceGroups[iFaceGroup]);
  113. case FaceGroup.Mode of
  114. fgmmTriangles, fgmmFlatTriangles:
  115. begin
  116. for iFace := 0 to FaceGroup.TriangleCount - 1 do
  117. begin
  118. List := @FaceGroup.VertexIndices.List[iFace * 3 + 0];
  119. AddIndexedFace(List^[0], List^[1], List^[2]);
  120. end;
  121. end;
  122. fgmmTriangleStrip:
  123. begin
  124. for iFace := 0 to FaceGroup.VertexIndices.Count - 3 do
  125. begin
  126. List := @FaceGroup.VertexIndices.List[iFace];
  127. if (iFace and 1) = 0 then
  128. AddIndexedFace(List^[0], List^[1], List^[2])
  129. else
  130. AddIndexedFace(List^[2], List^[1], List^[0]);
  131. end;
  132. end;
  133. fgmmTriangleFan:
  134. begin
  135. List := FaceGroup.VertexIndices.List;
  136. for iVertex := 2 to FaceGroup.VertexIndices.Count - 1 do
  137. AddIndexedFace(List^[0], List^[iVertex - 1], List^[iVertex])
  138. end;
  139. else
  140. Assert(false, 'Not supported');
  141. end;
  142. end;
  143. end;
  144. // ------------------
  145. // ------------------ TgxBaseMeshConnectivity ------------------
  146. // ------------------
  147. procedure TgxBaseMeshConnectivity.RebuildEdgeList;
  148. var
  149. i: integer;
  150. begin
  151. for i := 0 to ConnectivityCount - 1 do
  152. FaceGroupConnectivity[i].RebuildEdgeList;
  153. end;
  154. procedure TgxBaseMeshConnectivity.Clear(SaveFaceGroupConnectivity: boolean);
  155. var
  156. i: integer;
  157. begin
  158. if SaveFaceGroupConnectivity then
  159. begin
  160. for i := 0 to ConnectivityCount - 1 do
  161. FaceGroupConnectivity[i].Clear;
  162. end
  163. else
  164. begin
  165. for i := 0 to ConnectivityCount - 1 do
  166. FaceGroupConnectivity[i].Free;
  167. FFaceGroupConnectivityList.Clear;
  168. end;
  169. end;
  170. constructor TgxBaseMeshConnectivity.Create(APrecomputeFaceNormal: boolean);
  171. begin
  172. FFaceGroupConnectivityList := TList.Create;
  173. inherited;
  174. end;
  175. constructor TgxBaseMeshConnectivity.CreateFromMesh(aBaseMesh: TgxBaseMesh);
  176. begin
  177. Create(not(aBaseMesh is TgxActor));
  178. BaseMesh := aBaseMesh;
  179. end;
  180. procedure TgxBaseMeshConnectivity.SetBaseMesh(const Value: TgxBaseMesh);
  181. var
  182. i: integer;
  183. MO: TgxMeshObject;
  184. Connectivity: TgxFaceGroupConnectivity;
  185. begin
  186. Clear(false);
  187. FBaseMesh := Value;
  188. // Only precompute normals if the basemesh isn't an actor (because they change)
  189. FPrecomputeFaceNormal := not(Value is TgxActor);
  190. FBaseMesh := Value;
  191. for i := 0 to Value.MeshObjects.Count - 1 do
  192. begin
  193. MO := Value.MeshObjects[i];
  194. if MO.Visible then
  195. begin
  196. Connectivity := TgxFaceGroupConnectivity.CreateFromMesh(MO, FPrecomputeFaceNormal);
  197. FFaceGroupConnectivityList.Add(Connectivity);
  198. end;
  199. end;
  200. end;
  201. procedure TgxBaseMeshConnectivity.CreateSilhouette(const SilhouetteParameters: TgxSilhouetteParameters; var aSilhouette: TgxSilhouette; AddToSilhouette: boolean);
  202. var
  203. i: integer;
  204. begin
  205. if aSilhouette = nil then
  206. aSilhouette := TgxSilhouette.Create
  207. else
  208. aSilhouette.Flush;
  209. for i := 0 to ConnectivityCount - 1 do
  210. FaceGroupConnectivity[i].CreateSilhouette(silhouetteParameters, aSilhouette, true);
  211. end;
  212. destructor TgxBaseMeshConnectivity.Destroy;
  213. begin
  214. Clear(false);
  215. FFaceGroupConnectivityList.Free;
  216. inherited;
  217. end;
  218. function TgxBaseMeshConnectivity.GetConnectivityCount: integer;
  219. begin
  220. result := FFaceGroupConnectivityList.Count;
  221. end;
  222. function TgxBaseMeshConnectivity.GetEdgeCount: integer;
  223. var
  224. i: integer;
  225. begin
  226. result := 0;
  227. for i := 0 to ConnectivityCount - 1 do
  228. result := result + FaceGroupConnectivity[i].EdgeCount;
  229. end;
  230. function TgxBaseMeshConnectivity.GetFaceCount: integer;
  231. var
  232. i: integer;
  233. begin
  234. result := 0;
  235. for i := 0 to ConnectivityCount - 1 do
  236. result := result + FaceGroupConnectivity[i].FaceCount;
  237. end;
  238. function TgxBaseMeshConnectivity.GetFaceGroupConnectivity(i: integer): TgxFaceGroupConnectivity;
  239. begin
  240. result := TgxFaceGroupConnectivity(FFaceGroupConnectivityList[i]);
  241. end;
  242. end.