GLS.VerletClothify.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. //
  2. // The graphics engine GLScene
  3. //
  4. unit GLS.VerletClothify;
  5. (* Methods for turning a TGLBaseMesh into a Verlet cloth / jelly *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. System.SysUtils,
  12. Stage.OpenGLTokens,
  13. GLS.VectorFileObjects,
  14. GLS.VerletTypes,
  15. Stage.VectorTypes,
  16. GLS.VectorLists,
  17. Stage.VectorGeometry,
  18. GLS.Texture,
  19. GLS.RenderContextInfo,
  20. GLS.State,
  21. GLS.PersistentClasses,
  22. GLS.Context;
  23. type
  24. (*
  25. Class that represents a face. This structure
  26. is not used for rendering, but for extracting info from meshes
  27. *)
  28. TGLFace = class
  29. public
  30. Vertices: array [0 .. 2] of integer;
  31. Normal: TAffineVector;
  32. MeshObject: TGLMeshObject;
  33. Active: boolean;
  34. procedure UpdateNormal;
  35. constructor Create(aMeshObject: TGLMeshObject);
  36. end;
  37. // List of faces
  38. TGLFaceList = class(TList)
  39. private
  40. function GetItems(i: integer): TGLFace;
  41. procedure SetItems(i: integer; const Value: TGLFace);
  42. public
  43. property Items[i: integer]: TGLFace read GetItems write SetItems; default;
  44. end;
  45. // Class that extracts faces from a GLBaseMesh
  46. TGLFaceExtractor = class
  47. private
  48. FFaceList: TGLFaceList;
  49. FGLBaseMesh: TGLBaseMesh;
  50. FNodeList: TGLVerletNodeList;
  51. FWeldDistance: single;
  52. FEdgeDoublesSkipped: integer;
  53. procedure SetWeldDistance(const Value: single);
  54. protected
  55. procedure ProcessMeshObject(const MeshObject: TGLMeshObject); virtual;
  56. public
  57. procedure ExtractFacesFromVertexIndexList(const FaceGroup
  58. : TFGVertexIndexList; const MeshObject: TGLMeshObject);
  59. property FaceList: TGLFaceList read FFaceList;
  60. procedure Clear; virtual;
  61. procedure ProcessMesh; virtual;
  62. property WeldDistance: single read FWeldDistance write SetWeldDistance;
  63. property EdgeDoublesSkipped: integer read FEdgeDoublesSkipped;
  64. property GLBaseMesh: TGLBaseMesh read FGLBaseMesh;
  65. property NodeList: TGLVerletNodeList read FNodeList;
  66. function AddFace(const Vi0, Vi1, Vi2: integer;
  67. const MeshObject: TGLMeshObject): TGLFace; virtual;
  68. constructor Create(const aGLBaseMesh: TGLBaseMesh); virtual;
  69. destructor Destroy; override;
  70. end;
  71. TGLEdgeDetector = class;
  72. TGLEdge = class
  73. private
  74. FSolid: boolean;
  75. FLength: single;
  76. FMeshObject: TGLMeshObject;
  77. FOwner: TGLEdgeDetector;
  78. public
  79. Vertices: array [0 .. 1] of integer;
  80. Faces: array [0 .. 1] of TGLFace;
  81. procedure Contract;
  82. property Owner: TGLEdgeDetector read FOwner;
  83. property MeshObject: TGLMeshObject read FMeshObject write FMeshObject;
  84. property Length: single read FLength write FLength;
  85. property Solid: boolean read FSolid write FSolid;
  86. procedure UpdateEdgeLength;
  87. constructor Create(const AOwner: TGLEdgeDetector; AVi0, AVi1: integer;
  88. AFace0, AFace1: TGLFace; aMeshObject: TGLMeshObject; ASolid: boolean);
  89. end;
  90. TGLEdgeList = class(TList)
  91. private
  92. function GetItems(i: integer): TGLEdge;
  93. procedure SetItems(i: integer; const Value: TGLEdge);
  94. public
  95. property Items[i: integer]: TGLEdge read GetItems write SetItems; default;
  96. procedure SortByLength;
  97. function InsertSorted(AEdge: TGLEdge): integer;
  98. end;
  99. TGLEdgeDetector = class(TGLFaceExtractor)
  100. private
  101. FEdgeList: TGLEdgeList;
  102. FCurrentNodeOffset: integer;
  103. FNodesAdded: boolean;
  104. procedure BuildOpposingEdges;
  105. protected
  106. FCalcEdgeLength: boolean;
  107. public
  108. property EdgeList: TGLEdgeList read FEdgeList;
  109. procedure Clear; override;
  110. procedure ProcessMesh; override;
  111. function AddEdge(const Vi0, Vi1: integer; const Face: TGLFace;
  112. const aMeshObject: TGLMeshObject): TGLEdge;
  113. function AddFace(const Vi0, Vi1, Vi2: integer;
  114. const MeshObject: TGLMeshObject): TGLFace; override;
  115. function AddNode(const VerletWorld: TGLVerletWorld;
  116. const MeshObject: TGLMeshObject; const VertexIndex: integer)
  117. : TGLVerletNode; virtual;
  118. procedure AddNodes(const VerletWorld: TGLVerletWorld);
  119. procedure AddEdgesAsSticks(const VerletWorld: TGLVerletWorld;
  120. const Slack: single);
  121. procedure AddEdgesAsSprings(const VerletWorld: TGLVerletWorld;
  122. const Strength, Damping, Slack: single);
  123. procedure AddEdgesAsSolidEdges(const VerletWorld: TGLVerletWorld);
  124. procedure AddOuterEdgesAsSolidEdges(const VerletWorld: TGLVerletWorld);
  125. procedure RenderEdges(var rci: TGLRenderContextInfo);
  126. property CurrentNodeOffset: integer read FCurrentNodeOffset;
  127. property NodesAdded: boolean read FNodesAdded;
  128. procedure ReplaceVertexIndex(const ViRemove, ViReplaceWith: integer);
  129. constructor Create(const aGLBaseMesh: TGLBaseMesh); override;
  130. destructor Destroy; override;
  131. end;
  132. TGLMeshObjectVerletNode = class(TGLVerletNode)
  133. private
  134. MeshObject: TGLMeshObject;
  135. VertexIndices: TGLIntegerList;
  136. public
  137. procedure AfterProgress; override;
  138. constructor CreateOwned(const AOwner: TGLVerletWorld); override;
  139. destructor Destroy; override;
  140. end;
  141. // ----------------------------------------------------
  142. implementation
  143. // ----------------------------------------------------
  144. // ------------------
  145. // TGLFaceExtractor
  146. // ------------------
  147. procedure TGLFaceExtractor.Clear;
  148. var
  149. i: integer;
  150. begin
  151. for i := 0 to FaceList.Count - 1 do
  152. FaceList[i].Free;
  153. FaceList.Clear;
  154. end;
  155. constructor TGLFaceExtractor.Create(const aGLBaseMesh: TGLBaseMesh);
  156. begin
  157. FFaceList := TGLFaceList.Create;
  158. FGLBaseMesh := aGLBaseMesh;
  159. FNodeList := TGLVerletNodeList.Create;
  160. FWeldDistance := 0.01;
  161. end;
  162. destructor TGLFaceExtractor.Destroy;
  163. begin
  164. Clear;
  165. FreeAndNil(FNodeList);
  166. FreeAndNil(FFaceList);
  167. inherited;
  168. end;
  169. procedure TGLFaceExtractor.ExtractFacesFromVertexIndexList(const FaceGroup
  170. : TFGVertexIndexList; const MeshObject: TGLMeshObject);
  171. var
  172. List: PIntegerArray;
  173. iFace, iVertex: integer;
  174. begin
  175. case FaceGroup.Mode of
  176. fgmmTriangles, fgmmFlatTriangles:
  177. begin
  178. for iFace := 0 to FaceGroup.TriangleCount - 1 do
  179. begin
  180. List := @FaceGroup.VertexIndices.List[iFace * 3 + 0];
  181. AddFace(List^[0], List^[1], List^[2], MeshObject);
  182. end;
  183. end;
  184. fgmmTriangleStrip:
  185. begin
  186. for iFace := 0 to FaceGroup.VertexIndices.Count - 3 do
  187. begin
  188. List := @FaceGroup.VertexIndices.List[iFace];
  189. if (iFace and 1) = 0 then
  190. AddFace(List^[0], List^[1], List^[2], MeshObject)
  191. else
  192. AddFace(List^[2], List^[1], List^[0], MeshObject);
  193. end;
  194. end;
  195. fgmmTriangleFan:
  196. begin
  197. List := @FaceGroup.VertexIndices.List;
  198. for iVertex := 2 to FaceGroup.VertexIndices.Count - 1 do
  199. AddFace(List^[0], List^[iVertex - 1], List^[iVertex], MeshObject)
  200. end;
  201. else
  202. Assert(false, 'Not supported');
  203. end;
  204. end;
  205. procedure TGLFaceExtractor.ProcessMesh;
  206. var
  207. iMeshObject: integer;
  208. MeshObject: TGLMeshObject;
  209. begin
  210. for iMeshObject := 0 to FGLBaseMesh.MeshObjects.Count - 1 do
  211. begin
  212. MeshObject := FGLBaseMesh.MeshObjects[iMeshObject];
  213. ProcessMeshObject(MeshObject);
  214. end;
  215. end;
  216. procedure TGLFaceExtractor.ProcessMeshObject(const MeshObject: TGLMeshObject);
  217. var
  218. iFaceGroup: integer;
  219. begin
  220. if MeshObject.Mode = momFaceGroups then
  221. begin
  222. for iFaceGroup := 0 to MeshObject.FaceGroups.Count - 1 do
  223. begin
  224. if MeshObject.FaceGroups[iFaceGroup] is TFGVertexIndexList then
  225. begin
  226. ExtractFacesFromVertexIndexList(MeshObject.FaceGroups[iFaceGroup]
  227. as TFGVertexIndexList, MeshObject);
  228. end
  229. else
  230. Assert(false);
  231. end;
  232. end
  233. else
  234. Assert(false);
  235. end;
  236. function TGLFaceExtractor.AddFace(const Vi0, Vi1, Vi2: integer;
  237. const MeshObject: TGLMeshObject): TGLFace;
  238. var
  239. Face: TGLFace;
  240. begin
  241. Face := TGLFace.Create(MeshObject);
  242. FaceList.Add(Face);
  243. Face.Vertices[0] := Vi0;
  244. Face.Vertices[1] := Vi1;
  245. Face.Vertices[2] := Vi2;
  246. Result := Face;
  247. end;
  248. procedure TGLFaceExtractor.SetWeldDistance(const Value: single);
  249. begin
  250. FWeldDistance := Value;
  251. end;
  252. // ------------------
  253. // TGLFaceList
  254. // ------------------
  255. function TGLFaceList.GetItems(i: integer): TGLFace;
  256. begin
  257. result := TGLFace(Get(i));
  258. end;
  259. procedure TGLFaceList.SetItems(i: integer; const Value: TGLFace);
  260. begin
  261. Put(i, Value);
  262. end;
  263. // ------------------
  264. // TGLEdgeList
  265. // ------------------
  266. function TGLEdgeList.GetItems(i: integer): TGLEdge;
  267. begin
  268. result := TGLEdge(Get(i));
  269. end;
  270. function TGLEdgeList.InsertSorted(AEdge: TGLEdge): integer;
  271. var
  272. i: integer;
  273. begin
  274. for i := 0 to Count - 1 do
  275. begin
  276. if AEdge.Length < Items[i].Length then
  277. begin
  278. Insert(i, AEdge);
  279. Result := i;
  280. Exit;
  281. end;
  282. end;
  283. Result := Add(AEdge);
  284. end;
  285. procedure TGLEdgeList.SetItems(i: integer; const Value: TGLEdge);
  286. begin
  287. Put(i, Value);
  288. end;
  289. function EdgeLength(Item1, Item2: pointer): integer;
  290. begin
  291. if TGLEdge(Item1).Length < TGLEdge(Item2).Length then
  292. Result := -1
  293. else if TGLEdge(Item1).Length = TGLEdge(Item2).Length then
  294. Result := 0
  295. else
  296. Result := 1;
  297. end;
  298. procedure TGLEdgeList.SortByLength;
  299. begin
  300. Sort(@EdgeLength);
  301. end;
  302. // --------------------------
  303. // TGLMeshObjectVerletNode
  304. // --------------------------
  305. constructor TGLMeshObjectVerletNode.CreateOwned(const AOwner: TGLVerletWorld);
  306. begin
  307. inherited;
  308. VertexIndices := TGLIntegerList.Create;
  309. end;
  310. destructor TGLMeshObjectVerletNode.Destroy;
  311. begin
  312. VertexIndices.Free;
  313. inherited;
  314. end;
  315. procedure TGLMeshObjectVerletNode.AfterProgress;
  316. var
  317. i: integer;
  318. begin
  319. // Update the actual vertex
  320. for i := 0 to VertexIndices.Count - 1 do
  321. MeshObject.Vertices[VertexIndices[i]] :=
  322. MeshObject.Owner.Owner.AbsoluteToLocal(Location);
  323. end;
  324. // --------------------------
  325. // TGLEdgeDetector
  326. // --------------------------
  327. procedure TGLEdgeDetector.Clear;
  328. var
  329. i: integer;
  330. begin
  331. inherited;
  332. for i := 0 to EdgeList.Count - 1 do
  333. EdgeList[i].Free;
  334. EdgeList.Clear;
  335. FCurrentNodeOffset := 0;
  336. FNodesAdded := false;
  337. end;
  338. constructor TGLEdgeDetector.Create(const aGLBaseMesh: TGLBaseMesh);
  339. begin
  340. FEdgeList := TGLEdgeList.Create;
  341. FCurrentNodeOffset := 0;
  342. FNodesAdded := false;
  343. FCalcEdgeLength := false;
  344. inherited;
  345. end;
  346. destructor TGLEdgeDetector.Destroy;
  347. begin
  348. inherited;
  349. FreeAndNil(FEdgeList);
  350. end;
  351. function TGLEdgeDetector.AddEdge(const Vi0, Vi1: integer; const Face: TGLFace;
  352. const aMeshObject: TGLMeshObject): TGLEdge;
  353. var
  354. i: integer;
  355. Edge: TGLEdge;
  356. begin
  357. // Find an indentical edge, if there is one
  358. for i := 0 to EdgeList.Count - 1 do
  359. begin
  360. Edge := EdgeList[i];
  361. if (Edge.Vertices[0] = Vi0) and (Edge.Vertices[1] = Vi1) or
  362. (Edge.Vertices[1] = Vi0) and (Edge.Vertices[0] = Vi1) then
  363. begin
  364. Edge.Faces[1] := Face;
  365. Result := Edge;
  366. Exit;
  367. end;
  368. end;
  369. // No edge was found, create a new one
  370. Edge := TGLEdge.Create(self, Vi0, Vi1, Face, nil, aMeshObject, true);
  371. EdgeList.Add(Edge);
  372. Result := Edge;
  373. end;
  374. function TGLEdgeDetector.AddFace(const Vi0, Vi1, Vi2: integer;
  375. const MeshObject: TGLMeshObject): TGLFace;
  376. var
  377. Face: TGLFace;
  378. begin
  379. Face := TGLFace.Create(MeshObject);
  380. FaceList.Add(Face);
  381. Face.Vertices[0] := Vi0;
  382. Face.Vertices[1] := Vi1;
  383. Face.Vertices[2] := Vi2;
  384. AddEdge(Vi0, Vi1, Face, MeshObject);
  385. AddEdge(Vi1, Vi2, Face, MeshObject);
  386. AddEdge(Vi2, Vi0, Face, MeshObject); // }
  387. Result := Face;
  388. end;
  389. procedure TGLEdgeDetector.AddNodes(const VerletWorld: TGLVerletWorld);
  390. var
  391. i: integer;
  392. MO: TGLMeshObject;
  393. begin
  394. FNodesAdded := true;
  395. FCurrentNodeOffset := FNodeList.Count;
  396. MO := FGLBaseMesh.MeshObjects[0];
  397. for i := 0 to MO.Vertices.Count - 1 do
  398. AddNode(VerletWorld, MO, i);
  399. // Assert(FNodeList.Count = MO.Vertices.Count, Format('%d <> %d',[FNodeList.Count, MO.Vertices.Count]));
  400. end;
  401. procedure TGLEdgeDetector.AddEdgesAsSprings(const VerletWorld: TGLVerletWorld;
  402. const Strength, Damping, Slack: single);
  403. var
  404. i: integer;
  405. Edge: TGLEdge;
  406. begin
  407. if not FNodesAdded then
  408. AddNodes(VerletWorld);
  409. for i := 0 to EdgeList.Count - 1 do
  410. begin
  411. // if not EdgeList[i].SameSame(FNodeList) then
  412. Edge := EdgeList[i];
  413. if FNodeList[FCurrentNodeOffset + Edge.Vertices[0]] <> FNodeList
  414. [FCurrentNodeOffset + Edge.Vertices[1]] then
  415. begin
  416. VerletWorld.CreateSpring(FNodeList[FCurrentNodeOffset + Edge.Vertices[0]],
  417. FNodeList[FCurrentNodeOffset + Edge.Vertices[1]], Strength,
  418. Damping, Slack);
  419. end;
  420. end;
  421. end;
  422. procedure TGLEdgeDetector.AddEdgesAsSticks(const VerletWorld: TGLVerletWorld;
  423. const Slack: single);
  424. var
  425. i: integer;
  426. Edge: TGLEdge;
  427. begin
  428. if not FNodesAdded then
  429. AddNodes(VerletWorld);
  430. for i := 0 to EdgeList.Count - 1 do
  431. begin
  432. // if not EdgeList[i].SameSame(FNodeList) then
  433. Edge := EdgeList[i];
  434. if FNodeList[FCurrentNodeOffset + Edge.Vertices[0]] <> FNodeList
  435. [FCurrentNodeOffset + Edge.Vertices[1]] then
  436. begin
  437. VerletWorld.CreateStick(FNodeList[FCurrentNodeOffset + Edge.Vertices[0]],
  438. FNodeList[FCurrentNodeOffset + Edge.Vertices[1]], Slack);
  439. end;
  440. end;
  441. end;
  442. procedure TGLEdgeDetector.AddEdgesAsSolidEdges(const VerletWorld: TGLVerletWorld);
  443. var
  444. i: integer;
  445. Edge: TGLEdge;
  446. begin
  447. if not FNodesAdded then
  448. AddNodes(VerletWorld);
  449. for i := 0 to EdgeList.Count - 1 do
  450. begin
  451. // if not EdgeList[i].SameSame(FNodeList) then
  452. Edge := EdgeList[i];
  453. if FNodeList[FCurrentNodeOffset + Edge.Vertices[0]] <> FNodeList
  454. [FCurrentNodeOffset + Edge.Vertices[1]] then
  455. begin
  456. if Edge.Solid then
  457. VerletWorld.AddSolidEdge(FNodeList[FCurrentNodeOffset + Edge.Vertices[0]
  458. ], FNodeList[FCurrentNodeOffset + Edge.Vertices[1]]);
  459. end;
  460. end;
  461. end;
  462. procedure TGLEdgeDetector.AddOuterEdgesAsSolidEdges(const VerletWorld
  463. : TGLVerletWorld);
  464. var
  465. i: integer;
  466. Edge: TGLEdge;
  467. begin
  468. if not FNodesAdded then
  469. AddNodes(VerletWorld);
  470. for i := 0 to EdgeList.Count - 1 do
  471. begin
  472. // if not EdgeList[i].SameSame(FNodeList) then
  473. Edge := EdgeList[i];
  474. if FNodeList[FCurrentNodeOffset + Edge.Vertices[0]] <> FNodeList
  475. [FCurrentNodeOffset + Edge.Vertices[1]] then
  476. begin
  477. if Edge.Solid and (Edge.Faces[1] = nil) then
  478. VerletWorld.AddSolidEdge(FNodeList[FCurrentNodeOffset + Edge.Vertices[0]
  479. ], FNodeList[FCurrentNodeOffset + Edge.Vertices[1]]);
  480. end;
  481. end;
  482. end;
  483. procedure TGLEdgeDetector.RenderEdges(var rci: TGLRenderContextInfo);
  484. var
  485. i: integer;
  486. Edge: TGLEdge;
  487. Vertex0, Vertex1: TAffineVector;
  488. begin
  489. if EdgeList.Count > 0 then
  490. begin
  491. rci.GLStates.Disable(stLighting);
  492. rci.GLStates.LineWidth := 3;
  493. gl.Color3f(1, 1, 1);
  494. gl.Begin_(GL_LINES);
  495. for i := 0 to EdgeList.Count - 1 do
  496. begin
  497. Edge := EdgeList[i];
  498. Vertex0 := Edge.MeshObject.Vertices[Edge.Vertices[0]];
  499. Vertex1 := Edge.MeshObject.Vertices[Edge.Vertices[1]];
  500. gl.Vertex3fv(PGLfloat(@Vertex0));
  501. gl.Vertex3fv(PGLfloat(@Vertex1));
  502. end;
  503. gl.End_;
  504. end;
  505. // }
  506. end;
  507. procedure TGLEdgeDetector.BuildOpposingEdges;
  508. var
  509. iEdge, EdgeCount, Vi0, Vi1, iEdgeTest: integer;
  510. Face0, Face1: TGLFace;
  511. Edge, NewEdge, TestEdge: TGLEdge;
  512. begin
  513. // For each edge that's connected by two triangles, create a new edge that
  514. // connects the two "extra" vertices.... makes sense?
  515. EdgeCount := EdgeList.Count;
  516. for iEdge := 0 to EdgeCount - 1 do
  517. begin
  518. Edge := EdgeList[iEdge];
  519. if Assigned(Edge.Faces[1]) then
  520. begin
  521. Face0 := Edge.Faces[0];
  522. Face1 := Edge.Faces[1];
  523. if (Face0.Vertices[0] <> Edge.Vertices[0]) and
  524. (Face0.Vertices[0] <> Edge.Vertices[1]) then
  525. Vi0 := Face0.Vertices[0]
  526. else if (Face0.Vertices[1] <> Edge.Vertices[0]) and
  527. (Face0.Vertices[1] <> Edge.Vertices[1]) then
  528. Vi0 := Face0.Vertices[1]
  529. else
  530. Vi0 := Face0.Vertices[2];
  531. if (Face1.Vertices[0] <> Edge.Vertices[0]) and
  532. (Face1.Vertices[0] <> Edge.Vertices[1]) then
  533. Vi1 := Face1.Vertices[0]
  534. else if (Face1.Vertices[1] <> Edge.Vertices[0]) and
  535. (Face1.Vertices[1] <> Edge.Vertices[1]) then
  536. Vi1 := Face1.Vertices[1]
  537. else
  538. Vi1 := Face1.Vertices[2];
  539. if (Vi0 = Vi1) or (Vi0 = Edge.Vertices[0]) or (Vi0 = Edge.Vertices[1]) or
  540. (Vi1 = Edge.Vertices[0]) or (Vi1 = Edge.Vertices[1]) then
  541. continue;
  542. // Find an indentical edge, if there is one
  543. for iEdgeTest := 0 to EdgeList.Count - 1 do
  544. begin
  545. TestEdge := EdgeList[iEdgeTest];
  546. if (TestEdge.Vertices[0] = Vi0) and (TestEdge.Vertices[1] = Vi1) or
  547. (TestEdge.Vertices[1] = Vi0) and (TestEdge.Vertices[0] = Vi1) then
  548. begin
  549. // Edge allready exists!
  550. inc(FEdgeDoublesSkipped);
  551. continue;
  552. end;
  553. end;
  554. NewEdge := TGLEdge.Create(self, Vi0, Vi1, nil, nil, Edge.MeshObject, false);
  555. EdgeList.Add(NewEdge);
  556. // *)
  557. end;
  558. end;
  559. end;
  560. function TGLEdgeDetector.AddNode(const VerletWorld: TGLVerletWorld;
  561. const MeshObject: TGLMeshObject; const VertexIndex: integer): TGLVerletNode;
  562. var
  563. Location: TAffineVector;
  564. aNode: TGLMeshObjectVerletNode;
  565. i: integer;
  566. begin
  567. // Is there an identical node?
  568. Location := MeshObject.Owner.Owner.LocalToAbsolute
  569. (MeshObject.Vertices[VertexIndex]);
  570. for i := FCurrentNodeOffset to FNodeList.Count - 1 do
  571. begin
  572. aNode := TGLMeshObjectVerletNode(FNodeList[i]);
  573. if VectorDistance2(Location, aNode.Location) <= FWeldDistance then
  574. begin
  575. FNodeList.Add(aNode);
  576. aNode.VertexIndices.Add(VertexIndex);
  577. result := aNode;
  578. exit;
  579. end;
  580. end; // *)
  581. aNode := TGLMeshObjectVerletNode.CreateOwned(VerletWorld);
  582. aNode.MeshObject := MeshObject;
  583. aNode.VertexIndices.Add(VertexIndex);
  584. aNode.Location := Location;
  585. aNode.OldLocation := Location;
  586. FNodeList.Add(aNode);
  587. result := aNode;
  588. end;
  589. procedure TGLEdgeDetector.ProcessMesh;
  590. begin
  591. inherited;
  592. BuildOpposingEdges;
  593. end;
  594. procedure TGLEdgeDetector.ReplaceVertexIndex(const ViRemove,
  595. ViReplaceWith: integer);
  596. var
  597. i: integer;
  598. Done: boolean;
  599. Edge: TGLEdge;
  600. begin
  601. for i := 0 to FaceList.Count - 1 do
  602. with FaceList[i] do
  603. begin
  604. if Active then
  605. begin
  606. if Vertices[0] = ViRemove then
  607. Vertices[0] := ViReplaceWith;
  608. if Vertices[1] = ViRemove then
  609. Vertices[1] := ViReplaceWith;
  610. if Vertices[2] = ViRemove then
  611. Vertices[2] := ViReplaceWith;
  612. if (Vertices[0] = Vertices[1]) or (Vertices[1] = Vertices[2]) or
  613. (Vertices[2] = Vertices[0]) then
  614. Active := false;
  615. end;
  616. end;
  617. Done := false;
  618. while not Done do
  619. begin
  620. Done := true;
  621. for i := 0 to EdgeList.Count - 1 do
  622. with EdgeList[i] do
  623. begin
  624. if (Vertices[0] = ViRemove) or (Vertices[1] = ViRemove) then
  625. begin
  626. if Vertices[0] = ViRemove then
  627. Vertices[0] := ViReplaceWith;
  628. if Vertices[1] = ViRemove then
  629. Vertices[1] := ViReplaceWith;
  630. UpdateEdgeLength;
  631. Edge := EdgeList[i];
  632. EdgeList.Delete(i);
  633. if Edge.Length = -1 then
  634. Edge.Free
  635. else
  636. EdgeList.InsertSorted(Edge);
  637. Done := false;
  638. break; // }
  639. end;
  640. end;
  641. end;
  642. end;
  643. // --------------------------
  644. // TGLFace
  645. // --------------------------
  646. constructor TGLFace.Create(aMeshObject: TGLMeshObject);
  647. begin
  648. MeshObject := aMeshObject;
  649. Active := true;
  650. end;
  651. procedure TGLFace.UpdateNormal;
  652. begin
  653. CalcPlaneNormal(MeshObject.Vertices[Vertices[0]],
  654. MeshObject.Vertices[Vertices[1]], MeshObject.Vertices[Vertices[2]], Normal);
  655. end;
  656. // ------------------
  657. // TGLEdge
  658. // ------------------
  659. procedure TGLEdge.Contract;
  660. begin
  661. // We're removing vertex 1 and replacing it with vertex 0
  662. FOwner.ReplaceVertexIndex(Vertices[1], Vertices[0]);
  663. // MeshObject.Vertices[Vertices[0]] := MeshObject.Vertices[Vertices[1]];
  664. Length := -1;
  665. end;
  666. constructor TGLEdge.Create(const AOwner: TGLEdgeDetector; AVi0, AVi1: integer;
  667. AFace0, AFace1: TGLFace; aMeshObject: TGLMeshObject; ASolid: boolean);
  668. begin
  669. FOwner := AOwner;
  670. Vertices[0] := AVi0;
  671. Vertices[1] := AVi1;
  672. Faces[0] := AFace0;
  673. Faces[1] := AFace1;
  674. FMeshObject := aMeshObject;
  675. FSolid := true;
  676. UpdateEdgeLength;
  677. end;
  678. procedure TGLEdge.UpdateEdgeLength;
  679. begin
  680. if FOwner.FCalcEdgeLength then
  681. begin
  682. if Vertices[0] = Vertices[1] then
  683. Length := -1
  684. else
  685. Length := VectorDistance(FOwner.GLBaseMesh.LocalToAbsolute
  686. (FMeshObject.Vertices[Vertices[0]]),
  687. FOwner.GLBaseMesh.LocalToAbsolute(FMeshObject.Vertices[Vertices[1]]));
  688. end;
  689. end;
  690. end.