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