diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/SculptMesh.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/SculptMesh.cs | 1282 |
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 | ||
31 | using System; | 31 | using System; |
32 | using System.Collections.Generic; | 32 | using System.Collections.Generic; |
33 | using System.Text; | 33 | using System.Text; |
34 | using System.IO; | 34 | using System.IO; |
35 | 35 | ||
36 | #if SYSTEM_DRAWING | 36 | #if SYSTEM_DRAWING |
37 | using System.Drawing; | 37 | using System.Drawing; |
38 | using System.Drawing.Imaging; | 38 | using System.Drawing.Imaging; |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | namespace PrimMesher | 41 | namespace 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 | } | ||