123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- //
- // The graphics engine GXScene https://github.com/glscene
- //
- unit GXS.FileNMF;
- (* NormalMapper loading into GLScene FreeForms/Actors *)
- interface
- uses
- System.Classes,
- Stage.VectorTypes,
- GXS.VectorFileObjects,
- Stage.VectorGeometry,
- GXS.VectorLists,
- GXS.ApplicationFileIO;
- const
- NMF_HEADER_TAG = 'NMF ';
- NMF_TRIANGLE_TAG = 'TRIS';
- type
- TNmHeader = record
- hdr: array [0 .. 3] of AnsiChar;
- size: cardinal;
- end;
- TNmRawTriangle = record
- vert, norm: array [0 .. 2] of TAffineVector;
- texCoord: array [0 .. 2] of TTexPoint;
- end;
- TFileNMF = class
- public
- FileHeader, TrisHeader: TNmHeader;
- NumTris: Integer;
- RawTriangles: array of TNmRawTriangle;
- procedure LoadFromStream(Stream: TStream);
- procedure SaveToStream(Stream: TStream);
- end;
- type
- TgxNMFVectorFile = class(TgxVectorFile)
- public
- class function Capabilities: TDataFileCapabilities; override;
- procedure LoadFromStream(aStream: TStream); override;
- procedure SaveToStream(aStream: TStream); override;
- end;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- procedure TFileNMF.LoadFromStream(Stream: TStream);
- var
- Done: Boolean;
- begin
- Stream.Read(FileHeader, SizeOf(TNmHeader));
- if FileHeader.hdr <> NMF_HEADER_TAG then
- exit;
- Done := False;
- while not Done do
- begin
- Stream.Read(TrisHeader, SizeOf(TNmHeader));
- if TrisHeader.hdr = NMF_TRIANGLE_TAG then
- begin
- Stream.Read(NumTris, SizeOf(NumTris));
- if NumTris < 0 then
- exit;
- SetLength(RawTriangles, NumTris);
- Stream.Read(RawTriangles[0], SizeOf(TNmRawTriangle) * NumTris);
- Done := True;
- end;
- end;
- end;
- procedure TFileNMF.SaveToStream(Stream: TStream);
- begin
- NumTris := Length(RawTriangles);
- TrisHeader.hdr := NMF_TRIANGLE_TAG;
- TrisHeader.size := SizeOf(TNmRawTriangle) * NumTris + SizeOf(FileHeader);
- FileHeader.hdr := NMF_HEADER_TAG;
- FileHeader.size := TrisHeader.size + SizeOf(TrisHeader);
- Stream.Write(FileHeader, SizeOf(TNmHeader));
- Stream.Write(TrisHeader, SizeOf(TNmHeader));
- NumTris := Length(RawTriangles);
- Stream.Write(NumTris, SizeOf(NumTris));
- Stream.Write(RawTriangles[0], SizeOf(TNmRawTriangle) * NumTris);
- end;
- // ------------------
- // ------------------ TgxNMFVectorFile ------------------
- // ------------------
- class function TgxNMFVectorFile.Capabilities: TDataFileCapabilities;
- begin
- Result := [dfcRead, dfcWrite];
- end;
- // LoadFromStream
- //
- procedure TgxNMFVectorFile.LoadFromStream(aStream: TStream);
- var
- i, j: Integer;
- mesh: TgxMeshObject;
- nmf: TFileNMF;
- begin
- nmf := TFileNMF.Create;
- try
- nmf.LoadFromStream(aStream);
- mesh := TgxMeshObject.CreateOwned(Owner.MeshObjects);
- mesh.Mode := momTriangles;
- for i := 0 to nmf.NumTris - 1 do
- begin
- for j := 0 to 2 do
- begin
- mesh.Vertices.Add(nmf.RawTriangles[i].vert[j]);
- mesh.Normals.Add(nmf.RawTriangles[i].norm[j]);
- mesh.TexCoords.Add(nmf.RawTriangles[i].texCoord[j]);
- end;
- end;
- finally
- nmf.Free;
- end;
- end;
- // SaveToStream
- //
- procedure TgxNMFVectorFile.SaveToStream(aStream: TStream);
- var
- i, j: Integer;
- nmf: TFileNMF;
- Vertices, TempVertices, Normals, TexCoords: TgxAffineVectorList;
- begin
- nmf := TFileNMF.Create;
- Vertices := TgxAffineVectorList.Create;
- Normals := TgxAffineVectorList.Create;
- TexCoords := TgxAffineVectorList.Create;
- try
- for i := 0 to Owner.MeshObjects.Count - 1 do
- begin
- TempVertices := Owner.MeshObjects[i].ExtractTriangles(TexCoords, Normals);
- Vertices.Add(TempVertices);
- TempVertices.Free;
- end;
- nmf.NumTris := (Vertices.Count div 3);
- SetLength(nmf.RawTriangles, nmf.NumTris);
- for i := 0 to nmf.NumTris - 1 do
- begin
- for j := 0 to 2 do
- begin
- nmf.RawTriangles[i].vert[j] := Vertices[3 * i + j];
- nmf.RawTriangles[i].norm[j] := Normals[3 * i + j];
- nmf.RawTriangles[i].texCoord[j].S := TexCoords[3 * i + j].X;
- nmf.RawTriangles[i].texCoord[j].T := TexCoords[3 * i + j].Y;
- end;
- end;
- nmf.SaveToStream(aStream);
- finally
- Vertices.Free;
- Normals.Free;
- TexCoords.Free;
- nmf.Free;
- end;
- end;
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- // ------------------------------------------------------------------
- RegisterVectorFileFormat('nmf', 'NormalMapper files', TgxNMFVectorFile);
- end.
|