aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing/SculptMesh.cs
diff options
context:
space:
mode:
authorDahlia Trimble2009-05-19 10:09:33 +0000
committerDahlia Trimble2009-05-19 10:09:33 +0000
commit87b95e324e857dc2aaf86db1bd0dd8792da3277f (patch)
tree09f3457150e89a5dd4b74eaeed665f4ffe5be127 /OpenSim/Region/Physics/Meshing/SculptMesh.cs
parentRefactor RegionAssetService to load the service connector rather than (diff)
downloadopensim-SC_OLD-87b95e324e857dc2aaf86db1bd0dd8792da3277f.zip
opensim-SC_OLD-87b95e324e857dc2aaf86db1bd0dd8792da3277f.tar.gz
opensim-SC_OLD-87b95e324e857dc2aaf86db1bd0dd8792da3277f.tar.bz2
opensim-SC_OLD-87b95e324e857dc2aaf86db1bd0dd8792da3277f.tar.xz
Sculpt mesher refactor
adds some previously missing geometry to sculpties new LOD improves vertex accuracy fix torus mode mesh edge joining sync with primmesher r37
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/SculptMesh.cs')
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs156
1 files changed, 98 insertions, 58 deletions
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index 315ec53..77e4459 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -45,7 +45,6 @@ namespace PrimMesher
45 public List<UVCoord> uvs; 45 public List<UVCoord> uvs;
46 46
47 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; 47 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
48 private static float pixScale = 1.0f / 255;
49 48
50 private Bitmap ScaleImage(Bitmap srcImage, float scale) 49 private Bitmap ScaleImage(Bitmap srcImage, float scale)
51 { 50 {
@@ -73,7 +72,7 @@ namespace PrimMesher
73 scaledImage.SetResolution(96.0f, 96.0f); 72 scaledImage.SetResolution(96.0f, 96.0f);
74 73
75 Graphics grPhoto = Graphics.FromImage(scaledImage); 74 Graphics grPhoto = Graphics.FromImage(scaledImage);
76 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; 75 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
77 76
78 grPhoto.DrawImage(srcImage, 77 grPhoto.DrawImage(srcImage,
79 new Rectangle(destX, destY, destWidth, destHeight), 78 new Rectangle(destX, destY, destWidth, destHeight),
@@ -149,7 +148,6 @@ namespace PrimMesher
149 * p3-----p4 148 * p3-----p4
150 */ 149 */
151 150
152
153 p4 = rowOffset + x; 151 p4 = rowOffset + x;
154 p3 = p4 - 1; 152 p3 = p4 - 1;
155 153
@@ -206,6 +204,62 @@ namespace PrimMesher
206 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); 204 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert);
207 } 205 }
208 206
207 /// <summary>
208 /// converts a bitmap to a list lists of coords, while scaling the image.
209 /// the scaling is done in floating point so as to allow for reduced vertex position
210 /// quantization as the position will be averaged between pixel values. this routine will
211 /// likely fail if the bitmap width and height are not powers of 2.
212 /// </summary>
213 /// <param name="bitmap"></param>
214 /// <param name="scale"></param>
215 /// <param name="mirror"></param>
216 /// <returns></returns>
217 private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
218 {
219 int numRows = bitmap.Height / scale;
220 int numCols = bitmap.Width / scale;
221 List<List<Coord>> rows = new List<List<Coord>>(numRows);
222
223 float pixScale = 1.0f / (scale * scale);
224 pixScale /= 255;
225
226 int imageX, imageY = 0;
227
228 int rowNdx, colNdx;
229
230 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
231 {
232 List<Coord> row = new List<Coord>(numCols);
233 for (colNdx = 0; colNdx < numCols; colNdx++)
234 {
235 imageX = colNdx * scale;
236 int imageYStart = rowNdx * scale;
237 int imageYEnd = imageYStart + scale;
238 int imageXEnd = imageX + scale;
239 float rSum = 0.0f;
240 float gSum = 0.0f;
241 float bSum = 0.0f;
242 for (; imageX < imageXEnd; imageX++)
243 {
244 for (imageY = imageYStart; imageY < imageYEnd; imageY++)
245 {
246 Color c = bitmap.GetPixel(imageX, imageY);
247 rSum += c.R;
248 gSum += c.G;
249 bSum += c.B;
250 }
251 }
252 if (mirror)
253 row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
254 else
255 row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
256
257 }
258 rows.Add(row);
259 }
260 return rows;
261 }
262
209 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) 263 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
210 { 264 {
211 coords = new List<Coord>(); 265 coords = new List<Coord>();
@@ -213,58 +267,65 @@ namespace PrimMesher
213 normals = new List<Coord>(); 267 normals = new List<Coord>();
214 uvs = new List<UVCoord>(); 268 uvs = new List<UVCoord>();
215 269
270 sculptType = (SculptType)(((int)sculptType) & 0x07);
271
216 if (mirror) 272 if (mirror)
217 if (sculptType == SculptType.plane) 273 if (sculptType == SculptType.plane)
218 invert = !invert; 274 invert = !invert;
219 275
220 float sourceScaleFactor = (float)(lod) / (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height); 276 float sourceScaleFactor = (float)(lod) / (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height);
221 bool scaleSourceImage = sourceScaleFactor < 1.0f ? true : false;
222 277
223 Bitmap bitmap; 278 int scale = (int)(1.0f / sourceScaleFactor);
224 if (scaleSourceImage) 279 if (scale < 1) scale = 1;
225 bitmap = ScaleImage(sculptBitmap, sourceScaleFactor);
226 else
227 bitmap = sculptBitmap;
228 280
229 viewerFaces = new List<ViewerFace>(); 281 List<List<Coord>> rows = bitmap2Coords(sculptBitmap, scale, mirror);
230 282
231 int width = bitmap.Width; 283 viewerFaces = new List<ViewerFace>();
232 int height = bitmap.Height;
233 284
234 float widthUnit = 1.0f / width; 285 int width = sculptBitmap.Width / scale;
235 float heightUnit = 1.0f / (height - 1); 286 int height = sculptBitmap.Height / scale;
236 287
237 int p1, p2, p3, p4; 288 int p1, p2, p3, p4;
238 Color color;
239 float x, y, z;
240 289
241 int imageX, imageY; 290 int imageX, imageY;
242 291
243 if (sculptType == SculptType.sphere) 292 if (sculptType != SculptType.plane)
244 { 293 {
245 int lastRow = height - 1; 294 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
295 rows[rowNdx].Add(rows[rowNdx][0]);
296 }
246 297
247 // poles of sphere mesh are the center pixels of the top and bottom rows 298 Coord topPole = rows[0][width / 2];
248 Color newC1 = bitmap.GetPixel(width / 2, 0); 299 Coord bottomPole = rows[rows.Count - 1][width / 2];
249 Color newC2 = bitmap.GetPixel(width / 2, lastRow);
250 300
251 for (imageX = 0; imageX < width; imageX++) 301 if (sculptType == SculptType.sphere)
302 {
303 int count = rows[0].Count;
304 List<Coord> topPoleRow = new List<Coord>(count);
305 List<Coord> bottomPoleRow = new List<Coord>(count);
306
307 for (int i = 0; i < count; i++)
252 { 308 {
253 bitmap.SetPixel(imageX, 0, newC1); 309 topPoleRow.Add(topPole);
254 bitmap.SetPixel(imageX, lastRow, newC2); 310 bottomPoleRow.Add(bottomPole);
255 } 311 }
256 312 rows.Insert(0, topPoleRow);
313 rows.Add(bottomPoleRow);
257 } 314 }
315 else if (sculptType == SculptType.torus)
316 rows.Add(rows[0]);
258 317
318 int coordsDown = rows.Count;
319 int coordsAcross = rows[0].Count;
259 320
260 int pixelsDown = sculptType == SculptType.plane ? height : height + 1; 321 float widthUnit = 1.0f / (coordsAcross - 1);
261 int pixelsAcross = sculptType == SculptType.plane ? width : width + 1; 322 float heightUnit = 1.0f / (coordsDown - 1);
262 323
263 for (imageY = 0; imageY < pixelsDown; imageY++) 324 for (imageY = 0; imageY < coordsDown; imageY++)
264 { 325 {
265 int rowOffset = imageY * width; 326 int rowOffset = imageY * coordsAcross;
266 327
267 for (imageX = 0; imageX < pixelsAcross; imageX++) 328 for (imageX = 0; imageX < coordsAcross; imageX++)
268 { 329 {
269 /* 330 /*
270 * p1-----p2 331 * p1-----p2
@@ -274,29 +335,13 @@ namespace PrimMesher
274 * p3-----p4 335 * p3-----p4
275 */ 336 */
276 337
277 if (imageX < width) 338 p4 = rowOffset + imageX;
278 { 339 p3 = p4 - 1;
279 p4 = rowOffset + imageX;
280 p3 = p4 - 1;
281 }
282 else
283 {
284 p4 = rowOffset; // wrap around to beginning
285 p3 = rowOffset + imageX - 1;
286 }
287
288 p2 = p4 - width;
289 p1 = p3 - width;
290
291 color = bitmap.GetPixel(imageX == width ? 0 : imageX, imageY == height ? height - 1 : imageY);
292 340
293 x = (color.R - 128) * pixScale; 341 p2 = p4 - coordsAcross;
294 if (mirror) x = -x; 342 p1 = p3 - coordsAcross;
295 y = (color.G - 128) * pixScale;
296 z = (color.B - 128) * pixScale;
297 343
298 Coord c = new Coord(x, y, z); 344 this.coords.Add(rows[imageY][imageX]);
299 this.coords.Add(c);
300 if (viewerMode) 345 if (viewerMode)
301 { 346 {
302 this.normals.Add(new Coord()); 347 this.normals.Add(new Coord());
@@ -354,11 +399,8 @@ namespace PrimMesher
354 } 399 }
355 } 400 }
356 401
357 if (scaleSourceImage)
358 bitmap.Dispose();
359
360 if (viewerMode) 402 if (viewerMode)
361 calcVertexNormals(sculptType, width, height); 403 calcVertexNormals(sculptType, coordsAcross, coordsDown);
362 } 404 }
363 405
364 /// <summary> 406 /// <summary>
@@ -398,10 +440,9 @@ namespace PrimMesher
398 440
399 if (sculptType != SculptType.plane) 441 if (sculptType != SculptType.plane)
400 { // blend the vertex normals at the cylinder seam 442 { // blend the vertex normals at the cylinder seam
401 int pixelsAcross = xSize + 1;
402 for (int y = 0; y < ySize; y++) 443 for (int y = 0; y < ySize; y++)
403 { 444 {
404 int rowOffset = y * pixelsAcross; 445 int rowOffset = y * xSize;
405 446
406 this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); 447 this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
407 } 448 }
@@ -458,7 +499,6 @@ namespace PrimMesher
458 { 499 {
459 int i; 500 int i;
460 int numVerts = this.coords.Count; 501 int numVerts = this.coords.Count;
461 //Coord vert;
462 502
463 Coord m = new Coord(x, y, z); 503 Coord m = new Coord(x, y, z);
464 for (i = 0; i < numVerts; i++) 504 for (i = 0; i < numVerts; i++)