aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/SculptMesh.cs
diff options
context:
space:
mode:
authorDahlia Trimble2008-11-30 03:52:18 +0000
committerDahlia Trimble2008-11-30 03:52:18 +0000
commit07ee2c3504edb0c328020aed6f5d3f182a3b67c5 (patch)
treeeb373c5e8fef7ce2a840ecfa87c04cc7a10fa425 /OpenSim/Region/Physics/Meshing/SculptMesh.cs
parent* try a prebuild fix to the primmesher thing (diff)
downloadopensim-SC-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.zip
opensim-SC-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.gz
opensim-SC-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.bz2
opensim-SC-07ee2c3504edb0c328020aed6f5d3f182a3b67c5.tar.xz
Revert r7548 and r7549 until someone with prebuild-fu can help structure the dependencies
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/SculptMesh.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs343
1 files changed, 343 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
new file mode 100644
index 0000000..312f89a
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -0,0 +1,343 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31using System.IO;
32using System.Drawing;
33using System.Drawing.Imaging;
34
35namespace PrimMesher
36{
37
38 public class SculptMesh
39 {
40 public List<Coord> coords;
41 public List<Face> faces;
42
43 public List<ViewerFace> viewerFaces;
44 public List<Coord> normals;
45 public List<UVCoord> uvs;
46
47 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
48 private const float pixScale = 0.00390625f; // 1.0 / 256
49
50 private Bitmap ScaleImage(Bitmap srcImage, float scale)
51 {
52 int sourceWidth = srcImage.Width;
53 int sourceHeight = srcImage.Height;
54 int sourceX = 0;
55 int sourceY = 0;
56
57 int destX = 0;
58 int destY = 0;
59 int destWidth = (int)(sourceWidth * scale);
60 int destHeight = (int)(sourceHeight * scale);
61
62 Bitmap scaledImage = new Bitmap(destWidth, destHeight,
63 PixelFormat.Format24bppRgb);
64 scaledImage.SetResolution(srcImage.HorizontalResolution,
65 srcImage.VerticalResolution);
66
67 Graphics grPhoto = Graphics.FromImage(scaledImage);
68 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
69
70 grPhoto.DrawImage(srcImage,
71 new Rectangle(destX, destY, destWidth, destHeight),
72 new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
73 GraphicsUnit.Pixel);
74
75 grPhoto.Dispose();
76 return scaledImage;
77 }
78
79 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
80 {
81 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
82 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
83 bitmap.Dispose();
84 return sculptMesh;
85 }
86
87 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
88 {
89 coords = new List<Coord>();
90 faces = new List<Face>();
91 normals = new List<Coord>();
92 uvs = new List<UVCoord>();
93
94 float sourceScaleFactor = (float)lod / (float)Math.Max(sculptBitmap.Width, sculptBitmap.Height);
95 bool scaleSourceImage = sourceScaleFactor < 1.0f ? true : false;
96
97 Bitmap bitmap;
98 if (scaleSourceImage)
99 bitmap = ScaleImage(sculptBitmap, sourceScaleFactor);
100 else
101 bitmap = sculptBitmap;
102
103 viewerFaces = new List<ViewerFace>();
104
105 int width = bitmap.Width;
106 int height = bitmap.Height;
107
108 float widthUnit = 1.0f / width;
109 float heightUnit = 1.0f / (height - 1);
110
111 int p1, p2, p3, p4;
112 Color color;
113 float x, y, z;
114
115 int imageX, imageY;
116
117 if (sculptType == SculptType.sphere)
118 { // average the top and bottom row pixel values so the resulting vertices appear to converge
119 int lastRow = height - 1;
120 int r1 = 0, g1 = 0, b1 = 0;
121 int r2 = 0, g2 = 0, b2 = 0;
122 for (imageX = 0; imageX < width; imageX++)
123 {
124 Color c1 = bitmap.GetPixel(imageX, 0);
125 Color c2 = bitmap.GetPixel(imageX, lastRow);
126
127 r1 += c1.R;
128 g1 += c1.G;
129 b1 += c1.B;
130
131 r2 += c2.R;
132 g2 += c2.G;
133 b2 += c2.B;
134 }
135
136 Color newC1 = Color.FromArgb(r1 / width, g1 / width, b1 / width);
137 Color newC2 = Color.FromArgb(r2 / width, g2 / width, b2 / width);
138
139 for (imageX = 0; imageX < width; imageX++)
140 {
141 bitmap.SetPixel(imageX, 0, newC1);
142 bitmap.SetPixel(imageX, lastRow, newC2);
143 }
144 }
145
146
147 int pixelsAcross = sculptType == SculptType.plane ? width : width + 1;
148 int pixelsDown = sculptType == SculptType.sphere || sculptType == SculptType.cylinder ? height + 1 : height;
149
150 for (imageY = 0; imageY < pixelsDown; imageY++)
151 {
152 int rowOffset = imageY * width;
153
154 for (imageX = 0; imageX < pixelsAcross; imageX++)
155 {
156 /*
157 * p1-----p2
158 * | \ f2 |
159 * | \ |
160 * | f1 \|
161 * p3-----p4
162 */
163
164 if (imageX < width)
165 {
166 p4 = rowOffset + imageX;
167 p3 = p4 - 1;
168 }
169 else
170 {
171 p4 = rowOffset; // wrap around to beginning
172 p3 = rowOffset + imageX - 1;
173 }
174
175 p2 = p4 - width;
176 p1 = p3 - width;
177
178 color = bitmap.GetPixel(imageX == width ? 0 : imageX, imageY == height ? height - 1 : imageY);
179
180 x = (color.R - 128) * pixScale;
181 y = (color.G - 128) * pixScale;
182 z = (color.B - 128) * pixScale;
183
184 Coord c = new Coord(x, y, z);
185 this.coords.Add(c);
186 if (viewerMode)
187 {
188 this.normals.Add(new Coord());
189 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
190 }
191
192 if (imageY > 0 && imageX > 0)
193 {
194 Face f1, f2;
195
196 if (viewerMode)
197 {
198 f1 = new Face(p1, p3, p4, p1, p3, p4);
199 f1.uv1 = p1;
200 f1.uv2 = p3;
201 f1.uv3 = p4;
202
203 f2 = new Face(p1, p4, p2, p1, p4, p2);
204 f2.uv1 = p1;
205 f2.uv2 = p4;
206 f2.uv3 = p2;
207 }
208 else
209 {
210 f1 = new Face(p1, p3, p4);
211 f2 = new Face(p1, p4, p2);
212 }
213
214 this.faces.Add(f1);
215 this.faces.Add(f2);
216 }
217 }
218 }
219
220 if (scaleSourceImage)
221 bitmap.Dispose();
222
223 if (viewerMode)
224 { // compute vertex normals by summing all the surface normals of all the triangles sharing
225 // each vertex and then normalizing
226 int numFaces = this.faces.Count;
227 for (int i = 0; i < numFaces; i++)
228 {
229 Face face = this.faces[i];
230 Coord surfaceNormal = face.SurfaceNormal(this.coords);
231 this.normals[face.v1] += surfaceNormal;
232 this.normals[face.v2] += surfaceNormal;
233 this.normals[face.v3] += surfaceNormal;
234 }
235
236 int numCoords = this.coords.Count;
237 for (int i = 0; i < numCoords; i++)
238 this.coords[i].Normalize();
239
240 if (sculptType != SculptType.plane)
241 { // blend the vertex normals at the cylinder seam
242 pixelsAcross = width + 1;
243 for (imageY = 0; imageY < height; imageY++)
244 {
245 int rowOffset = imageY * pixelsAcross;
246
247 this.normals[rowOffset] = this.normals[rowOffset + width - 1] = (this.normals[rowOffset] + this.normals[rowOffset + width - 1]).Normalize();
248 }
249 }
250
251 foreach (Face face in this.faces)
252 {
253 ViewerFace vf = new ViewerFace(0);
254 vf.v1 = this.coords[face.v1];
255 vf.v2 = this.coords[face.v2];
256 vf.v3 = this.coords[face.v3];
257
258 vf.n1 = this.normals[face.n1];
259 vf.n2 = this.normals[face.n2];
260 vf.n3 = this.normals[face.n3];
261
262 vf.uv1 = this.uvs[face.uv1];
263 vf.uv2 = this.uvs[face.uv2];
264 vf.uv3 = this.uvs[face.uv3];
265
266 this.viewerFaces.Add(vf);
267 }
268 }
269 }
270
271 public void AddRot(Quat q)
272 {
273 int i;
274 int numVerts = this.coords.Count;
275
276 for (i = 0; i < numVerts; i++)
277 this.coords[i] *= q;
278
279 if (this.viewerFaces != null)
280 {
281 int numViewerFaces = this.viewerFaces.Count;
282
283 for (i = 0; i < numViewerFaces; i++)
284 {
285 ViewerFace v = this.viewerFaces[i];
286 v.v1 *= q;
287 v.v2 *= q;
288 v.v3 *= q;
289
290 v.n1 *= q;
291 v.n2 *= q;
292 v.n3 *= q;
293
294 this.viewerFaces[i] = v;
295 }
296 }
297 }
298
299 public void Scale(float x, float y, float z)
300 {
301 int i;
302 int numVerts = this.coords.Count;
303 //Coord vert;
304
305 Coord m = new Coord(x, y, z);
306 for (i = 0; i < numVerts; i++)
307 this.coords[i] *= m;
308
309 if (this.viewerFaces != null)
310 {
311 int numViewerFaces = this.viewerFaces.Count;
312 for (i = 0; i < numViewerFaces; i++)
313 {
314 ViewerFace v = this.viewerFaces[i];
315 v.v1 *= m;
316 v.v2 *= m;
317 v.v3 *= m;
318 this.viewerFaces[i] = v;
319 }
320 }
321 }
322
323 public void DumpRaw(String path, String name, String title)
324 {
325 if (path == null)
326 return;
327 String fileName = name + "_" + title + ".raw";
328 String completePath = Path.Combine(path, fileName);
329 StreamWriter sw = new StreamWriter(completePath);
330
331 for (int i = 0; i < this.faces.Count; i++)
332 {
333 string s = this.coords[this.faces[i].v1].ToString();
334 s += " " + this.coords[this.faces[i].v2].ToString();
335 s += " " + this.coords[this.faces[i].v3].ToString();
336
337 sw.WriteLine(s);
338 }
339
340 sw.Close();
341 }
342 }
343}