123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- //
- // The graphics engine GLScene
- //
- unit GLS.BaseMeshSilhouette;
- (* Silhouette classes for GLBaseMesh and FaceGroups. *)
- interface
- {$I Stage.Defines.inc}
- uses
- System.Classes,
- Stage.VectorGeometry,
- GLS.VectorLists,
- GLS.VectorFileObjects,
- GLS.Silhouette;
- type
- TGLFaceGroupConnectivity = class(TGLConnectivity)
- private
- FMeshObject: TGLMeshObject;
- FOwnsVertices: boolean;
- procedure SetMeshObject(const Value: TGLMeshObject);
- public
- procedure Clear; override;
- // Builds the connectivity information.
- procedure RebuildEdgeList;
- property MeshObject: TGLMeshObject read FMeshObject write SetMeshObject;
- constructor Create(APrecomputeFaceNormal: boolean); override;
- constructor CreateFromMesh(aMeshObject: TGLMeshObject; APrecomputeFaceNormal: boolean);
- destructor Destroy; override;
- end;
- TGLBaseMeshConnectivity = class(TGLBaseConnectivity)
- private
- FBaseMesh: TGLBaseMesh;
- FFaceGroupConnectivityList: TList;
- function GetFaceGroupConnectivity(i: integer): TGLFaceGroupConnectivity;
- function GetConnectivityCount: integer;
- procedure SetBaseMesh(const Value: TGLBaseMesh);
- protected
- function GetEdgeCount: integer; override;
- function GetFaceCount: integer; override;
- public
- property ConnectivityCount: integer read GetConnectivityCount;
- property FaceGroupConnectivity[i: integer]: TGLFaceGroupConnectivity read GetFaceGroupConnectivity;
- property BaseMesh: TGLBaseMesh read FBaseMesh write SetBaseMesh;
- procedure Clear(SaveFaceGroupConnectivity: boolean);
- // Builds the connectivity information.
- procedure RebuildEdgeList;
- procedure CreateSilhouette(const silhouetteParameters: TGLSilhouetteParameters; var aSilhouette: TGLSilhouette;
- AddToSilhouette: boolean);
- constructor Create(APrecomputeFaceNormal: boolean); override;
- constructor CreateFromMesh(aBaseMesh: TGLBaseMesh);
- destructor Destroy; override;
- end;
- //==============================================================================
- implementation
- //==============================================================================
- // ------------------
- // ------------------ TGLFaceGroupConnectivity ------------------
- // ------------------
- procedure TGLFaceGroupConnectivity.Clear;
- begin
- if Assigned(FVertices) then
- begin
- if FOwnsVertices then
- FVertices.Clear
- else
- FVertices := nil;
- inherited;
- if not FOwnsVertices and Assigned(FMeshObject) then
- FVertices := FMeshObject.Vertices;
- end
- else
- inherited;
- end;
- constructor TGLFaceGroupConnectivity.Create(APrecomputeFaceNormal: boolean);
- begin
- inherited;
- FOwnsVertices := true;
- end;
- procedure TGLFaceGroupConnectivity.SetMeshObject(const Value: TGLMeshObject);
- begin
- Clear;
- FMeshObject := Value;
- if FOwnsVertices then
- FVertices.Free;
- FVertices := FMeshObject.Vertices;
- FOwnsVertices := false;
- RebuildEdgeList;
- end;
- constructor TGLFaceGroupConnectivity.CreateFromMesh(aMeshObject: TGLMeshObject; APrecomputeFaceNormal: boolean);
- begin
- Create(APrecomputeFaceNormal);
- MeshObject := aMeshObject;
- end;
- destructor TGLFaceGroupConnectivity.Destroy;
- begin
- if FOwnsVertices then
- FVertices.Free;
- FVertices := nil;
- inherited;
- end;
- procedure TGLFaceGroupConnectivity.RebuildEdgeList;
- var
- iFaceGroup, iFace, iVertex: integer;
- FaceGroup: TFGVertexIndexList;
- List: PIntegerArray;
- begin
- // Make sure that the connectivity information is empty
- Clear;
- // Create a list of edges for the meshobject
- for iFaceGroup := 0 to FMeshObject.FaceGroups.Count - 1 do
- begin
- Assert(FMeshObject.FaceGroups[iFaceGroup] is TFGVertexIndexList, 'Method only works for descendants of TFGVertexIndexList.');
- FaceGroup := TFGVertexIndexList(FMeshObject.FaceGroups[iFaceGroup]);
- case FaceGroup.Mode of
- fgmmTriangles, fgmmFlatTriangles:
- begin
- for iFace := 0 to FaceGroup.TriangleCount - 1 do
- begin
- List := @FaceGroup.VertexIndices.List[iFace * 3 + 0];
- AddIndexedFace(List^[0], List^[1], List^[2]);
- 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
- AddIndexedFace(List^[0], List^[1], List^[2])
- else
- AddIndexedFace(List^[2], List^[1], List^[0]);
- end;
- end;
- fgmmTriangleFan:
- begin
- List := FaceGroup.VertexIndices.List;
- for iVertex := 2 to FaceGroup.VertexIndices.Count - 1 do
- AddIndexedFace(List^[0], List^[iVertex - 1], List^[iVertex])
- end;
- else
- Assert(false, 'Not supported');
- end;
- end;
- end;
- // ------------------
- // ------------------ TGLBaseMeshConnectivity ------------------
- // ------------------
- procedure TGLBaseMeshConnectivity.RebuildEdgeList;
- var
- i: integer;
- begin
- for i := 0 to ConnectivityCount - 1 do
- FaceGroupConnectivity[i].RebuildEdgeList;
- end;
- procedure TGLBaseMeshConnectivity.Clear(SaveFaceGroupConnectivity: boolean);
- var
- i: integer;
- begin
- if SaveFaceGroupConnectivity then
- begin
- for i := 0 to ConnectivityCount - 1 do
- FaceGroupConnectivity[i].Clear;
- end
- else
- begin
- for i := 0 to ConnectivityCount - 1 do
- FaceGroupConnectivity[i].Free;
- FFaceGroupConnectivityList.Clear;
- end;
- end;
- constructor TGLBaseMeshConnectivity.Create(APrecomputeFaceNormal: boolean);
- begin
- FFaceGroupConnectivityList := TList.Create;
- inherited;
- end;
- constructor TGLBaseMeshConnectivity.CreateFromMesh(aBaseMesh: TGLBaseMesh);
- begin
- Create(not(aBaseMesh is TGLActor));
- BaseMesh := aBaseMesh;
- end;
- procedure TGLBaseMeshConnectivity.SetBaseMesh(const Value: TGLBaseMesh);
- var
- i: integer;
- MO: TGLMeshObject;
- Connectivity: TGLFaceGroupConnectivity;
- begin
- Clear(false);
- FBaseMesh := Value;
- // Only precompute normals if the basemesh isn't an actor (because they change)
- FPrecomputeFaceNormal := not(Value is TGLActor);
- FBaseMesh := Value;
- for i := 0 to Value.MeshObjects.Count - 1 do
- begin
- MO := Value.MeshObjects[i];
- if MO.Visible then
- begin
- Connectivity := TGLFaceGroupConnectivity.CreateFromMesh(MO, FPrecomputeFaceNormal);
- FFaceGroupConnectivityList.Add(Connectivity);
- end;
- end;
- end;
- procedure TGLBaseMeshConnectivity.CreateSilhouette(const silhouetteParameters: TGLSilhouetteParameters;
- var aSilhouette: TGLSilhouette; AddToSilhouette: boolean);
- var
- i: integer;
- begin
- if aSilhouette = nil then
- aSilhouette := TGLSilhouette.Create
- else
- aSilhouette.Flush;
- for i := 0 to ConnectivityCount - 1 do
- FaceGroupConnectivity[i].CreateSilhouette(silhouetteParameters, aSilhouette, true);
- end;
- destructor TGLBaseMeshConnectivity.Destroy;
- begin
- Clear(false);
- FFaceGroupConnectivityList.Free;
- inherited;
- end;
- function TGLBaseMeshConnectivity.GetConnectivityCount: integer;
- begin
- result := FFaceGroupConnectivityList.Count;
- end;
- function TGLBaseMeshConnectivity.GetEdgeCount: integer;
- var
- i: integer;
- begin
- result := 0;
- for i := 0 to ConnectivityCount - 1 do
- result := result + FaceGroupConnectivity[i].EdgeCount;
- end;
- function TGLBaseMeshConnectivity.GetFaceCount: integer;
- var
- i: integer;
- begin
- result := 0;
- for i := 0 to ConnectivityCount - 1 do
- result := result + FaceGroupConnectivity[i].FaceCount;
- end;
- function TGLBaseMeshConnectivity.GetFaceGroupConnectivity(i: integer): TGLFaceGroupConnectivity;
- begin
- result := TGLFaceGroupConnectivity(FFaceGroupConnectivityList[i]);
- end;
- end.
|