From 6e217965841d474ba7e19c99dcfa5e86c1c459da Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Fri, 12 Oct 2012 23:37:28 +0100
Subject: [TEST] disk cache meshs

---
 OpenSim/Region/Physics/UbitMeshing/Mesh.cs        | 551 +++++++++++++---------
 OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | 259 +++++++---
 OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs  |   4 +-
 3 files changed, 532 insertions(+), 282 deletions(-)

(limited to 'OpenSim/Region')

diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index a0a18c4..1e9b8bc 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -32,30 +32,49 @@ using System.Runtime.InteropServices;
 using OpenSim.Region.Physics.Manager;
 using PrimMesher;
 using OpenMetaverse;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
 
 namespace OpenSim.Region.Physics.Meshing
 {
-    public class Mesh : IMesh
+    public class MeshBuildingData
     {
+        public Dictionary<Vertex, int> m_vertices;
+        public List<Triangle> m_triangles;
+        public float m_obbXmin;
+        public float m_obbXmax;
+        public float m_obbYmin;
+        public float m_obbYmax;
+        public float m_obbZmin;
+        public float m_obbZmax;
+        public Vector3 m_centroid;
+        public int m_centroidDiv;
+    }
 
-        private Dictionary<Vertex, int> m_vertices;
-        private List<Triangle> m_triangles;
-        GCHandle m_pinnedVertexes;
-        GCHandle m_pinnedIndex;
+    [Serializable()]
+    public class Mesh : IMesh
+    {
+        float[] vertices;
+        int[] indexes;
+        Vector3 m_obb;
+        Vector3 m_obboffset;
+        [NonSerialized()]
+        MeshBuildingData m_bdata;
+        [NonSerialized()]
+        GCHandle vhandler;
+        [NonSerialized()]
+        GCHandle ihandler;
+        [NonSerialized()]
         IntPtr m_verticesPtr = IntPtr.Zero;
-        int m_vertexCount = 0;
+        [NonSerialized()]
         IntPtr m_indicesPtr = IntPtr.Zero;
+        [NonSerialized()]
+        int m_vertexCount = 0;
+        [NonSerialized()]
         int m_indexCount = 0;
-        public float[] m_normals;
-        Vector3 m_centroid;
-        float m_obbXmin;
-        float m_obbXmax;
-        float m_obbYmin;
-        float m_obbYmax;
-        float m_obbZmin;
-        float m_obbZmax;
 
-        int m_centroidDiv;
+        public int RefCount { get; set; }
+        public AMeshKey Key { get; set; }
 
         private class vertexcomp : IEqualityComparer<Vertex>
         {
@@ -79,42 +98,82 @@ namespace OpenSim.Region.Physics.Meshing
         {
             vertexcomp vcomp = new vertexcomp();
 
-            m_vertices = new Dictionary<Vertex, int>(vcomp);
-            m_triangles = new List<Triangle>();
-            m_centroid = Vector3.Zero;
-            m_centroidDiv = 0;
-            m_obbXmin = float.MaxValue;
-            m_obbXmax = float.MinValue;
-            m_obbYmin = float.MaxValue;
-            m_obbYmax = float.MinValue;
-            m_obbZmin = float.MaxValue;
-            m_obbZmax = float.MinValue;
+            m_bdata = new MeshBuildingData();
+            m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
+            m_bdata.m_triangles = new List<Triangle>();
+            m_bdata.m_centroid = Vector3.Zero;
+            m_bdata.m_centroidDiv = 0;
+            m_bdata.m_obbXmin = float.MaxValue;
+            m_bdata.m_obbXmax = float.MinValue;
+            m_bdata.m_obbYmin = float.MaxValue;
+            m_bdata.m_obbYmax = float.MinValue;
+            m_bdata.m_obbZmin = float.MaxValue;
+            m_bdata.m_obbZmax = float.MinValue;
+            m_obb = new Vector3(0.5f, 0.5f, 0.5f);
+            m_obboffset = Vector3.Zero;
         }
 
-        public int RefCount { get; set; }
-
-        public AMeshKey Key { get; set; }
 
-        public void Scale(Vector3 scale)
+        public Mesh Scale(Vector3 scale)
         {
+            if (m_verticesPtr == null || m_indicesPtr == null)
+                return null;
+
+            Mesh result = new Mesh();
+
+            float x = scale.X;
+            float y = scale.Y;
+            float z = scale.Z;
+
+            result.m_obb.X = m_obb.X * x;
+            result.m_obb.Y = m_obb.Y * y;
+            result.m_obb.Z = m_obb.Z * z;
+            result.m_obboffset.X = m_obboffset.X * x;
+            result.m_obboffset.Y = m_obboffset.Y * y;
+            result.m_obboffset.Z = m_obboffset.Z * z;
+
+            result.vertices = new float[vertices.Length];
+            int j = 0;
+            for (int i = 0; i < m_vertexCount; i++)
+            {
+                result.vertices[j] = vertices[j] * x;
+                j++;
+                result.vertices[j] = vertices[j] * y;
+                j++;
+                result.vertices[j] = vertices[j] * z;
+                j++;
+            }
+
+            result.indexes = new int[indexes.Length];
+            indexes.CopyTo(result.indexes,0);
+
+            result.pinMemory();
+
+            return result;
         }
 
         public Mesh Clone()
         {
             Mesh result = new Mesh();
 
-            foreach (Triangle t in m_triangles)
+            if (m_bdata != null)
             {
-                result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
+                result.m_bdata = new MeshBuildingData();
+                foreach (Triangle t in m_bdata.m_triangles)
+                {
+                    result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
+                }
+                result.m_bdata.m_centroid = m_bdata.m_centroid;
+                result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
+                result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
+                result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
+                result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
+                result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
+                result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
+                result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
             }
-            result.m_centroid = m_centroid;
-            result.m_centroidDiv = m_centroidDiv;
-            result.m_obbXmin = m_obbXmin;
-            result.m_obbXmax = m_obbXmax;
-            result.m_obbYmin = m_obbYmin;
-            result.m_obbYmax = m_obbYmax;
-            result.m_obbZmin = m_obbZmin;
-            result.m_obbZmax = m_obbZmax;
+            result.m_obb = m_obb;
+            result.m_obboffset = m_obboffset;
             return result;
         }
 
@@ -124,37 +183,34 @@ namespace OpenSim.Region.Physics.Meshing
             float y = v.Y;
             float z = v.Z;
 
-            m_centroid.X += x;
-            m_centroid.Y += y;
-            m_centroid.Z += z;
-            m_centroidDiv++;
+            m_bdata.m_centroid.X += x;
+            m_bdata.m_centroid.Y += y;
+            m_bdata.m_centroid.Z += z;
+            m_bdata.m_centroidDiv++;
 
-            if (x > m_obbXmax)
-                m_obbXmax = x;
-            else if (x < m_obbXmin)
-                m_obbXmin = x;
+            if (x > m_bdata.m_obbXmax)
+                m_bdata.m_obbXmax = x;
+            else if (x < m_bdata.m_obbXmin)
+                m_bdata.m_obbXmin = x;
 
-            if (y > m_obbYmax)
-                m_obbYmax = y;
-            else if (y < m_obbYmin)
-                m_obbYmin = y;
+            if (y > m_bdata.m_obbYmax)
+                m_bdata.m_obbYmax = y;
+            else if (y < m_bdata.m_obbYmin)
+                m_bdata.m_obbYmin = y;
 
-            if (z > m_obbZmax)
-                m_obbZmax = z;
-            else if (z < m_obbZmin)
-                m_obbZmin = z;
+            if (z > m_bdata.m_obbZmax)
+                m_bdata.m_obbZmax = z;
+            else if (z < m_bdata.m_obbZmin)
+                m_bdata.m_obbZmin = z;
 
         }
 
 
         public void Add(Triangle triangle)
         {
-            if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+            if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
                 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
-            // If a vertex of the triangle is not yet in the vertices list,
-            // add it and set its index to the current index count
-            // vertex == seems broken
-            // skip colapsed triangles
+
             if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
                 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
                 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
@@ -163,46 +219,45 @@ namespace OpenSim.Region.Physics.Meshing
                 return;
             }
 
-            if (m_vertices.Count == 0)
+            if (m_bdata.m_vertices.Count == 0)
             {
-                m_centroidDiv = 0;
-                m_centroid = Vector3.Zero;
+                m_bdata.m_centroidDiv = 0;
+                m_bdata.m_centroid = Vector3.Zero;
             }
 
-            if (!m_vertices.ContainsKey(triangle.v1))
+            if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
             {
-                m_vertices[triangle.v1] = m_vertices.Count;
+                m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
                 addVertexLStats(triangle.v1);
             }
-            if (!m_vertices.ContainsKey(triangle.v2))
+            if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
             {
-                m_vertices[triangle.v2] = m_vertices.Count;
+                m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
                 addVertexLStats(triangle.v2);
             }
-            if (!m_vertices.ContainsKey(triangle.v3))
+            if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
             {
-                m_vertices[triangle.v3] = m_vertices.Count;
+                m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
                 addVertexLStats(triangle.v3);
             }
-            m_triangles.Add(triangle);
+            m_bdata.m_triangles.Add(triangle);
         }
 
         public Vector3 GetCentroid()
         {
-            if (m_centroidDiv > 0)
-                return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
-            else
-                return Vector3.Zero;
+            return m_obboffset;
+
         }
 
         public Vector3 GetOBB()
         {
+            return m_obb;
             float x, y, z;
-            if (m_centroidDiv > 0)
+            if (m_bdata.m_centroidDiv > 0)
             {
-                x = (m_obbXmax - m_obbXmin) * 0.5f;
-                y = (m_obbYmax - m_obbYmin) * 0.5f;
-                z = (m_obbZmax - m_obbZmin) * 0.5f;
+                x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
+                y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
+                z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
             }
             else // ??
             {
@@ -213,72 +268,10 @@ namespace OpenSim.Region.Physics.Meshing
             return new Vector3(x, y, z);
         }
 
-        public void CalcNormals()
-        {
-            int iTriangles = m_triangles.Count;
-
-            this.m_normals = new float[iTriangles * 3];
-
-            int i = 0;
-            foreach (Triangle t in m_triangles)
-            {
-                float ux, uy, uz;
-                float vx, vy, vz;
-                float wx, wy, wz;
-
-                ux = t.v1.X;
-                uy = t.v1.Y;
-                uz = t.v1.Z;
-
-                vx = t.v2.X;
-                vy = t.v2.Y;
-                vz = t.v2.Z;
-
-                wx = t.v3.X;
-                wy = t.v3.Y;
-                wz = t.v3.Z;
-
-
-                // Vectors for edges
-                float e1x, e1y, e1z;
-                float e2x, e2y, e2z;
-
-                e1x = ux - vx;
-                e1y = uy - vy;
-                e1z = uz - vz;
-
-                e2x = ux - wx;
-                e2y = uy - wy;
-                e2z = uz - wz;
-
-
-                // Cross product for normal
-                float nx, ny, nz;
-                nx = e1y * e2z - e1z * e2y;
-                ny = e1z * e2x - e1x * e2z;
-                nz = e1x * e2y - e1y * e2x;
-
-                // Length
-                float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
-                float lReciprocal = 1.0f / l;
-
-                // Normalized "normal"
-                //nx /= l;
-                //ny /= l;
-                //nz /= l;
-
-                m_normals[i] = nx * lReciprocal;
-                m_normals[i + 1] = ny * lReciprocal;
-                m_normals[i + 2] = nz * lReciprocal;
-
-                i += 3;
-            }
-        }
-
         public List<Vector3> getVertexList()
         {
             List<Vector3> result = new List<Vector3>();
-            foreach (Vertex v in m_vertices.Keys)
+            foreach (Vertex v in m_bdata.m_vertices.Keys)
             {
                 result.Add(new Vector3(v.X, v.Y, v.Z));
             }
@@ -287,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
 
         private float[] getVertexListAsFloat()
         {
-            if (m_vertices == null)
+            if (m_bdata.m_vertices == null)
                 throw new NotSupportedException();
-            float[] result = new float[m_vertices.Count * 3];
-            foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
+            float[] result = new float[m_bdata.m_vertices.Count * 3];
+            foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
             {
                 Vertex v = kvp.Key;
                 int i = kvp.Value;
@@ -303,74 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
 
         public float[] getVertexListAsFloatLocked()
         {
-            if (m_pinnedVertexes.IsAllocated)
-                return (float[])(m_pinnedVertexes.Target);
-
-            float[] result = getVertexListAsFloat();
-            m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
-            // Inform the garbage collector of this unmanaged allocation so it can schedule
-            // the next GC round more intelligently
-            GC.AddMemoryPressure(Buffer.ByteLength(result));
-
-            return result;
-        }
-
-        public void PrepForOde()
-        {
-            // If there isn't an unmanaged array allocated yet, do it now
-            if (m_verticesPtr == IntPtr.Zero)
-            {
-                float[] vertexList = getVertexListAsFloat();
-                // Each vertex is 3 elements (floats)
-                m_vertexCount = vertexList.Length / 3;
-                int byteCount = m_vertexCount * 3 * sizeof(float);
-                m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
-                System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
-            }
-
-            // If there isn't an unmanaged array allocated yet, do it now
-            if (m_indicesPtr == IntPtr.Zero)
-            {
-                int[] indexList = getIndexListAsInt();
-                m_indexCount = indexList.Length;
-                int byteCount = m_indexCount * sizeof(int);
-                m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
-                System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
-            }
-
-            releaseSourceMeshData();
+            return null;
         }
 
-        public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
+        public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
         {
             // A vertex is 3 floats
             vertexStride = 3 * sizeof(float);
 
             // If there isn't an unmanaged array allocated yet, do it now
-            if (m_verticesPtr == IntPtr.Zero)
+            if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
             {
-                float[] vertexList = getVertexListAsFloat();
+                vertices = getVertexListAsFloat();
                 // Each vertex is 3 elements (floats)
-                m_vertexCount = vertexList.Length / 3;
-                int byteCount = m_vertexCount * vertexStride;
-                m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
-                System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
+                m_vertexCount = vertices.Length / 3;
+                vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
+                m_verticesPtr = vhandler.AddrOfPinnedObject();
+                GC.AddMemoryPressure(Buffer.ByteLength(vertices));
             }
-            vertices = m_verticesPtr;
+            _vertices = m_verticesPtr;
             vertexCount = m_vertexCount;
         }
 
         public int[] getIndexListAsInt()
         {
-            if (m_triangles == null)
+            if (m_bdata.m_triangles == null)
                 throw new NotSupportedException();
-            int[] result = new int[m_triangles.Count * 3];
-            for (int i = 0; i < m_triangles.Count; i++)
+            int[] result = new int[m_bdata.m_triangles.Count * 3];
+            for (int i = 0; i < m_bdata.m_triangles.Count; i++)
             {
-                Triangle t = m_triangles[i];
-                result[3 * i + 0] = m_vertices[t.v1];
-                result[3 * i + 1] = m_vertices[t.v2];
-                result[3 * i + 2] = m_vertices[t.v3];
+                Triangle t = m_bdata.m_triangles[i];
+                result[3 * i + 0] = m_bdata.m_vertices[t.v1];
+                result[3 * i + 1] = m_bdata.m_vertices[t.v2];
+                result[3 * i + 2] = m_bdata.m_vertices[t.v3];
             }
             return result;
         }
@@ -381,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
         /// <returns></returns>
         public int[] getIndexListAsIntLocked()
         {
-            if (m_pinnedIndex.IsAllocated)
-                return (int[])(m_pinnedIndex.Target);
-        
-            int[] result = getIndexListAsInt();
-            m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
-            // Inform the garbage collector of this unmanaged allocation so it can schedule
-            // the next GC round more intelligently
-            GC.AddMemoryPressure(Buffer.ByteLength(result));
-
-            return result;
+            return null;
         }
 
         public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
         {
             // If there isn't an unmanaged array allocated yet, do it now
-            if (m_indicesPtr == IntPtr.Zero)
+            if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
             {
-                int[] indexList = getIndexListAsInt();
-                m_indexCount = indexList.Length;
-                int byteCount = m_indexCount * sizeof(int);
-                m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
-                System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
+                indexes = getIndexListAsInt();
+                m_indexCount = indexes.Length;
+                ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
+                m_indicesPtr = ihandler.AddrOfPinnedObject();
+                GC.AddMemoryPressure(Buffer.ByteLength(indexes));
             }
             // A triangle is 3 ints (indices)
             triStride = 3 * sizeof(int);
@@ -412,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
 
         public void releasePinned()
         {
-            if (m_pinnedVertexes.IsAllocated)
-                m_pinnedVertexes.Free();
-            if (m_pinnedIndex.IsAllocated)
-                m_pinnedIndex.Free();
             if (m_verticesPtr != IntPtr.Zero)
             {
-                System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
+                vhandler.Free();
+                vertices = null;
                 m_verticesPtr = IntPtr.Zero;
             }
             if (m_indicesPtr != IntPtr.Zero)
             {
-                System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
+                ihandler.Free();
+                indexes = null;
                 m_indicesPtr = IntPtr.Zero;
             }
         }
@@ -433,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
         /// </summary>
         public void releaseSourceMeshData()
         {
-            m_triangles = null;
-            m_vertices = null;
+            if (m_bdata != null)
+            {
+                m_bdata.m_triangles = null;
+                m_bdata.m_vertices = null;
+            }
+        }
+
+        public void releaseBuildingMeshData()
+        {
+            if (m_bdata != null)
+            {
+                m_bdata.m_triangles = null;
+                m_bdata.m_vertices = null;
+                m_bdata = null;
+            }
         }
 
         public void Append(IMesh newMesh)
         {
-            if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+            if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
                 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
         
             if (!(newMesh is Mesh))
                 return;
 
-            foreach (Triangle t in ((Mesh)newMesh).m_triangles)
+            foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
                 Add(t);
         }
 
         // Do a linear transformation of  mesh.
         public void TransformLinear(float[,] matrix, float[] offset)
         {
-            if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+            if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
                 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
-        
-            foreach (Vertex v in m_vertices.Keys)
+
+            foreach (Vertex v in m_bdata.m_vertices.Keys)
             {
                 if (v == null)
                     continue;
@@ -473,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
         {
             if (path == null)
                 return;
+            if (m_bdata == null)
+                return;
             String fileName = name + "_" + title + ".raw";
             String completePath = System.IO.Path.Combine(path, fileName);
             StreamWriter sw = new StreamWriter(completePath);
-            foreach (Triangle t in m_triangles)
+            foreach (Triangle t in m_bdata.m_triangles)
             {
                 String s = t.ToStringRaw();
                 sw.WriteLine(s);
@@ -486,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
 
         public void TrimExcess()
         {
-            m_triangles.TrimExcess();
+            m_bdata.m_triangles.TrimExcess();
+        }
+
+        public void pinMemory()
+        {
+            m_vertexCount = vertices.Length / 3;
+            vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
+            m_verticesPtr = vhandler.AddrOfPinnedObject();
+            GC.AddMemoryPressure(Buffer.ByteLength(vertices));
+
+            m_indexCount = indexes.Length;
+            ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
+            m_indicesPtr = ihandler.AddrOfPinnedObject();
+            GC.AddMemoryPressure(Buffer.ByteLength(indexes));
+        }
+
+        public void PrepForOde()
+        {
+            // If there isn't an unmanaged array allocated yet, do it now
+            if (m_verticesPtr == IntPtr.Zero)
+                vertices = getVertexListAsFloat();
+
+            // If there isn't an unmanaged array allocated yet, do it now
+            if (m_indicesPtr == IntPtr.Zero)
+                indexes = getIndexListAsInt();
+
+            pinMemory();
+
+            float x, y, z;
+
+            if (m_bdata.m_centroidDiv > 0)
+            {
+                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);
+                x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
+                y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
+                z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
+            }
+
+            else
+            {
+                m_obboffset = Vector3.Zero;
+                x = 0.5f;
+                y = 0.5f;
+                z = 0.5f;
+            }
+            m_obb = new Vector3(x, y, z);
+
+            releaseBuildingMeshData();
+        }
+        public bool ToStream(Stream st)
+        {
+            if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
+                return false;
+
+            BinaryWriter bw = new BinaryWriter(st);
+            bool ok = true;
+
+            try
+            {
+
+                bw.Write(m_vertexCount);
+                bw.Write(m_indexCount);
+
+                for (int i = 0; i < 3 * m_vertexCount; i++)
+                    bw.Write(vertices[i]);
+                for (int i = 0; i < m_indexCount; i++)
+                    bw.Write(indexes[i]);
+                bw.Write(m_obb.X);
+                bw.Write(m_obb.Y);
+                bw.Write(m_obb.Z);
+                bw.Write(m_obboffset.X);
+                bw.Write(m_obboffset.Y);
+                bw.Write(m_obboffset.Z);
+            }
+            catch
+            {
+                ok = false;
+            }
+
+            if (bw != null)
+            {
+                bw.Flush();
+                bw.Close();
+            }
+
+            return ok;
+        }
+
+        public static Mesh FromStream(Stream st, AMeshKey key)
+        {
+            Mesh mesh = new Mesh();
+            mesh.releaseBuildingMeshData();
+
+            BinaryReader br = new BinaryReader(st);
+
+            bool ok = true;
+            try
+            {
+                mesh.m_vertexCount = br.ReadInt32();
+                mesh.m_indexCount = br.ReadInt32();
+
+                int n = 3 * mesh.m_vertexCount;
+                mesh.vertices = new float[n];
+                for (int i = 0; i < n; i++)
+                    mesh.vertices[i] = br.ReadSingle();
+
+                mesh.indexes = new int[mesh.m_indexCount];
+                for (int i = 0; i < mesh.m_indexCount; i++)
+                    mesh.indexes[i] = br.ReadInt32();
+
+                mesh.m_obb.X = br.ReadSingle();
+                mesh.m_obb.Y = br.ReadSingle();
+                mesh.m_obb.Z = br.ReadSingle();
+
+                mesh.m_obboffset.X = br.ReadSingle();
+                mesh.m_obboffset.Y = br.ReadSingle();
+                mesh.m_obboffset.Z = br.ReadSingle();
+            }
+            catch
+            {
+                ok = false;
+            }
+
+            br.Close();
+
+            if (ok)
+            {
+                mesh.pinMemory();
+
+                mesh.Key = key;
+                mesh.RefCount = 1;
+
+                return mesh;
+            }
+
+            mesh.vertices = null;
+            mesh.indexes = null;
+            return null;
         }
     }
 }
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index dec5eb7..952ecc8 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -42,6 +42,8 @@ using System.Reflection;
 using System.IO;
 using ComponentAce.Compression.Libs.zlib;
 using OpenSim.Region.Physics.ConvexDecompositionDotNet;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
 
 namespace OpenSim.Region.Physics.Meshing
 {
@@ -68,18 +70,20 @@ namespace OpenSim.Region.Physics.Meshing
 
         // Setting baseDir to a path will enable the dumping of raw files
         // raw files can be imported by blender so a visual inspection of the results can be done
-#if SPAM
-        const string baseDir = "rawFiles";
-#else
+
+        public object diskLock = new object();
+
+        public bool doMeshFileCache = true;
+
+        public string cachePath = "MeshCache";
+
+//        const string baseDir = "rawFiles";
         private const string baseDir = null; //"rawFiles";
-#endif
 
         private bool useMeshiesPhysicsMesh = false;
 
         private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
 
-//        private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
-//        private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>();
         private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
         private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
 
@@ -89,8 +93,16 @@ namespace OpenSim.Region.Physics.Meshing
             IConfig mesh_config = config.Configs["Mesh"];
 
             if(mesh_config != null)
+            {
                 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
-
+                if(useMeshiesPhysicsMesh)
+                {
+                    doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
+                    cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
+                }
+                else
+                    doMeshFileCache = false;
+            }
         }
 
         /// <summary>
@@ -188,7 +200,7 @@ namespace OpenSim.Region.Physics.Meshing
         /// <param name="size">Size of entire object</param>
         /// <param name="coords"></param>
         /// <param name="faces"></param>
-        private void AddSubMesh(OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces)
+        private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
         {
     //                                    Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
     
@@ -221,9 +233,9 @@ namespace OpenSim.Region.Physics.Meshing
                 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
     
                 Coord c = new Coord(
-                Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
-                Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
-                Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
+                Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
+                Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
+                Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
     
                 coords.Add(c);
             }
@@ -247,7 +259,7 @@ namespace OpenSim.Region.Physics.Meshing
         /// <param name="size"></param>
         /// <param name="lod"></param>
         /// <returns></returns>
-        private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex)
+        private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
         {
 //            m_log.DebugFormat(
 //                "[MESH]: Creating physics proxy for {0}, shape {1}",
@@ -263,18 +275,18 @@ namespace OpenSim.Region.Physics.Meshing
                     if (!useMeshiesPhysicsMesh)
                         return null;
 
-                    if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
+                    if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
                         return null;
                 }
                 else
                 {
-                    if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
+                    if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
                         return null;
                 }
             }
             else
             {
-                if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
+                if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
                     return null;
             }
 
@@ -309,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
         /// <param name="faces">Faces are added to this list by the method.</param>
         /// <returns>true if coords and faces were successfully generated, false if not</returns>
         private bool GenerateCoordsAndFacesFromPrimMeshData(
-            string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces, bool convex)
+            string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
         {
 //            m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
 
@@ -382,7 +394,7 @@ namespace OpenSim.Region.Physics.Meshing
                 OSD decodedMeshOsd = new OSD();
                 byte[] meshBytes = new byte[physSize];
                 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
-//                        byte[] decompressed = new byte[physSize * 5];
+
                 try
                 {
                     using (MemoryStream inMs = new MemoryStream(meshBytes))
@@ -420,13 +432,13 @@ namespace OpenSim.Region.Physics.Meshing
                     // physics_shape is an array of OSDMaps, one for each submesh
                     if (decodedMeshOsd is OSDArray)
                     {
-//                            Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
+//                      Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
 
                         decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
                         foreach (OSD subMeshOsd in decodedMeshOsdArray)
                         {
                             if (subMeshOsd is OSDMap)
-                                AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
+                                AddSubMesh(subMeshOsd as OSDMap, coords, faces);
                         }
                     }
                 }
@@ -498,9 +510,9 @@ namespace OpenSim.Region.Physics.Meshing
                                     t3 = data[ptr++];
                                     t3 += data[ptr++] << 8;
 
-                                    f3 = new float3((t1 * range.X + min.X) * size.X,
-                                              (t2 * range.Y + min.Y) * size.Y,
-                                              (t3 * range.Z + min.Z) * size.Z);
+                                    f3 = new float3((t1 * range.X + min.X),
+                                              (t2 * range.Y + min.Y),
+                                              (t3 * range.Z + min.Z));
                                     vs.Add(f3);
                                 }
 
@@ -597,9 +609,9 @@ namespace OpenSim.Region.Physics.Meshing
                             t3 = data[i++];
                             t3 += data[i++] << 8;
 
-                            f3 = new float3((t1 * range.X + min.X) * size.X,
-                                      (t2 * range.Y + min.Y) * size.Y,
-                                      (t3 * range.Z + min.Z) * size.Z);
+                            f3 = new float3((t1 * range.X + min.X),
+                                      (t2 * range.Y + min.Y),
+                                      (t3 * range.Z + min.Z));
                             vs.Add(f3);
                         }
 
@@ -687,7 +699,7 @@ namespace OpenSim.Region.Physics.Meshing
         /// <param name="faces">Faces are added to this list by the method.</param>
         /// <returns>true if coords and faces were successfully generated, false if not</returns>
         private bool GenerateCoordsAndFacesFromPrimSculptData(
-            string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
+            string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
         {
             coords = new List<Coord>();
             faces = new List<Face>();
@@ -757,9 +769,7 @@ namespace OpenSim.Region.Physics.Meshing
 
             idata.Dispose();
 
-            sculptMesh.DumpRaw(baseDir, primName, "primMesh");
-
-            sculptMesh.Scale(size.X, size.Y, size.Z);
+//            sculptMesh.DumpRaw(baseDir, primName, "primMesh");
 
             coords = sculptMesh.coords;
             faces = sculptMesh.faces;
@@ -777,7 +787,7 @@ namespace OpenSim.Region.Physics.Meshing
         /// <param name="faces">Faces are added to this list by the method.</param>
         /// <returns>true if coords and faces were successfully generated, false if not</returns>
         private bool GenerateCoordsAndFacesFromPrimShapeData(
-            string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
+            string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
         {
             PrimMesh primMesh;
             coords = new List<Coord>();
@@ -912,9 +922,7 @@ namespace OpenSim.Region.Physics.Meshing
                 }
             }
 
-            primMesh.DumpRaw(baseDir, primName, "primMesh");
-
-            primMesh.Scale(size.X, size.Y, size.Z);
+//            primMesh.DumpRaw(baseDir, primName, "primMesh");
 
             coords = primMesh.coords;
             faces = primMesh.faces;
@@ -934,6 +942,7 @@ namespace OpenSim.Region.Physics.Meshing
             {
                 key.uuid = primShape.SculptTexture;
                 key.hashB = mdjb2(key.hashB, primShape.SculptType);
+                key.hashB = mdjb2(key.hashB, primShape.PCode);
             }
             else
             {
@@ -956,6 +965,7 @@ namespace OpenSim.Region.Physics.Meshing
                 hash = mdjb2(hash, primShape.ProfileBegin);
                 hash = mdjb2(hash, primShape.ProfileEnd);
                 hash = mdjb2(hash, primShape.ProfileHollow);
+                hash = mdjb2(hash, primShape.PCode);
                 key.hashA = hash;
             }
 
@@ -1001,8 +1011,6 @@ namespace OpenSim.Region.Physics.Meshing
             return CreateMesh(primName, primShape, size, lod, false,false,false);
         }
 
-        private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f);
-
         public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
         {
             Mesh mesh = null;
@@ -1031,7 +1039,13 @@ namespace OpenSim.Region.Physics.Meshing
                 {
                     m_uniqueReleasedMeshes.Remove(key);
                     lock (m_uniqueMeshes)
-                        m_uniqueMeshes.Add(key, mesh);
+                    {
+                        try
+                        {
+                            m_uniqueMeshes.Add(key, mesh);
+                        }
+                        catch { }
+                    }
                     mesh.RefCount = 1;
                     return mesh;
                 }
@@ -1039,6 +1053,8 @@ namespace OpenSim.Region.Physics.Meshing
             return null;
         }
 
+        private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
+        
         public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
         {
 #if SPAM
@@ -1074,41 +1090,78 @@ namespace OpenSim.Region.Physics.Meshing
                 {
                     m_uniqueReleasedMeshes.Remove(key);
                     lock (m_uniqueMeshes)
-                        m_uniqueMeshes.Add(key, mesh);
+                    {
+                        try
+                        {
+                            m_uniqueMeshes.Add(key, mesh);
+                        }
+                        catch { }
+                    }
                     mesh.RefCount = 1;
                     return mesh;
                 }
             }
 
-            mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex);
+            Mesh UnitMesh = null;
+            AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
 
-            if (mesh != null)
+            lock (m_uniqueReleasedMeshes)
             {
-                if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
+                m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
+                if (UnitMesh != null)
                 {
-#if SPAM
-                m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + 
-                            minSizeForComplexMesh.ToString() + " - creating simple bounding box");
-#endif
-                    mesh = CreateBoundingBoxMesh(mesh);
-                    mesh.DumpRaw(baseDir, primName, "Z extruded");
+                    UnitMesh.RefCount = 1;
                 }
+            }
+
+            if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
+                UnitMesh = GetFromFileCache(unitKey);
+
+            if (UnitMesh == null)
+            {
+                UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
+
+                if (UnitMesh == null)
+                    return null;
+
+                UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
 
                 if (forOde)
                 {
                     // force pinned mem allocation
-                    mesh.PrepForOde();
+                    UnitMesh.PrepForOde();
                 }
                 else
-                    mesh.TrimExcess();
+                    UnitMesh.TrimExcess();
 
-                mesh.Key = key;
-                mesh.RefCount = 1;
+                UnitMesh.Key = unitKey;
+                UnitMesh.RefCount = 1;
 
-                lock(m_uniqueMeshes)
-                    m_uniqueMeshes.Add(key, mesh);
+                if (doMeshFileCache && primShape.SculptEntry)
+                    StoreToFileCache(unitKey, UnitMesh);
+
+                lock (m_uniqueReleasedMeshes)
+                {
+                    try
+                    {
+                        m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
+                    }
+                    catch { }
+                }
             }
 
+            mesh = UnitMesh.Scale(size);
+            mesh.Key = key;
+            mesh.RefCount = 1;
+            lock (m_uniqueMeshes)
+            {
+                try
+                {
+                    m_uniqueMeshes.Add(key, mesh);
+                }
+                catch { }
+            }           
+
             return mesh;
         }
 
@@ -1133,7 +1186,13 @@ namespace OpenSim.Region.Physics.Meshing
                 mesh.RefCount = 0;
                 m_uniqueMeshes.Remove(mesh.Key);
                 lock (m_uniqueReleasedMeshes)
-                    m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
+                {
+                    try
+                    {
+                        m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
+                    }
+                    catch { }
+                }           
             }
         }
 
