GXS.BaseMeshSilhouette.pas 7.7 KB

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