2
0

GLFileNurbs.pas 4.7 KB

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