aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/SculptMesh.cs
diff options
context:
space:
mode:
authorDiva Canto2010-05-07 21:29:56 -0700
committerDiva Canto2010-05-07 21:29:56 -0700
commita58859a0d4206c194c9c56212218e2cafc2cc373 (patch)
treefed51a4e40c344b76f6b8b4d5c5b2ec0d2e142e4 /OpenSim/Region/Physics/Meshing/SculptMesh.cs
parentimprove handling of undersize sculpt textures (diff)
downloadopensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.zip
opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.gz
opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.bz2
opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.xz
GridUserService in place. Replaces the contrived concept of storing user's home and position info in the presence service. WARNING: I violated a taboo by deleting 2 migration files and simplifying the original table creation for Presence. This should not cause any problems to anyone, though. Things will work with the new simplified table, as well as with the previous contrived one. If there are any problems, solving them is as easy as dropping the presence table and deleting its row in the migrations table. The presence info only exists during a user's session anyway.
BTW, the Meshing files want to be committed too -- EOFs.
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/SculptMesh.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs1282
1 files changed, 641 insertions, 641 deletions
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index 06606c3..6aa8fe4 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -1,647 +1,647 @@
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 OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator 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
28// to build without references to System.Drawing, comment this out 28// to build without references to System.Drawing, comment this out
29#define SYSTEM_DRAWING 29#define SYSTEM_DRAWING
30 30
31using System; 31using System;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Text; 33using System.Text;
34using System.IO; 34using System.IO;
35 35
36#if SYSTEM_DRAWING 36#if SYSTEM_DRAWING
37using System.Drawing; 37using System.Drawing;
38using System.Drawing.Imaging; 38using System.Drawing.Imaging;
39#endif 39#endif
40 40
41namespace PrimMesher 41namespace PrimMesher
42{ 42{
43 43
44 public class SculptMesh 44 public class SculptMesh
45 { 45 {
46 public List<Coord> coords; 46 public List<Coord> coords;
47 public List<Face> faces; 47 public List<Face> faces;
48 48
49 public List<ViewerFace> viewerFaces; 49 public List<ViewerFace> viewerFaces;
50 public List<Coord> normals; 50 public List<Coord> normals;
51 public List<UVCoord> uvs; 51 public List<UVCoord> uvs;
52 52
53 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; 53 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
54 54
55#if SYSTEM_DRAWING 55#if SYSTEM_DRAWING
56 56
57 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) 57 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
58 { 58 {
59 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); 59 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
60 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); 60 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
61 bitmap.Dispose(); 61 bitmap.Dispose();
62 return sculptMesh; 62 return sculptMesh;
63 } 63 }
64 64
65 65
66 public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) 66 public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
67 { 67 {
68 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); 68 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
69 _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); 69 _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
70 bitmap.Dispose(); 70 bitmap.Dispose();
71 } 71 }
72#endif 72#endif
73 73
74 /// <summary> 74 /// <summary>
75 /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications 75 /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications
76 /// Construct a sculpt mesh from a 2D array of floats 76 /// Construct a sculpt mesh from a 2D array of floats
77 /// </summary> 77 /// </summary>
78 /// <param name="zMap"></param> 78 /// <param name="zMap"></param>
79 /// <param name="xBegin"></param> 79 /// <param name="xBegin"></param>
80 /// <param name="xEnd"></param> 80 /// <param name="xEnd"></param>
81 /// <param name="yBegin"></param> 81 /// <param name="yBegin"></param>
82 /// <param name="yEnd"></param> 82 /// <param name="yEnd"></param>
83 /// <param name="viewerMode"></param> 83 /// <param name="viewerMode"></param>
84 public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) 84 public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
85 { 85 {
86 float xStep, yStep; 86 float xStep, yStep;
87 float uStep, vStep; 87 float uStep, vStep;
88 88
89 int numYElements = zMap.GetLength(0); 89 int numYElements = zMap.GetLength(0);
90 int numXElements = zMap.GetLength(1); 90 int numXElements = zMap.GetLength(1);
91 91
92 try 92 try
93 { 93 {
94 xStep = (xEnd - xBegin) / (float)(numXElements - 1); 94 xStep = (xEnd - xBegin) / (float)(numXElements - 1);
95 yStep = (yEnd - yBegin) / (float)(numYElements - 1); 95 yStep = (yEnd - yBegin) / (float)(numYElements - 1);
96 96
97 uStep = 1.0f / (numXElements - 1); 97 uStep = 1.0f / (numXElements - 1);
98 vStep = 1.0f / (numYElements - 1); 98 vStep = 1.0f / (numYElements - 1);
99 } 99 }
100 catch (DivideByZeroException) 100 catch (DivideByZeroException)
101 { 101 {
102 return; 102 return;
103 } 103 }
104 104
105 coords = new List<Coord>(); 105 coords = new List<Coord>();
106 faces = new List<Face>(); 106 faces = new List<Face>();
107 normals = new List<Coord>(); 107 normals = new List<Coord>();
108 uvs = new List<UVCoord>(); 108 uvs = new List<UVCoord>();
109 109
110 viewerFaces = new List<ViewerFace>(); 110 viewerFaces = new List<ViewerFace>();
111 111
112 int p1, p2, p3, p4; 112 int p1, p2, p3, p4;
113 113
114 int x, y; 114 int x, y;
115 int xStart = 0, yStart = 0; 115 int xStart = 0, yStart = 0;
116 116
117 for (y = yStart; y < numYElements; y++) 117 for (y = yStart; y < numYElements; y++)
118 { 118 {
119 int rowOffset = y * numXElements; 119 int rowOffset = y * numXElements;
120 120
121 for (x = xStart; x < numXElements; x++) 121 for (x = xStart; x < numXElements; x++)
122 { 122 {
123 /*
124 * p1-----p2
125 * | \ f2 |
126 * | \ |
127 * | f1 \|
128 * p3-----p4
129 */
130
131 p4 = rowOffset + x;
132 p3 = p4 - 1;
133
134 p2 = p4 - numXElements;
135 p1 = p3 - numXElements;
136
137 Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
138 this.coords.Add(c);
139 if (viewerMode)
140 {
141 this.normals.Add(new Coord());
142 this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
143 }
144
145 if (y > 0 && x > 0)
146 {
147 Face f1, f2;
148
149 if (viewerMode)
150 {
151 f1 = new Face(p1, p4, p3, p1, p4, p3);
152 f1.uv1 = p1;
153 f1.uv2 = p4;
154 f1.uv3 = p3;
155
156 f2 = new Face(p1, p2, p4, p1, p2, p4);
157 f2.uv1 = p1;
158 f2.uv2 = p2;
159 f2.uv3 = p4;
160 }
161 else
162 {
163 f1 = new Face(p1, p4, p3);
164 f2 = new Face(p1, p2, p4);
165 }
166
167 this.faces.Add(f1);
168 this.faces.Add(f2);
169 }
170 }
171 }
172
173 if (viewerMode)
174 calcVertexNormals(SculptType.plane, numXElements, numYElements);
175 }
176
177#if SYSTEM_DRAWING
178 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
179 {
180 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
181 }
182
183 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
184 {
185 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
186 }
187#endif
188
189 public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
190 {
191 _SculptMesh(rows, sculptType, viewerMode, mirror, invert);
192 }
193
194#if SYSTEM_DRAWING
195 /// <summary>
196 /// converts a bitmap to a list of lists of coords, while scaling the image.
197 /// the scaling is done in floating point so as to allow for reduced vertex position
198 /// quantization as the position will be averaged between pixel values. this routine will
199 /// likely fail if the bitmap width and height are not powers of 2.
200 /// </summary>
201 /// <param name="bitmap"></param>
202 /// <param name="scale"></param>
203 /// <param name="mirror"></param>
204 /// <returns></returns>
205 private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
206 {
207 int numRows = bitmap.Height / scale;
208 int numCols = bitmap.Width / scale;
209 List<List<Coord>> rows = new List<List<Coord>>(numRows);
210
211 float pixScale = 1.0f / (scale * scale);
212 pixScale /= 255;
213
214 int imageX, imageY = 0;
215
216 int rowNdx, colNdx;
217
218 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
219 {
220 List<Coord> row = new List<Coord>(numCols);
221 for (colNdx = 0; colNdx < numCols; colNdx++)
222 {
223 imageX = colNdx * scale;
224 int imageYStart = rowNdx * scale;
225 int imageYEnd = imageYStart + scale;
226 int imageXEnd = imageX + scale;
227 float rSum = 0.0f;
228 float gSum = 0.0f;
229 float bSum = 0.0f;
230 for (; imageX < imageXEnd; imageX++)
231 {
232 for (imageY = imageYStart; imageY < imageYEnd; imageY++)
233 {
234 Color c = bitmap.GetPixel(imageX, imageY);
235 if (c.A != 255)
236 {
237 bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
238 c = bitmap.GetPixel(imageX, imageY);
239 }
240 rSum += c.R;
241 gSum += c.G;
242 bSum += c.B;
243 }
244 }
245 if (mirror)
246 row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
247 else
248 row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
249
250 }
251 rows.Add(row);
252 }
253 return rows;
254 }
255
256 private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror)
257 {
258 int numRows = bitmap.Height / scale;
259 int numCols = bitmap.Width / scale;
260 List<List<Coord>> rows = new List<List<Coord>>(numRows);
261
262 float pixScale = 1.0f / 256.0f;
263
264 int imageX, imageY = 0;
265
266 int rowNdx, colNdx;
267
268 for (rowNdx = 0; rowNdx <= numRows; rowNdx++)
269 {
270 List<Coord> row = new List<Coord>(numCols);
271 imageY = rowNdx * scale;
272 if (rowNdx == numRows) imageY--;
273 for (colNdx = 0; colNdx <= numCols; colNdx++)
274 {
275 imageX = colNdx * scale;
276 if (colNdx == numCols) imageX--;
277
278 Color c = bitmap.GetPixel(imageX, imageY);
279 if (c.A != 255)
280 {
281 bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
282 c = bitmap.GetPixel(imageX, imageY);
283 }
284
285 if (mirror)
286 row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
287 else
288 row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
289
290 }
291 rows.Add(row);
292 }
293 return rows;
294 }
295
296
297 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
298 {
299 _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert);
300 }
301#endif
302
303 void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
304 {
305 coords = new List<Coord>();
306 faces = new List<Face>();
307 normals = new List<Coord>();
308 uvs = new List<UVCoord>();
309
310 sculptType = (SculptType)(((int)sculptType) & 0x07);
311
312 if (mirror)
313 if (sculptType == SculptType.plane)
314 invert = !invert;
315
316 viewerFaces = new List<ViewerFace>();
317
318 int width = rows[0].Count;
319
320 int p1, p2, p3, p4;
321
322 int imageX, imageY;
323
324 if (sculptType != SculptType.plane)
325 {
326 if (rows.Count % 2 == 0)
327 {
328 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
329 rows[rowNdx].Add(rows[rowNdx][0]);
330 }
331 else
332 {
333 int lastIndex = rows[0].Count - 1;
334
335 for (int i = 0; i < rows.Count; i++)
336 rows[i][0] = rows[i][lastIndex];
337 }
338 }
339
340 Coord topPole = rows[0][width / 2];
341 Coord bottomPole = rows[rows.Count - 1][width / 2];
342
343 if (sculptType == SculptType.sphere)
344 {
345 if (rows.Count % 2 == 0)
346 {
347 int count = rows[0].Count;
348 List<Coord> topPoleRow = new List<Coord>(count);
349 List<Coord> bottomPoleRow = new List<Coord>(count);
350
351 for (int i = 0; i < count; i++)
352 {
353 topPoleRow.Add(topPole);
354 bottomPoleRow.Add(bottomPole);
355 }
356 rows.Insert(0, topPoleRow);
357 rows.Add(bottomPoleRow);
358 }
359 else
360 {
361 int count = rows[0].Count;
362
363 List<Coord> topPoleRow = rows[0];
364 List<Coord> bottomPoleRow = rows[rows.Count - 1];
365
366 for (int i = 0; i < count; i++)
367 {
368 topPoleRow[i] = topPole;
369 bottomPoleRow[i] = bottomPole;
370 }
371 }
372 }
373
374 if (sculptType == SculptType.torus)
375 rows.Add(rows[0]);
376
377 int coordsDown = rows.Count;
378 int coordsAcross = rows[0].Count;
379 int lastColumn = coordsAcross - 1;
380
381 float widthUnit = 1.0f / (coordsAcross - 1);
382 float heightUnit = 1.0f / (coordsDown - 1);
383
384 for (imageY = 0; imageY < coordsDown; imageY++)
385 {
386 int rowOffset = imageY * coordsAcross;
387
388 for (imageX = 0; imageX < coordsAcross; imageX++)
389 {
390 /* 123 /*
391 * p1-----p2 124 * p1-----p2
392 * | \ f2 | 125 * | \ f2 |
393 * | \ | 126 * | \ |
394 * | f1 \| 127 * | f1 \|
395 * p3-----p4 128 * p3-----p4
396 */ 129 */
397 130
398 p4 = rowOffset + imageX; 131 p4 = rowOffset + x;
399 p3 = p4 - 1; 132 p3 = p4 - 1;
400 133
401 p2 = p4 - coordsAcross; 134 p2 = p4 - numXElements;
402 p1 = p3 - coordsAcross; 135 p1 = p3 - numXElements;
403 136
404 this.coords.Add(rows[imageY][imageX]); 137 Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
405 if (viewerMode) 138 this.coords.Add(c);
406 { 139 if (viewerMode)
407 this.normals.Add(new Coord()); 140 {
408 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); 141 this.normals.Add(new Coord());
409 } 142 this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
410 143 }
411 if (imageY > 0 && imageX > 0) 144
412 { 145 if (y > 0 && x > 0)
413 Face f1, f2; 146 {
414 147 Face f1, f2;
415 if (viewerMode) 148
416 { 149 if (viewerMode)
417 if (invert) 150 {
418 { 151 f1 = new Face(p1, p4, p3, p1, p4, p3);
419 f1 = new Face(p1, p4, p3, p1, p4, p3); 152 f1.uv1 = p1;
420 f1.uv1 = p1; 153 f1.uv2 = p4;
421 f1.uv2 = p4; 154 f1.uv3 = p3;
422 f1.uv3 = p3; 155
423 156 f2 = new Face(p1, p2, p4, p1, p2, p4);
424 f2 = new Face(p1, p2, p4, p1, p2, p4); 157 f2.uv1 = p1;
425 f2.uv1 = p1; 158 f2.uv2 = p2;
426 f2.uv2 = p2; 159 f2.uv3 = p4;
427 f2.uv3 = p4; 160 }
428 } 161 else
429 else 162 {
430 { 163 f1 = new Face(p1, p4, p3);
431 f1 = new Face(p1, p3, p4, p1, p3, p4); 164 f2 = new Face(p1, p2, p4);
432 f1.uv1 = p1; 165 }
433 f1.uv2 = p3; 166
434 f1.uv3 = p4; 167 this.faces.Add(f1);
435 168 this.faces.Add(f2);
436 f2 = new Face(p1, p4, p2, p1, p4, p2); 169 }
437 f2.uv1 = p1; 170 }
438 f2.uv2 = p4; 171 }
439 f2.uv3 = p2; 172
440 } 173 if (viewerMode)
441 } 174 calcVertexNormals(SculptType.plane, numXElements, numYElements);
442 else 175 }
443 { 176
444 if (invert) 177#if SYSTEM_DRAWING
445 { 178 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
446 f1 = new Face(p1, p4, p3); 179 {
447 f2 = new Face(p1, p2, p4); 180 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
448 } 181 }
449 else 182
450 { 183 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
451 f1 = new Face(p1, p3, p4); 184 {
452 f2 = new Face(p1, p4, p2); 185 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
453 } 186 }
454 } 187#endif
455 188
456 this.faces.Add(f1); 189 public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
457 this.faces.Add(f2); 190 {
458 } 191 _SculptMesh(rows, sculptType, viewerMode, mirror, invert);
459 } 192 }
460 } 193
461 194#if SYSTEM_DRAWING
462 if (viewerMode) 195 /// <summary>
463 calcVertexNormals(sculptType, coordsAcross, coordsDown); 196 /// converts a bitmap to a list of lists of coords, while scaling the image.
464 } 197 /// the scaling is done in floating point so as to allow for reduced vertex position
465 198 /// quantization as the position will be averaged between pixel values. this routine will
466 /// <summary> 199 /// likely fail if the bitmap width and height are not powers of 2.
467 /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. 200 /// </summary>
468 /// </summary> 201 /// <param name="bitmap"></param>
469 /// <returns></returns> 202 /// <param name="scale"></param>
470 public SculptMesh Copy() 203 /// <param name="mirror"></param>
471 { 204 /// <returns></returns>
472 return new SculptMesh(this); 205 private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
473 } 206 {
474 207 int numRows = bitmap.Height / scale;
475 public SculptMesh(SculptMesh sm) 208 int numCols = bitmap.Width / scale;
476 { 209 List<List<Coord>> rows = new List<List<Coord>>(numRows);
477 coords = new List<Coord>(sm.coords); 210
478 faces = new List<Face>(sm.faces); 211 float pixScale = 1.0f / (scale * scale);
479 viewerFaces = new List<ViewerFace>(sm.viewerFaces); 212 pixScale /= 255;
480 normals = new List<Coord>(sm.normals); 213
481 uvs = new List<UVCoord>(sm.uvs); 214 int imageX, imageY = 0;
482 } 215
483 216 int rowNdx, colNdx;
484 private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) 217
485 { // compute vertex normals by summing all the surface normals of all the triangles sharing 218 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
486 // each vertex and then normalizing 219 {
487 int numFaces = this.faces.Count; 220 List<Coord> row = new List<Coord>(numCols);
488 for (int i = 0; i < numFaces; i++) 221 for (colNdx = 0; colNdx < numCols; colNdx++)
489 { 222 {
490 Face face = this.faces[i]; 223 imageX = colNdx * scale;
491 Coord surfaceNormal = face.SurfaceNormal(this.coords); 224 int imageYStart = rowNdx * scale;
492 this.normals[face.n1] += surfaceNormal; 225 int imageYEnd = imageYStart + scale;
493 this.normals[face.n2] += surfaceNormal; 226 int imageXEnd = imageX + scale;
494 this.normals[face.n3] += surfaceNormal; 227 float rSum = 0.0f;
495 } 228 float gSum = 0.0f;
496 229 float bSum = 0.0f;
497 int numNormals = this.normals.Count; 230 for (; imageX < imageXEnd; imageX++)
498 for (int i = 0; i < numNormals; i++) 231 {
499 this.normals[i] = this.normals[i].Normalize(); 232 for (imageY = imageYStart; imageY < imageYEnd; imageY++)
500 233 {
501 if (sculptType != SculptType.plane) 234 Color c = bitmap.GetPixel(imageX, imageY);
502 { // blend the vertex normals at the cylinder seam 235 if (c.A != 255)
503 for (int y = 0; y < ySize; y++) 236 {
504 { 237 bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
505 int rowOffset = y * xSize; 238 c = bitmap.GetPixel(imageX, imageY);
506 239 }
507 this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); 240 rSum += c.R;
508 } 241 gSum += c.G;
509 } 242 bSum += c.B;
510 243 }
511 foreach (Face face in this.faces) 244 }
512 { 245 if (mirror)
513 ViewerFace vf = new ViewerFace(0); 246 row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
514 vf.v1 = this.coords[face.v1]; 247 else
515 vf.v2 = this.coords[face.v2]; 248 row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
516 vf.v3 = this.coords[face.v3]; 249
517 250 }
518 vf.coordIndex1 = face.v1; 251 rows.Add(row);
519 vf.coordIndex2 = face.v2; 252 }
520 vf.coordIndex3 = face.v3; 253 return rows;
521 254 }
522 vf.n1 = this.normals[face.n1]; 255
523 vf.n2 = this.normals[face.n2]; 256 private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror)
524 vf.n3 = this.normals[face.n3]; 257 {
525 258 int numRows = bitmap.Height / scale;
526 vf.uv1 = this.uvs[face.uv1]; 259 int numCols = bitmap.Width / scale;
527 vf.uv2 = this.uvs[face.uv2]; 260 List<List<Coord>> rows = new List<List<Coord>>(numRows);
528 vf.uv3 = this.uvs[face.uv3]; 261
529 262 float pixScale = 1.0f / 256.0f;
530 this.viewerFaces.Add(vf); 263
531 } 264 int imageX, imageY = 0;
532 } 265
533 266 int rowNdx, colNdx;
534 /// <summary> 267
535 /// Adds a value to each XYZ vertex coordinate in the mesh 268 for (rowNdx = 0; rowNdx <= numRows; rowNdx++)
536 /// </summary> 269 {
537 /// <param name="x"></param> 270 List<Coord> row = new List<Coord>(numCols);
538 /// <param name="y"></param> 271 imageY = rowNdx * scale;
539 /// <param name="z"></param> 272 if (rowNdx == numRows) imageY--;
540 public void AddPos(float x, float y, float z) 273 for (colNdx = 0; colNdx <= numCols; colNdx++)
541 { 274 {
542 int i; 275 imageX = colNdx * scale;
543 int numVerts = this.coords.Count; 276 if (colNdx == numCols) imageX--;
544 Coord vert; 277
545 278 Color c = bitmap.GetPixel(imageX, imageY);
546 for (i = 0; i < numVerts; i++) 279 if (c.A != 255)
547 { 280 {
548 vert = this.coords[i]; 281 bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
549 vert.X += x; 282 c = bitmap.GetPixel(imageX, imageY);
550 vert.Y += y; 283 }
551 vert.Z += z; 284
552 this.coords[i] = vert; 285 if (mirror)
553 } 286 row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
554 287 else
555 if (this.viewerFaces != null) 288 row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f));
556 { 289
557 int numViewerFaces = this.viewerFaces.Count; 290 }
558 291 rows.Add(row);
559 for (i = 0; i < numViewerFaces; i++) 292 }
560 { 293 return rows;
561 ViewerFace v = this.viewerFaces[i]; 294 }
562 v.AddPos(x, y, z); 295
563 this.viewerFaces[i] = v; 296
564 } 297 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
565 } 298 {
566 } 299 _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert);
567 300 }
568 /// <summary> 301#endif
569 /// Rotates the mesh 302
570 /// </summary> 303 void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
571 /// <param name="q"></param> 304 {
572 public void AddRot(Quat q) 305 coords = new List<Coord>();
573 { 306 faces = new List<Face>();
574 int i; 307 normals = new List<Coord>();
575 int numVerts = this.coords.Count; 308 uvs = new List<UVCoord>();
576 309
577 for (i = 0; i < numVerts; i++) 310 sculptType = (SculptType)(((int)sculptType) & 0x07);
578 this.coords[i] *= q; 311
579 312 if (mirror)
580 int numNormals = this.normals.Count; 313 if (sculptType == SculptType.plane)
581 for (i = 0; i < numNormals; i++) 314 invert = !invert;
582 this.normals[i] *= q; 315
583 316 viewerFaces = new List<ViewerFace>();
584 if (this.viewerFaces != null) 317
585 { 318 int width = rows[0].Count;
586 int numViewerFaces = this.viewerFaces.Count; 319
587 320 int p1, p2, p3, p4;
588 for (i = 0; i < numViewerFaces; i++) 321
589 { 322 int imageX, imageY;
590 ViewerFace v = this.viewerFaces[i]; 323
591 v.v1 *= q; 324 if (sculptType != SculptType.plane)
592 v.v2 *= q; 325 {
593 v.v3 *= q; 326 if (rows.Count % 2 == 0)
594 327 {
595 v.n1 *= q; 328 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
596 v.n2 *= q; 329 rows[rowNdx].Add(rows[rowNdx][0]);
597 v.n3 *= q; 330 }
598 331 else
599 this.viewerFaces[i] = v; 332 {
600 } 333 int lastIndex = rows[0].Count - 1;
601 } 334
602 } 335 for (int i = 0; i < rows.Count; i++)
603 336 rows[i][0] = rows[i][lastIndex];
604 public void Scale(float x, float y, float z) 337 }
605 { 338 }
606 int i; 339
607 int numVerts = this.coords.Count; 340 Coord topPole = rows[0][width / 2];
608 341 Coord bottomPole = rows[rows.Count - 1][width / 2];
609 Coord m = new Coord(x, y, z); 342
610 for (i = 0; i < numVerts; i++) 343 if (sculptType == SculptType.sphere)
611 this.coords[i] *= m; 344 {
612 345 if (rows.Count % 2 == 0)
613 if (this.viewerFaces != null) 346 {
614 { 347 int count = rows[0].Count;
615 int numViewerFaces = this.viewerFaces.Count; 348 List<Coord> topPoleRow = new List<Coord>(count);
616 for (i = 0; i < numViewerFaces; i++) 349 List<Coord> bottomPoleRow = new List<Coord>(count);
617 { 350
618 ViewerFace v = this.viewerFaces[i]; 351 for (int i = 0; i < count; i++)
619 v.v1 *= m; 352 {
620 v.v2 *= m; 353 topPoleRow.Add(topPole);
621 v.v3 *= m; 354 bottomPoleRow.Add(bottomPole);
622 this.viewerFaces[i] = v; 355 }
623 } 356 rows.Insert(0, topPoleRow);
624 } 357 rows.Add(bottomPoleRow);
625 } 358 }
626 359 else
627 public void DumpRaw(String path, String name, String title) 360 {
628 { 361 int count = rows[0].Count;
629 if (path == null) 362
630 return; 363 List<Coord> topPoleRow = rows[0];
631 String fileName = name + "_" + title + ".raw"; 364 List<Coord> bottomPoleRow = rows[rows.Count - 1];
632 String completePath = System.IO.Path.Combine(path, fileName); 365
633 StreamWriter sw = new StreamWriter(completePath); 366 for (int i = 0; i < count; i++)
634 367 {
635 for (int i = 0; i < this.faces.Count; i++) 368 topPoleRow[i] = topPole;
636 { 369 bottomPoleRow[i] = bottomPole;
637 string s = this.coords[this.faces[i].v1].ToString(); 370 }
638 s += " " + this.coords[this.faces[i].v2].ToString(); 371 }
639 s += " " + this.coords[this.faces[i].v3].ToString(); 372 }
640 373
641 sw.WriteLine(s); 374 if (sculptType == SculptType.torus)
642 } 375 rows.Add(rows[0]);
643 376
644 sw.Close(); 377 int coordsDown = rows.Count;
645 } 378 int coordsAcross = rows[0].Count;
646 } 379 int lastColumn = coordsAcross - 1;
647} 380
381 float widthUnit = 1.0f / (coordsAcross - 1);
382 float heightUnit = 1.0f / (coordsDown - 1);
383
384 for (imageY = 0; imageY < coordsDown; imageY++)
385 {
386 int rowOffset = imageY * coordsAcross;
387
388 for (imageX = 0; imageX < coordsAcross; imageX++)
389 {
390 /*
391 * p1-----p2
392 * | \ f2 |
393 * | \ |
394 * | f1 \|
395 * p3-----p4
396 */
397
398 p4 = rowOffset + imageX;
399 p3 = p4 - 1;
400
401 p2 = p4 - coordsAcross;
402 p1 = p3 - coordsAcross;
403
404 this.coords.Add(rows[imageY][imageX]);
405 if (viewerMode)
406 {
407 this.normals.Add(new Coord());
408 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
409 }
410
411 if (imageY > 0 && imageX > 0)
412 {
413 Face f1, f2;
414
415 if (viewerMode)
416 {
417 if (invert)
418 {
419 f1 = new Face(p1, p4, p3, p1, p4, p3);
420 f1.uv1 = p1;
421 f1.uv2 = p4;
422 f1.uv3 = p3;
423
424 f2 = new Face(p1, p2, p4, p1, p2, p4);
425 f2.uv1 = p1;
426 f2.uv2 = p2;
427 f2.uv3 = p4;
428 }
429 else
430 {
431 f1 = new Face(p1, p3, p4, p1, p3, p4);
432 f1.uv1 = p1;
433 f1.uv2 = p3;
434 f1.uv3 = p4;
435
436 f2 = new Face(p1, p4, p2, p1, p4, p2);
437 f2.uv1 = p1;
438 f2.uv2 = p4;
439 f2.uv3 = p2;
440 }
441 }
442 else
443 {
444 if (invert)
445 {
446 f1 = new Face(p1, p4, p3);
447 f2 = new Face(p1, p2, p4);
448 }
449 else
450 {
451 f1 = new Face(p1, p3, p4);
452 f2 = new Face(p1, p4, p2);
453 }
454 }
455
456 this.faces.Add(f1);
457 this.faces.Add(f2);
458 }
459 }
460 }
461
462 if (viewerMode)
463 calcVertexNormals(sculptType, coordsAcross, coordsDown);
464 }
465
466 /// <summary>
467 /// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
468 /// </summary>
469 /// <returns></returns>
470 public SculptMesh Copy()
471 {
472 return new SculptMesh(this);
473 }
474
475 public SculptMesh(SculptMesh sm)
476 {
477 coords = new List<Coord>(sm.coords);
478 faces = new List<Face>(sm.faces);
479 viewerFaces = new List<ViewerFace>(sm.viewerFaces);
480 normals = new List<Coord>(sm.normals);
481 uvs = new List<UVCoord>(sm.uvs);
482 }
483
484 private void calcVertexNormals(SculptType sculptType, int xSize, int ySize)
485 { // compute vertex normals by summing all the surface normals of all the triangles sharing
486 // each vertex and then normalizing
487 int numFaces = this.faces.Count;
488 for (int i = 0; i < numFaces; i++)
489 {
490 Face face = this.faces[i];
491 Coord surfaceNormal = face.SurfaceNormal(this.coords);
492 this.normals[face.n1] += surfaceNormal;
493 this.normals[face.n2] += surfaceNormal;
494 this.normals[face.n3] += surfaceNormal;
495 }
496
497 int numNormals = this.normals.Count;
498 for (int i = 0; i < numNormals; i++)
499 this.normals[i] = this.normals[i].Normalize();
500
501 if (sculptType != SculptType.plane)
502 { // blend the vertex normals at the cylinder seam
503 for (int y = 0; y < ySize; y++)
504 {
505 int rowOffset = y * xSize;
506
507 this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
508 }
509 }
510
511 foreach (Face face in this.faces)
512 {
513 ViewerFace vf = new ViewerFace(0);
514 vf.v1 = this.coords[face.v1];
515 vf.v2 = this.coords[face.v2];
516 vf.v3 = this.coords[face.v3];
517
518 vf.coordIndex1 = face.v1;
519 vf.coordIndex2 = face.v2;
520 vf.coordIndex3 = face.v3;
521
522 vf.n1 = this.normals[face.n1];
523 vf.n2 = this.normals[face.n2];
524 vf.n3 = this.normals[face.n3];
525
526 vf.uv1 = this.uvs[face.uv1];
527 vf.uv2 = this.uvs[face.uv2];
528 vf.uv3 = this.uvs[face.uv3];
529
530 this.viewerFaces.Add(vf);
531 }
532 }
533
534 /// <summary>
535 /// Adds a value to each XYZ vertex coordinate in the mesh
536 /// </summary>
537 /// <param name="x"></param>
538 /// <param name="y"></param>
539 /// <param name="z"></param>
540 public void AddPos(float x, float y, float z)
541 {
542 int i;
543 int numVerts = this.coords.Count;
544 Coord vert;
545
546 for (i = 0; i < numVerts; i++)
547 {
548 vert = this.coords[i];
549 vert.X += x;
550 vert.Y += y;
551 vert.Z += z;
552 this.coords[i] = vert;
553 }
554
555 if (this.viewerFaces != null)
556 {
557 int numViewerFaces = this.viewerFaces.Count;
558
559 for (i = 0; i < numViewerFaces; i++)
560 {
561 ViewerFace v = this.viewerFaces[i];
562 v.AddPos(x, y, z);
563 this.viewerFaces[i] = v;
564 }
565 }
566 }
567
568 /// <summary>
569 /// Rotates the mesh
570 /// </summary>
571 /// <param name="q"></param>
572 public void AddRot(Quat q)
573 {
574 int i;
575 int numVerts = this.coords.Count;
576
577 for (i = 0; i < numVerts; i++)
578 this.coords[i] *= q;
579
580 int numNormals = this.normals.Count;
581 for (i = 0; i < numNormals; i++)
582 this.normals[i] *= q;
583
584 if (this.viewerFaces != null)
585 {
586 int numViewerFaces = this.viewerFaces.Count;
587
588 for (i = 0; i < numViewerFaces; i++)
589 {
590 ViewerFace v = this.viewerFaces[i];
591 v.v1 *= q;
592 v.v2 *= q;
593 v.v3 *= q;
594
595 v.n1 *= q;
596 v.n2 *= q;
597 v.n3 *= q;
598
599 this.viewerFaces[i] = v;
600 }
601 }
602 }
603
604 public void Scale(float x, float y, float z)
605 {
606 int i;
607 int numVerts = this.coords.Count;
608
609 Coord m = new Coord(x, y, z);
610 for (i = 0; i < numVerts; i++)
611 this.coords[i] *= m;
612
613 if (this.viewerFaces != null)
614 {
615 int numViewerFaces = this.viewerFaces.Count;
616 for (i = 0; i < numViewerFaces; i++)
617 {
618 ViewerFace v = this.viewerFaces[i];
619 v.v1 *= m;
620 v.v2 *= m;
621 v.v3 *= m;
622 this.viewerFaces[i] = v;
623 }
624 }
625 }
626
627 public void DumpRaw(String path, String name, String title)
628 {
629 if (path == null)
630 return;
631 String fileName = name + "_" + title + ".raw";
632 String completePath = System.IO.Path.Combine(path, fileName);
633 StreamWriter sw = new StreamWriter(completePath);
634
635 for (int i = 0; i < this.faces.Count; i++)
636 {
637 string s = this.coords[this.faces[i].v1].ToString();
638 s += " " + this.coords[this.faces[i].v2].ToString();
639 s += " " + this.coords[this.faces[i].v3].ToString();
640
641 sw.WriteLine(s);
642 }
643
644 sw.Close();
645 }
646 }
647}