diff options
author | Diva Canto | 2010-05-07 21:29:56 -0700 |
---|---|---|
committer | Diva Canto | 2010-05-07 21:29:56 -0700 |
commit | a58859a0d4206c194c9c56212218e2cafc2cc373 (patch) | |
tree | fed51a4e40c344b76f6b8b4d5c5b2ec0d2e142e4 /OpenSim/Region/Physics/Meshing/SculptMesh.cs | |
parent | improve handling of undersize sculpt textures (diff) | |
download | opensim-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.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 | } | ||