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