aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs103
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMap.cs176
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs152
3 files changed, 346 insertions, 85 deletions
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 932943c..53022ad 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -257,7 +257,6 @@ namespace PrimMesher
257 public int uv2; 257 public int uv2;
258 public int uv3; 258 public int uv3;
259 259
260
261 public Face(int v1, int v2, int v3) 260 public Face(int v1, int v2, int v3)
262 { 261 {
263 primFace = 0; 262 primFace = 0;
@@ -630,6 +629,9 @@ namespace PrimMesher
630 internal int numOuterVerts = 0; 629 internal int numOuterVerts = 0;
631 internal int numHollowVerts = 0; 630 internal int numHollowVerts = 0;
632 631
632 internal int outerFaceNumber = -1;
633 internal int hollowFaceNumber = -1;
634
633 internal bool calcVertexNormals = false; 635 internal bool calcVertexNormals = false;
634 internal int bottomFaceNumber = 0; 636 internal int bottomFaceNumber = 0;
635 internal int numPrimFaces = 0; 637 internal int numPrimFaces = 0;
@@ -936,10 +938,10 @@ namespace PrimMesher
936 938
937 if (calcVertexNormals && hasProfileCut) 939 if (calcVertexNormals && hasProfileCut)
938 { 940 {
941 int lastOuterVertIndex = this.numOuterVerts - 1;
942
939 if (hasHollow) 943 if (hasHollow)
940 { 944 {
941 int lastOuterVertIndex = this.numOuterVerts - 1;
942
943 this.cut1CoordIndices.Add(0); 945 this.cut1CoordIndices.Add(0);
944 this.cut1CoordIndices.Add(this.coords.Count - 1); 946 this.cut1CoordIndices.Add(this.coords.Count - 1);
945 947
@@ -955,6 +957,12 @@ namespace PrimMesher
955 957
956 else 958 else
957 { 959 {
960 this.cut1CoordIndices.Add(0);
961 this.cut1CoordIndices.Add(1);
962
963 this.cut2CoordIndices.Add(lastOuterVertIndex);
964 this.cut2CoordIndices.Add(0);
965
958 this.cutNormal1.X = this.vertexNormals[1].Y; 966 this.cutNormal1.X = this.vertexNormals[1].Y;
959 this.cutNormal1.Y = -this.vertexNormals[1].X; 967 this.cutNormal1.Y = -this.vertexNormals[1].X;
960 968
@@ -979,11 +987,14 @@ namespace PrimMesher
979 // I know it's ugly but so is the whole concept of prim face numbers 987 // I know it's ugly but so is the whole concept of prim face numbers
980 988
981 int faceNum = 1; // start with outer faces 989 int faceNum = 1; // start with outer faces
990 this.outerFaceNumber = faceNum;
991
982 int startVert = hasProfileCut && !hasHollow ? 1 : 0; 992 int startVert = hasProfileCut && !hasHollow ? 1 : 0;
983 if (startVert > 0) 993 if (startVert > 0)
984 this.faceNumbers.Add(-1); 994 this.faceNumbers.Add(-1);
985 for (int i = 0; i < this.numOuterVerts - 1; i++) 995 for (int i = 0; i < this.numOuterVerts - 1; i++)
986 this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); 996 //this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum);
997 this.faceNumbers.Add(sides < 5 && i < sides ? faceNum++ : faceNum);
987 998
988 //if (!hasHollow && !hasProfileCut) 999 //if (!hasHollow && !hasProfileCut)
989 // this.bottomFaceNumber = faceNum++; 1000 // this.bottomFaceNumber = faceNum++;
@@ -993,12 +1004,15 @@ namespace PrimMesher
993 if (sides > 4 && (hasHollow || hasProfileCut)) 1004 if (sides > 4 && (hasHollow || hasProfileCut))
994 faceNum++; 1005 faceNum++;
995 1006
1007 if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides)
1008 faceNum++;
1009
996 if (hasHollow) 1010 if (hasHollow)
997 { 1011 {
998 for (int i = 0; i < this.numHollowVerts; i++) 1012 for (int i = 0; i < this.numHollowVerts; i++)
999 this.faceNumbers.Add(faceNum); 1013 this.faceNumbers.Add(faceNum);
1000 1014
1001 faceNum++; 1015 this.hollowFaceNumber = faceNum++;
1002 } 1016 }
1003 //if (hasProfileCut || hasHollow) 1017 //if (hasProfileCut || hasHollow)
1004 // this.bottomFaceNumber = faceNum++; 1018 // this.bottomFaceNumber = faceNum++;
@@ -1006,11 +1020,11 @@ namespace PrimMesher
1006 1020
1007 if (hasHollow && hasProfileCut) 1021 if (hasHollow && hasProfileCut)
1008 this.faceNumbers.Add(faceNum++); 1022 this.faceNumbers.Add(faceNum++);
1023
1009 for (int i = 0; i < this.faceNumbers.Count; i++) 1024 for (int i = 0; i < this.faceNumbers.Count; i++)
1010 if (this.faceNumbers[i] == -1) 1025 if (this.faceNumbers[i] == -1)
1011 this.faceNumbers[i] = faceNum++; 1026 this.faceNumbers[i] = faceNum++;
1012 1027
1013
1014 this.numPrimFaces = faceNum; 1028 this.numPrimFaces = faceNum;
1015 } 1029 }
1016 1030
@@ -1455,11 +1469,15 @@ namespace PrimMesher
1455 public float revolutions = 1.0f; 1469 public float revolutions = 1.0f;
1456 public int stepsPerRevolution = 24; 1470 public int stepsPerRevolution = 24;
1457 1471
1472 private int profileOuterFaceNumber = -1;
1473 private int profileHollowFaceNumber = -1;
1474
1458 private bool hasProfileCut = false; 1475 private bool hasProfileCut = false;
1459 private bool hasHollow = false; 1476 private bool hasHollow = false;
1460 public bool calcVertexNormals = false; 1477 public bool calcVertexNormals = false;
1461 private bool normalsProcessed = false; 1478 private bool normalsProcessed = false;
1462 public bool viewerMode = false; 1479 public bool viewerMode = false;
1480 public bool sphereMode = false;
1463 1481
1464 public int numPrimFaces = 0; 1482 public int numPrimFaces = 0;
1465 1483
@@ -1491,10 +1509,35 @@ namespace PrimMesher
1491 s += "\nradius...............: " + this.radius.ToString(); 1509 s += "\nradius...............: " + this.radius.ToString();
1492 s += "\nrevolutions..........: " + this.revolutions.ToString(); 1510 s += "\nrevolutions..........: " + this.revolutions.ToString();
1493 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); 1511 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1512 s += "\nsphereMode...........: " + this.sphereMode.ToString();
1513 s += "\nhasProfileCut........: " + this.hasProfileCut.ToString();
1514 s += "\nhasHollow............: " + this.hasHollow.ToString();
1515 s += "\nviewerMode...........: " + this.viewerMode.ToString();
1494 1516
1495 return s; 1517 return s;
1496 } 1518 }
1497 1519
1520 public int ProfileOuterFaceNumber
1521 {
1522 get { return profileOuterFaceNumber; }
1523 }
1524
1525 public int ProfileHollowFaceNumber
1526 {
1527 get { return profileHollowFaceNumber; }
1528 }
1529
1530 public bool HasProfileCut
1531 {
1532 get { return hasProfileCut; }
1533 }
1534
1535 public bool HasHollow
1536 {
1537 get { return hasHollow; }
1538 }
1539
1540
1498 /// <summary> 1541 /// <summary>
1499 /// Constructs a PrimMesh object and creates the profile for extrusion. 1542 /// Constructs a PrimMesh object and creates the profile for extrusion.
1500 /// </summary> 1543 /// </summary>
@@ -1531,8 +1574,12 @@ namespace PrimMesher
1531 if (hollow < 0.0f) 1574 if (hollow < 0.0f)
1532 this.hollow = 0.0f; 1575 this.hollow = 0.0f;
1533 1576
1534 this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); 1577 //if (sphereMode)
1535 this.hasHollow = (this.hollow > 0.001f); 1578 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1579 //else
1580 // //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1581 // this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1582 //this.hasHollow = (this.hollow > 0.001f);
1536 } 1583 }
1537 1584
1538 /// <summary> 1585 /// <summary>
@@ -1540,6 +1587,8 @@ namespace PrimMesher
1540 /// </summary> 1587 /// </summary>
1541 public void Extrude(PathType pathType) 1588 public void Extrude(PathType pathType)
1542 { 1589 {
1590 bool needEndFaces = false;
1591
1543 this.coords = new List<Coord>(); 1592 this.coords = new List<Coord>();
1544 this.faces = new List<Face>(); 1593 this.faces = new List<Face>();
1545 1594
@@ -1565,6 +1614,12 @@ namespace PrimMesher
1565 steps = (int)(steps * 4.5 * length); 1614 steps = (int)(steps * 4.5 * length);
1566 } 1615 }
1567 1616
1617 if (sphereMode)
1618 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1619 else
1620 //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f);
1621 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1622 this.hasHollow = (this.hollow > 0.001f);
1568 1623
1569 float twistBegin = this.twistBegin / 360.0f * twoPi; 1624 float twistBegin = this.twistBegin / 360.0f * twoPi;
1570 float twistEnd = this.twistEnd / 360.0f * twoPi; 1625 float twistEnd = this.twistEnd / 360.0f * twoPi;
@@ -1634,6 +1689,32 @@ namespace PrimMesher
1634 1689
1635 this.numPrimFaces = profile.numPrimFaces; 1690 this.numPrimFaces = profile.numPrimFaces;
1636 1691
1692 //profileOuterFaceNumber = profile.faceNumbers[0];
1693 //if (!needEndFaces)
1694 // profileOuterFaceNumber--;
1695 //profileOuterFaceNumber = needEndFaces ? 1 : 0;
1696
1697
1698 //if (hasHollow)
1699 //{
1700 // if (needEndFaces)
1701 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts + 1];
1702 // else
1703 // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts] - 1;
1704 //}
1705
1706
1707 profileOuterFaceNumber = profile.outerFaceNumber;
1708 if (!needEndFaces)
1709 profileOuterFaceNumber--;
1710
1711 if (hasHollow)
1712 {
1713 profileHollowFaceNumber = profile.hollowFaceNumber;
1714 if (!needEndFaces)
1715 profileHollowFaceNumber--;
1716 }
1717
1637 int cut1Vert = -1; 1718 int cut1Vert = -1;
1638 int cut2Vert = -1; 1719 int cut2Vert = -1;
1639 if (hasProfileCut) 1720 if (hasProfileCut)
@@ -1673,7 +1754,7 @@ namespace PrimMesher
1673 1754
1674 path.Create(pathType, steps); 1755 path.Create(pathType, steps);
1675 1756
1676 bool needEndFaces = false; 1757
1677 if (pathType == PathType.Circular) 1758 if (pathType == PathType.Circular)
1678 { 1759 {
1679 needEndFaces = false; 1760 needEndFaces = false;
@@ -1761,7 +1842,7 @@ namespace PrimMesher
1761 int startVert = coordsLen + 1; 1842 int startVert = coordsLen + 1;
1762 int endVert = this.coords.Count; 1843 int endVert = this.coords.Count;
1763 1844
1764 if (sides < 5 || this.hasProfileCut || hollow > 0.0f) 1845 if (sides < 5 || this.hasProfileCut || this.hasHollow)
1765 startVert--; 1846 startVert--;
1766 1847
1767 for (int i = startVert; i < endVert; i++) 1848 for (int i = startVert; i < endVert; i++)
@@ -1813,11 +1894,13 @@ namespace PrimMesher
1813 u1 -= (int)u1; 1894 u1 -= (int)u1;
1814 if (u2 < 0.1f) 1895 if (u2 < 0.1f)
1815 u2 = 1.0f; 1896 u2 = 1.0f;
1897 //this.profileOuterFaceNumber = primFaceNum;
1816 } 1898 }
1817 else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) 1899 else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1)
1818 { 1900 {
1819 u1 *= 2.0f; 1901 u1 *= 2.0f;
1820 u2 *= 2.0f; 1902 u2 *= 2.0f;
1903 //this.profileHollowFaceNumber = primFaceNum;
1821 } 1904 }
1822 } 1905 }
1823 1906
diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs
new file mode 100644
index 0000000..d2d71de
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/SculptMap.cs
@@ -0,0 +1,176 @@
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 OpenSimulator 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
28// to build without references to System.Drawing, comment this out
29#define SYSTEM_DRAWING
30
31using System;
32using System.Collections.Generic;
33using System.Text;
34
35#if SYSTEM_DRAWING
36using System.Drawing;
37using System.Drawing.Imaging;
38
39namespace PrimMesher
40{
41 public class SculptMap
42 {
43 public int width;
44 public int height;
45 public byte[] redBytes;
46 public byte[] greenBytes;
47 public byte[] blueBytes;
48
49 public SculptMap()
50 {
51 }
52
53 public SculptMap(Bitmap bm, int lod)
54 {
55 int bmW = bm.Width;
56 int bmH = bm.Height;
57
58 if (bmW == 0 || bmH == 0)
59 throw new Exception("SculptMap: bitmap has no data");
60
61 int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
62
63 bool needsScaling = false;
64
65 width = bmW;
66 height = bmH;
67 while (width * height > numLodPixels)
68 {
69 width >>= 1;
70 height >>= 1;
71 needsScaling = true;
72 }
73
74
75
76 try
77 {
78 if (needsScaling)
79 bm = ScaleImage(bm, width, height,
80 System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
81 }
82
83 catch (Exception e)
84 {
85 throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
86 }
87
88 if (width * height > lod * lod)
89 {
90 width >>= 1;
91 height >>= 1;
92 }
93
94 int numBytes = (width + 1) * (height + 1);
95 redBytes = new byte[numBytes];
96 greenBytes = new byte[numBytes];
97 blueBytes = new byte[numBytes];
98
99 int byteNdx = 0;
100
101 try
102 {
103 for (int y = 0; y <= height; y++)
104 {
105 for (int x = 0; x <= width; x++)
106 {
107 int bmY = y < height ? y * 2 : y * 2 - 1;
108 int bmX = x < width ? x * 2 : x * 2 - 1;
109 Color c = bm.GetPixel(bmX, bmY);
110
111 redBytes[byteNdx] = c.R;
112 greenBytes[byteNdx] = c.G;
113 blueBytes[byteNdx] = c.B;
114
115 ++byteNdx;
116 }
117 }
118 }
119 catch (Exception e)
120 {
121 throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString());
122 }
123
124 width++;
125 height++;
126 }
127
128 public List<List<Coord>> ToRows(bool mirror)
129 {
130 int numRows = height;
131 int numCols = width;
132
133 List<List<Coord>> rows = new List<List<Coord>>(numRows);
134
135 float pixScale = 1.0f / 255;
136
137 int rowNdx, colNdx;
138 int smNdx = 0;
139
140 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
141 {
142 List<Coord> row = new List<Coord>(numCols);
143 for (colNdx = 0; colNdx < numCols; colNdx++)
144 {
145 if (mirror)
146 row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f));
147 else
148 row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f));
149
150 ++smNdx;
151 }
152 rows.Add(row);
153 }
154 return rows;
155 }
156
157 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight,
158 System.Drawing.Drawing2D.InterpolationMode interpMode)
159 {
160 Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight);
161 scaledImage.SetResolution(96.0f, 96.0f);
162
163 Graphics grPhoto = Graphics.FromImage(scaledImage);
164 grPhoto.InterpolationMode = interpMode;
165
166 grPhoto.DrawImage(srcImage,
167 new Rectangle(0, 0, destWidth, destHeight),
168 new Rectangle(0, 0, srcImage.Width, srcImage.Height),
169 GraphicsUnit.Pixel);
170
171 grPhoto.Dispose();
172 return scaledImage;
173 }
174 }
175}
176#endif
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index ebc5be6..6aa8fe4 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -53,50 +53,6 @@ namespace PrimMesher
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, bool removeAlpha)
57 {
58 int sourceWidth = srcImage.Width;
59 int sourceHeight = srcImage.Height;
60 int sourceX = 0;
61 int sourceY = 0;
62
63 int destX = 0;
64 int destY = 0;
65 int destWidth = (int)(srcImage.Width * scale);
66 int destHeight = (int)(srcImage.Height * scale);
67
68 Bitmap scaledImage;
69
70 if (removeAlpha)
71 {
72 if (srcImage.PixelFormat == PixelFormat.Format32bppArgb)
73 for (int y = 0; y < srcImage.Height; y++)
74 for (int x = 0; x < srcImage.Width; x++)
75 {
76 Color c = srcImage.GetPixel(x, y);
77 srcImage.SetPixel(x, y, Color.FromArgb(255, c.R, c.G, c.B));
78 }
79
80 scaledImage = new Bitmap(destWidth, destHeight,
81 PixelFormat.Format24bppRgb);
82 }
83 else
84 scaledImage = new Bitmap(srcImage, destWidth, destHeight);
85
86 scaledImage.SetResolution(96.0f, 96.0f);
87
88 Graphics grPhoto = Graphics.FromImage(scaledImage);
89 grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
90
91 grPhoto.DrawImage(srcImage,
92 new Rectangle(destX, destY, destWidth, destHeight),
93 new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
94 GraphicsUnit.Pixel);
95
96 grPhoto.Dispose();
97 return scaledImage;
98 }
99
100 56
101 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) 57 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
102 { 58 {
@@ -106,6 +62,7 @@ namespace PrimMesher
106 return sculptMesh; 62 return sculptMesh;
107 } 63 }
108 64
65
109 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)
110 { 67 {
111 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); 68 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
@@ -296,36 +253,53 @@ namespace PrimMesher
296 return rows; 253 return rows;
297 } 254 }
298 255
299 256 private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror)
300 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert)
301 { 257 {
302 coords = new List<Coord>(); 258 int numRows = bitmap.Height / scale;
303 faces = new List<Face>(); 259 int numCols = bitmap.Width / scale;
304 normals = new List<Coord>(); 260 List<List<Coord>> rows = new List<List<Coord>>(numRows);
305 uvs = new List<UVCoord>();
306 261
307 sculptType = (SculptType)(((int)sculptType) & 0x07); 262 float pixScale = 1.0f / 256.0f;
308 263
309 if (mirror) 264 int imageX, imageY = 0;
310 if (sculptType == SculptType.plane) 265
311 invert = !invert; 266 int rowNdx, colNdx;
312 267
313 float sculptBitmapLod = (float)Math.Sqrt(sculptBitmap.Width * sculptBitmap.Height); 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--;
314 277
315 float sourceScaleFactor = (float)(lod) / sculptBitmapLod; 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 }
316 284
317 float fScale = 1.0f / sourceScaleFactor; 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));
318 289
319 int iScale = (int)fScale; 290 }
320 if (iScale < 1) iScale = 1; 291 rows.Add(row);
321 if (iScale > 2 && iScale % 2 == 0) 292 }
322 _SculptMesh(bitmap2Coords(ScaleImage(sculptBitmap, 64.0f / sculptBitmapLod, true), 64 / lod, mirror), sculptType, viewerMode, mirror, invert); 293 return rows;
323 else
324 _SculptMesh(bitmap2Coords(sculptBitmap, iScale, mirror), sculptType, viewerMode, mirror, invert);
325 } 294 }
326#endif
327 295
328 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
329 void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) 303 void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
330 { 304 {
331 coords = new List<Coord>(); 305 coords = new List<Coord>();
@@ -349,8 +323,18 @@ namespace PrimMesher
349 323
350 if (sculptType != SculptType.plane) 324 if (sculptType != SculptType.plane)
351 { 325 {
352 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) 326 if (rows.Count % 2 == 0)
353 rows[rowNdx].Add(rows[rowNdx][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 }
354 } 338 }
355 339
356 Coord topPole = rows[0][width / 2]; 340 Coord topPole = rows[0][width / 2];
@@ -358,23 +342,41 @@ namespace PrimMesher
358 342
359 if (sculptType == SculptType.sphere) 343 if (sculptType == SculptType.sphere)
360 { 344 {
361 int count = rows[0].Count; 345 if (rows.Count % 2 == 0)
362 List<Coord> topPoleRow = new List<Coord>(count); 346 {
363 List<Coord> bottomPoleRow = new List<Coord>(count); 347 int count = rows[0].Count;
348 List<Coord> topPoleRow = new List<Coord>(count);
349 List<Coord> bottomPoleRow = new List<Coord>(count);
364 350
365 for (int i = 0; i < count; i++) 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
366 { 360 {
367 topPoleRow.Add(topPole); 361 int count = rows[0].Count;
368 bottomPoleRow.Add(bottomPole); 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 }
369 } 371 }
370 rows.Insert(0, topPoleRow);
371 rows.Add(bottomPoleRow);
372 } 372 }
373 else if (sculptType == SculptType.torus) 373
374 if (sculptType == SculptType.torus)
374 rows.Add(rows[0]); 375 rows.Add(rows[0]);
375 376
376 int coordsDown = rows.Count; 377 int coordsDown = rows.Count;
377 int coordsAcross = rows[0].Count; 378 int coordsAcross = rows[0].Count;
379 int lastColumn = coordsAcross - 1;
378 380
379 float widthUnit = 1.0f / (coordsAcross - 1); 381 float widthUnit = 1.0f / (coordsAcross - 1);
380 float heightUnit = 1.0f / (coordsDown - 1); 382 float heightUnit = 1.0f / (coordsDown - 1);