123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.VerletClothify;
- (* Methods for turning a TgxBaseMesh into a Verlet cloth / jelly *)
- interface
- {$I Stage.Defines.inc}
- uses
- Winapi.OpenGL,
- System.Classes,
- System.SysUtils,
- Stage.VectorTypes,
- GXS.VectorLists,
- Stage.VectorGeometry,
- GXS.VectorFileObjects,
- GXS.VerletTypes,
- GXS.Texture,
- GXS.RenderContextInfo,
- GXS.State,
- GXS.Context;
- type
- (* Class that represents a face. This structure is not used for rendering, but
- for extracting info from meshes *)
- TFace = class
- public
- Vertices : array[0..2] of integer;
- Normal : TAffineVector;
- MeshObject : TgxMeshObject;
- Active : boolean;
- procedure UpdateNormal;
- constructor Create(aMeshObject : TgxMeshObject);
- end;
- { List of faces }
- TFaceList = class(TList)
- private
- function GetItems(i: integer): TFace;
- procedure SetItems(i: integer; const Value: TFace);
- public
- property Items[i : integer] : TFace read GetItems write SetItems; default;
- end;
- // Class that extracts faces from a GLBaseMesh
- TFaceExtractor = class
- private
- FFaceList : TFaceList;
- FGLBaseMesh : TgxBaseMesh;
- FNodeList : TgxVerletNodeList;
- FWeldDistance: single;
- FEdgeDoublesSkipped : integer;
- procedure SetWeldDistance(const Value: single);
- protected
- procedure ProcessMeshObject(const MeshObject : TgxMeshObject); virtual;
- public
- procedure ExtractFacesFromVertexIndexList(
- const FaceGroup : TgxFGVertexIndexList; const MeshObject : TgxMeshObject);
- property FaceList : TFaceList read FFaceList;
- procedure Clear; virtual;
- procedure ProcessMesh; virtual;
- property WeldDistance : single read FWeldDistance write SetWeldDistance;
- property EdgeDoublesSkipped : integer read FEdgeDoublesSkipped;
- property GLBaseMesh : TgxBaseMesh read FGLBaseMesh;
- property NodeList : TgxVerletNodeList read FNodeList;
- function AddFace(const Vi0, Vi1, Vi2 : integer; const MeshObject : TgxMeshObject) : TFace; virtual;
- constructor Create(const aGLBaseMesh : TgxBaseMesh); virtual;
- destructor Destroy; override;
- end;
- // *** EDGE DETECTOR
- TEdgeDetector = class;
- TEdge = class
- private
- FSolid: boolean;
- FLength: single;
- FMeshObject: TgxMeshObject;
- FOwner: TEdgeDetector;
- public
- Vertices : array[0..1] of integer;
- Faces : array[0..1] of TFace;
- procedure Contract;
- property Owner : TEdgeDetector read FOwner;
- property MeshObject : TgxMeshObject read FMeshObject write FMeshObject;
- property Length : single read FLength write FLength;
- property Solid : boolean read FSolid write FSolid;
- procedure UpdateEdgeLength;
- constructor Create(const AOwner: TEdgeDetector; AVi0, AVi1 : integer;
- AFace0, AFace1 : TFace; AMeshObject : TgxMeshObject; ASolid : boolean);
- end;
- TEdgeList = class(TList)
- private
- function GetItems(i: integer): TEdge;
- procedure SetItems(i: integer; const Value: TEdge);
- public
- property Items[i : integer] : TEdge read GetItems write SetItems; default;
- procedure SortByLength;
- function InsertSorted(AEdge : TEdge) : integer;
- end;
- TEdgeDetector = class(TFaceExtractor)
- private
- FEdgeList : TEdgeList;
- FCurrentNodeOffset : integer;
- FNodesAdded : boolean;
- procedure BuildOpposingEdges;
- protected
- FCalcEdgeLength : boolean;
- public
- property EdgeList : TEdgeList read FEdgeList;
- procedure Clear; override;
- procedure ProcessMesh; override;
- function AddEdge(const Vi0, Vi1 : integer; const Face : TFace; const AMeshObject : TgxMeshObject) : TEdge;
- function AddFace(const Vi0, Vi1, Vi2 : integer; const MeshObject : TgxMeshObject) : TFace; override;
- function AddNode(const VerletWorld : TgxVerletWorld; const MeshObject : TgxMeshObject; const VertexIndex : integer) : TgxVerletNode; virtual;
- procedure AddNodes(const VerletWorld : TgxVerletWorld);
- procedure AddEdgesAsSticks(const VerletWorld : TgxVerletWorld; const Slack : single);
- procedure AddEdgesAsSprings(const VerletWorld : TgxVerletWorld; const Strength, Damping, Slack : single);
- procedure AddEdgesAsSolidEdges(const VerletWorld : TgxVerletWorld);
- procedure AddOuterEdgesAsSolidEdges(const VerletWorld : TgxVerletWorld);
- procedure RenderEdges(var rci : TgxRenderContextInfo);
- property CurrentNodeOffset : integer read FCurrentNodeOffset;
- property NodesAdded : boolean read FNodesAdded;
- procedure ReplaceVertexIndex(const ViRemove, ViReplaceWith : integer);
- constructor Create(const aGLBaseMesh : TgxBaseMesh); override;
- destructor Destroy; override;
- end;
- TgxMeshObjectVerletNode = class(TgxVerletNode)
- private
- MeshObject : TgxMeshObject;
- VertexIndices : TgxIntegerList;
- public
- procedure AfterProgress; override;
- constructor CreateOwned(const aOwner : TgxVerletWorld); override;
- destructor Destroy; override;
- end;
- //---------------------------------------------------------------------------
- implementation
- //---------------------------------------------------------------------------
- //----------------------------------------
- // TFaceExtractor
- //----------------------------------------
- procedure TFaceExtractor.Clear;
- var
- i : integer;
- begin
- for i := 0 to FaceList.Count-1 do
- FaceList[i].Free;
- FaceList.Clear;
- end;
- constructor TFaceExtractor.Create(const aGLBaseMesh : TgxBaseMesh);
- begin
- FFaceList := TFaceList.Create;
- FGLBaseMesh := aGLBaseMesh;
- FNodeList := TgxVerletNodeList.Create;
- FWeldDistance := 0.01;
- end;
- destructor TFaceExtractor.Destroy;
- begin
- Clear;
- FreeAndNil(FNodeList);
- FreeAndNil(FFaceList);
- inherited;
- end;
- procedure TFaceExtractor.ExtractFacesFromVertexIndexList(
- const FaceGroup : TgxFGVertexIndexList; const MeshObject : TgxMeshObject);
- var
- List : PIntegerArray;
- iFace, iVertex : integer;
- begin
- case FaceGroup.Mode of
- fgmmTriangles, fgmmFlatTriangles :
- begin
- for iFace := 0 to FaceGroup.TriangleCount - 1 do
- begin
- List := @FaceGroup.VertexIndices.List[iFace * 3 + 0];
- AddFace(List^[0], List^[1], List^[2], MeshObject);
- end;
- end;
- fgmmTriangleStrip :
- begin
- for iFace:=0 to FaceGroup.VertexIndices.Count-3 do
- begin
- List := @FaceGroup.VertexIndices.List[iFace];
- if (iFace and 1)=0 then
- AddFace(List^[0], List^[1], List^[2], MeshObject)
- else
- AddFace(List^[2], List^[1], List^[0], MeshObject);
- end;
- end;
- fgmmTriangleFan :
- begin
- List := @FaceGroup.VertexIndices.List;
- for iVertex:=2 to FaceGroup.VertexIndices.Count-1 do
- AddFace(List^[0], List^[iVertex-1], List^[iVertex], MeshObject)
- end;
- else
- Assert(false,'Not supported');
- end;
- end;
- procedure TFaceExtractor.ProcessMesh;
- var
- iMeshObject : integer;
- MeshObject : TgxMeshObject;
- begin
- for iMeshObject := 0 to FGLBaseMesh.MeshObjects.Count - 1 do
- begin
- MeshObject := FGLBaseMesh.MeshObjects[iMeshObject];
- ProcessMeshObject(MeshObject);
- end;
- end;
- procedure TFaceExtractor.ProcessMeshObject(const MeshObject : TgxMeshObject);
- var
- iFaceGroup : integer;
- begin
- if MeshObject.Mode = momFaceGroups then
- begin
- for iFaceGroup := 0 to MeshObject.FaceGroups.Count - 1 do
- begin
- if MeshObject.FaceGroups[iFaceGroup] is TgxFGVertexIndexList then
- begin
- ExtractFacesFromVertexIndexList(MeshObject.FaceGroups[iFaceGroup] as TgxFGVertexIndexList, MeshObject);
- end else
- Assert(false);
- end;
- end else
- Assert(false);
- end;
- function TFaceExtractor.AddFace(const Vi0, Vi1, Vi2: integer; const MeshObject : TgxMeshObject) : TFace;
- var
- Face : TFace;
- begin
- Face := TFace.Create(MeshObject);
- FaceList.Add(Face);
- Face.Vertices[0] := Vi0;
- Face.Vertices[1] := Vi1;
- Face.Vertices[2] := Vi2;
- result := Face;
- end;
- procedure TFaceExtractor.SetWeldDistance(const Value: single);
- begin
- FWeldDistance := Value;
- end;
- //----------------------------------------
- // TFaceList
- //----------------------------------------
- function TFaceList.GetItems(i: integer): TFace;
- begin
- result := TFace(Get(i));
- end;
- procedure TFaceList.SetItems(i: integer; const Value: TFace);
- begin
- Put(i, Value);
- end;
- //----------------------------------------
- // TEdgeList
- //----------------------------------------
- function TEdgeList.GetItems(i: integer): TEdge;
- begin
- result := TEdge(Get(i));
- end;
- function TEdgeList.InsertSorted(AEdge: TEdge): integer;
- var
- i : integer;
- begin
- for i := 0 to Count-1 do
- begin
- if AEdge.Length<Items[i].Length then
- begin
- Insert(i, AEdge);
- result := i;
- exit;
- end;
- end;
- result := Add(AEdge);
- end;
- procedure TEdgeList.SetItems(i: integer; const Value: TEdge);
- begin
- Put(i, Value);
- end;
- function EdgeLength(Item1, Item2 : pointer) : integer;
- begin
- if TEdge(Item1).Length < TEdge(Item2).Length then
- result := -1
- else if TEdge(Item1).Length = TEdge(Item2).Length then
- result := 0
- else
- result := 1;
- end;
- procedure TEdgeList.SortByLength;
- begin
- Sort(@EdgeLength);
- end;
- //----------------------------------------
- // TgxMeshObjectVerletNode
- //----------------------------------------
- constructor TgxMeshObjectVerletNode.CreateOwned(const aOwner: TgxVerletWorld);
- begin
- inherited;
- VertexIndices := TgxIntegerList.Create;
- end;
- destructor TgxMeshObjectVerletNode.Destroy;
- begin
- VertexIndices.Free;
- inherited;
- end;
- procedure TgxMeshObjectVerletNode.AfterProgress;
- var
- i : integer;
- begin
- // Update the actual vertex
- for i := 0 to VertexIndices.Count-1 do
- MeshObject.Vertices[VertexIndices[i]] := MeshObject.Owner.Owner.AbsoluteToLocal(Location);
- end;
- //----------------------------------------
- // TEdgeDetector
- //----------------------------------------
- procedure TEdgeDetector.Clear;
- var
- i : integer;
- begin
- inherited;
- for i := 0 to EdgeList.Count-1 do
- EdgeList[i].Free;
- EdgeList.Clear;
- FCurrentNodeOffset := 0;
- FNodesAdded := false;
- end;
- constructor TEdgeDetector.Create(const aGLBaseMesh: TgxBaseMesh);
- begin
- FEdgeList := TEdgeList.Create;
- FCurrentNodeOffset := 0;
- FNodesAdded := false;
- FCalcEdgeLength := false;
- inherited;
- end;
- destructor TEdgeDetector.Destroy;
- begin
- inherited;
- FreeAndNil(FEdgeList);
- end;
- function TEdgeDetector.AddEdge(const Vi0, Vi1: integer; const Face: TFace; const AMeshObject : TgxMeshObject): TEdge;
- var
- i : integer;
- Edge : TEdge;
- begin
- // Find an indentical edge, if there is one
- for i := 0 to EdgeList.Count - 1 do
- begin
- Edge := EdgeList[i];
- if (Edge.Vertices[0]=Vi0) and (Edge.Vertices[1]=Vi1) or
- (Edge.Vertices[1]=Vi0) and (Edge.Vertices[0]=Vi1) then
- begin
- Edge.Faces[1] := Face;
- result := Edge;
- exit;
- end;
- end;
- // No edge was found, create a new one
- Edge := TEdge.Create(self, Vi0, Vi1, Face, nil, AMeshObject, true);
- EdgeList.Add(Edge);
- result := Edge;
- end;
- function TEdgeDetector.AddFace(const Vi0, Vi1, Vi2: integer;
- const MeshObject: TgxMeshObject): TFace;
- var
- Face : TFace;
- begin
- Face := TFace.Create(MeshObject);
- FaceList.Add(Face);
- Face.Vertices[0] := Vi0;
- Face.Vertices[1] := Vi1;
- Face.Vertices[2] := Vi2;
- AddEdge(Vi0, Vi1, Face, MeshObject);
- AddEdge(Vi1, Vi2, Face, MeshObject);
- AddEdge(Vi2, Vi0, Face, MeshObject);//}
- result := Face;
- end;
- procedure TEdgeDetector.AddNodes(const VerletWorld : TgxVerletWorld);
- var
- i : integer;
- MO : TgxMeshObject;
- begin
- FNodesAdded := true;
- FCurrentNodeOffset := FNodeList.Count;
- MO := FGLBaseMesh.MeshObjects[0];
- for i := 0 to MO.Vertices.Count-1 do
- AddNode(VerletWorld, MO, i);
- // Assert(FNodeList.Count = MO.Vertices.Count, Format('%d <> %d',[FNodeList.Count, MO.Vertices.Count]));
- end;
- procedure TEdgeDetector.AddEdgesAsSprings(const VerletWorld : TgxVerletWorld;
- const Strength, Damping, Slack: single);
- var
- i : integer;
- Edge : TEdge;
- begin
- if not FNodesAdded then
- AddNodes(VerletWorld);
- for i := 0 to EdgeList.Count-1 do
- begin
- // if not EdgeList[i].SameSame(FNodeList) then
- Edge := EdgeList[i];
- if FNodeList[FCurrentNodeOffset+Edge.Vertices[0]] <> FNodeList[FCurrentNodeOffset+Edge.Vertices[1]] then
- begin
- VerletWorld.CreateSpring(
- FNodeList[FCurrentNodeOffset+Edge.Vertices[0]],
- FNodeList[FCurrentNodeOffset+Edge.Vertices[1]],
- Strength, Damping, Slack);
- end;
- end;
- end;
- procedure TEdgeDetector.AddEdgesAsSticks(const VerletWorld : TgxVerletWorld;
- const Slack : single);
- var
- i : integer;
- Edge : TEdge;
- begin
- if not FNodesAdded then
- AddNodes(VerletWorld);
- for i := 0 to EdgeList.Count-1 do
- begin
- // if not EdgeList[i].SameSame(FNodeList) then
- Edge := EdgeList[i];
- if FNodeList[FCurrentNodeOffset+Edge.Vertices[0]] <> FNodeList[FCurrentNodeOffset+Edge.Vertices[1]] then
- begin
- VerletWorld.CreateStick(
- FNodeList[FCurrentNodeOffset + Edge.Vertices[0]],
- FNodeList[FCurrentNodeOffset + Edge.Vertices[1]],
- Slack);
- end;
- end;
- end;
- procedure TEdgeDetector.AddEdgesAsSolidEdges(
- const VerletWorld: TgxVerletWorld);
- var
- i : integer;
- Edge : TEdge;
- begin
- if not FNodesAdded then
- AddNodes(VerletWorld);
- for i := 0 to EdgeList.Count-1 do
- begin
- // if not EdgeList[i].SameSame(FNodeList) then
- Edge := EdgeList[i];
- if FNodeList[FCurrentNodeOffset+Edge.Vertices[0]] <> FNodeList[FCurrentNodeOffset+Edge.Vertices[1]] then
- begin
- if Edge.Solid then
- VerletWorld.AddSolidEdge(
- FNodeList[FCurrentNodeOffset + Edge.Vertices[0]],
- FNodeList[FCurrentNodeOffset + Edge.Vertices[1]]);
- end;
- end;
- end;
- procedure TEdgeDetector.AddOuterEdgesAsSolidEdges(
- const VerletWorld: TgxVerletWorld);
- var
- i : integer;
- Edge : TEdge;
- begin
- if not FNodesAdded then
- AddNodes(VerletWorld);
- for i := 0 to EdgeList.Count-1 do
- begin
- // if not EdgeList[i].SameSame(FNodeList) then
- Edge := EdgeList[i];
- if FNodeList[FCurrentNodeOffset+Edge.Vertices[0]] <> FNodeList[FCurrentNodeOffset+Edge.Vertices[1]] then
- begin
- if Edge.Solid and (Edge.Faces[1]=nil) then
- VerletWorld.AddSolidEdge(
- FNodeList[FCurrentNodeOffset + Edge.Vertices[0]],
- FNodeList[FCurrentNodeOffset + Edge.Vertices[1]]);
- end;
- end;
- end;
- procedure TEdgeDetector.RenderEdges(var rci: TgxRenderContextInfo);
- var
- i : integer;
- Edge : TEdge;
- Vertex0, Vertex1 : TAffineVector;
- begin
- if EdgeList.Count>0 then
- begin
- rci.gxStates.Disable(stLighting);
- rci.gxStates.LineWidth := 3;
- glColor3f(1,1,1);
- glBegin(GL_LINES);
- for i := 0 to EdgeList.Count - 1 do
- begin
- Edge := EdgeList[i];
- Vertex0 := Edge.MeshObject.Vertices[Edge.Vertices[0]];
- Vertex1 := Edge.MeshObject.Vertices[Edge.Vertices[1]];
- glVertex3fv(PGLfloat(@Vertex0));
- glVertex3fv(PGLfloat(@Vertex1));
- end;
- glEnd;
- end;//}
- end;
- procedure TEdgeDetector.BuildOpposingEdges;
- var
- iEdge, EdgeCount, vi0, vi1, iEdgeTest : integer;
- Face0, Face1 : TFace;
- Edge, NewEdge, TestEdge : TEdge;
- begin
- // For each edge that's connected by two triangles, create a new edge that
- // connects the two "extra" vertices.... makes sense?
- EdgeCount := EdgeList.Count;
- for iEdge := 0 to EdgeCount-1 do
- begin
- Edge := EdgeList[iEdge];
- if Assigned(Edge.Faces[1]) then
- begin
- Face0 := Edge.Faces[0];
- Face1 := Edge.Faces[1];
- if (Face0.Vertices[0] <> Edge.Vertices[0]) and (Face0.Vertices[0] <> Edge.Vertices[1]) then
- vi0 := Face0.Vertices[0]
- else if (Face0.Vertices[1] <> Edge.Vertices[0]) and (Face0.Vertices[1] <> Edge.Vertices[1]) then
- vi0 := Face0.Vertices[1]
- else
- vi0 := Face0.Vertices[2];
- if (Face1.Vertices[0] <> Edge.Vertices[0]) and (Face1.Vertices[0] <> Edge.Vertices[1]) then
- vi1 := Face1.Vertices[0]
- else if (Face1.Vertices[1] <> Edge.Vertices[0]) and (Face1.Vertices[1] <> Edge.Vertices[1]) then
- vi1 := Face1.Vertices[1]
- else
- vi1 := Face1.Vertices[2];
- if (vi0=vi1) or
- (vi0=Edge.Vertices[0]) or
- (vi0=Edge.Vertices[1]) or
- (vi1=Edge.Vertices[0]) or
- (vi1=Edge.Vertices[1]) then
- continue;
- // Find an indentical edge, if there is one
- for iEdgeTest := 0 to EdgeList.Count - 1 do
- begin
- TestEdge := EdgeList[iEdgeTest];
- if (TestEdge.Vertices[0]=Vi0) and (TestEdge.Vertices[1]=Vi1) or
- (TestEdge.Vertices[1]=Vi0) and (TestEdge.Vertices[0]=Vi1) then
- begin
- // Edge allready exists!
- inc(FEdgeDoublesSkipped);
- continue;
- end;
- end;
- NewEdge := TEdge.Create(self, Vi0, Vi1, nil, nil, Edge.MeshObject, false);
- EdgeList.Add(NewEdge);//}
- end;
- end;
- end;
- function TEdgeDetector.AddNode(const VerletWorld : TgxVerletWorld; const MeshObject: TgxMeshObject;
- const VertexIndex: integer): TgxVerletNode;
- var
- Location : TAffineVector;
- aNode : TgxMeshObjectVerletNode;
- i : integer;
- begin
- // Is there an identical node?
- Location := MeshObject.Owner.Owner.LocalToAbsolute(MeshObject.Vertices[VertexIndex]);
- for i := FCurrentNodeOffset to FNodeList.Count-1 do
- begin
- aNode := TgxMeshObjectVerletNode(FNodeList[i]);
- if VectorDistance2(Location, aNode.Location)<=FWeldDistance then
- begin
- FNodeList.Add(aNode);
- aNode.VertexIndices.Add(VertexIndex);
- Result:=aNode;
- Exit;
- end;
- end;//}
- aNode := TgxMeshObjectVerletNode.CreateOwned(VerletWorld);
- aNode.MeshObject := MeshObject;
- aNode.VertexIndices.Add(VertexIndex);
- aNode.Location := Location;
- aNode.OldLocation := Location;
- FNodeList.Add(aNode);
- Result:=aNode;
- end;
- procedure TEdgeDetector.ProcessMesh;
- begin
- inherited;
- BuildOpposingEdges;
- end;
- procedure TEdgeDetector.ReplaceVertexIndex(const ViRemove,
- ViReplaceWith: integer);
- var
- i : integer;
- Done : boolean;
- Edge : TEdge;
- begin
- for i := 0 to FaceList.Count-1 do
- with FaceList[i] do
- begin
- if Active then
- begin
- if Vertices[0] = ViRemove then
- Vertices[0] := ViReplaceWith;
- if Vertices[1] = ViRemove then
- Vertices[1] := ViReplaceWith;
- if Vertices[2] = ViRemove then
- Vertices[2] := ViReplaceWith;
- if (Vertices[0]=Vertices[1]) or
- (Vertices[1]=Vertices[2]) or
- (Vertices[2]=Vertices[0]) then
- Active := false;
- end;
- end;
- Done := false;
- while not Done do
- begin
- Done := true;
- for i := 0 to EdgeList.Count-1 do
- with EdgeList[i] do
- begin
- if (Vertices[0] = ViRemove) or (Vertices[1] = ViRemove) then
- begin
- if Vertices[0] = ViRemove then
- Vertices[0] := ViReplaceWith;
- if Vertices[1] = ViRemove then
- Vertices[1] := ViReplaceWith;
- UpdateEdgeLength;
- Edge := EdgeList[i];
- EdgeList.Delete(i);
- if Edge.Length=-1 then
- Edge.Free
- else
- EdgeList.InsertSorted(Edge);
- Done := false;
- break;//}
- end;
- end;
- end;
- end;
- //----------------------------------------
- // TFace
- //----------------------------------------
- constructor TFace.Create(aMeshObject: TgxMeshObject);
- begin
- MeshObject := aMeshObject;
- Active := true;
- end;
- procedure TFace.UpdateNormal;
- begin
- CalcPlaneNormal(
- MeshObject.Vertices[Vertices[0]],
- MeshObject.Vertices[Vertices[1]],
- MeshObject.Vertices[Vertices[2]], Normal);
- end;
- //----------------------------------------
- // TEdge
- //----------------------------------------
- procedure TEdge.Contract;
- begin
- // We're removing vertex 1 and replacing it with vertex 0
- FOwner.ReplaceVertexIndex(Vertices[1], Vertices[0]);
- //MeshObject.Vertices[Vertices[0]] := MeshObject.Vertices[Vertices[1]];
- Length := -1;
- end;
- constructor TEdge.Create(const AOwner: TEdgeDetector; AVi0, AVi1 : integer;
- AFace0, AFace1 : TFace; AMeshObject : TgxMeshObject; ASolid : boolean);
- begin
- FOwner := AOwner;
- Vertices[0] := AVi0;
- Vertices[1] := AVi1;
- Faces[0] := AFace0;
- Faces[1] := AFace1;
- FMeshObject := AMeshObject;
- FSolid := true;
- UpdateEdgeLength;
- end;
- procedure TEdge.UpdateEdgeLength;
- begin
- if FOwner.FCalcEdgeLength then
- begin
- if Vertices[0] = Vertices[1] then
- Length := -1
- else
- Length := VectorDistance(
- FOwner.GLBaseMesh.LocalToAbsolute(FMeshObject.Vertices[Vertices[0]]),
- FOwner.GLBaseMesh.LocalToAbsolute(FMeshObject.Vertices[Vertices[1]]));
- end;
- end;
- end.
|