diff options
author | Dahlia Trimble | 2009-05-19 10:09:33 +0000 |
---|---|---|
committer | Dahlia Trimble | 2009-05-19 10:09:33 +0000 |
commit | 87b95e324e857dc2aaf86db1bd0dd8792da3277f (patch) | |
tree | 09f3457150e89a5dd4b74eaeed665f4ffe5be127 /OpenSim/Region/Physics/Meshing/SculptMesh.cs | |
parent | Refactor RegionAssetService to load the service connector rather than (diff) | |
download | opensim-SC-87b95e324e857dc2aaf86db1bd0dd8792da3277f.zip opensim-SC-87b95e324e857dc2aaf86db1bd0dd8792da3277f.tar.gz opensim-SC-87b95e324e857dc2aaf86db1bd0dd8792da3277f.tar.bz2 opensim-SC-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.cs | 156 |
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++) |