aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitMeshing
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitMeshing')
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs57
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs183
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/SculptMap.cs95
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs440
4 files changed, 284 insertions, 491 deletions
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index c715642..98c0f0b 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -37,6 +37,7 @@ namespace OpenSim.Region.Physics.Meshing
37{ 37{
38 public class Mesh : IMesh 38 public class Mesh : IMesh
39 { 39 {
40
40 private Dictionary<Vertex, int> m_vertices; 41 private Dictionary<Vertex, int> m_vertices;
41 private List<Triangle> m_triangles; 42 private List<Triangle> m_triangles;
42 GCHandle m_pinnedVertexes; 43 GCHandle m_pinnedVertexes;
@@ -46,8 +47,9 @@ namespace OpenSim.Region.Physics.Meshing
46 IntPtr m_indicesPtr = IntPtr.Zero; 47 IntPtr m_indicesPtr = IntPtr.Zero;
47 int m_indexCount = 0; 48 int m_indexCount = 0;
48 public float[] m_normals; 49 public float[] m_normals;
49 Vector3 _centroid; 50 Vector3 m_centroid;
50 int _centroidDiv; 51 int m_centroidDiv;
52
51 53
52 private class vertexcomp : IEqualityComparer<Vertex> 54 private class vertexcomp : IEqualityComparer<Vertex>
53 { 55 {
@@ -65,7 +67,6 @@ namespace OpenSim.Region.Physics.Meshing
65 int c = v.Z.GetHashCode(); 67 int c = v.Z.GetHashCode();
66 return (a << 16) ^ (b << 8) ^ c; 68 return (a << 16) ^ (b << 8) ^ c;
67 } 69 }
68
69 } 70 }
70 71
71 public Mesh() 72 public Mesh()
@@ -74,8 +75,18 @@ namespace OpenSim.Region.Physics.Meshing
74 75
75 m_vertices = new Dictionary<Vertex, int>(vcomp); 76 m_vertices = new Dictionary<Vertex, int>(vcomp);
76 m_triangles = new List<Triangle>(); 77 m_triangles = new List<Triangle>();
77 _centroid = Vector3.Zero; 78 m_centroid = Vector3.Zero;
78 _centroidDiv = 0; 79 m_centroidDiv = 0;
80 }
81
82 public int RefCount { get; set; }
83
84 public AMeshKey Key { get; set; }
85
86 public void Scale(Vector3 scale)
87 {
88
89
79 } 90 }
80 91
81 public Mesh Clone() 92 public Mesh Clone()
@@ -86,8 +97,8 @@ namespace OpenSim.Region.Physics.Meshing
86 { 97 {
87 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); 98 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
88 } 99 }
89 result._centroid = _centroid; 100 result.m_centroid = m_centroid;
90 result._centroidDiv = _centroidDiv; 101 result.m_centroidDiv = m_centroidDiv;
91 return result; 102 return result;
92 } 103 }
93 104
@@ -109,41 +120,41 @@ namespace OpenSim.Region.Physics.Meshing
109 120
110 if (m_vertices.Count == 0) 121 if (m_vertices.Count == 0)
111 { 122 {
112 _centroidDiv = 0; 123 m_centroidDiv = 0;
113 _centroid = Vector3.Zero; 124 m_centroid = Vector3.Zero;
114 } 125 }
115 126
116 if (!m_vertices.ContainsKey(triangle.v1)) 127 if (!m_vertices.ContainsKey(triangle.v1))
117 { 128 {
118 m_vertices[triangle.v1] = m_vertices.Count; 129 m_vertices[triangle.v1] = m_vertices.Count;
119 _centroid.X += triangle.v1.X; 130 m_centroid.X += triangle.v1.X;
120 _centroid.Y += triangle.v1.Y; 131 m_centroid.Y += triangle.v1.Y;
121 _centroid.Z += triangle.v1.Z; 132 m_centroid.Z += triangle.v1.Z;
122 _centroidDiv++; 133 m_centroidDiv++;
123 } 134 }
124 if (!m_vertices.ContainsKey(triangle.v2)) 135 if (!m_vertices.ContainsKey(triangle.v2))
125 { 136 {
126 m_vertices[triangle.v2] = m_vertices.Count; 137 m_vertices[triangle.v2] = m_vertices.Count;
127 _centroid.X += triangle.v2.X; 138 m_centroid.X += triangle.v2.X;
128 _centroid.Y += triangle.v2.Y; 139 m_centroid.Y += triangle.v2.Y;
129 _centroid.Z += triangle.v2.Z; 140 m_centroid.Z += triangle.v2.Z;
130 _centroidDiv++; 141 m_centroidDiv++;
131 } 142 }
132 if (!m_vertices.ContainsKey(triangle.v3)) 143 if (!m_vertices.ContainsKey(triangle.v3))
133 { 144 {
134 m_vertices[triangle.v3] = m_vertices.Count; 145 m_vertices[triangle.v3] = m_vertices.Count;
135 _centroid.X += triangle.v3.X; 146 m_centroid.X += triangle.v3.X;
136 _centroid.Y += triangle.v3.Y; 147 m_centroid.Y += triangle.v3.Y;
137 _centroid.Z += triangle.v3.Z; 148 m_centroid.Z += triangle.v3.Z;
138 _centroidDiv++; 149 m_centroidDiv++;
139 } 150 }
140 m_triangles.Add(triangle); 151 m_triangles.Add(triangle);
141 } 152 }
142 153
143 public Vector3 GetCentroid() 154 public Vector3 GetCentroid()
144 { 155 {
145 if (_centroidDiv > 0) 156 if (m_centroidDiv > 0)
146 return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv); 157 return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
147 else 158 else
148 return Vector3.Zero; 159 return Vector3.Zero;
149 } 160 }
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index f002bba..4c40175 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -82,7 +82,10 @@ namespace OpenSim.Region.Physics.Meshing
82 82
83 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 83 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
84 84
85 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); 85// private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
86// private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>();
87 private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
88 private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
86 89
87 public Meshmerizer(IConfigSource config) 90 public Meshmerizer(IConfigSource config)
88 { 91 {
@@ -314,6 +317,9 @@ namespace OpenSim.Region.Physics.Meshing
314 coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z)); 317 coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z));
315 } 318 }
316 319
320 coords.Clear();
321 faces.Clear();
322
317 return mesh; 323 return mesh;
318 } 324 }
319 325
@@ -780,7 +786,9 @@ namespace OpenSim.Region.Physics.Meshing
780 } 786 }
781 787
782 PrimMesher.SculptMesh.SculptType sculptType; 788 PrimMesher.SculptMesh.SculptType sculptType;
783 switch ((OpenMetaverse.SculptType)primShape.SculptType) 789 // remove mirror and invert bits
790 OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f));
791 switch (pbsSculptType)
784 { 792 {
785 case OpenMetaverse.SculptType.Cylinder: 793 case OpenMetaverse.SculptType.Cylinder:
786 sculptType = PrimMesher.SculptMesh.SculptType.cylinder; 794 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
@@ -802,7 +810,7 @@ namespace OpenSim.Region.Physics.Meshing
802 bool mirror = ((primShape.SculptType & 128) != 0); 810 bool mirror = ((primShape.SculptType & 128) != 0);
803 bool invert = ((primShape.SculptType & 64) != 0); 811 bool invert = ((primShape.SculptType & 64) != 0);
804 812
805 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); 813 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, mirror, invert);
806 814
807 idata.Dispose(); 815 idata.Dispose();
808 816
@@ -971,6 +979,76 @@ namespace OpenSim.Region.Physics.Meshing
971 return true; 979 return true;
972 } 980 }
973 981
982 public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex)
983 {
984 AMeshKey key = new AMeshKey();
985 Byte[] someBytes;
986
987 key.hashB = 5181;
988 ulong hash = 5381;
989
990 if (primShape.SculptEntry)
991 {
992 key.uuid = primShape.SculptTexture;
993 key.hashB = mdjb2(key.hashB, primShape.SculptType);
994 }
995 else
996 {
997 hash = mdjb2(hash, primShape.PathCurve);
998 hash = mdjb2(hash, (byte)primShape.HollowShape);
999 hash = mdjb2(hash, (byte)primShape.ProfileShape);
1000 hash = mdjb2(hash, primShape.PathBegin);
1001 hash = mdjb2(hash, primShape.PathEnd);
1002 hash = mdjb2(hash, primShape.PathScaleX);
1003 hash = mdjb2(hash, primShape.PathScaleY);
1004 hash = mdjb2(hash, primShape.PathShearX);
1005 hash = mdjb2(hash, primShape.PathShearY);
1006 hash = mdjb2(hash, (byte)primShape.PathTwist);
1007 hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
1008 hash = mdjb2(hash, (byte)primShape.PathRadiusOffset);
1009 hash = mdjb2(hash, (byte)primShape.PathTaperX);
1010 hash = mdjb2(hash, (byte)primShape.PathTaperY);
1011 hash = mdjb2(hash, primShape.PathRevolutions);
1012 hash = mdjb2(hash, (byte)primShape.PathSkew);
1013 hash = mdjb2(hash, primShape.ProfileBegin);
1014 hash = mdjb2(hash, primShape.ProfileEnd);
1015 hash = mdjb2(hash, primShape.ProfileHollow);
1016 key.hashA = hash;
1017 }
1018
1019 hash = key.hashB;
1020
1021 someBytes = size.GetBytes();
1022 for (int i = 0; i < someBytes.Length; i++)
1023 hash = mdjb2(hash, someBytes[i]);
1024
1025 hash = mdjb2(hash, lod);
1026
1027 hash &= 0x3fffffffffffffff;
1028
1029 if (convex)
1030 hash |= 0x4000000000000000;
1031
1032 if (primShape.SculptEntry)
1033 hash |= 0x8000000000000000;
1034
1035 key.hashB = hash;
1036
1037 return key;
1038 }
1039
1040 private ulong mdjb2(ulong hash, byte c)
1041 {
1042 return ((hash << 5) + hash) + (ulong)c;
1043 }
1044
1045 private ulong mdjb2(ulong hash, ushort c)
1046 {
1047 hash = ((hash << 5) + hash) + (ulong)((byte)c);
1048 return ((hash << 5) + hash) + (ulong)(c >> 8);
1049 }
1050
1051
974 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 1052 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
975 { 1053 {
976 return CreateMesh(primName, primShape, size, lod, false,false); 1054 return CreateMesh(primName, primShape, size, lod, false,false);
@@ -981,6 +1059,8 @@ namespace OpenSim.Region.Physics.Meshing
981 return CreateMesh(primName, primShape, size, lod, false,false); 1059 return CreateMesh(primName, primShape, size, lod, false,false);
982 } 1060 }
983 1061
1062 private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f);
1063
984 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) 1064 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
985 { 1065 {
986#if SPAM 1066#if SPAM
@@ -988,18 +1068,42 @@ namespace OpenSim.Region.Physics.Meshing
988#endif 1068#endif
989 1069
990 Mesh mesh = null; 1070 Mesh mesh = null;
991 ulong key = 0; 1071// ulong key = 0;
992 1072
993 // If this mesh has been created already, return it instead of creating another copy
994 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
995 key = primShape.GetMeshKey(size, lod, convex);
996 if (m_uniqueMeshes.TryGetValue(key, out mesh))
997 return mesh;
998 1073
999 if (size.X < 0.01f) size.X = 0.01f; 1074 if (size.X < 0.01f) size.X = 0.01f;
1000 if (size.Y < 0.01f) size.Y = 0.01f; 1075 if (size.Y < 0.01f) size.Y = 0.01f;
1001 if (size.Z < 0.01f) size.Z = 0.01f; 1076 if (size.Z < 0.01f) size.Z = 0.01f;
1002 1077
1078 // try to find a identical mesh on meshs in use
1079// key = primShape.GetMeshKey(size, lod, convex);
1080 AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
1081
1082 lock (m_uniqueMeshes)
1083 {
1084 m_uniqueMeshes.TryGetValue(key, out mesh);
1085
1086 if (mesh != null)
1087 {
1088 mesh.RefCount++;
1089 return mesh;
1090 }
1091 }
1092
1093 // try to find a identical mesh on meshs recently released
1094 lock (m_uniqueReleasedMeshes)
1095 {
1096 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1097 if (mesh != null)
1098 {
1099 m_uniqueReleasedMeshes.Remove(key);
1100 lock (m_uniqueMeshes)
1101 m_uniqueMeshes.Add(key, mesh);
1102 mesh.RefCount = 1;
1103 return mesh;
1104 }
1105 }
1106
1003 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); 1107 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex);
1004 1108
1005 if (mesh != null) 1109 if (mesh != null)
@@ -1016,11 +1120,68 @@ namespace OpenSim.Region.Physics.Meshing
1016 1120
1017 // trim the vertex and triangle lists to free up memory 1121 // trim the vertex and triangle lists to free up memory
1018 mesh.TrimExcess(); 1122 mesh.TrimExcess();
1123 mesh.Key = key;
1124 mesh.RefCount = 1;
1019 1125
1020 m_uniqueMeshes.Add(key, mesh); 1126 lock(m_uniqueMeshes)
1127 m_uniqueMeshes.Add(key, mesh);
1021 } 1128 }
1022 1129
1023 return mesh; 1130 return mesh;
1024 } 1131 }
1132
1133 public void ReleaseMesh(IMesh imesh)
1134 {
1135 if (imesh == null)
1136 return;
1137
1138 Mesh mesh = (Mesh)imesh;
1139
1140 int curRefCount = mesh.RefCount;
1141 curRefCount--;
1142
1143 if (curRefCount > 0)
1144 {
1145 mesh.RefCount = curRefCount;
1146 return;
1147 }
1148
1149 lock (m_uniqueMeshes)
1150 {
1151 mesh.RefCount = 0;
1152 m_uniqueMeshes.Remove(mesh.Key);
1153 lock (m_uniqueReleasedMeshes)
1154 m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
1155 }
1156 }
1157
1158 public void ExpireReleaseMeshs()
1159 {
1160 if (m_uniqueReleasedMeshes.Count == 0)
1161 return;
1162
1163 List<Mesh> meshstodelete = new List<Mesh>();
1164 int refcntr;
1165
1166 lock (m_uniqueReleasedMeshes)
1167 {
1168 foreach (Mesh m in m_uniqueReleasedMeshes.Values)
1169 {
1170 refcntr = m.RefCount;
1171 refcntr--;
1172 if (refcntr > -6)
1173 m.RefCount = refcntr;
1174 else
1175 meshstodelete.Add(m);
1176 }
1177
1178 foreach (Mesh m in meshstodelete)
1179 {
1180 m_uniqueReleasedMeshes.Remove(m.Key);
1181 m.releaseSourceMeshData();
1182 m.releasePinned();
1183 }
1184 }
1185 }
1025 } 1186 }
1026} 1187}
diff --git a/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs b/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs
index b3d9cb6..1c75db6 100644
--- a/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs
@@ -25,14 +25,10 @@
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
29#define SYSTEM_DRAWING
30
31using System; 28using System;
32using System.Collections.Generic; 29using System.Collections.Generic;
33using System.Text; 30using System.Text;
34 31
35#if SYSTEM_DRAWING
36using System.Drawing; 32using System.Drawing;
37using System.Drawing.Imaging; 33using System.Drawing.Imaging;
38 34
@@ -60,11 +56,12 @@ namespace PrimMesher
60 56
61 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image 57 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
62 58
63 bool smallMap = bmW * bmH <= numLodPixels;
64 bool needsScaling = false; 59 bool needsScaling = false;
60 bool smallMap = false;
65 61
66 width = bmW; 62 width = bmW;
67 height = bmH; 63 height = bmH;
64
68 while (width * height > numLodPixels * 4) 65 while (width * height > numLodPixels * 4)
69 { 66 {
70 width >>= 1; 67 width >>= 1;
@@ -85,9 +82,12 @@ namespace PrimMesher
85 82
86 if (width * height > numLodPixels) 83 if (width * height > numLodPixels)
87 { 84 {
85 smallMap = false;
88 width >>= 1; 86 width >>= 1;
89 height >>= 1; 87 height >>= 1;
90 } 88 }
89 else
90 smallMap = true;
91 91
92 int numBytes = (width + 1) * (height + 1); 92 int numBytes = (width + 1) * (height + 1);
93 redBytes = new byte[numBytes]; 93 redBytes = new byte[numBytes];
@@ -95,21 +95,18 @@ namespace PrimMesher
95 blueBytes = new byte[numBytes]; 95 blueBytes = new byte[numBytes];
96 96
97 int byteNdx = 0; 97 int byteNdx = 0;
98 Color c;
98 99
99 try 100 try
100 { 101 {
101 for (int y = 0; y <= height; y++) 102 for (int y = 0; y <= height; y++)
102 { 103 {
103 for (int x = 0; x <= width; x++) 104 for (int x = 0; x < width; x++)
104 { 105 {
105 Color c;
106
107 if (smallMap) 106 if (smallMap)
108 c = bm.GetPixel(x < width ? x : x - 1, 107 c = bm.GetPixel(x, y < height ? y : y - 1);
109 y < height ? y : y - 1);
110 else 108 else
111 c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1, 109 c = bm.GetPixel(x * 2, y < height ? y * 2 : y * 2 - 1);
112 y < height ? y * 2 : y * 2 - 1);
113 110
114 redBytes[byteNdx] = c.R; 111 redBytes[byteNdx] = c.R;
115 greenBytes[byteNdx] = c.G; 112 greenBytes[byteNdx] = c.G;
@@ -117,6 +114,17 @@ namespace PrimMesher
117 114
118 ++byteNdx; 115 ++byteNdx;
119 } 116 }
117
118 if (smallMap)
119 c = bm.GetPixel(width - 1, y < height ? y : y - 1);
120 else
121 c = bm.GetPixel(width * 2 - 1, y < height ? y * 2 : y * 2 - 1);
122
123 redBytes[byteNdx] = c.R;
124 greenBytes[byteNdx] = c.G;
125 blueBytes[byteNdx] = c.B;
126
127 ++byteNdx;
120 } 128 }
121 } 129 }
122 catch (Exception e) 130 catch (Exception e)
@@ -140,7 +148,6 @@ namespace PrimMesher
140 int rowNdx, colNdx; 148 int rowNdx, colNdx;
141 int smNdx = 0; 149 int smNdx = 0;
142 150
143
144 for (rowNdx = 0; rowNdx < numRows; rowNdx++) 151 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
145 { 152 {
146 List<Coord> row = new List<Coord>(numCols); 153 List<Coord> row = new List<Coord>(numCols);
@@ -163,16 +170,27 @@ namespace PrimMesher
163 { 170 {
164 171
165 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); 172 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
166 173
167 Color c; 174 Color c;
168 float xscale = srcImage.Width / destWidth;
169 float yscale = srcImage.Height / destHeight;
170 175
176
177 // will let last step to be eventually diferent, as seems to be in sl
178
179 float xscale = (float)srcImage.Width / (float)destWidth;
180 float yscale = (float)srcImage.Height / (float)destHeight;
181
182 int lastsx = srcImage.Width - 1;
183 int lastsy = srcImage.Height - 1;
184 int lastdx = destWidth - 1;
185 int lastdy = destHeight - 1;
186
171 float sy = 0.5f; 187 float sy = 0.5f;
172 for (int y = 0; y < destHeight; y++) 188 float sx;
189
190 for (int y = 0; y < lastdy; y++)
173 { 191 {
174 float sx = 0.5f; 192 sx = 0.5f;
175 for (int x = 0; x < destWidth; x++) 193 for (int x = 0; x < lastdx; x++)
176 { 194 {
177 try 195 try
178 { 196 {
@@ -182,16 +200,45 @@ namespace PrimMesher
182 catch (IndexOutOfRangeException) 200 catch (IndexOutOfRangeException)
183 { 201 {
184 } 202 }
185
186 sx += xscale; 203 sx += xscale;
187 } 204 }
205 try
206 {
207 c = srcImage.GetPixel(lastsx, (int)(sy));
208 scaledImage.SetPixel(lastdx, y, Color.FromArgb(c.R, c.G, c.B));
209 }
210 catch (IndexOutOfRangeException)
211 {
212 }
213
188 sy += yscale; 214 sy += yscale;
189 } 215 }
216
217 sx = 0.5f;
218 for (int x = 0; x < lastdx; x++)
219 {
220 try
221 {
222 c = srcImage.GetPixel((int)(sx), lastsy);
223 scaledImage.SetPixel(x, lastdy, Color.FromArgb(c.R, c.G, c.B));
224 }
225 catch (IndexOutOfRangeException)
226 {
227 }
228
229 sx += xscale;
230 }
231 try
232 {
233 c = srcImage.GetPixel(lastsx, lastsy);
234 scaledImage.SetPixel(lastdx, lastdy, Color.FromArgb(c.R, c.G, c.B));
235 }
236 catch (IndexOutOfRangeException)
237 {
238 }
239
190 srcImage.Dispose(); 240 srcImage.Dispose();
191 return scaledImage; 241 return scaledImage;
192 } 242 }
193
194 }
195
196 } 243 }
197#endif 244} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs b/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs
index 4a7f3ad..bc1375b 100644
--- a/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs
@@ -25,18 +25,13 @@
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
29#define SYSTEM_DRAWING
30
31using System; 28using System;
32using System.Collections.Generic; 29using System.Collections.Generic;
33using System.Text; 30using System.Text;
34using System.IO; 31using System.IO;
35 32
36#if SYSTEM_DRAWING
37using System.Drawing; 33using System.Drawing;
38using System.Drawing.Imaging; 34using System.Drawing.Imaging;
39#endif
40 35
41namespace PrimMesher 36namespace PrimMesher
42{ 37{
@@ -46,274 +41,28 @@ namespace PrimMesher
46 public List<Coord> coords; 41 public List<Coord> coords;
47 public List<Face> faces; 42 public List<Face> faces;
48 43
49 public List<ViewerFace> viewerFaces;
50 public List<Coord> normals;
51 public List<UVCoord> uvs;
52
53 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; 44 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
54 45
55#if SYSTEM_DRAWING
56
57 public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode)
58 {
59 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
60 SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode);
61 bitmap.Dispose();
62 return sculptMesh;
63 }
64
65
66 public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
67 {
68 Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
69 _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
70 bitmap.Dispose();
71 }
72#endif
73
74 /// <summary>
75 /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications
76 /// Construct a sculpt mesh from a 2D array of floats
77 /// </summary>
78 /// <param name="zMap"></param>
79 /// <param name="xBegin"></param>
80 /// <param name="xEnd"></param>
81 /// <param name="yBegin"></param>
82 /// <param name="yEnd"></param>
83 /// <param name="viewerMode"></param>
84 public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode)
85 {
86 float xStep, yStep;
87 float uStep, vStep;
88
89 int numYElements = zMap.GetLength(0);
90 int numXElements = zMap.GetLength(1);
91
92 try
93 {
94 xStep = (xEnd - xBegin) / (float)(numXElements - 1);
95 yStep = (yEnd - yBegin) / (float)(numYElements - 1);
96
97 uStep = 1.0f / (numXElements - 1);
98 vStep = 1.0f / (numYElements - 1);
99 }
100 catch (DivideByZeroException)
101 {
102 return;
103 }
104
105 coords = new List<Coord>();
106 faces = new List<Face>();
107 normals = new List<Coord>();
108 uvs = new List<UVCoord>();
109
110 viewerFaces = new List<ViewerFace>();
111
112 int p1, p2, p3, p4;
113
114 int x, y;
115 int xStart = 0, yStart = 0;
116
117 for (y = yStart; y < numYElements; y++)
118 {
119 int rowOffset = y * numXElements;
120
121 for (x = xStart; x < numXElements; x++)
122 {
123 /*
124 * p1-----p2
125 * | \ f2 |
126 * | \ |
127 * | f1 \|
128 * p3-----p4
129 */
130
131 p4 = rowOffset + x;
132 p3 = p4 - 1;
133
134 p2 = p4 - numXElements;
135 p1 = p3 - numXElements;
136
137 Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]);
138 this.coords.Add(c);
139 if (viewerMode)
140 {
141 this.normals.Add(new Coord());
142 this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y));
143 }
144
145 if (y > 0 && x > 0)
146 {
147 Face f1, f2;
148
149 if (viewerMode)
150 {
151 f1 = new Face(p1, p4, p3, p1, p4, p3);
152 f1.uv1 = p1;
153 f1.uv2 = p4;
154 f1.uv3 = p3;
155
156 f2 = new Face(p1, p2, p4, p1, p2, p4);
157 f2.uv1 = p1;
158 f2.uv2 = p2;
159 f2.uv3 = p4;
160 }
161 else
162 {
163 f1 = new Face(p1, p4, p3);
164 f2 = new Face(p1, p2, p4);
165 }
166
167 this.faces.Add(f1);
168 this.faces.Add(f2);
169 }
170 }
171 }
172
173 if (viewerMode)
174 calcVertexNormals(SculptType.plane, numXElements, numYElements);
175 }
176
177#if SYSTEM_DRAWING
178 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode)
179 {
180 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false);
181 }
182 46
183 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) 47 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool mirror, bool invert)
184 { 48 {
185 _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); 49 if (mirror)
186 } 50 invert = !invert;
187#endif
188
189 public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert)
190 {
191 _SculptMesh(rows, sculptType, viewerMode, mirror, invert);
192 }
193
194#if SYSTEM_DRAWING
195 /// <summary>
196 /// converts a bitmap to a list of lists of coords, while scaling the image.
197 /// the scaling is done in floating point so as to allow for reduced vertex position
198 /// quantization as the position will be averaged between pixel values. this routine will
199 /// likely fail if the bitmap width and height are not powers of 2.
200 /// </summary>
201 /// <param name="bitmap"></param>
202 /// <param name="scale"></param>
203 /// <param name="mirror"></param>
204 /// <returns></returns>
205 private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror)
206 {
207 int numRows = bitmap.Height / scale;
208 int numCols = bitmap.Width / scale;
209 List<List<Coord>> rows = new List<List<Coord>>(numRows);
210
211 float pixScale = 1.0f / (scale * scale);
212 pixScale /= 255;
213
214 int imageX, imageY = 0;
215
216 int rowNdx, colNdx;
217
218 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
219 {
220 List<Coord> row = new List<Coord>(numCols);
221 for (colNdx = 0; colNdx < numCols; colNdx++)
222 {
223 imageX = colNdx * scale;
224 int imageYStart = rowNdx * scale;
225 int imageYEnd = imageYStart + scale;
226 int imageXEnd = imageX + scale;
227 float rSum = 0.0f;
228 float gSum = 0.0f;
229 float bSum = 0.0f;
230 for (; imageX < imageXEnd; imageX++)
231 {
232 for (imageY = imageYStart; imageY < imageYEnd; imageY++)
233 {
234 Color c = bitmap.GetPixel(imageX, imageY);
235 if (c.A != 255)
236 {
237 bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B));
238 c = bitmap.GetPixel(imageX, imageY);
239 }
240 rSum += c.R;
241 gSum += c.G;
242 bSum += c.B;
243 }
244 }
245 if (mirror)
246 row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
247 else
248 row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f));
249
250 }
251 rows.Add(row);
252 }
253 return rows;
254 }
255
256 private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror)
257 {
258 int numRows = bitmap.Height / scale;
259 int numCols = bitmap.Width / scale;
260 List<List<Coord>> rows = new List<List<Coord>>(numRows);
261
262 float pixScale = 1.0f / 256.0f;
263
264 int imageX, imageY = 0;
265
266 int rowNdx, colNdx;
267
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--;
277
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 }
284
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));
289 51
290 } 52 SculptMap smap = new SculptMap(sculptBitmap, lod);
291 rows.Add(row);
292 }
293 return rows;
294 }
295 53
54 List<List<Coord>> rows = smap.ToRows(mirror);
296 55
297 void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) 56 _SculptMesh(rows, sculptType, invert);
298 {
299 _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert);
300 } 57 }
301#endif
302 58
303 void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) 59 private void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool invert)
304 { 60 {
305 coords = new List<Coord>(); 61 coords = new List<Coord>();
306 faces = new List<Face>(); 62 faces = new List<Face>();
307 normals = new List<Coord>();
308 uvs = new List<UVCoord>();
309 63
310 sculptType = (SculptType)(((int)sculptType) & 0x07); 64 sculptType = (SculptType)(((int)sculptType) & 0x07);
311 65
312 if (mirror)
313 invert = !invert;
314
315 viewerFaces = new List<ViewerFace>();
316
317 int width = rows[0].Count; 66 int width = rows[0].Count;
318 67
319 int p1, p2, p3, p4; 68 int p1, p2, p3, p4;
@@ -375,7 +124,6 @@ namespace PrimMesher
375 124
376 int coordsDown = rows.Count; 125 int coordsDown = rows.Count;
377 int coordsAcross = rows[0].Count; 126 int coordsAcross = rows[0].Count;
378// int lastColumn = coordsAcross - 1;
379 127
380 float widthUnit = 1.0f / (coordsAcross - 1); 128 float widthUnit = 1.0f / (coordsAcross - 1);
381 float heightUnit = 1.0f / (coordsDown - 1); 129 float heightUnit = 1.0f / (coordsDown - 1);
@@ -401,45 +149,11 @@ namespace PrimMesher
401 p1 = p3 - coordsAcross; 149 p1 = p3 - coordsAcross;
402 150
403 this.coords.Add(rows[imageY][imageX]); 151 this.coords.Add(rows[imageY][imageX]);
404 if (viewerMode)
405 {
406 this.normals.Add(new Coord());
407 this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY));
408 }
409 152
410 if (imageY > 0 && imageX > 0) 153 if (imageY > 0 && imageX > 0)
411 { 154 {
412 Face f1, f2; 155 Face f1, f2;
413 156
414 if (viewerMode)
415 {
416 if (invert)
417 {
418 f1 = new Face(p1, p4, p3, p1, p4, p3);
419 f1.uv1 = p1;
420 f1.uv2 = p4;
421 f1.uv3 = p3;
422
423 f2 = new Face(p1, p2, p4, p1, p2, p4);
424 f2.uv1 = p1;
425 f2.uv2 = p2;
426 f2.uv3 = p4;
427 }
428 else
429 {
430 f1 = new Face(p1, p3, p4, p1, p3, p4);
431 f1.uv1 = p1;
432 f1.uv2 = p3;
433 f1.uv3 = p4;
434
435 f2 = new Face(p1, p4, p2, p1, p4, p2);
436 f2.uv1 = p1;
437 f2.uv2 = p4;
438 f2.uv3 = p2;
439 }
440 }
441 else
442 {
443 if (invert) 157 if (invert)
444 { 158 {
445 f1 = new Face(p1, p4, p3); 159 f1 = new Face(p1, p4, p3);
@@ -450,16 +164,12 @@ namespace PrimMesher
450 f1 = new Face(p1, p3, p4); 164 f1 = new Face(p1, p3, p4);
451 f2 = new Face(p1, p4, p2); 165 f2 = new Face(p1, p4, p2);
452 } 166 }
453 }
454 167
455 this.faces.Add(f1); 168 this.faces.Add(f1);
456 this.faces.Add(f2); 169 this.faces.Add(f2);
457 } 170 }
458 } 171 }
459 } 172 }
460
461 if (viewerMode)
462 calcVertexNormals(sculptType, coordsAcross, coordsDown);
463 } 173 }
464 174
465 /// <summary> 175 /// <summary>
@@ -475,129 +185,6 @@ namespace PrimMesher
475 { 185 {
476 coords = new List<Coord>(sm.coords); 186 coords = new List<Coord>(sm.coords);
477 faces = new List<Face>(sm.faces); 187 faces = new List<Face>(sm.faces);
478 viewerFaces = new List<ViewerFace>(sm.viewerFaces);
479 normals = new List<Coord>(sm.normals);
480 uvs = new List<UVCoord>(sm.uvs);
481 }
482
483 private void calcVertexNormals(SculptType sculptType, int xSize, int ySize)
484 { // compute vertex normals by summing all the surface normals of all the triangles sharing
485 // each vertex and then normalizing
486 int numFaces = this.faces.Count;
487 for (int i = 0; i < numFaces; i++)
488 {
489 Face face = this.faces[i];
490 Coord surfaceNormal = face.SurfaceNormal(this.coords);
491 this.normals[face.n1] += surfaceNormal;
492 this.normals[face.n2] += surfaceNormal;
493 this.normals[face.n3] += surfaceNormal;
494 }
495
496 int numNormals = this.normals.Count;
497 for (int i = 0; i < numNormals; i++)
498 this.normals[i] = this.normals[i].Normalize();
499
500 if (sculptType != SculptType.plane)
501 { // blend the vertex normals at the cylinder seam
502 for (int y = 0; y < ySize; y++)
503 {
504 int rowOffset = y * xSize;
505
506 this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize();
507 }
508 }
509
510 foreach (Face face in this.faces)
511 {
512 ViewerFace vf = new ViewerFace(0);
513 vf.v1 = this.coords[face.v1];
514 vf.v2 = this.coords[face.v2];
515 vf.v3 = this.coords[face.v3];
516
517 vf.coordIndex1 = face.v1;
518 vf.coordIndex2 = face.v2;
519 vf.coordIndex3 = face.v3;
520
521 vf.n1 = this.normals[face.n1];
522 vf.n2 = this.normals[face.n2];
523 vf.n3 = this.normals[face.n3];
524
525 vf.uv1 = this.uvs[face.uv1];
526 vf.uv2 = this.uvs[face.uv2];
527 vf.uv3 = this.uvs[face.uv3];
528
529 this.viewerFaces.Add(vf);
530 }
531 }
532
533 /// <summary>
534 /// Adds a value to each XYZ vertex coordinate in the mesh
535 /// </summary>
536 /// <param name="x"></param>
537 /// <param name="y"></param>
538 /// <param name="z"></param>
539 public void AddPos(float x, float y, float z)
540 {
541 int i;
542 int numVerts = this.coords.Count;
543 Coord vert;
544
545 for (i = 0; i < numVerts; i++)
546 {
547 vert = this.coords[i];
548 vert.X += x;
549 vert.Y += y;
550 vert.Z += z;
551 this.coords[i] = vert;
552 }
553
554 if (this.viewerFaces != null)
555 {
556 int numViewerFaces = this.viewerFaces.Count;
557
558 for (i = 0; i < numViewerFaces; i++)
559 {
560 ViewerFace v = this.viewerFaces[i];
561 v.AddPos(x, y, z);
562 this.viewerFaces[i] = v;
563 }
564 }
565 }
566
567 /// <summary>
568 /// Rotates the mesh
569 /// </summary>
570 /// <param name="q"></param>
571 public void AddRot(Quat q)
572 {
573 int i;
574 int numVerts = this.coords.Count;
575
576 for (i = 0; i < numVerts; i++)
577 this.coords[i] *= q;
578
579 int numNormals = this.normals.Count;
580 for (i = 0; i < numNormals; i++)
581 this.normals[i] *= q;
582
583 if (this.viewerFaces != null)
584 {
585 int numViewerFaces = this.viewerFaces.Count;
586
587 for (i = 0; i < numViewerFaces; i++)
588 {
589 ViewerFace v = this.viewerFaces[i];
590 v.v1 *= q;
591 v.v2 *= q;
592 v.v3 *= q;
593
594 v.n1 *= q;
595 v.n2 *= q;
596 v.n3 *= q;
597
598 this.viewerFaces[i] = v;
599 }
600 }
601 } 188 }
602 189
603 public void Scale(float x, float y, float z) 190 public void Scale(float x, float y, float z)
@@ -608,19 +195,6 @@ namespace PrimMesher
608 Coord m = new Coord(x, y, z); 195 Coord m = new Coord(x, y, z);
609 for (i = 0; i < numVerts; i++) 196 for (i = 0; i < numVerts; i++)
610 this.coords[i] *= m; 197 this.coords[i] *= m;
611
612 if (this.viewerFaces != null)
613 {
614 int numViewerFaces = this.viewerFaces.Count;
615 for (i = 0; i < numViewerFaces; i++)
616 {
617 ViewerFace v = this.viewerFaces[i];
618 v.v1 *= m;
619 v.v2 *= m;
620 v.v3 *= m;
621 this.viewerFaces[i] = v;
622 }
623 }
624 } 198 }
625 199
626 public void DumpRaw(String path, String name, String title) 200 public void DumpRaw(String path, String name, String title)