@@ -1160,10 +1219,102 @@ namespace OpenSim.Region.Physics.Meshing
                 foreach (Mesh m in meshstodelete)
                 {
                     m_uniqueReleasedMeshes.Remove(m.Key);
-                    m.releaseSourceMeshData();
+                    m.releaseBuildingMeshData();
                     m.releasePinned();
                 }
             }
         }
+
+        public void FileNames(AMeshKey key, out string dir,out string fullFileName)
+        {
+            string id = key.ToString();
+            string init = id.Substring(0, 1);
+            dir = System.IO.Path.Combine(cachePath, init);
+            fullFileName = System.IO.Path.Combine(dir, id);
+        }
+
+        public string FullFileName(AMeshKey key)
+        {
+            string id = key.ToString();
+            string init = id.Substring(0,1);
+            id = System.IO.Path.Combine(init, id);
+            id = System.IO.Path.Combine(cachePath, id);
+            return id;
+        }
+
+        private Mesh GetFromFileCache(AMeshKey key)
+        {
+            Mesh mesh = null;
+            string filename = FullFileName(key);
+            bool ok = true;
+
+            lock (diskLock)
+            {
+                if (File.Exists(filename))
+                {
+                    FileStream stream = null;
+                    try
+                    {
+                        stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+                        BinaryFormatter bformatter = new BinaryFormatter();
+
+                        mesh = Mesh.FromStream(stream, key);
+                    }
+                    catch (Exception e)
+                    {
+                        ok = false;
+                        m_log.ErrorFormat(
+                            "[MESH CACHE]: Failed to get file {0}.  Exception {1} {2}",
+                            filename, e.Message, e.StackTrace);
+                    }
+                    if (stream != null)
+                        stream.Close();
+
+                    if (mesh == null || !ok)
+                        File.Delete(filename);
+                }
+            }
+
+            return mesh;
+        }
+
+        private void StoreToFileCache(AMeshKey key, Mesh mesh)
+        {
+            Stream stream = null;
+            bool ok = false;
+
+            // Make sure the target cache directory exists
+            string dir = String.Empty;
+            string filename = String.Empty;
+
+            FileNames(key, out dir, out filename);
+
+            lock (diskLock)
+            {
+                try
+                {
+                    if (!Directory.Exists(dir))
+                    {
+                        Directory.CreateDirectory(dir);
+                    }
+
+                    stream = File.Open(filename, FileMode.Create);
+                    ok = mesh.ToStream(stream);
+                }
+                catch (IOException e)
+                {
+                    m_log.ErrorFormat(
+                        "[MESH CACHE]: Failed to write file {0}.  Exception {1} {2}.",
+                        filename, e.Message, e.StackTrace);
+                    ok = false;
+                }
+
+                if (stream != null)
+                    stream.Close();
+
+                if (!ok && File.Exists(filename))
+                    File.Delete(filename);
+            }
+        }
     }
 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 03048a4..6592e6c 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -718,7 +718,7 @@ namespace OpenSim.Region.Physics.OdePlugin
 
                 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
                     return;
-
+/*
 // debug
                 PhysicsActor dp2;
                 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
@@ -742,7 +742,7 @@ namespace OpenSim.Region.Physics.OdePlugin
                     }
                 }
 //
-
+*/
 
 
                 if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
-- 
cgit v1.1