GLS.BaseMeshSilhouette.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.BaseMeshSilhouette;
  5. (* Silhouette classes for GLBaseMesh and FaceGroups. *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. Stage.VectorGeometry,
  11. GLS.VectorLists,
  12. GLS.VectorFileObjects,
  13. GLS.Silhouette;
  14. type
  15. TGLFaceGroupConnectivity = class(TGLConnectivity)
  16. private
  17. FMeshObject: TGLMeshObject;
  18. FOwnsVertices: boolean;
  19. procedure SetMeshObject(const Value: TGLMeshObject);
  20. public
  21. procedure Clear; override;
  22. // Builds the connectivity information.
  23. procedure RebuildEdgeList;
  24. property MeshObject: TGLMeshObject read FMeshObject write SetMeshObject;
  25. constructor Create(APrecomputeFaceNormal: boolean); override;
  26. constructor CreateFromMesh(aMeshObject: TGLMeshObject; APrecomputeFaceNormal: boolean);
  27. destructor Destroy; override;
  28. end;
  29. TGLBaseMeshConnectivity = class(TGLBaseConnectivity)
  30. private
  31. FBaseMesh: TGLBaseMesh;
  32. FFaceGroupConnectivityList: TList;
  33. function GetFaceGroupConnectivity(i: integer): TGLFaceGroupConnectivity;
  34. function GetConnectivityCount: integer;
  35. procedure SetBaseMesh(const Value: TGLBaseMesh);
  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]: TGLFaceGroupConnectivity read GetFaceGroupConnectivity;
  42. property BaseMesh: TGLBaseMesh read FBaseMesh write SetBaseMesh;
  43. procedure Clear(SaveFaceGroupConnectivity: boolean);
  44. // Builds the connectivity information.
  45. procedure RebuildEdgeList;
  46. procedure CreateSilhouette(const silhouetteParameters: TGLSilhouetteParameters; var aSilhouette: TGLSilhouette;
  47. AddToSilhouette: boolean);
  48. constructor Create(APrecomputeFaceNormal: boolean); override;
  49. constructor CreateFromMesh(aBaseMesh: TGLBaseMesh);
  50. destructor Destroy; override;
  51. end;
  52. //==============================================================================
  53. implementation
  54. //==============================================================================
  55. // ------------------
  56. // ------------------ TGLFaceGroupConnectivity ------------------
  57. // ------------------
  58. procedure TGLFaceGroupConnectivity.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 TGLFaceGroupConnectivity.Create(APrecomputeFaceNormal: boolean);
  74. begin
  75. inherited;
  76. FOwnsVertices := true;
  77. end;
  78. procedure TGLFaceGroupConnectivity.SetMeshObject(const Value: TGLMeshObject);
  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 TGLFaceGroupConnectivity.CreateFromMesh(aMeshObject: TGLMeshObject; APrecomputeFaceNormal: boolean);
  89. begin
  90. Create(APrecomputeFaceNormal);
  91. MeshObject := aMeshObject;
  92. end;
  93. destructor TGLFaceGroupConnectivity.Destroy;
  94. begin
  95. if FOwnsVertices then
  96. FVertices.Free;
  97. FVertices := nil;
  98. inherited;
  99. end;
  100. procedure TGLFaceGroupConnectivity.RebuildEdgeList;
  101. var
  102. iFaceGroup, iFace, iVertex: integer;
  103. FaceGroup: TFGVertexIndexList;
  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 TFGVertexIndexList, 'Method only works for descendants of TFGVertexIndexList.');
  112. FaceGroup := TFGVertexIndexList(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. // ------------------ TGLBaseMeshConnectivity ------------------
  146. // ------------------
  147. procedure TGLBaseMeshConnectivity.RebuildEdgeList;
  148. var
  149. i: integer;
  150. begin
  151. for i := 0 to ConnectivityCount - 1 do
  152. FaceGroupConnectivity[i].RebuildEdgeList;
  153. end;
  154. procedure TGLBaseMeshConnectivity.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 TGLBaseMeshConnectivity.Create(APrecomputeFaceNormal: boolean);
  171. begin
  172. FFaceGroupConnectivityList := TList.Create;
  173. inherited;
  174. end;
  175. constructor TGLBaseMeshConnectivity.CreateFromMesh(aBaseMesh: TGLBaseMesh);
  176. begin
  177. Create(not(aBaseMesh is TGLActor));
  178. BaseMesh := aBaseMesh;
  179. end;
  180. procedure TGLBaseMeshConnectivity.SetBaseMesh(const Value: TGLBaseMesh);
  181. var
  182. i: integer;
  183. MO: TGLMeshObject;
  184. Connectivity: TGLFaceGroupConnectivity;
  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 TGLActor);
  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 := TGLFaceGroupConnectivity.CreateFromMesh(MO, FPrecomputeFaceNormal);
  197. FFaceGroupConnectivityList.Add(Connectivity);
  198. end;
  199. end;
  200. end;
  201. procedure TGLBaseMeshConnectivity.CreateSilhouette(const silhouetteParameters: TGLSilhouetteParameters;
  202. var aSilhouette: TGLSilhouette; AddToSilhouette: boolean);
  203. var
  204. i: integer;
  205. begin
  206. if aSilhouette = nil then
  207. aSilhouette := TGLSilhouette.Create
  208. else
  209. aSilhouette.Flush;
  210. for i := 0 to ConnectivityCount - 1 do
  211. FaceGroupConnectivity[i].CreateSilhouette(silhouetteParameters, aSilhouette, true);
  212. end;
  213. destructor TGLBaseMeshConnectivity.Destroy;
  214. begin
  215. Clear(false);
  216. FFaceGroupConnectivityList.Free;
  217. inherited;
  218. end;
  219. function TGLBaseMeshConnectivity.GetConnectivityCount: integer;
  220. begin
  221. result := FFaceGroupConnectivityList.Count;
  222. end;
  223. function TGLBaseMeshConnectivity.GetEdgeCount: integer;
  224. var
  225. i: integer;
  226. begin
  227. result := 0;
  228. for i := 0 to ConnectivityCount - 1 do
  229. result := result + FaceGroupConnectivity[i].EdgeCount;
  230. end;
  231. function TGLBaseMeshConnectivity.GetFaceCount: integer;
  232. var
  233. i: integer;
  234. begin
  235. result := 0;
  236. for i := 0 to ConnectivityCount - 1 do
  237. result := result + FaceGroupConnectivity[i].FaceCount;
  238. end;
  239. function TGLBaseMeshConnectivity.GetFaceGroupConnectivity(i: integer): TGLFaceGroupConnectivity;
  240. begin
  241. result := TGLFaceGroupConnectivity(FFaceGroupConnectivityList[i]);
  242. end;
  243. end.