aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitMeshing
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs517
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs501
2 files changed, 713 insertions, 305 deletions
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index 98c0f0b..1e9b8bc 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -32,24 +32,49 @@ using System.Runtime.InteropServices;
32using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
33using PrimMesher; 33using PrimMesher;
34using OpenMetaverse; 34using OpenMetaverse;
35using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary;
35 37
36namespace OpenSim.Region.Physics.Meshing 38namespace OpenSim.Region.Physics.Meshing
37{ 39{
38 public class Mesh : IMesh 40 public class MeshBuildingData
39 { 41 {
42 public Dictionary<Vertex, int> m_vertices;
43 public List<Triangle> m_triangles;
44 public float m_obbXmin;
45 public float m_obbXmax;
46 public float m_obbYmin;
47 public float m_obbYmax;
48 public float m_obbZmin;
49 public float m_obbZmax;
50 public Vector3 m_centroid;
51 public int m_centroidDiv;
52 }
40 53
41 private Dictionary<Vertex, int> m_vertices; 54 [Serializable()]
42 private List<Triangle> m_triangles; 55 public class Mesh : IMesh
43 GCHandle m_pinnedVertexes; 56 {
44 GCHandle m_pinnedIndex; 57 float[] vertices;
58 int[] indexes;
59 Vector3 m_obb;
60 Vector3 m_obboffset;
61 [NonSerialized()]
62 MeshBuildingData m_bdata;
63 [NonSerialized()]
64 GCHandle vhandler;
65 [NonSerialized()]
66 GCHandle ihandler;
67 [NonSerialized()]
45 IntPtr m_verticesPtr = IntPtr.Zero; 68 IntPtr m_verticesPtr = IntPtr.Zero;
46 int m_vertexCount = 0; 69 [NonSerialized()]
47 IntPtr m_indicesPtr = IntPtr.Zero; 70 IntPtr m_indicesPtr = IntPtr.Zero;
71 [NonSerialized()]
72 int m_vertexCount = 0;
73 [NonSerialized()]
48 int m_indexCount = 0; 74 int m_indexCount = 0;
49 public float[] m_normals;
50 Vector3 m_centroid;
51 int m_centroidDiv;
52 75
76 public int RefCount { get; set; }
77 public AMeshKey Key { get; set; }
53 78
54 private class vertexcomp : IEqualityComparer<Vertex> 79 private class vertexcomp : IEqualityComparer<Vertex>
55 { 80 {
@@ -73,43 +98,119 @@ namespace OpenSim.Region.Physics.Meshing
73 { 98 {
74 vertexcomp vcomp = new vertexcomp(); 99 vertexcomp vcomp = new vertexcomp();
75 100
76 m_vertices = new Dictionary<Vertex, int>(vcomp); 101 m_bdata = new MeshBuildingData();
77 m_triangles = new List<Triangle>(); 102 m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
78 m_centroid = Vector3.Zero; 103 m_bdata.m_triangles = new List<Triangle>();
79 m_centroidDiv = 0; 104 m_bdata.m_centroid = Vector3.Zero;
105 m_bdata.m_centroidDiv = 0;
106 m_bdata.m_obbXmin = float.MaxValue;
107 m_bdata.m_obbXmax = float.MinValue;
108 m_bdata.m_obbYmin = float.MaxValue;
109 m_bdata.m_obbYmax = float.MinValue;
110 m_bdata.m_obbZmin = float.MaxValue;
111 m_bdata.m_obbZmax = float.MinValue;
112 m_obb = new Vector3(0.5f, 0.5f, 0.5f);
113 m_obboffset = Vector3.Zero;
80 } 114 }
81 115
82 public int RefCount { get; set; }
83
84 public AMeshKey Key { get; set; }
85 116
86 public void Scale(Vector3 scale) 117 public Mesh Scale(Vector3 scale)
87 { 118 {
119 if (m_verticesPtr == null || m_indicesPtr == null)
120 return null;
121
122 Mesh result = new Mesh();
123
124 float x = scale.X;
125 float y = scale.Y;
126 float z = scale.Z;
127
128 result.m_obb.X = m_obb.X * x;
129 result.m_obb.Y = m_obb.Y * y;
130 result.m_obb.Z = m_obb.Z * z;
131 result.m_obboffset.X = m_obboffset.X * x;
132 result.m_obboffset.Y = m_obboffset.Y * y;
133 result.m_obboffset.Z = m_obboffset.Z * z;
88 134
135 result.vertices = new float[vertices.Length];
136 int j = 0;
137 for (int i = 0; i < m_vertexCount; i++)
138 {
139 result.vertices[j] = vertices[j] * x;
140 j++;
141 result.vertices[j] = vertices[j] * y;
142 j++;
143 result.vertices[j] = vertices[j] * z;
144 j++;
145 }
146
147 result.indexes = new int[indexes.Length];
148 indexes.CopyTo(result.indexes,0);
149
150 result.pinMemory();
89 151
152 return result;
90 } 153 }
91 154
92 public Mesh Clone() 155 public Mesh Clone()
93 { 156 {
94 Mesh result = new Mesh(); 157 Mesh result = new Mesh();
95 158
96 foreach (Triangle t in m_triangles) 159 if (m_bdata != null)
97 { 160 {
98 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); 161 result.m_bdata = new MeshBuildingData();
162 foreach (Triangle t in m_bdata.m_triangles)
163 {
164 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
165 }
166 result.m_bdata.m_centroid = m_bdata.m_centroid;
167 result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
168 result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
169 result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
170 result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
171 result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
172 result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
173 result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
99 } 174 }
100 result.m_centroid = m_centroid; 175 result.m_obb = m_obb;
101 result.m_centroidDiv = m_centroidDiv; 176 result.m_obboffset = m_obboffset;
102 return result; 177 return result;
103 } 178 }
104 179
180 public void addVertexLStats(Vertex v)
181 {
182 float x = v.X;
183 float y = v.Y;
184 float z = v.Z;
185
186 m_bdata.m_centroid.X += x;
187 m_bdata.m_centroid.Y += y;
188 m_bdata.m_centroid.Z += z;
189 m_bdata.m_centroidDiv++;
190
191 if (x > m_bdata.m_obbXmax)
192 m_bdata.m_obbXmax = x;
193 else if (x < m_bdata.m_obbXmin)
194 m_bdata.m_obbXmin = x;
195
196 if (y > m_bdata.m_obbYmax)
197 m_bdata.m_obbYmax = y;
198 else if (y < m_bdata.m_obbYmin)
199 m_bdata.m_obbYmin = y;
200
201 if (z > m_bdata.m_obbZmax)
202 m_bdata.m_obbZmax = z;
203 else if (z < m_bdata.m_obbZmin)
204 m_bdata.m_obbZmin = z;
205
206 }
207
208
105 public void Add(Triangle triangle) 209 public void Add(Triangle triangle)
106 { 210 {
107 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) 211 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
108 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 212 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
109 // If a vertex of the triangle is not yet in the vertices list, 213
110 // add it and set its index to the current index count
111 // vertex == seems broken
112 // skip colapsed triangles
113 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) 214 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
114 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) 215 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
115 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) 216 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
@@ -118,113 +219,59 @@ namespace OpenSim.Region.Physics.Meshing
118 return; 219 return;
119 } 220 }
120 221
121 if (m_vertices.Count == 0) 222 if (m_bdata.m_vertices.Count == 0)
122 { 223 {
123 m_centroidDiv = 0; 224 m_bdata.m_centroidDiv = 0;
124 m_centroid = Vector3.Zero; 225 m_bdata.m_centroid = Vector3.Zero;
125 } 226 }
126 227
127 if (!m_vertices.ContainsKey(triangle.v1)) 228 if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
128 { 229 {
129 m_vertices[triangle.v1] = m_vertices.Count; 230 m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
130 m_centroid.X += triangle.v1.X; 231 addVertexLStats(triangle.v1);
131 m_centroid.Y += triangle.v1.Y;
132 m_centroid.Z += triangle.v1.Z;
133 m_centroidDiv++;
134 } 232 }
135 if (!m_vertices.ContainsKey(triangle.v2)) 233 if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
136 { 234 {
137 m_vertices[triangle.v2] = m_vertices.Count; 235 m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
138 m_centroid.X += triangle.v2.X; 236 addVertexLStats(triangle.v2);
139 m_centroid.Y += triangle.v2.Y;
140 m_centroid.Z += triangle.v2.Z;
141 m_centroidDiv++;
142 } 237 }
143 if (!m_vertices.ContainsKey(triangle.v3)) 238 if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
144 { 239 {
145 m_vertices[triangle.v3] = m_vertices.Count; 240 m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
146 m_centroid.X += triangle.v3.X; 241 addVertexLStats(triangle.v3);
147 m_centroid.Y += triangle.v3.Y;
148 m_centroid.Z += triangle.v3.Z;
149 m_centroidDiv++;
150 } 242 }
151 m_triangles.Add(triangle); 243 m_bdata.m_triangles.Add(triangle);
152 } 244 }
153 245
154 public Vector3 GetCentroid() 246 public Vector3 GetCentroid()
155 { 247 {
156 if (m_centroidDiv > 0) 248 return m_obboffset;
157 return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv); 249
158 else
159 return Vector3.Zero;
160 } 250 }
161 251
162 public void CalcNormals() 252 public Vector3 GetOBB()
163 { 253 {
164 int iTriangles = m_triangles.Count; 254 return m_obb;
165 255 float x, y, z;
166 this.m_normals = new float[iTriangles * 3]; 256 if (m_bdata.m_centroidDiv > 0)
167
168 int i = 0;
169 foreach (Triangle t in m_triangles)
170 { 257 {
171 float ux, uy, uz; 258 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
172 float vx, vy, vz; 259 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
173 float wx, wy, wz; 260 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
174 261 }
175 ux = t.v1.X; 262 else // ??
176 uy = t.v1.Y; 263 {
177 uz = t.v1.Z; 264 x = 0.5f;
178 265 y = 0.5f;
179 vx = t.v2.X; 266 z = 0.5f;
180 vy = t.v2.Y;
181 vz = t.v2.Z;
182
183 wx = t.v3.X;
184 wy = t.v3.Y;
185 wz = t.v3.Z;
186
187
188 // Vectors for edges
189 float e1x, e1y, e1z;
190 float e2x, e2y, e2z;
191
192 e1x = ux - vx;
193 e1y = uy - vy;
194 e1z = uz - vz;
195
196 e2x = ux - wx;
197 e2y = uy - wy;
198 e2z = uz - wz;
199
200
201 // Cross product for normal
202 float nx, ny, nz;
203 nx = e1y * e2z - e1z * e2y;
204 ny = e1z * e2x - e1x * e2z;
205 nz = e1x * e2y - e1y * e2x;
206
207 // Length
208 float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
209 float lReciprocal = 1.0f / l;
210
211 // Normalized "normal"
212 //nx /= l;
213 //ny /= l;
214 //nz /= l;
215
216 m_normals[i] = nx * lReciprocal;
217 m_normals[i + 1] = ny * lReciprocal;
218 m_normals[i + 2] = nz * lReciprocal;
219
220 i += 3;
221 } 267 }
268 return new Vector3(x, y, z);
222 } 269 }
223 270
224 public List<Vector3> getVertexList() 271 public List<Vector3> getVertexList()
225 { 272 {
226 List<Vector3> result = new List<Vector3>(); 273 List<Vector3> result = new List<Vector3>();
227 foreach (Vertex v in m_vertices.Keys) 274 foreach (Vertex v in m_bdata.m_vertices.Keys)
228 { 275 {
229 result.Add(new Vector3(v.X, v.Y, v.Z)); 276 result.Add(new Vector3(v.X, v.Y, v.Z));
230 } 277 }
@@ -233,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
233 280
234 private float[] getVertexListAsFloat() 281 private float[] getVertexListAsFloat()
235 { 282 {
236 if (m_vertices == null) 283 if (m_bdata.m_vertices == null)
237 throw new NotSupportedException(); 284 throw new NotSupportedException();
238 float[] result = new float[m_vertices.Count * 3]; 285 float[] result = new float[m_bdata.m_vertices.Count * 3];
239 foreach (KeyValuePair<Vertex, int> kvp in m_vertices) 286 foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
240 { 287 {
241 Vertex v = kvp.Key; 288 Vertex v = kvp.Key;
242 int i = kvp.Value; 289 int i = kvp.Value;
@@ -249,48 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
249 296
250 public float[] getVertexListAsFloatLocked() 297 public float[] getVertexListAsFloatLocked()
251 { 298 {
252 if (m_pinnedVertexes.IsAllocated) 299 return null;
253 return (float[])(m_pinnedVertexes.Target);
254
255 float[] result = getVertexListAsFloat();
256 m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
257 // Inform the garbage collector of this unmanaged allocation so it can schedule
258 // the next GC round more intelligently
259 GC.AddMemoryPressure(Buffer.ByteLength(result));
260
261 return result;
262 } 300 }
263 301
264 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) 302 public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
265 { 303 {
266 // A vertex is 3 floats 304 // A vertex is 3 floats
267 vertexStride = 3 * sizeof(float); 305 vertexStride = 3 * sizeof(float);
268 306
269 // If there isn't an unmanaged array allocated yet, do it now 307 // If there isn't an unmanaged array allocated yet, do it now
270 if (m_verticesPtr == IntPtr.Zero) 308 if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
271 { 309 {
272 float[] vertexList = getVertexListAsFloat(); 310 vertices = getVertexListAsFloat();
273 // Each vertex is 3 elements (floats) 311 // Each vertex is 3 elements (floats)
274 m_vertexCount = vertexList.Length / 3; 312 m_vertexCount = vertices.Length / 3;
275 int byteCount = m_vertexCount * vertexStride; 313 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
276 m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); 314 m_verticesPtr = vhandler.AddrOfPinnedObject();
277 System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3); 315 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
278 } 316 }
279 vertices = m_verticesPtr; 317 _vertices = m_verticesPtr;
280 vertexCount = m_vertexCount; 318 vertexCount = m_vertexCount;
281 } 319 }
282 320
283 public int[] getIndexListAsInt() 321 public int[] getIndexListAsInt()
284 { 322 {
285 if (m_triangles == null) 323 if (m_bdata.m_triangles == null)
286 throw new NotSupportedException(); 324 throw new NotSupportedException();
287 int[] result = new int[m_triangles.Count * 3]; 325 int[] result = new int[m_bdata.m_triangles.Count * 3];
288 for (int i = 0; i < m_triangles.Count; i++) 326 for (int i = 0; i < m_bdata.m_triangles.Count; i++)
289 { 327 {
290 Triangle t = m_triangles[i]; 328 Triangle t = m_bdata.m_triangles[i];
291 result[3 * i + 0] = m_vertices[t.v1]; 329 result[3 * i + 0] = m_bdata.m_vertices[t.v1];
292 result[3 * i + 1] = m_vertices[t.v2]; 330 result[3 * i + 1] = m_bdata.m_vertices[t.v2];
293 result[3 * i + 2] = m_vertices[t.v3]; 331 result[3 * i + 2] = m_bdata.m_vertices[t.v3];
294 } 332 }
295 return result; 333 return result;
296 } 334 }
@@ -301,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
301 /// <returns></returns> 339 /// <returns></returns>
302 public int[] getIndexListAsIntLocked() 340 public int[] getIndexListAsIntLocked()
303 { 341 {
304 if (m_pinnedIndex.IsAllocated) 342 return null;
305 return (int[])(m_pinnedIndex.Target);
306
307 int[] result = getIndexListAsInt();
308 m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
309 // Inform the garbage collector of this unmanaged allocation so it can schedule
310 // the next GC round more intelligently
311 GC.AddMemoryPressure(Buffer.ByteLength(result));
312
313 return result;
314 } 343 }
315 344
316 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount) 345 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
317 { 346 {
318 // If there isn't an unmanaged array allocated yet, do it now 347 // If there isn't an unmanaged array allocated yet, do it now
319 if (m_indicesPtr == IntPtr.Zero) 348 if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
320 { 349 {
321 int[] indexList = getIndexListAsInt(); 350 indexes = getIndexListAsInt();
322 m_indexCount = indexList.Length; 351 m_indexCount = indexes.Length;
323 int byteCount = m_indexCount * sizeof(int); 352 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
324 m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount); 353 m_indicesPtr = ihandler.AddrOfPinnedObject();
325 System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount); 354 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
326 } 355 }
327 // A triangle is 3 ints (indices) 356 // A triangle is 3 ints (indices)
328 triStride = 3 * sizeof(int); 357 triStride = 3 * sizeof(int);
@@ -332,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
332 361
333 public void releasePinned() 362 public void releasePinned()
334 { 363 {
335 if (m_pinnedVertexes.IsAllocated)
336 m_pinnedVertexes.Free();
337 if (m_pinnedIndex.IsAllocated)
338 m_pinnedIndex.Free();
339 if (m_verticesPtr != IntPtr.Zero) 364 if (m_verticesPtr != IntPtr.Zero)
340 { 365 {
341 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr); 366 vhandler.Free();
367 vertices = null;
342 m_verticesPtr = IntPtr.Zero; 368 m_verticesPtr = IntPtr.Zero;
343 } 369 }
344 if (m_indicesPtr != IntPtr.Zero) 370 if (m_indicesPtr != IntPtr.Zero)
345 { 371 {
346 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr); 372 ihandler.Free();
373 indexes = null;
347 m_indicesPtr = IntPtr.Zero; 374 m_indicesPtr = IntPtr.Zero;
348 } 375 }
349 } 376 }
@@ -353,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
353 /// </summary> 380 /// </summary>
354 public void releaseSourceMeshData() 381 public void releaseSourceMeshData()
355 { 382 {
356 m_triangles = null; 383 if (m_bdata != null)
357 m_vertices = null; 384 {
385 m_bdata.m_triangles = null;
386 m_bdata.m_vertices = null;
387 }
388 }
389
390 public void releaseBuildingMeshData()
391 {
392 if (m_bdata != null)
393 {
394 m_bdata.m_triangles = null;
395 m_bdata.m_vertices = null;
396 m_bdata = null;
397 }
358 } 398 }
359 399
360 public void Append(IMesh newMesh) 400 public void Append(IMesh newMesh)
361 { 401 {
362 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) 402 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
363 throw new NotSupportedException("Attempt to Append to a pinned Mesh"); 403 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
364 404
365 if (!(newMesh is Mesh)) 405 if (!(newMesh is Mesh))
366 return; 406 return;
367 407
368 foreach (Triangle t in ((Mesh)newMesh).m_triangles) 408 foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
369 Add(t); 409 Add(t);
370 } 410 }
371 411
372 // Do a linear transformation of mesh. 412 // Do a linear transformation of mesh.
373 public void TransformLinear(float[,] matrix, float[] offset) 413 public void TransformLinear(float[,] matrix, float[] offset)
374 { 414 {
375 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) 415 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
376 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); 416 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
377 417
378 foreach (Vertex v in m_vertices.Keys) 418 foreach (Vertex v in m_bdata.m_vertices.Keys)
379 { 419 {
380 if (v == null) 420 if (v == null)
381 continue; 421 continue;
@@ -393,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
393 { 433 {
394 if (path == null) 434 if (path == null)
395 return; 435 return;
436 if (m_bdata == null)
437 return;
396 String fileName = name + "_" + title + ".raw"; 438 String fileName = name + "_" + title + ".raw";
397 String completePath = System.IO.Path.Combine(path, fileName); 439 String completePath = System.IO.Path.Combine(path, fileName);
398 StreamWriter sw = new StreamWriter(completePath); 440 StreamWriter sw = new StreamWriter(completePath);
399 foreach (Triangle t in m_triangles) 441 foreach (Triangle t in m_bdata.m_triangles)
400 { 442 {
401 String s = t.ToStringRaw(); 443 String s = t.ToStringRaw();
402 sw.WriteLine(s); 444 sw.WriteLine(s);
@@ -406,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
406 448
407 public void TrimExcess() 449 public void TrimExcess()
408 { 450 {
409 m_triangles.TrimExcess(); 451 m_bdata.m_triangles.TrimExcess();
452 }
453
454 public void pinMemory()
455 {
456 m_vertexCount = vertices.Length / 3;
457 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
458 m_verticesPtr = vhandler.AddrOfPinnedObject();
459 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
460
461 m_indexCount = indexes.Length;
462 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
463 m_indicesPtr = ihandler.AddrOfPinnedObject();
464 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
465 }
466
467 public void PrepForOde()
468 {
469 // If there isn't an unmanaged array allocated yet, do it now
470 if (m_verticesPtr == IntPtr.Zero)
471 vertices = getVertexListAsFloat();
472
473 // If there isn't an unmanaged array allocated yet, do it now
474 if (m_indicesPtr == IntPtr.Zero)
475 indexes = getIndexListAsInt();
476
477 pinMemory();
478
479 float x, y, z;
480
481 if (m_bdata.m_centroidDiv > 0)
482 {
483 m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
484 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
485 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
486 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
487 }
488
489 else
490 {
491 m_obboffset = Vector3.Zero;
492 x = 0.5f;
493 y = 0.5f;
494 z = 0.5f;
495 }
496 m_obb = new Vector3(x, y, z);
497
498 releaseBuildingMeshData();
499 }
500 public bool ToStream(Stream st)
501 {
502 if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
503 return false;
504
505 BinaryWriter bw = new BinaryWriter(st);
506 bool ok = true;
507
508 try
509 {
510
511 bw.Write(m_vertexCount);
512 bw.Write(m_indexCount);
513
514 for (int i = 0; i < 3 * m_vertexCount; i++)
515 bw.Write(vertices[i]);
516 for (int i = 0; i < m_indexCount; i++)
517 bw.Write(indexes[i]);
518 bw.Write(m_obb.X);
519 bw.Write(m_obb.Y);
520 bw.Write(m_obb.Z);
521 bw.Write(m_obboffset.X);
522 bw.Write(m_obboffset.Y);
523 bw.Write(m_obboffset.Z);
524 }
525 catch
526 {
527 ok = false;
528 }
529
530 if (bw != null)
531 {
532 bw.Flush();
533 bw.Close();
534 }
535
536 return ok;
537 }
538
539 public static Mesh FromStream(Stream st, AMeshKey key)
540 {
541 Mesh mesh = new Mesh();
542 mesh.releaseBuildingMeshData();
543
544 BinaryReader br = new BinaryReader(st);
545
546 bool ok = true;
547 try
548 {
549 mesh.m_vertexCount = br.ReadInt32();
550 mesh.m_indexCount = br.ReadInt32();
551
552 int n = 3 * mesh.m_vertexCount;
553 mesh.vertices = new float[n];
554 for (int i = 0; i < n; i++)
555 mesh.vertices[i] = br.ReadSingle();
556
557 mesh.indexes = new int[mesh.m_indexCount];
558 for (int i = 0; i < mesh.m_indexCount; i++)
559 mesh.indexes[i] = br.ReadInt32();
560
561 mesh.m_obb.X = br.ReadSingle();
562 mesh.m_obb.Y = br.ReadSingle();
563 mesh.m_obb.Z = br.ReadSingle();
564
565 mesh.m_obboffset.X = br.ReadSingle();
566 mesh.m_obboffset.Y = br.ReadSingle();
567 mesh.m_obboffset.Z = br.ReadSingle();
568 }
569 catch
570 {
571 ok = false;
572 }
573
574 br.Close();
575
576 if (ok)
577 {
578 mesh.pinMemory();
579
580 mesh.Key = key;
581 mesh.RefCount = 1;
582
583 return mesh;
584 }
585
586 mesh.vertices = null;
587 mesh.indexes = null;
588 return null;
410 } 589 }
411 } 590 }
412} 591}
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index 4c40175..29fdda4 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -42,6 +42,8 @@ using System.Reflection;
42using System.IO; 42using System.IO;
43using ComponentAce.Compression.Libs.zlib; 43using ComponentAce.Compression.Libs.zlib;
44using OpenSim.Region.Physics.ConvexDecompositionDotNet; 44using OpenSim.Region.Physics.ConvexDecompositionDotNet;
45using System.Runtime.Serialization;
46using System.Runtime.Serialization.Formatters.Binary;
45 47
46namespace OpenSim.Region.Physics.Meshing 48namespace OpenSim.Region.Physics.Meshing
47{ 49{
@@ -68,22 +70,22 @@ namespace OpenSim.Region.Physics.Meshing
68 70
69 // Setting baseDir to a path will enable the dumping of raw files 71 // Setting baseDir to a path will enable the dumping of raw files
70 // raw files can be imported by blender so a visual inspection of the results can be done 72 // raw files can be imported by blender so a visual inspection of the results can be done
71#if SPAM
72 const string baseDir = "rawFiles";
73#else
74 private const string baseDir = null; //"rawFiles";
75#endif
76 73
77 private bool cacheSculptMaps = true; 74 public object diskLock = new object();
78 private bool cacheSculptAlphaMaps = true; 75
76 public bool doMeshFileCache = true;
77
78 public string cachePath = "MeshCache";
79 public TimeSpan CacheExpire;
80 public bool doCacheExpire = true;
81
82// const string baseDir = "rawFiles";
83 private const string baseDir = null; //"rawFiles";
79 84
80 private string decodedSculptMapPath = null;
81 private bool useMeshiesPhysicsMesh = false; 85 private bool useMeshiesPhysicsMesh = false;
82 86
83 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 87 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
84 88
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>(); 89 private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
88 private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>(); 90 private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
89 91
@@ -92,29 +94,29 @@ namespace OpenSim.Region.Physics.Meshing
92 IConfig start_config = config.Configs["Startup"]; 94 IConfig start_config = config.Configs["Startup"];
93 IConfig mesh_config = config.Configs["Mesh"]; 95 IConfig mesh_config = config.Configs["Mesh"];
94 96
95 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
96 97
97 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); 98 float fcache = 48.0f;
99// float fcache = 0.02f;
98 100
99 if (Environment.OSVersion.Platform == PlatformID.Unix) 101 if(mesh_config != null)
100 { 102 {
101 cacheSculptAlphaMaps = false; 103 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
104 if (useMeshiesPhysicsMesh)
105 {
106 doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
107 cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
108 fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
109 doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
110 }
111 else
112 {
113 doMeshFileCache = false;
114 doCacheExpire = false;
115 }
102 } 116 }
103 else
104 cacheSculptAlphaMaps = cacheSculptMaps;
105 117
106 if(mesh_config != null) 118 CacheExpire = TimeSpan.FromHours(fcache);
107 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
108 119
109 try
110 {
111 if (!Directory.Exists(decodedSculptMapPath))
112 Directory.CreateDirectory(decodedSculptMapPath);
113 }
114 catch (Exception e)
115 {
116 m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message);
117 }
118 } 120 }
119 121
120 /// <summary> 122 /// <summary>
@@ -212,7 +214,7 @@ namespace OpenSim.Region.Physics.Meshing
212 /// <param name="size">Size of entire object</param> 214 /// <param name="size">Size of entire object</param>
213 /// <param name="coords"></param> 215 /// <param name="coords"></param>
214 /// <param name="faces"></param> 216 /// <param name="faces"></param>
215 private void AddSubMesh(OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces) 217 private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
216 { 218 {
217 // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); 219 // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
218 220
@@ -245,9 +247,9 @@ namespace OpenSim.Region.Physics.Meshing
245 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4); 247 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
246 248
247 Coord c = new Coord( 249 Coord c = new Coord(
248 Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X, 250 Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
249 Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y, 251 Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
250 Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z); 252 Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
251 253
252 coords.Add(c); 254 coords.Add(c);
253 } 255 }
@@ -271,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing
271 /// <param name="size"></param> 273 /// <param name="size"></param>
272 /// <param name="lod"></param> 274 /// <param name="lod"></param>
273 /// <returns></returns> 275 /// <returns></returns>
274 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex) 276 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
275 { 277 {
276// m_log.DebugFormat( 278// m_log.DebugFormat(
277// "[MESH]: Creating physics proxy for {0}, shape {1}", 279// "[MESH]: Creating physics proxy for {0}, shape {1}",
@@ -287,18 +289,18 @@ namespace OpenSim.Region.Physics.Meshing
287 if (!useMeshiesPhysicsMesh) 289 if (!useMeshiesPhysicsMesh)
288 return null; 290 return null;
289 291
290 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex)) 292 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
291 return null; 293 return null;
292 } 294 }
293 else 295 else
294 { 296 {
295 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) 297 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
296 return null; 298 return null;
297 } 299 }
298 } 300 }
299 else 301 else
300 { 302 {
301 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) 303 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
302 return null; 304 return null;
303 } 305 }
304 306
@@ -333,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing
333 /// <param name="faces">Faces are added to this list by the method.</param> 335 /// <param name="faces">Faces are added to this list by the method.</param>
334 /// <returns>true if coords and faces were successfully generated, false if not</returns> 336 /// <returns>true if coords and faces were successfully generated, false if not</returns>
335 private bool GenerateCoordsAndFacesFromPrimMeshData( 337 private bool GenerateCoordsAndFacesFromPrimMeshData(
336 string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces, bool convex) 338 string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
337 { 339 {
338// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); 340// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
339 341
@@ -345,7 +347,7 @@ namespace OpenSim.Region.Physics.Meshing
345 347
346 if (primShape.SculptData.Length <= 0) 348 if (primShape.SculptData.Length <= 0)
347 { 349 {
348 m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName); 350// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
349 return false; 351 return false;
350 } 352 }
351 353
@@ -406,7 +408,7 @@ namespace OpenSim.Region.Physics.Meshing
406 OSD decodedMeshOsd = new OSD(); 408 OSD decodedMeshOsd = new OSD();
407 byte[] meshBytes = new byte[physSize]; 409 byte[] meshBytes = new byte[physSize];
408 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 410 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
409// byte[] decompressed = new byte[physSize * 5]; 411
410 try 412 try
411 { 413 {
412 using (MemoryStream inMs = new MemoryStream(meshBytes)) 414 using (MemoryStream inMs = new MemoryStream(meshBytes))
@@ -444,13 +446,13 @@ namespace OpenSim.Region.Physics.Meshing
444 // physics_shape is an array of OSDMaps, one for each submesh 446 // physics_shape is an array of OSDMaps, one for each submesh
445 if (decodedMeshOsd is OSDArray) 447 if (decodedMeshOsd is OSDArray)
446 { 448 {
447 // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 449// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
448 450
449 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 451 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
450 foreach (OSD subMeshOsd in decodedMeshOsdArray) 452 foreach (OSD subMeshOsd in decodedMeshOsdArray)
451 { 453 {
452 if (subMeshOsd is OSDMap) 454 if (subMeshOsd is OSDMap)
453 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 455 AddSubMesh(subMeshOsd as OSDMap, coords, faces);
454 } 456 }
455 } 457 }
456 } 458 }
@@ -522,9 +524,9 @@ namespace OpenSim.Region.Physics.Meshing
522 t3 = data[ptr++]; 524 t3 = data[ptr++];
523 t3 += data[ptr++] << 8; 525 t3 += data[ptr++] << 8;
524 526
525 f3 = new float3((t1 * range.X + min.X) * size.X, 527 f3 = new float3((t1 * range.X + min.X),
526 (t2 * range.Y + min.Y) * size.Y, 528 (t2 * range.Y + min.Y),
527 (t3 * range.Z + min.Z) * size.Z); 529 (t3 * range.Z + min.Z));
528 vs.Add(f3); 530 vs.Add(f3);
529 } 531 }
530 532
@@ -621,9 +623,9 @@ namespace OpenSim.Region.Physics.Meshing
621 t3 = data[i++]; 623 t3 = data[i++];
622 t3 += data[i++] << 8; 624 t3 += data[i++] << 8;
623 625
624 f3 = new float3((t1 * range.X + min.X) * size.X, 626 f3 = new float3((t1 * range.X + min.X),
625 (t2 * range.Y + min.Y) * size.Y, 627 (t2 * range.Y + min.Y),
626 (t3 * range.Z + min.Z) * size.Z); 628 (t3 * range.Z + min.Z));
627 vs.Add(f3); 629 vs.Add(f3);
628 } 630 }
629 631
@@ -711,35 +713,13 @@ namespace OpenSim.Region.Physics.Meshing
711 /// <param name="faces">Faces are added to this list by the method.</param> 713 /// <param name="faces">Faces are added to this list by the method.</param>
712 /// <returns>true if coords and faces were successfully generated, false if not</returns> 714 /// <returns>true if coords and faces were successfully generated, false if not</returns>
713 private bool GenerateCoordsAndFacesFromPrimSculptData( 715 private bool GenerateCoordsAndFacesFromPrimSculptData(
714 string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces) 716 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
715 { 717 {
716 coords = new List<Coord>(); 718 coords = new List<Coord>();
717 faces = new List<Face>(); 719 faces = new List<Face>();
718 PrimMesher.SculptMesh sculptMesh; 720 PrimMesher.SculptMesh sculptMesh;
719 Image idata = null; 721 Image idata = null;
720 string decodedSculptFileName = "";
721
722 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
723 {
724 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
725 try
726 {
727 if (File.Exists(decodedSculptFileName))
728 {
729 idata = Image.FromFile(decodedSculptFileName);
730 }
731 }
732 catch (Exception e)
733 {
734 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
735 722
736 }
737 //if (idata != null)
738 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
739 }
740
741 if (idata == null)
742 {
743 if (primShape.SculptData == null || primShape.SculptData.Length == 0) 723 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
744 return false; 724 return false;
745 725
@@ -748,25 +728,15 @@ namespace OpenSim.Region.Physics.Meshing
748 OpenMetaverse.Imaging.ManagedImage unusedData; 728 OpenMetaverse.Imaging.ManagedImage unusedData;
749 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); 729 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
750 730
731 unusedData = null;
732
751 if (idata == null) 733 if (idata == null)
752 { 734 {
753 // In some cases it seems that the decode can return a null bitmap without throwing 735 // In some cases it seems that the decode can return a null bitmap without throwing
754 // an exception 736 // an exception
755 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName); 737 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
756
757 return false; 738 return false;
758 } 739 }
759
760 unusedData = null;
761
762 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
763
764 if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
765 // don't cache images with alpha channel in linux since mono can't load them correctly)
766 {
767 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
768 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
769 }
770 } 740 }
771 catch (DllNotFoundException) 741 catch (DllNotFoundException)
772 { 742 {
@@ -783,7 +753,6 @@ namespace OpenSim.Region.Physics.Meshing
783 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message); 753 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
784 return false; 754 return false;
785 } 755 }
786 }
787 756
788 PrimMesher.SculptMesh.SculptType sculptType; 757 PrimMesher.SculptMesh.SculptType sculptType;
789 // remove mirror and invert bits 758 // remove mirror and invert bits
@@ -814,9 +783,7 @@ namespace OpenSim.Region.Physics.Meshing
814 783
815 idata.Dispose(); 784 idata.Dispose();
816 785
817 sculptMesh.DumpRaw(baseDir, primName, "primMesh"); 786// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
818
819 sculptMesh.Scale(size.X, size.Y, size.Z);
820 787
821 coords = sculptMesh.coords; 788 coords = sculptMesh.coords;
822 faces = sculptMesh.faces; 789 faces = sculptMesh.faces;
@@ -834,7 +801,7 @@ namespace OpenSim.Region.Physics.Meshing
834 /// <param name="faces">Faces are added to this list by the method.</param> 801 /// <param name="faces">Faces are added to this list by the method.</param>
835 /// <returns>true if coords and faces were successfully generated, false if not</returns> 802 /// <returns>true if coords and faces were successfully generated, false if not</returns>
836 private bool GenerateCoordsAndFacesFromPrimShapeData( 803 private bool GenerateCoordsAndFacesFromPrimShapeData(
837 string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces) 804 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
838 { 805 {
839 PrimMesh primMesh; 806 PrimMesh primMesh;
840 coords = new List<Coord>(); 807 coords = new List<Coord>();
@@ -969,9 +936,7 @@ namespace OpenSim.Region.Physics.Meshing
969 } 936 }
970 } 937 }
971 938
972 primMesh.DumpRaw(baseDir, primName, "primMesh"); 939// primMesh.DumpRaw(baseDir, primName, "primMesh");
973
974 primMesh.Scale(size.X, size.Y, size.Z);
975 940
976 coords = primMesh.coords; 941 coords = primMesh.coords;
977 faces = primMesh.faces; 942 faces = primMesh.faces;
@@ -985,12 +950,14 @@ namespace OpenSim.Region.Physics.Meshing
985 Byte[] someBytes; 950 Byte[] someBytes;
986 951
987 key.hashB = 5181; 952 key.hashB = 5181;
953 key.hashC = 5181;
988 ulong hash = 5381; 954 ulong hash = 5381;
989 955
990 if (primShape.SculptEntry) 956 if (primShape.SculptEntry)
991 { 957 {
992 key.uuid = primShape.SculptTexture; 958 key.uuid = primShape.SculptTexture;
993 key.hashB = mdjb2(key.hashB, primShape.SculptType); 959 key.hashC = mdjb2(key.hashC, primShape.SculptType);
960 key.hashC = mdjb2(key.hashC, primShape.PCode);
994 } 961 }
995 else 962 else
996 { 963 {
@@ -1002,6 +969,8 @@ namespace OpenSim.Region.Physics.Meshing
1002 hash = mdjb2(hash, primShape.PathScaleX); 969 hash = mdjb2(hash, primShape.PathScaleX);
1003 hash = mdjb2(hash, primShape.PathScaleY); 970 hash = mdjb2(hash, primShape.PathScaleY);
1004 hash = mdjb2(hash, primShape.PathShearX); 971 hash = mdjb2(hash, primShape.PathShearX);
972 key.hashA = hash;
973 hash = key.hashB;
1005 hash = mdjb2(hash, primShape.PathShearY); 974 hash = mdjb2(hash, primShape.PathShearY);
1006 hash = mdjb2(hash, (byte)primShape.PathTwist); 975 hash = mdjb2(hash, (byte)primShape.PathTwist);
1007 hash = mdjb2(hash, (byte)primShape.PathTwistBegin); 976 hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
@@ -1013,26 +982,38 @@ namespace OpenSim.Region.Physics.Meshing
1013 hash = mdjb2(hash, primShape.ProfileBegin); 982 hash = mdjb2(hash, primShape.ProfileBegin);
1014 hash = mdjb2(hash, primShape.ProfileEnd); 983 hash = mdjb2(hash, primShape.ProfileEnd);
1015 hash = mdjb2(hash, primShape.ProfileHollow); 984 hash = mdjb2(hash, primShape.ProfileHollow);
1016 key.hashA = hash; 985 hash = mdjb2(hash, primShape.PCode);
986 key.hashB = hash;
1017 } 987 }
1018 988
1019 hash = key.hashB; 989 hash = key.hashC;
1020
1021 someBytes = size.GetBytes();
1022 for (int i = 0; i < someBytes.Length; i++)
1023 hash = mdjb2(hash, someBytes[i]);
1024 990
1025 hash = mdjb2(hash, lod); 991 hash = mdjb2(hash, lod);
1026 992
1027 hash &= 0x3fffffffffffffff; 993 if (size == m_MeshUnitSize)
994 {
995 hash = hash << 8;
996 hash |= 8;
997 }
998 else
999 {
1000 someBytes = size.GetBytes();
1001 for (int i = 0; i < someBytes.Length; i++)
1002 hash = mdjb2(hash, someBytes[i]);
1003 hash = hash << 8;
1004 }
1028 1005
1029 if (convex) 1006 if (convex)
1030 hash |= 0x4000000000000000; 1007 hash |= 4;
1031 1008
1032 if (primShape.SculptEntry) 1009 if (primShape.SculptEntry)
1033 hash |= 0x8000000000000000; 1010 {
1011 hash |= 1;
1012 if (primShape.SculptType == (byte)SculptType.Mesh)
1013 hash |= 2;
1014 }
1034 1015
1035 key.hashB = hash; 1016 key.hashC = hash;
1036 1017
1037 return key; 1018 return key;
1038 } 1019 }
@@ -1048,35 +1029,74 @@ namespace OpenSim.Region.Physics.Meshing
1048 return ((hash << 5) + hash) + (ulong)(c >> 8); 1029 return ((hash << 5) + hash) + (ulong)(c >> 8);
1049 } 1030 }
1050 1031
1051
1052 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 1032 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
1053 { 1033 {
1054 return CreateMesh(primName, primShape, size, lod, false,false); 1034 return CreateMesh(primName, primShape, size, lod, false,false,false);
1055 } 1035 }
1056 1036
1057 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 1037 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
1058 { 1038 {
1059 return CreateMesh(primName, primShape, size, lod, false,false); 1039 return CreateMesh(primName, primShape, size, lod, false,false,false);
1060 } 1040 }
1061 1041
1062 private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f); 1042 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1043 {
1044 Mesh mesh = null;
1045
1046 if (size.X < 0.01f) size.X = 0.01f;
1047 if (size.Y < 0.01f) size.Y = 0.01f;
1048 if (size.Z < 0.01f) size.Z = 0.01f;
1049
1050 AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex);
1051 lock (m_uniqueMeshes)
1052 {
1053 m_uniqueMeshes.TryGetValue(key, out mesh);
1054
1055 if (mesh != null)
1056 {
1057 mesh.RefCount++;
1058 return mesh;
1059 }
1060 }
1061
1062 // try to find a identical mesh on meshs recently released
1063 lock (m_uniqueReleasedMeshes)
1064 {
1065 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1066 if (mesh != null)
1067 {
1068 m_uniqueReleasedMeshes.Remove(key);
1069 lock (m_uniqueMeshes)
1070 {
1071 try
1072 {
1073 m_uniqueMeshes.Add(key, mesh);
1074 }
1075 catch { }
1076 }
1077 mesh.RefCount = 1;
1078 return mesh;
1079 }
1080 }
1081 return null;
1082 }
1063 1083
1064 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) 1084 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
1085
1086 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
1065 { 1087 {
1066#if SPAM 1088#if SPAM
1067 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); 1089 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
1068#endif 1090#endif
1069 1091
1070 Mesh mesh = null; 1092 Mesh mesh = null;
1071// ulong key = 0;
1072
1073 1093
1074 if (size.X < 0.01f) size.X = 0.01f; 1094 if (size.X < 0.01f) size.X = 0.01f;
1075 if (size.Y < 0.01f) size.Y = 0.01f; 1095 if (size.Y < 0.01f) size.Y = 0.01f;
1076 if (size.Z < 0.01f) size.Z = 0.01f; 1096 if (size.Z < 0.01f) size.Z = 0.01f;
1077 1097
1078 // try to find a identical mesh on meshs in use 1098 // try to find a identical mesh on meshs in use
1079// key = primShape.GetMeshKey(size, lod, convex); 1099
1080 AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex); 1100 AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
1081 1101
1082 lock (m_uniqueMeshes) 1102 lock (m_uniqueMeshes)
@@ -1098,35 +1118,78 @@ namespace OpenSim.Region.Physics.Meshing
1098 { 1118 {
1099 m_uniqueReleasedMeshes.Remove(key); 1119 m_uniqueReleasedMeshes.Remove(key);
1100 lock (m_uniqueMeshes) 1120 lock (m_uniqueMeshes)
1101 m_uniqueMeshes.Add(key, mesh); 1121 {
1122 try
1123 {
1124 m_uniqueMeshes.Add(key, mesh);
1125 }
1126 catch { }
1127 }
1102 mesh.RefCount = 1; 1128 mesh.RefCount = 1;
1103 return mesh; 1129 return mesh;
1104 } 1130 }
1105 } 1131 }
1106 1132
1107 mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); 1133 Mesh UnitMesh = null;
1134 AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
1108 1135
1109 if (mesh != null) 1136 lock (m_uniqueReleasedMeshes)
1110 { 1137 {
1111 if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) 1138 m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
1139 if (UnitMesh != null)
1112 { 1140 {
1113#if SPAM 1141 UnitMesh.RefCount = 1;
1114 m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " +
1115 minSizeForComplexMesh.ToString() + " - creating simple bounding box");
1116#endif
1117 mesh = CreateBoundingBoxMesh(mesh);
1118 mesh.DumpRaw(baseDir, primName, "Z extruded");
1119 } 1142 }
1143 }
1120 1144
1121 // trim the vertex and triangle lists to free up memory 1145 if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
1122 mesh.TrimExcess(); 1146 UnitMesh = GetFromFileCache(unitKey);
1123 mesh.Key = key;
1124 mesh.RefCount = 1;
1125 1147
1126 lock(m_uniqueMeshes) 1148 if (UnitMesh == null)
1127 m_uniqueMeshes.Add(key, mesh); 1149 {
1150 UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
1151
1152 if (UnitMesh == null)
1153 return null;
1154
1155 UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
1156
1157 if (forOde)
1158 {
1159 // force pinned mem allocation
1160 UnitMesh.PrepForOde();
1161 }
1162 else
1163 UnitMesh.TrimExcess();
1164
1165 UnitMesh.Key = unitKey;
1166 UnitMesh.RefCount = 1;
1167
1168 if (doMeshFileCache && primShape.SculptEntry)
1169 StoreToFileCache(unitKey, UnitMesh);
1170
1171 lock (m_uniqueReleasedMeshes)
1172 {
1173 try
1174 {
1175 m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
1176 }
1177 catch { }
1178 }
1128 } 1179 }
1129 1180
1181 mesh = UnitMesh.Scale(size);
1182 mesh.Key = key;
1183 mesh.RefCount = 1;
1184 lock (m_uniqueMeshes)
1185 {
1186 try
1187 {
1188 m_uniqueMeshes.Add(key, mesh);
1189 }
1190 catch { }
1191 }
1192
1130 return mesh; 1193 return mesh;
1131 } 1194 }
1132 1195
@@ -1137,21 +1200,27 @@ namespace OpenSim.Region.Physics.Meshing
1137 1200
1138 Mesh mesh = (Mesh)imesh; 1201 Mesh mesh = (Mesh)imesh;
1139 1202
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) 1203 lock (m_uniqueMeshes)
1150 { 1204 {
1205 int curRefCount = mesh.RefCount;
1206 curRefCount--;
1207
1208 if (curRefCount > 0)
1209 {
1210 mesh.RefCount = curRefCount;
1211 return;
1212 }
1213
1151 mesh.RefCount = 0; 1214 mesh.RefCount = 0;
1152 m_uniqueMeshes.Remove(mesh.Key); 1215 m_uniqueMeshes.Remove(mesh.Key);
1153 lock (m_uniqueReleasedMeshes) 1216 lock (m_uniqueReleasedMeshes)
1154 m_uniqueReleasedMeshes.Add(mesh.Key, mesh); 1217 {
1218 try
1219 {
1220 m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
1221 }
1222 catch { }
1223 }
1155 } 1224 }
1156 } 1225 }
1157 1226
@@ -1178,10 +1247,170 @@ namespace OpenSim.Region.Physics.Meshing
1178 foreach (Mesh m in meshstodelete) 1247 foreach (Mesh m in meshstodelete)
1179 { 1248 {
1180 m_uniqueReleasedMeshes.Remove(m.Key); 1249 m_uniqueReleasedMeshes.Remove(m.Key);
1181 m.releaseSourceMeshData(); 1250 m.releaseBuildingMeshData();
1182 m.releasePinned(); 1251 m.releasePinned();
1183 } 1252 }
1184 } 1253 }
1185 } 1254 }
1255
1256 public void FileNames(AMeshKey key, out string dir,out string fullFileName)
1257 {
1258 string id = key.ToString();
1259 string init = id.Substring(0, 1);
1260 dir = System.IO.Path.Combine(cachePath, init);
1261 fullFileName = System.IO.Path.Combine(dir, id);
1262 }
1263
1264 public string FullFileName(AMeshKey key)
1265 {
1266 string id = key.ToString();
1267 string init = id.Substring(0,1);
1268 id = System.IO.Path.Combine(init, id);
1269 id = System.IO.Path.Combine(cachePath, id);
1270 return id;
1271 }
1272
1273 private Mesh GetFromFileCache(AMeshKey key)
1274 {
1275 Mesh mesh = null;
1276 string filename = FullFileName(key);
1277 bool ok = true;
1278
1279 lock (diskLock)
1280 {
1281 if (File.Exists(filename))
1282 {
1283 FileStream stream = null;
1284 try
1285 {
1286 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
1287 BinaryFormatter bformatter = new BinaryFormatter();
1288
1289 mesh = Mesh.FromStream(stream, key);
1290
1291 }
1292 catch (Exception e)
1293 {
1294 ok = false;
1295 m_log.ErrorFormat(
1296 "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
1297 filename, e.Message, e.StackTrace);
1298 }
1299
1300 if (stream != null)
1301 stream.Close();
1302
1303 if (mesh == null || !ok)
1304 File.Delete(filename);
1305 else
1306 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1307 }
1308 }
1309
1310 return mesh;
1311 }
1312
1313 private void StoreToFileCache(AMeshKey key, Mesh mesh)
1314 {
1315 Stream stream = null;
1316 bool ok = false;
1317
1318 // Make sure the target cache directory exists
1319 string dir = String.Empty;
1320 string filename = String.Empty;
1321
1322 FileNames(key, out dir, out filename);
1323
1324 lock (diskLock)
1325 {
1326 try
1327 {
1328 if (!Directory.Exists(dir))
1329 {
1330 Directory.CreateDirectory(dir);
1331 }
1332
1333 stream = File.Open(filename, FileMode.Create);
1334 ok = mesh.ToStream(stream);
1335 }
1336 catch (IOException e)
1337 {
1338 m_log.ErrorFormat(
1339 "[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.",
1340 filename, e.Message, e.StackTrace);
1341 ok = false;
1342 }
1343
1344 if (stream != null)
1345 stream.Close();
1346
1347 if (File.Exists(filename))
1348 {
1349 if (ok)
1350 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1351 else
1352 File.Delete(filename);
1353 }
1354 }
1355 }
1356
1357 public void ExpireFileCache()
1358 {
1359 if (!doCacheExpire)
1360 return;
1361
1362 string controlfile = System.IO.Path.Combine(cachePath, "cntr");
1363
1364 lock (diskLock)
1365 {
1366 try
1367 {
1368 if (File.Exists(controlfile))
1369 {
1370 int ndeleted = 0;
1371 int totalfiles = 0;
1372 int ndirs = 0;
1373 DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
1374 File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
1375
1376 foreach (string dir in Directory.GetDirectories(cachePath))
1377 {
1378 try
1379 {
1380 foreach (string file in Directory.GetFiles(dir))
1381 {
1382 try
1383 {
1384 if (File.GetLastAccessTimeUtc(file) < OlderTime)
1385 {
1386 File.Delete(file);
1387 ndeleted++;
1388 }
1389 }
1390 catch { }
1391 totalfiles++;
1392 }
1393 }
1394 catch { }
1395 ndirs++;
1396 }
1397
1398 if (ndeleted == 0)
1399 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires",
1400 totalfiles,ndirs);
1401 else
1402 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}",
1403 totalfiles,ndirs, ndeleted, OlderTime.ToString());
1404 }
1405 else
1406 {
1407 m_log.Info("[MESH CACHE]: Expire delayed to next startup");
1408 FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough);
1409 fs.Close();
1410 }
1411 }
1412 catch { }
1413 }
1414 }
1186 } 1415 }
1187} 1416}