GXS.VerletClothify.pas 20 KB

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