aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/SculptMesh.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/SculptMesh.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs686
1 files changed, 343 insertions, 343 deletions
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index 312f89a..826030b 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -1,343 +1,343 @@
1/* 1/*
2 * Copyright (c) Contributors 2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using System.IO; 31using System.IO;
32using System.Drawing; 32using System.Drawing;
33using System.Drawing.Imaging; 33using System.Drawing.Imaging;
34 34
35namespace PrimMesher 35namespace PrimMesher
36{ 36{
37 37
38 public class SculptMesh 38 public class SculptMesh
39 { 39 {
40 public List<Coord> coords; 40 public List<Coord> coords;
41 public List<Face> faces; 41 public List<Face> faces;
42 42
43 public List<ViewerFace> viewerFaces; 43 public List<ViewerFace> viewerFaces;
44 public List<Coord> normals; 44 public List<Coord> normals;
45 public List<UVCoord> uvs; 45 public List<UVCoord> uvs;
46 46
47 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; 47 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
48 private const float pixScale = 0.00390625f; // 1.0 / 256 48 private const float pixScale = 0.00390625f; // 1.0 / 256
49 49
50 private Bitmap ScaleImage(Bitmap srcImage, float scale) 50 private Bitmap ScaleImage(Bitmap srcImage, float scale)
51 { 51 {
52 int sourceWidth = srcImage.Width; 52 int sourceWidth = srcImage.Width;
53 int sourceHeight = srcImage.Height; 53 int sourceHeight = srcImage.Height;
54 int sourceX = 0; 54 int sourceX = 0;
55 int sourceY = 0; 55 int sourceY = 0;
56 56
57 int destX = 0; 57 int destX = 0;
58 int destY = 0; 58 int destY = 0;
59 int destWidth = (int)(sourceWidth * scale); 59 int destWidth = (int)(sourceWidth * scale);
60 int destHeight = (int)(sourceHeight * scale); 60 int destHeight = (int)(sourceHeight * scale);
61 61
62 Bitmap scaledImage = new Bitmap(destWidth, destHeight, 62 Bitmap scaledImage = new Bitmap(destWidth, destHeight,
63 PixelFormat.Format24bppRgb); 63 PixelFormat.Format24bppRgb);
64 scaledImage.SetResolution(srcImage.HorizontalResolution, 64 scaledImage.SetResolution(srcImage.HorizontalResolution,
65 srcImage.VerticalResolution); 65 srcImage.VerticalResolution);
66 66
67 Graphics grPhoto = Graphics.FromImage(scaledImage); 67 Graphics grPhoto = Graphics.FromImage(scaledImage);
68 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; 68 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
69 69
70 grPhoto.DrawImage(srcImage, 70 grPhoto.DrawImage(srcImage,
71 new Rectangle(destX, destY, destWidth, destHeight), 71 new Rectangle(destX, destY, destWidth, destHeight),
72 new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), 72 new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
73 GraphicsUnit.Pixel); 73 GraphicsUnit.Pixel);
74 74
75 grPhoto.Dispose(); 75 grPhoto.Dispose();
76 return scaledImage; 76 return scaledImage;
77 } 77 }
78 78
79 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) 79 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
80 { 80 {
81 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); 81 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
82 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); 82 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
83 bitmap.Dispose(); 83 bitmap.Dispose();
84 return sculptMesh; 84 return sculptMesh;
85 } 85 }
86 86
87 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) 87 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
88 { 88 {
89 coords = new List<Coord>(); 89 coords = new List<Coord>();
90 faces = new List<Face>(); 90 faces = new List<Face>();
91 normals = new List<Coord>(); 91 normals = new List<Coord>();
92 uvs = new List<UVCoord>(); 92 uvs = new List<UVCoord>();
93 93
94 float sourceScaleFactor = (float)lod / (float)Math.Max(sculptBitmap.Width, sculptBitmap.Height); 94 float sourceScaleFactor = (float)lod / (float)Math.Max(sculptBitmap.Width, sculptBitmap.Height);
95 bool scaleSourceImage = sourceScaleFactor < 1.0f ? true : false; 95 bool scaleSourceImage = sourceScaleFactor < 1.0f ? true : false;
96 96
97 Bitmap bitmap; 97 Bitmap bitmap;
98 if (scaleSourceImage) 98 if (scaleSourceImage)
99 bitmap = ScaleImage(sculptBitmap, sourceScaleFactor); 99 bitmap = ScaleImage(sculptBitmap, sourceScaleFactor);
100 else 100 else
101 bitmap = sculptBitmap; 101 bitmap = sculptBitmap;
102 102
103 viewerFaces = new List<ViewerFace>(); 103 viewerFaces = new List<ViewerFace>();
104 104
105 int width = bitmap.Width; 105 int width = bitmap.Width;
106 int height = bitmap.Height; 106 int height = bitmap.Height;
107 107
108 float widthUnit = 1.0f / width; 108 float widthUnit = 1.0f / width;
109 float heightUnit = 1.0f / (height - 1); 109 float heightUnit = 1.0f / (height - 1);
110 110
111 int p1, p2, p3, p4; 111 int p1, p2, p3, p4;
112 Color color; 112 Color color;
113 float x, y, z; 113 float x, y, z;
114 114
115 int imageX, imageY; 115 int imageX, imageY;
116 116
117 if (sculptType == SculptType.sphere) 117 if (sculptType == SculptType.sphere)
118 { // average the top and bottom row pixel values so the resulting vertices appear to converge 118 { // average the top and bottom row pixel values so the resulting vertices appear to converge
119 int lastRow = height - 1; 119 int lastRow = height - 1;
120 int r1 = 0, g1 = 0, b1 = 0; 120 int r1 = 0, g1 = 0, b1 = 0;
121 int r2 = 0, g2 = 0, b2 = 0; 121 int r2 = 0, g2 = 0, b2 = 0;
122 for (imageX = 0; imageX < width; imageX++) 122 for (imageX = 0; imageX < width; imageX++)
123 { 123 {
124 Color c1 = bitmap.GetPixel(imageX, 0); 124 Color c1 = bitmap.GetPixel(imageX, 0);
125 Color c2 = bitmap.GetPixel(imageX, lastRow); 125 Color c2 = bitmap.GetPixel(imageX, lastRow);
126 126
127 r1 += c1.R; 127 r1 += c1.R;
128 g1 += c1.G; 128 g1 += c1.G;
129 b1 += c1.B; 129 b1 += c1.B;
130 130
131 r2 += c2.R; 131 r2 += c2.R;
132 g2 += c2.G; 132 g2 += c2.G;
133 b2 += c2.B; 133 b2 += c2.B;
134 } 134 }
135 135
136 Color newC1 = Color.FromArgb(r1 / width, g1 / width, b1 / width); 136 Color newC1 = Color.FromArgb(r1 / width, g1 / width, b1 / width);
137 Color newC2 = Color.FromArgb(r2 / width, g2 / width, b2 / width); 137 Color newC2 = Color.FromArgb(r2 / width, g2 / width, b2 / width);
138 138
139 for (imageX = 0; imageX < width; imageX++) 139 for (imageX = 0; imageX < width; imageX++)
140 { 140 {
141 bitmap.SetPixel(imageX, 0, newC1); 141 bitmap.SetPixel(imageX, 0, newC1);
142 bitmap.SetPixel(imageX, lastRow, newC2); 142 bitmap.SetPixel(imageX, lastRow, newC2);
143 } 143 }
144 } 144 }
145 145
146 146
147 int pixelsAcross = sculptType == SculptType.plane ? width : width + 1; 147 int pixelsAcross = sculptType == SculptType.plane ? width : width + 1;
148 int pixelsDown = sculptType == SculptType.sphere || sculptType == SculptType.cylinder ? height + 1 : height; 148 int pixelsDown = sculptType == SculptType.sphere || sculptType == SculptType.cylinder ? height + 1 : height;
149 149
150 for (imageY = 0; imageY < pixelsDown; imageY++) 150 for (imageY = 0; imageY < pixelsDown; imageY++)
151 { 151 {
152 int rowOffset = imageY * width; 152 int rowOffset = imageY * width;
153 153
154 for (imageX = 0; imageX < pixelsAcross; imageX++) 154 for (imageX = 0; imageX < pixelsAcross; imageX++)
155 { 155 {
156 /* 156 /*
157 * p1-----p2 157 * p1-----p2
158 * | \ f2 | 158 * | \ f2 |
159 * | \ | 159 * | \ |
160 * | f1 \| 160 * | f1 \|
161 * p3-----p4 161 * p3-----p4
162 */ 162 */
163 163
164 if (imageX < width) 164 if (imageX < width)
165 { 165 {
166 p4 = rowOffset + imageX; 166 p4 = rowOffset + imageX;
167 p3 = p4 - 1; 167 p3 = p4 - 1;
168 } 168 }
169 else 169 else
170 { 170 {
171 p4 = rowOffset; // wrap around to beginning 171 p4 = rowOffset; // wrap around to beginning
172 p3 = rowOffset + imageX - 1; 172 p3 = rowOffset + imageX - 1;
173 } 173 }
174 174
175 p2 = p4 - width; 175 p2 = p4 - width;
176 p1 = p3 - width; 176 p1 = p3 - width;
177 177
178 color = bitmap.GetPixel(imageX == width ? 0 : imageX, imageY == height ? height - 1 : imageY); 178 color = bitmap.GetPixel(imageX == width ? 0 : imageX, imageY == height ? height - 1 : imageY);
179 179
180 x = (color.R - 128) * pixScale; 180 x = (color.R - 128) * pixScale;
181 y = (color.G - 128) * pixScale; 181 y = (color.G - 128) * pixScale;
182 z = (color.B - 128) * pixScale; 182 z = (color.B - 128) * pixScale;
183 183
184 Coord c = new Coord(x, y, z); 184 Coord c = new Coord(x, y, z);
185 this.coords.Add(c); 185 this.coords.Add(c);
186 if (viewerMode) 186 if (viewerMode)
187 { 187 {
188 this.normals.Add(new Coord()); 188 this.normals.Add(new Coord());
189 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); 189 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
190 } 190 }
191 191
192 if (imageY > 0 && imageX > 0) 192 if (imageY > 0 && imageX > 0)
193 { 193 {
194 Face f1, f2; 194 Face f1, f2;
195 195
196 if (viewerMode) 196 if (viewerMode)
197 { 197 {
198 f1 = new Face(p1, p3, p4, p1, p3, p4); 198 f1 = new Face(p1, p3, p4, p1, p3, p4);
199 f1.uv1 = p1; 199 f1.uv1 = p1;
200 f1.uv2 = p3; 200 f1.uv2 = p3;
201 f1.uv3 = p4; 201 f1.uv3 = p4;
202 202
203 f2 = new Face(p1, p4, p2, p1, p4, p2); 203 f2 = new Face(p1, p4, p2, p1, p4, p2);
204 f2.uv1 = p1; 204 f2.uv1 = p1;
205 f2.uv2 = p4; 205 f2.uv2 = p4;
206 f2.uv3 = p2; 206 f2.uv3 = p2;
207 } 207 }
208 else 208 else
209 { 209 {
210 f1 = new Face(p1, p3, p4); 210 f1 = new Face(p1, p3, p4);
211 f2 = new Face(p1, p4, p2); 211 f2 = new Face(p1, p4, p2);
212 } 212 }
213 213
214 this.faces.Add(f1); 214 this.faces.Add(f1);
215 this.faces.Add(f2); 215 this.faces.Add(f2);
216 } 216 }
217 } 217 }
218 } 218 }
219 219
220 if (scaleSourceImage) 220 if (scaleSourceImage)
221 bitmap.Dispose(); 221 bitmap.Dispose();
222 222
223 if (viewerMode) 223 if (viewerMode)
224 { // compute vertex normals by summing all the surface normals of all the triangles sharing 224 { // compute vertex normals by summing all the surface normals of all the triangles sharing
225 // each vertex and then normalizing 225 // each vertex and then normalizing
226 int numFaces = this.faces.Count; 226 int numFaces = this.faces.Count;
227 for (int i = 0; i < numFaces; i++) 227 for (int i = 0; i < numFaces; i++)
228 { 228 {
229 Face face = this.faces[i]; 229 Face face = this.faces[i];
230 Coord surfaceNormal = face.SurfaceNormal(this.coords); 230 Coord surfaceNormal = face.SurfaceNormal(this.coords);
231 this.normals[face.v1] += surfaceNormal; 231 this.normals[face.v1] += surfaceNormal;
232 this.normals[face.v2] += surfaceNormal; 232 this.normals[face.v2] += surfaceNormal;
233 this.normals[face.v3] += surfaceNormal; 233 this.normals[face.v3] += surfaceNormal;
234 } 234 }
235 235
236 int numCoords = this.coords.Count; 236 int numCoords = this.coords.Count;
237 for (int i = 0; i < numCoords; i++) 237 for (int i = 0; i < numCoords; i++)
238 this.coords[i].Normalize(); 238 this.coords[i].Normalize();
239 239
240 if (sculptType != SculptType.plane) 240 if (sculptType != SculptType.plane)
241 { // blend the vertex normals at the cylinder seam 241 { // blend the vertex normals at the cylinder seam
242 pixelsAcross = width + 1; 242 pixelsAcross = width + 1;
243 for (imageY = 0; imageY < height; imageY++) 243 for (imageY = 0; imageY < height; imageY++)
244 { 244 {
245 int rowOffset = imageY * pixelsAcross; 245 int rowOffset = imageY * pixelsAcross;
246 246
247 this.normals[rowOffset] = this.normals[rowOffset + width - 1] = (this.normals[rowOffset] + this.normals[rowOffset + width - 1]).Normalize(); 247 this.normals[rowOffset] = this.normals[rowOffset + width - 1] = (this.normals[rowOffset] + this.normals[rowOffset + width - 1]).Normalize();
248 } 248 }
249 } 249 }
250 250
251 foreach (Face face in this.faces) 251 foreach (Face face in this.faces)
252 { 252 {
253 ViewerFace vf = new ViewerFace(0); 253 ViewerFace vf = new ViewerFace(0);
254 vf.v1 = this.coords[face.v1]; 254 vf.v1 = this.coords[face.v1];
255 vf.v2 = this.coords[face.v2]; 255 vf.v2 = this.coords[face.v2];
256 vf.v3 = this.coords[face.v3]; 256 vf.v3 = this.coords[face.v3];
257 257
258 vf.n1 = this.normals[face.n1]; 258 vf.n1 = this.normals[face.n1];
259 vf.n2 = this.normals[face.n2]; 259 vf.n2 = this.normals[face.n2];
260 vf.n3 = this.normals[face.n3]; 260 vf.n3 = this.normals[face.n3];
261 261
262 vf.uv1 = this.uvs[face.uv1]; 262 vf.uv1 = this.uvs[face.uv1];
263 vf.uv2 = this.uvs[face.uv2]; 263 vf.uv2 = this.uvs[face.uv2];
264 vf.uv3 = this.uvs[face.uv3]; 264 vf.uv3 = this.uvs[face.uv3];
265 265
266 this.viewerFaces.Add(vf); 266 this.viewerFaces.Add(vf);
267 } 267 }
268 } 268 }
269 } 269 }
270 270
271 public void AddRot(Quat q) 271 public void AddRot(Quat q)
272 { 272 {
273 int i; 273 int i;
274 int numVerts = this.coords.Count; 274 int numVerts = this.coords.Count;
275 275
276 for (i = 0; i < numVerts; i++) 276 for (i = 0; i < numVerts; i++)
277 this.coords[i] *= q; 277 this.coords[i] *= q;
278 278
279 if (this.viewerFaces != null) 279 if (this.viewerFaces != null)
280 { 280 {
281 int numViewerFaces = this.viewerFaces.Count; 281 int numViewerFaces = this.viewerFaces.Count;
282 282
283 for (i = 0; i < numViewerFaces; i++) 283 for (i = 0; i < numViewerFaces; i++)
284 { 284 {
285 ViewerFace v = this.viewerFaces[i]; 285 ViewerFace v = this.viewerFaces[i];
286 v.v1 *= q; 286 v.v1 *= q;
287 v.v2 *= q; 287 v.v2 *= q;
288 v.v3 *= q; 288 v.v3 *= q;
289 289
290 v.n1 *= q; 290 v.n1 *= q;
291 v.n2 *= q; 291 v.n2 *= q;
292 v.n3 *= q; 292 v.n3 *= q;
293 293
294 this.viewerFaces[i] = v; 294 this.viewerFaces[i] = v;
295 } 295 }
296 } 296 }
297 } 297 }
298 298
299 public void Scale(float x, float y, float z) 299 public void Scale(float x, float y, float z)
300 { 300 {
301 int i; 301 int i;
302 int numVerts = this.coords.Count; 302 int numVerts = this.coords.Count;
303 //Coord vert; 303 //Coord vert;
304 304
305 Coord m = new Coord(x, y, z); 305 Coord m = new Coord(x, y, z);
306 for (i = 0; i < numVerts; i++) 306 for (i = 0; i < numVerts; i++)
307 this.coords[i] *= m; 307 this.coords[i] *= m;
308 308
309 if (this.viewerFaces != null) 309 if (this.viewerFaces != null)
310 { 310 {
311 int numViewerFaces = this.viewerFaces.Count; 311 int numViewerFaces = this.viewerFaces.Count;
312 for (i = 0; i < numViewerFaces; i++) 312 for (i = 0; i < numViewerFaces; i++)
313 { 313 {
314 ViewerFace v = this.viewerFaces[i]; 314 ViewerFace v = this.viewerFaces[i];
315 v.v1 *= m; 315 v.v1 *= m;
316 v.v2 *= m; 316 v.v2 *= m;
317 v.v3 *= m; 317 v.v3 *= m;
318 this.viewerFaces[i] = v; 318 this.viewerFaces[i] = v;
319 } 319 }
320 } 320 }
321 } 321 }
322 322
323 public void DumpRaw(String path, String name, String title) 323 public void DumpRaw(String path, String name, String title)
324 { 324 {
325 if (path == null) 325 if (path == null)
326 return; 326 return;
327 String fileName = name + "_" + title + ".raw"; 327 String fileName = name + "_" + title + ".raw";
328 String completePath = Path.Combine(path, fileName); 328 String completePath = Path.Combine(path, fileName);
329 StreamWriter sw = new StreamWriter(completePath); 329 StreamWriter sw = new StreamWriter(completePath);
330 330
331 for (int i = 0; i < this.faces.Count; i++) 331 for (int i = 0; i < this.faces.Count; i++)
332 { 332 {
333 string s = this.coords[this.faces[i].v1].ToString(); 333 string s = this.coords[this.faces[i].v1].ToString();
334 s += " " + this.coords[this.faces[i].v2].ToString(); 334 s += " " + this.coords[this.faces[i].v2].ToString();
335 s += " " + this.coords[this.faces[i].v3].ToString(); 335 s += " " + this.coords[this.faces[i].v3].ToString();
336 336
337 sw.WriteLine(s); 337 sw.WriteLine(s);
338 } 338 }
339 339
340 sw.Close(); 340 sw.Close();
341 } 341 }
342 } 342 }
343} 343}