123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.FileNurbs;
- (* Nurbs surfaces vector file loading *)
- interface
- uses
- System.Classes,
- System.SysUtils,
- Stage.VectorGeometry,
- Stage.VectorTypes,
- GXS.VectorFileObjects,
- GXS.VectorLists,
- GXS.ApplicationFileIO,
- GXS.ParametricSurfaces,
- GXS.ImageUtils;
- type
- TgxNurbsVectorFile = class(TgxVectorFile)
- public
- class function Capabilities: TDataFileCapabilities; override;
- procedure LoadFromStream(stream: TStream); override;
- end;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- // ------------------
- // ------------------ TgxNurbsVectorFile ------------------
- // ------------------
- class function TgxNurbsVectorFile.Capabilities: TDataFileCapabilities;
- begin
- Result := [dfcRead];
- end;
- procedure TgxNurbsVectorFile.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: TgxSingleList): 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(StrToFloatDef(vals[k], 0));
- Inc(idx);
- end;
- Result := idx;
- finally
- vals.Free;
- end;
- end;
- function ReadVectorArray(sl: TStrings; idx: Integer;
- list: TgxAffineVectorList): 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(StrToFloatDef(vals[0], 0),
- StrToFloatDef(vals[1], 0),
- StrToFloatDef(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: TgxAffineVectorList;
- 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 := psrOpenVX;
- 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 := TgxAffineVectorList.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', TgxNurbsVectorFile);
- end.
|