GXS.FileNurbs.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.FileNurbs;
  5. (* Nurbs surfaces vector file loading *)
  6. interface
  7. uses
  8. System.Classes,
  9. System.SysUtils,
  10. Stage.VectorGeometry,
  11. Stage.VectorTypes,
  12. GXS.VectorFileObjects,
  13. GXS.VectorLists,
  14. GXS.ApplicationFileIO,
  15. GXS.ParametricSurfaces,
  16. GXS.ImageUtils;
  17. type
  18. TgxNurbsVectorFile = class(TgxVectorFile)
  19. public
  20. class function Capabilities: TDataFileCapabilities; override;
  21. procedure LoadFromStream(stream: TStream); override;
  22. end;
  23. // ------------------------------------------------------------------
  24. implementation
  25. // ------------------------------------------------------------------
  26. // ------------------
  27. // ------------------ TgxNurbsVectorFile ------------------
  28. // ------------------
  29. class function TgxNurbsVectorFile.Capabilities: TDataFileCapabilities;
  30. begin
  31. Result := [dfcRead];
  32. end;
  33. procedure TgxNurbsVectorFile.LoadFromStream(stream: TStream);
  34. function CleanupLine(const line: String): String;
  35. var
  36. p: Integer;
  37. begin
  38. p := Pos('#', line);
  39. if p > 0 then
  40. Result := LowerCase(Trim(Copy(line, 1, p - 1)))
  41. else
  42. Result := LowerCase(Trim(line));
  43. end;
  44. function ReadSingleArray(sl: TStrings; idx: Integer;
  45. list: TgxSingleList): Integer;
  46. var
  47. k: Integer;
  48. buf: String;
  49. vals: TStringList;
  50. begin
  51. vals := TStringList.Create;
  52. try
  53. while idx < sl.Count do
  54. begin
  55. buf := CleanupLine(sl[idx]);
  56. if buf = ']' then
  57. Break;
  58. vals.CommaText := buf;
  59. for k := 0 to vals.Count - 1 do
  60. if vals[k] <> '' then
  61. list.Add(StrToFloatDef(vals[k], 0));
  62. Inc(idx);
  63. end;
  64. Result := idx;
  65. finally
  66. vals.Free;
  67. end;
  68. end;
  69. function ReadVectorArray(sl: TStrings; idx: Integer;
  70. list: TgxAffineVectorList): Integer;
  71. var
  72. buf: String;
  73. vals: TStringList;
  74. begin
  75. vals := TStringList.Create;
  76. try
  77. while idx < sl.Count do
  78. begin
  79. buf := CleanupLine(sl[idx]);
  80. if buf = ']' then
  81. Break;
  82. vals.CommaText := buf;
  83. if vals.Count >= 3 then
  84. list.Add(StrToFloatDef(vals[0], 0),
  85. StrToFloatDef(vals[1], 0),
  86. StrToFloatDef(vals[2], 0));
  87. Inc(idx);
  88. end;
  89. Result := idx;
  90. finally
  91. vals.Free;
  92. end;
  93. end;
  94. var
  95. sl, buf: TStringList;
  96. ss: TStringStream;
  97. i, j: Integer;
  98. surface: TMOParametricSurface;
  99. invert: Boolean;
  100. invControlPoints: TgxAffineVectorList;
  101. begin
  102. ss := TStringStream.Create('');
  103. sl := TStringList.Create;
  104. buf := TStringList.Create;
  105. surface := TMOParametricSurface.CreateOwned(Owner.MeshObjects);
  106. with surface do
  107. begin
  108. Name := 'Nurbs' + IntToStr(Owner.IndexOf(surface));
  109. Basis := psbBSpline;
  110. Renderer := psrOpenVX;
  111. AutoKnots := False;
  112. end;
  113. invert := False;
  114. try
  115. ss.CopyFrom(stream, stream.Size - stream.Position);
  116. sl.Text := ss.DataString;
  117. i := 0;
  118. while i < sl.Count do
  119. begin
  120. buf.CommaText := CleanupLine(sl[i]);
  121. if buf.Count > 1 then
  122. begin
  123. if buf[0] = 'uorder' then
  124. surface.OrderU := StrToIntDef(buf[1], 2)
  125. else if buf[0] = 'vorder' then
  126. surface.OrderV := StrToIntDef(buf[1], 2)
  127. else if buf[0] = 'uknot' then
  128. i := ReadSingleArray(sl, i + 1, surface.KnotsU)
  129. else if buf[0] = 'vknot' then
  130. i := ReadSingleArray(sl, i + 1, surface.KnotsV)
  131. else if buf[0] = 'weight' then
  132. i := ReadSingleArray(sl, i + 1, surface.Weights)
  133. else if buf[0] = 'udimension' then
  134. surface.CountU := StrToIntDef(buf[1], 0)
  135. else if buf[0] = 'vdimension' then
  136. surface.CountV := StrToIntDef(buf[1], 0)
  137. else if buf[0] = 'controlpoint' then
  138. i := ReadVectorArray(sl, i + 1, surface.ControlPoints)
  139. else if buf[0] = 'ccw' then
  140. invert := (buf[1] = 'false');
  141. end;
  142. Inc(i);
  143. end;
  144. if invert then
  145. begin
  146. invControlPoints := TgxAffineVectorList.Create;
  147. for i := surface.CountV - 1 downto 0 do
  148. for j := 0 to surface.CountU - 1 do
  149. invControlPoints.Add(surface.ControlPoints[i * surface.CountU + j]);
  150. surface.ControlPoints.Assign(invControlPoints);
  151. invControlPoints.Free;
  152. end;
  153. finally
  154. buf.Free;
  155. sl.Free;
  156. ss.Free;
  157. end;
  158. end;
  159. // ------------------------------------------------------------------
  160. initialization
  161. // ------------------------------------------------------------------
  162. RegisterVectorFileFormat('nurbs', 'Nurbs model files', TgxNurbsVectorFile);
  163. end.