diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Mesh.cs | 72 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 28 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/SculptMap.cs | 62 |
3 files changed, 132 insertions, 30 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs index f781ff9..c715642 100644 --- a/OpenSim/Region/Physics/Meshing/Mesh.cs +++ b/OpenSim/Region/Physics/Meshing/Mesh.cs | |||
@@ -46,11 +46,36 @@ namespace OpenSim.Region.Physics.Meshing | |||
46 | IntPtr m_indicesPtr = IntPtr.Zero; | 46 | IntPtr m_indicesPtr = IntPtr.Zero; |
47 | int m_indexCount = 0; | 47 | int m_indexCount = 0; |
48 | public float[] m_normals; | 48 | public float[] m_normals; |
49 | Vector3 _centroid; | ||
50 | int _centroidDiv; | ||
51 | |||
52 | private class vertexcomp : IEqualityComparer<Vertex> | ||
53 | { | ||
54 | public bool Equals(Vertex v1, Vertex v2) | ||
55 | { | ||
56 | if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z) | ||
57 | return true; | ||
58 | else | ||
59 | return false; | ||
60 | } | ||
61 | public int GetHashCode(Vertex v) | ||
62 | { | ||
63 | int a = v.X.GetHashCode(); | ||
64 | int b = v.Y.GetHashCode(); | ||
65 | int c = v.Z.GetHashCode(); | ||
66 | return (a << 16) ^ (b << 8) ^ c; | ||
67 | } | ||
68 | |||
69 | } | ||
49 | 70 | ||
50 | public Mesh() | 71 | public Mesh() |
51 | { | 72 | { |
52 | m_vertices = new Dictionary<Vertex, int>(); | 73 | vertexcomp vcomp = new vertexcomp(); |
74 | |||
75 | m_vertices = new Dictionary<Vertex, int>(vcomp); | ||
53 | m_triangles = new List<Triangle>(); | 76 | m_triangles = new List<Triangle>(); |
77 | _centroid = Vector3.Zero; | ||
78 | _centroidDiv = 0; | ||
54 | } | 79 | } |
55 | 80 | ||
56 | public Mesh Clone() | 81 | public Mesh Clone() |
@@ -61,7 +86,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
61 | { | 86 | { |
62 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); | 87 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); |
63 | } | 88 | } |
64 | 89 | result._centroid = _centroid; | |
90 | result._centroidDiv = _centroidDiv; | ||
65 | return result; | 91 | return result; |
66 | } | 92 | } |
67 | 93 | ||
@@ -71,15 +97,57 @@ namespace OpenSim.Region.Physics.Meshing | |||
71 | throw new NotSupportedException("Attempt to Add to a pinned Mesh"); | 97 | throw new NotSupportedException("Attempt to Add to a pinned Mesh"); |
72 | // If a vertex of the triangle is not yet in the vertices list, | 98 | // If a vertex of the triangle is not yet in the vertices list, |
73 | // add it and set its index to the current index count | 99 | // add it and set its index to the current index count |
100 | // vertex == seems broken | ||
101 | // skip colapsed triangles | ||
102 | if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) | ||
103 | || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) | ||
104 | || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) | ||
105 | ) | ||
106 | { | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | if (m_vertices.Count == 0) | ||
111 | { | ||
112 | _centroidDiv = 0; | ||
113 | _centroid = Vector3.Zero; | ||
114 | } | ||
115 | |||
74 | if (!m_vertices.ContainsKey(triangle.v1)) | 116 | if (!m_vertices.ContainsKey(triangle.v1)) |
117 | { | ||
75 | m_vertices[triangle.v1] = m_vertices.Count; | 118 | m_vertices[triangle.v1] = m_vertices.Count; |
119 | _centroid.X += triangle.v1.X; | ||
120 | _centroid.Y += triangle.v1.Y; | ||
121 | _centroid.Z += triangle.v1.Z; | ||
122 | _centroidDiv++; | ||
123 | } | ||
76 | if (!m_vertices.ContainsKey(triangle.v2)) | 124 | if (!m_vertices.ContainsKey(triangle.v2)) |
125 | { | ||
77 | m_vertices[triangle.v2] = m_vertices.Count; | 126 | m_vertices[triangle.v2] = m_vertices.Count; |
127 | _centroid.X += triangle.v2.X; | ||
128 | _centroid.Y += triangle.v2.Y; | ||
129 | _centroid.Z += triangle.v2.Z; | ||
130 | _centroidDiv++; | ||
131 | } | ||
78 | if (!m_vertices.ContainsKey(triangle.v3)) | 132 | if (!m_vertices.ContainsKey(triangle.v3)) |
133 | { | ||
79 | m_vertices[triangle.v3] = m_vertices.Count; | 134 | m_vertices[triangle.v3] = m_vertices.Count; |
135 | _centroid.X += triangle.v3.X; | ||
136 | _centroid.Y += triangle.v3.Y; | ||
137 | _centroid.Z += triangle.v3.Z; | ||
138 | _centroidDiv++; | ||
139 | } | ||
80 | m_triangles.Add(triangle); | 140 | m_triangles.Add(triangle); |
81 | } | 141 | } |
82 | 142 | ||
143 | public Vector3 GetCentroid() | ||
144 | { | ||
145 | if (_centroidDiv > 0) | ||
146 | return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv); | ||
147 | else | ||
148 | return Vector3.Zero; | ||
149 | } | ||
150 | |||
83 | public void CalcNormals() | 151 | public void CalcNormals() |
84 | { | 152 | { |
85 | int iTriangles = m_triangles.Count; | 153 | int iTriangles = m_triangles.Count; |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 3bd15ce..825b858 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -74,6 +74,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
74 | #endif | 74 | #endif |
75 | 75 | ||
76 | private bool cacheSculptMaps = true; | 76 | private bool cacheSculptMaps = true; |
77 | private bool cacheSculptAlphaMaps = true; | ||
78 | |||
77 | private string decodedSculptMapPath = null; | 79 | private string decodedSculptMapPath = null; |
78 | private bool useMeshiesPhysicsMesh = false; | 80 | private bool useMeshiesPhysicsMesh = false; |
79 | 81 | ||
@@ -87,7 +89,16 @@ namespace OpenSim.Region.Physics.Meshing | |||
87 | IConfig mesh_config = config.Configs["Mesh"]; | 89 | IConfig mesh_config = config.Configs["Mesh"]; |
88 | 90 | ||
89 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); | 91 | decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); |
92 | |||
90 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); | 93 | cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); |
94 | |||
95 | if (Environment.OSVersion.Platform == PlatformID.Unix) | ||
96 | { | ||
97 | cacheSculptAlphaMaps = false; | ||
98 | } | ||
99 | else | ||
100 | cacheSculptAlphaMaps = cacheSculptMaps; | ||
101 | |||
91 | if(mesh_config != null) | 102 | if(mesh_config != null) |
92 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); | 103 | useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); |
93 | 104 | ||
@@ -268,15 +279,18 @@ namespace OpenSim.Region.Physics.Meshing | |||
268 | { | 279 | { |
269 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) | 280 | if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) |
270 | return null; | 281 | return null; |
282 | // Remove the reference to any JPEG2000 sculpt data so it can be GCed | ||
283 | // don't loose it | ||
284 | // primShape.SculptData = Utils.EmptyBytes; | ||
271 | } | 285 | } |
286 | // primShape.SculptDataLoaded = true; | ||
272 | } | 287 | } |
273 | else | 288 | else |
274 | { | 289 | { |
275 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) | 290 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) |
276 | return null; | 291 | return null; |
277 | } | 292 | } |
278 | 293 | // keep compatible | |
279 | // Remove the reference to any JPEG2000 sculpt data so it can be GCed | ||
280 | primShape.SculptData = Utils.EmptyBytes; | 294 | primShape.SculptData = Utils.EmptyBytes; |
281 | 295 | ||
282 | int numCoords = coords.Count; | 296 | int numCoords = coords.Count; |
@@ -321,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
321 | 335 | ||
322 | if (primShape.SculptData.Length <= 0) | 336 | if (primShape.SculptData.Length <= 0) |
323 | { | 337 | { |
324 | m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName); | 338 | m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); |
325 | return false; | 339 | return false; |
326 | } | 340 | } |
327 | 341 | ||
@@ -482,7 +496,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
482 | 496 | ||
483 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); | 497 | //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); |
484 | 498 | ||
485 | if (cacheSculptMaps) | 499 | if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0))) |
500 | // don't cache images with alpha channel in linux since mono can't load them correctly) | ||
486 | { | 501 | { |
487 | try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } | 502 | try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } |
488 | catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } | 503 | catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } |
@@ -702,6 +717,11 @@ namespace OpenSim.Region.Physics.Meshing | |||
702 | return CreateMesh(primName, primShape, size, lod, false); | 717 | return CreateMesh(primName, primShape, size, lod, false); |
703 | } | 718 | } |
704 | 719 | ||
720 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | ||
721 | { | ||
722 | return CreateMesh(primName, primShape, size, lod, false); | ||
723 | } | ||
724 | |||
705 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) | 725 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) |
706 | { | 726 | { |
707 | #if SPAM | 727 | #if SPAM |
diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs index 740424e..b3d9cb6 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMap.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMap.cs | |||
@@ -58,28 +58,24 @@ namespace PrimMesher | |||
58 | if (bmW == 0 || bmH == 0) | 58 | if (bmW == 0 || bmH == 0) |
59 | throw new Exception("SculptMap: bitmap has no data"); | 59 | throw new Exception("SculptMap: bitmap has no data"); |
60 | 60 | ||
61 | int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image | 61 | int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image |
62 | 62 | ||
63 | bool smallMap = bmW * bmH <= numLodPixels; | ||
63 | bool needsScaling = false; | 64 | bool needsScaling = false; |
64 | 65 | ||
65 | bool smallMap = bmW * bmH <= lod * lod; | ||
66 | |||
67 | width = bmW; | 66 | width = bmW; |
68 | height = bmH; | 67 | height = bmH; |
69 | while (width * height > numLodPixels) | 68 | while (width * height > numLodPixels * 4) |
70 | { | 69 | { |
71 | width >>= 1; | 70 | width >>= 1; |
72 | height >>= 1; | 71 | height >>= 1; |
73 | needsScaling = true; | 72 | needsScaling = true; |
74 | } | 73 | } |
75 | 74 | ||
76 | |||
77 | |||
78 | try | 75 | try |
79 | { | 76 | { |
80 | if (needsScaling) | 77 | if (needsScaling) |
81 | bm = ScaleImage(bm, width, height, | 78 | bm = ScaleImage(bm, width, height); |
82 | System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); | ||
83 | } | 79 | } |
84 | 80 | ||
85 | catch (Exception e) | 81 | catch (Exception e) |
@@ -87,7 +83,7 @@ namespace PrimMesher | |||
87 | throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); | 83 | throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); |
88 | } | 84 | } |
89 | 85 | ||
90 | if (width * height > lod * lod) | 86 | if (width * height > numLodPixels) |
91 | { | 87 | { |
92 | width >>= 1; | 88 | width >>= 1; |
93 | height >>= 1; | 89 | height >>= 1; |
@@ -144,15 +140,17 @@ namespace PrimMesher | |||
144 | int rowNdx, colNdx; | 140 | int rowNdx, colNdx; |
145 | int smNdx = 0; | 141 | int smNdx = 0; |
146 | 142 | ||
143 | |||
147 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) | 144 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) |
148 | { | 145 | { |
149 | List<Coord> row = new List<Coord>(numCols); | 146 | List<Coord> row = new List<Coord>(numCols); |
150 | for (colNdx = 0; colNdx < numCols; colNdx++) | 147 | for (colNdx = 0; colNdx < numCols; colNdx++) |
151 | { | 148 | { |
149 | |||
152 | if (mirror) | 150 | if (mirror) |
153 | row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); | 151 | row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f)); |
154 | else | 152 | else |
155 | row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); | 153 | row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f)); |
156 | 154 | ||
157 | ++smNdx; | 155 | ++smNdx; |
158 | } | 156 | } |
@@ -161,23 +159,39 @@ namespace PrimMesher | |||
161 | return rows; | 159 | return rows; |
162 | } | 160 | } |
163 | 161 | ||
164 | private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, | 162 | private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight) |
165 | System.Drawing.Drawing2D.InterpolationMode interpMode) | ||
166 | { | 163 | { |
167 | Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight); | ||
168 | scaledImage.SetResolution(96.0f, 96.0f); | ||
169 | |||
170 | Graphics grPhoto = Graphics.FromImage(scaledImage); | ||
171 | grPhoto.InterpolationMode = interpMode; | ||
172 | 164 | ||
173 | grPhoto.DrawImage(srcImage, | 165 | Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); |
174 | new Rectangle(0, 0, destWidth, destHeight), | 166 | |
175 | new Rectangle(0, 0, srcImage.Width, srcImage.Height), | 167 | Color c; |
176 | GraphicsUnit.Pixel); | 168 | float xscale = srcImage.Width / destWidth; |
169 | float yscale = srcImage.Height / destHeight; | ||
170 | |||
171 | float sy = 0.5f; | ||
172 | for (int y = 0; y < destHeight; y++) | ||
173 | { | ||
174 | float sx = 0.5f; | ||
175 | for (int x = 0; x < destWidth; x++) | ||
176 | { | ||
177 | try | ||
178 | { | ||
179 | c = srcImage.GetPixel((int)(sx), (int)(sy)); | ||
180 | scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B)); | ||
181 | } | ||
182 | catch (IndexOutOfRangeException) | ||
183 | { | ||
184 | } | ||
177 | 185 | ||
178 | grPhoto.Dispose(); | 186 | sx += xscale; |
187 | } | ||
188 | sy += yscale; | ||
189 | } | ||
190 | srcImage.Dispose(); | ||
179 | return scaledImage; | 191 | return scaledImage; |
180 | } | 192 | } |
193 | |||
194 | } | ||
195 | |||
181 | } | 196 | } |
182 | } | ||
183 | #endif | 197 | #endif |