123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- //
- // The graphics engine GLScene
- //
- unit GLS.FileNurbs;
- (* Loading Nurbs surfaces vector files. *)
- interface
- uses
- System.Classes,
- System.SysUtils,
- Stage.VectorTypes,
- GLS.VectorFileObjects,
- Stage.VectorGeometry,
- GLS.VectorLists,
- GLS.ApplicationFileIO,
- GLS.ParametricSurfaces,
- Stage.Utils;
- type
- TGLNurbsVectorFile = class(TGLVectorFile)
- public
- class function Capabilities: TGLDataFileCapabilities; override;
- procedure LoadFromStream(stream: TStream); override;
- end;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- // ------------------
- // ------------------ TGLNurbsVectorFile ------------------
- // ------------------
- class function TGLNurbsVectorFile.Capabilities: TGLDataFileCapabilities;
- begin
- Result := [dfcRead];
- end;
- procedure TGLNurbsVectorFile.LoadFromStream(stream: TStream);
- function CleanupLine(const line: String): String;
- var
- p: Integer;
- begin
- p := Pos('#', line);
- if p > 0 then
- Result := LowerCase(Trim(Copy(line, 1, p - 1)))
- else
- Result := LowerCase(Trim(line));
- end;
- function ReadSingleArray(sl: TStrings; idx: Integer;
- list: TGLSingleList): Integer;
- var
- k: Integer;
- buf: String;
- vals: TStringList;
- begin
- vals := TStringList.Create;
- try
- while idx < sl.Count do
- begin
- buf := CleanupLine(sl[idx]);
- if buf = ']' then
- Break;
- vals.CommaText := buf;
- for k := 0 to vals.Count - 1 do
- if vals[k] <> '' then
- list.Add(GLStrToFloatDef(vals[k], 0));
- Inc(idx);
- end;
- Result := idx;
- finally
- vals.Free;
- end;
- end;
- function ReadVectorArray(sl: TStrings; idx: Integer;
- list: TGLAffineVectorList): Integer;
- var
- buf: String;
- vals: TStringList;
- begin
- vals := TStringList.Create;
- try
- while idx < sl.Count do
- begin
- buf := CleanupLine(sl[idx]);
- if buf = ']' then
- Break;
- vals.CommaText := buf;
- if vals.Count >= 3 then
- list.Add(GLStrToFloatDef(vals[0], 0),
- GLStrToFloatDef(vals[1], 0),
- GLStrToFloatDef(vals[2], 0));
- Inc(idx);
- end;
- Result := idx;
- finally
- vals.Free;
- end;
- end;
- var
- sl, buf: TStringList;
- ss: TStringStream;
- i, j: Integer;
- surface: TMOParametricSurface;
- invert: Boolean;
- invControlPoints: TGLAffineVectorList;
- begin
- ss := TStringStream.Create('');
- sl := TStringList.Create;
- buf := TStringList.Create;
- surface := TMOParametricSurface.CreateOwned(Owner.MeshObjects);
- with surface do
- begin
- Name := 'Nurbs' + IntToStr(Owner.IndexOf(surface));
- Basis := psbBSpline;
- Renderer := psrOpenGL;
- AutoKnots := False;
- end;
- invert := False;
- try
- ss.CopyFrom(stream, stream.Size - stream.Position);
- sl.Text := ss.DataString;
- i := 0;
- while i < sl.Count do
- begin
- buf.CommaText := CleanupLine(sl[i]);
- if buf.Count > 1 then
- begin
- if buf[0] = 'uorder' then
- surface.OrderU := StrToIntDef(buf[1], 2)
- else if buf[0] = 'vorder' then
- surface.OrderV := StrToIntDef(buf[1], 2)
- else if buf[0] = 'uknot' then
- i := ReadSingleArray(sl, i + 1, surface.KnotsU)
- else if buf[0] = 'vknot' then
- i := ReadSingleArray(sl, i + 1, surface.KnotsV)
- else if buf[0] = 'weight' then
- i := ReadSingleArray(sl, i + 1, surface.Weights)
- else if buf[0] = 'udimension' then
- surface.CountU := StrToIntDef(buf[1], 0)
- else if buf[0] = 'vdimension' then
- surface.CountV := StrToIntDef(buf[1], 0)
- else if buf[0] = 'controlpoint' then
- i := ReadVectorArray(sl, i + 1, surface.ControlPoints)
- else if buf[0] = 'ccw' then
- invert := (buf[1] = 'false');
- end;
- Inc(i);
- end;
- if invert then
- begin
- invControlPoints := TGLAffineVectorList.Create;
- for i := surface.CountV - 1 downto 0 do
- for j := 0 to surface.CountU - 1 do
- invControlPoints.Add(surface.ControlPoints[i * surface.CountU + j]);
- surface.ControlPoints.Assign(invControlPoints);
- invControlPoints.Free;
- end;
- finally
- buf.Free;
- sl.Free;
- ss.Free;
- end;
- end;
- // ------------------------------------------------------------------
- initialization
- // ------------------------------------------------------------------
- RegisterVectorFileFormat('nurbs', 'Nurbs model files', TGLNurbsVectorFile);
- end.
|