From cb07ba0d68eeb57bae1cb60f387483ff720cc29d Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Sat, 10 Nov 2007 19:13:52 +0000
Subject: * Moves the Meshmerizer to a separate plugin * Experimental.   Linux
 Prebuild needs testing. * One more update after this to remove the ODEMeshing
 directory....

---
 OpenSim/Region/Application/OpenSimMain.cs          |   6 +-
 .../Region/ClientStack/RegionApplicationBase.cs    |   7 +-
 OpenSim/Region/Examples/SimpleApp/Program.cs       |   4 +-
 .../BasicPhysicsPlugin/BasicPhysicsPlugin.cs       |   7 +-
 .../Region/Physics/BulletXPlugin/BulletXPlugin.cs  | 145 ++++++--
 .../BulletXPlugin/TriangleIndexVertexArray.cs      | 161 +++++++++
 OpenSim/Region/Physics/Manager/IMesher.cs          |  26 ++
 .../Region/Physics/Manager/PhysicsPluginManager.cs |  67 +++-
 OpenSim/Region/Physics/Manager/PhysicsScene.cs     |  11 +-
 OpenSim/Region/Physics/Meshing/Extruder.cs         |  83 +++++
 OpenSim/Region/Physics/Meshing/HelperTypes.cs      | 306 ++++++++++++++++
 OpenSim/Region/Physics/Meshing/Mesh.cs             | 213 +++++++++++
 OpenSim/Region/Physics/Meshing/Meshmerizer.cs      | 393 +++++++++++++++++++++
 OpenSim/Region/Physics/Meshing/SimpleHull.cs       | 363 +++++++++++++++++++
 OpenSim/Region/Physics/Meshing/Simplex.cs          | 198 +++++++++++
 OpenSim/Region/Physics/OdePlugin/OdePlugin.cs      |  31 +-
 OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs  |   6 +
 prebuild.xml                                       |  37 +-
 18 files changed, 1996 insertions(+), 68 deletions(-)
 create mode 100644 OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
 create mode 100644 OpenSim/Region/Physics/Manager/IMesher.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/Extruder.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/HelperTypes.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/Mesh.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/Meshmerizer.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/SimpleHull.cs
 create mode 100644 OpenSim/Region/Physics/Meshing/Simplex.cs

diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs
index 684a9a8..42f1b94 100644
--- a/OpenSim/Region/Application/OpenSimMain.cs
+++ b/OpenSim/Region/Application/OpenSimMain.cs
@@ -54,6 +54,7 @@ namespace OpenSim
         private const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml";
 
         public string m_physicsEngine;
+        public string m_meshEngineName;
         public string m_scriptEngine;
         public bool m_sandbox;
         public bool user_accounts;
@@ -210,6 +211,7 @@ namespace OpenSim
             {
                 m_sandbox = !startupConfig.GetBoolean("gridmode", false);
                 m_physicsEngine = startupConfig.GetString("physics", "basicphysics");
+                m_meshEngineName = startupConfig.GetString("meshing", "Meshmerizer");
                 m_verbose = startupConfig.GetBoolean("verbose", true);
                 m_permissions = startupConfig.GetBoolean("serverside_object_permissions", false);
 
@@ -404,7 +406,7 @@ namespace OpenSim
 
         protected override PhysicsScene GetPhysicsScene()
         {
-            return GetPhysicsScene(m_physicsEngine);
+            return GetPhysicsScene(m_physicsEngine, m_meshEngineName);
         }
 
         private class SimStatusHandler : IStreamedRequestHandler
@@ -767,4 +769,4 @@ namespace OpenSim
 
         #endregion
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 6071dcd..b0e6419 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -29,6 +29,7 @@ using System;
 using System.Collections.Generic;
 using System.Net;
 using libsecondlife;
+using Nini.Config;
 using OpenSim.Framework;
 using OpenSim.Framework.Communications;
 using OpenSim.Framework.Communications.Cache;
@@ -89,12 +90,12 @@ namespace OpenSim.Region.ClientStack
         protected abstract PhysicsScene GetPhysicsScene();
         protected abstract StorageManager CreateStorageManager(RegionInfo regionInfo);
 
-        protected PhysicsScene GetPhysicsScene(string engine)
+        protected PhysicsScene GetPhysicsScene(string engine, string meshEngine)
         {
             PhysicsPluginManager physicsPluginManager;
             physicsPluginManager = new PhysicsPluginManager();
             physicsPluginManager.LoadPlugins();
-            return physicsPluginManager.GetPhysicsScene(engine);
+            return physicsPluginManager.GetPhysicsScene(engine, meshEngine);
         }
 
         protected Scene SetupScene(RegionInfo regionInfo, out UDPServer udpServer)
@@ -150,4 +151,4 @@ namespace OpenSim.Region.ClientStack
         protected abstract Scene CreateScene(RegionInfo regionInfo, StorageManager storageManager,
                                              AgentCircuitManager circuitManager);
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Examples/SimpleApp/Program.cs b/OpenSim/Region/Examples/SimpleApp/Program.cs
index 875bc4c..49fae93 100644
--- a/OpenSim/Region/Examples/SimpleApp/Program.cs
+++ b/OpenSim/Region/Examples/SimpleApp/Program.cs
@@ -182,7 +182,7 @@ namespace SimpleApp
 
         protected override PhysicsScene GetPhysicsScene()
         {
-            return GetPhysicsScene("basicphysics");
+            return GetPhysicsScene("basicphysics", "Meshmerizer");
         }
 
         #region conscmd_callback Members
@@ -206,4 +206,4 @@ namespace SimpleApp
             app.Run();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
index 6377392..1d1c14f 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
@@ -70,6 +70,11 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
         {
         }
 
+        public override void Initialise(IMesher meshmerizer)
+        {
+            // Does nothing right now
+        }
+
         public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
         {
             BasicActor act = new BasicActor();
@@ -274,4 +279,4 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
         {
         }
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
index c733adb..2db7a54 100644
--- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
+++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs
@@ -64,6 +64,7 @@ using System;
 using System.Collections.Generic;
 using MonoXnaCompactMaths;
 using OpenSim.Framework;
+using OpenSim.Framework.Console;
 using OpenSim.Region.Physics.Manager;
 using XnaDevRu.BulletX;
 using XnaDevRu.BulletX.Dynamics;
@@ -74,15 +75,6 @@ using BoxShape=XnaDevRu.BulletX.BoxShape;
 
 namespace OpenSim.Region.Physics.BulletXPlugin
 {
-    /// <summary>
-    /// This class is only here for compilations reasons
-    /// </summary>
-    public class Mesh
-    {
-        public Mesh()
-        {
-        }
-    }
 
     /// <summary>
     /// BulletXConversions are called now BulletXMaths
@@ -268,6 +260,65 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         }
     }
 
+
+    // Class to detect and debug collisions
+    // Mainly used for debugging purposes
+    class CollisionDispatcherLocal : CollisionDispatcher
+    {
+
+        BulletXScene relatedScene;
+
+        public CollisionDispatcherLocal(BulletXScene s)
+            : base()
+        {
+            relatedScene=s;
+        }
+
+        public override bool NeedsCollision(CollisionObject bodyA, CollisionObject bodyB)
+        {
+            RigidBody rb;
+            BulletXCharacter bxcA=null;
+            BulletXPrim bxpA = null;
+            Type t = bodyA.GetType();
+            if (t==typeof(RigidBody)) {
+                rb = (RigidBody)bodyA;
+                relatedScene._characters.TryGetValue(rb, out bxcA);
+                relatedScene._prims.TryGetValue(rb, out bxpA);
+            }
+            String nameA;
+            if (bxcA != null)
+                nameA = bxcA._name;
+            else if (bxpA != null)
+                nameA = bxpA._name;
+            else
+                nameA = "null";
+
+            BulletXCharacter bxcB = null;
+            BulletXPrim bxpB = null;
+            t = bodyB.GetType();
+            if (t == typeof(RigidBody))
+            {
+                rb = (RigidBody)bodyB;
+                relatedScene._characters.TryGetValue(rb, out bxcB);
+                relatedScene._prims.TryGetValue(rb, out bxpB);
+            }
+            String nameB;
+            if (bxcB != null)
+                nameB = bxcB._name;
+            else if (bxpB != null)
+                nameB = bxpB._name;
+            else
+                nameB = "null";
+
+            bool needsCollision=base.NeedsCollision(bodyA, bodyB);
+
+            MainLog.Instance.Debug("BulletX", "A collision was detected between {0} and {1} --> {2}", nameA, nameB, needsCollision);
+
+
+            return needsCollision;
+        }
+    }
+   
     /// <summary>
     /// PhysicsScene Class for BulletX
     /// </summary>
@@ -294,8 +345,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         private const int simulationSubSteps = 10;
         //private float[] _heightmap;
         private BulletXPlanet _simFlatPlanet;
-        private List<BulletXCharacter> _characters = new List<BulletXCharacter>();
-        private List<BulletXPrim> _prims = new List<BulletXPrim>();
+        internal Dictionary<RigidBody, BulletXCharacter> _characters = new Dictionary<RigidBody, BulletXCharacter>();
+        internal Dictionary<RigidBody, BulletXPrim> _prims = new Dictionary<RigidBody, BulletXPrim>();
+
+        public IMesher mesher;
+
 
         public static float Gravity
         {
@@ -334,7 +388,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
 
         public BulletXScene()
         {
-            cDispatcher = new CollisionDispatcher();
+            cDispatcher = new CollisionDispatcherLocal(this);
             Vector3 worldMinDim = new Vector3((float) minXY, (float) minXY, (float) minZ);
             Vector3 worldMaxDim = new Vector3((float) maxXY, (float) maxXY, (float) maxZ);
             opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
@@ -348,6 +402,12 @@ namespace OpenSim.Region.Physics.BulletXPlugin
             //this._heightmap = new float[65536];
         }
 
+        public override void Initialise(IMesher meshmerizer)
+        {
+            mesher = meshmerizer;
+        }
+
+
         public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
         {
             PhysicsVector pos = new PhysicsVector();
@@ -358,7 +418,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
             lock (BulletXLock)
             {
                 newAv = new BulletXCharacter(avName, this, pos);
-                _characters.Add(newAv);
+                _characters.Add(newAv.RigidBody, newAv);
             }
             return newAv;
         }
@@ -379,7 +439,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
                         ((BulletXCharacter) actor).RigidBody.ActivationState = ActivationState.DisableSimulation;
                         AddForgottenRigidBody(((BulletXCharacter) actor).RigidBody);
                     }
-                    _characters.Remove((BulletXCharacter) actor);
+                    _characters.Remove(((BulletXCharacter)actor).RigidBody);
                 }
                 GC.Collect();
             }
@@ -405,7 +465,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
                     }
                     else
                     {
-                        Mesh mesh = null;
+                        IMesh mesh = mesher.CreateMesh(primName, pbs, size);
                         result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
                     }
                     break;
@@ -419,13 +479,13 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         }
 
         public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation,
-                                    Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
+                                    IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
         {
             BulletXPrim newPrim = null;
             lock (BulletXLock)
             {
                 newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs, isPhysical);
-                _prims.Add(newPrim);
+                _prims.Add(newPrim.RigidBody, newPrim);
             }
             return newPrim;
         }
@@ -446,7 +506,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
                         ((BulletXPrim) prim).RigidBody.ActivationState = ActivationState.DisableSimulation;
                         AddForgottenRigidBody(((BulletXPrim) prim).RigidBody);
                     }
-                    _prims.Remove((BulletXPrim) prim);
+                    _prims.Remove(((BulletXPrim) prim).RigidBody);
                 }
                 GC.Collect();
             }
@@ -470,11 +530,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
 
         private void MoveAllObjects(float timeStep)
         {
-            foreach (BulletXCharacter actor in _characters)
+            foreach (BulletXCharacter actor in _characters.Values)
             {
                 actor.Move(timeStep);
             }
-            foreach (BulletXPrim prim in _prims)
+            foreach (BulletXPrim prim in _prims.Values)
             {
             }
         }
@@ -482,14 +542,14 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         private void ValidateHeightForAll()
         {
             float _height;
-            foreach (BulletXCharacter actor in _characters)
+            foreach (BulletXCharacter actor in _characters.Values)
             {
                 //_height = HeightValue(actor.RigidBodyPosition);
                 _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition);
                 actor.ValidateHeight(_height);
                 //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height);
             }
-            foreach (BulletXPrim prim in _prims)
+            foreach (BulletXPrim prim in _prims.Values)
             {
                 //_height = HeightValue(prim.RigidBodyPosition); 
                 _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition);
@@ -510,11 +570,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         {
             //UpdatePosition > UpdateKinetics.
             //Not only position will be updated, also velocity cause acceleration.
-            foreach (BulletXCharacter actor in _characters)
+            foreach (BulletXCharacter actor in _characters.Values)
             {
                 actor.UpdateKinetics();
             }
-            foreach (BulletXPrim prim in _prims)
+            foreach (BulletXPrim prim in _prims.Values)
             {
                 prim.UpdateKinetics();
             }
@@ -646,9 +706,11 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         protected PhysicsVector m_rotationalVelocity = PhysicsVector.Zero;
         protected RigidBody rigidBody;
         private Boolean iscolliding = false;
+        internal string _name;
 
-        public BulletXActor()
+        public BulletXActor(String name)
         {
+            _name = name;
         }
 
         public override PhysicsVector Position
@@ -847,6 +909,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         }
         public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity,
                                 PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation)
+            : base(avName)
         {
             //This fields will be removed. They're temporal
             float _sizeX = 0.5f;
@@ -1016,14 +1079,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         private bool m_lastUpdateSent = false;
 
         public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size,
-                           AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
+                           AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool isPhysical)
             : this(primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs, isPhysical)
         {
         }
         public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity,
                            PhysicsVector size,
-                           PhysicsVector acceleration, AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, 
+                           PhysicsVector acceleration, AxiomQuaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, 
                            bool isPhysical)
+            : base(primName)
         {
             if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0");
             if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity;
@@ -1037,7 +1101,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
 
             _parent_scene = parent_scene;
 
-            CreateRigidBody(parent_scene, pos, size);
+            CreateRigidBody(parent_scene, mesh, pos, size);
         }
 
         public override PhysicsVector Position
@@ -1191,7 +1255,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
         }
 
         #region Methods for updating values of RigidBody
-        internal protected void CreateRigidBody(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size)
+        internal protected void CreateRigidBody(BulletXScene parent_scene, IMesh mesh, PhysicsVector pos, PhysicsVector size)
         {
             //For RigidBody Constructor. The next values might change
             float _linearDamping = 0.0f;
@@ -1204,7 +1268,26 @@ namespace OpenSim.Region.Physics.BulletXPlugin
             {
                 _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
                 //For now all prims are boxes
-                CollisionShape _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f);
+                CollisionShape _collisionShape;
+                if (mesh == null)
+                {
+                    _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(size) / 2.0f);
+                } else {
+                    int iVertexCount = mesh.getVertexList().Count;
+                    int[] indices = mesh.getIndexListAsInt();
+                    Vector3[] v3Vertices = new Vector3[iVertexCount];
+                    for (int i = 0; i < iVertexCount; i++)
+                    {
+                        PhysicsVector v=mesh.getVertexList()[i];
+                        if (v != null) // Note, null has special meaning. See meshing code for details
+                            v3Vertices[i] = BulletXMaths.PhysicsVectorToXnaVector3(v);
+                        else
+                            v3Vertices[i] = MonoXnaCompactMaths.Vector3.Zero;
+                    }
+                    TriangleIndexVertexArray triMesh = new TriangleIndexVertexArray(indices, v3Vertices);
+
+                    _collisionShape = new XnaDevRu.BulletX.TriangleMeshShape(triMesh);
+                }
                 DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
                 Vector3 _localInertia = new Vector3();
                 if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0
@@ -1231,7 +1314,7 @@ namespace OpenSim.Region.Physics.BulletXPlugin
                 rigidBody.ActivationState = ActivationState.DisableSimulation;
                 this._parent_scene.AddForgottenRigidBody(rigidBody);
             }
-            CreateRigidBody(this._parent_scene, this._position, size);
+            CreateRigidBody(this._parent_scene, null, this._position, size); // Note, null for the meshing definitely is wrong. It's here for the moment to apease the compiler
             if (_physical) Speed();//Static objects don't have linear velocity
             ReOrient();
             GC.Collect();
diff --git a/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
new file mode 100644
index 0000000..fb30296
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletXPlugin/TriangleIndexVertexArray.cs
@@ -0,0 +1,161 @@
+/*
+  Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
+  Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ 
+ This file contains a class TriangleIndexVertexArray. I tried using the class with the same name 
+ from the BulletX implementation and found it unusable for the purpose of using triangle meshes 
+ within BulletX as the implementation was painfully incomplete.
+ The attempt to derive from the original class failed as viable members were hidden.
+ Fiddling around with BulletX itself was not my intention.
+ So I copied the class to the BulletX-plugin and modified it.
+ If you want to fiddle around with it it's up to you to move all this to BulletX.
+ If someone someday implements the missing functionality in BulletX, feel free to remove this class.
+ It's just an ugly hack.
+ 
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+using MonoXnaCompactMaths;
+
+namespace OpenSim.Region.Physics.BulletXPlugin
+{
+    /// <summary>
+    /// IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements
+    /// instead of the number of indices, we pass the number of triangles
+    /// </summary>
+    public struct IndexedMesh
+    {
+        private int _numTriangles;
+        private int[] _triangleIndexBase;
+        private int _triangleIndexStride;
+        private int _numVertices;
+        private Vector3[] _vertexBase;
+        private int _vertexStride;
+
+        public IndexedMesh(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
+        {
+            _numTriangles = numTriangleIndices;
+            _triangleIndexBase = triangleIndexBase;
+            _triangleIndexStride = triangleIndexStride;
+            _vertexBase = vertexBase;
+            _numVertices = numVertices;
+            _vertexStride = vertexStride;
+        }
+
+        public IndexedMesh(int[] triangleIndexBase, Vector3[] vertexBase)
+        {
+            _numTriangles = triangleIndexBase.Length;
+            _triangleIndexBase = triangleIndexBase;
+            _triangleIndexStride = 32;
+            _vertexBase = vertexBase;
+            _numVertices = vertexBase.Length;
+            _vertexStride = 24;
+        }
+
+        public int TriangleCount { get { return _numTriangles; } set { _numTriangles = value; } }
+        public int[] TriangleIndexBase { get { return _triangleIndexBase; } set { _triangleIndexBase = value; } }
+        public int TriangleIndexStride { get { return _triangleIndexStride; } set { _triangleIndexStride = value; } }
+        public int VertexCount { get { return _numVertices; } set { _numVertices = value; } }
+        public Vector3[] VertexBase { get { return _vertexBase; } set { _vertexBase = value; } }
+        public int VertexStride { get { return _vertexStride; } set { _vertexStride = value; } }
+    }
+
+    /// <summary>
+    /// TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
+    /// Additional meshes can be added using addIndexedMesh
+    /// </summary>
+    public class TriangleIndexVertexArray : XnaDevRu.BulletX.StridingMeshInterface
+    {
+        List<IndexedMesh> _indexedMeshes = new List<IndexedMesh>();
+
+        public TriangleIndexVertexArray() { }
+
+        public TriangleIndexVertexArray(int numTriangleIndices, int[] triangleIndexBase, int triangleIndexStride, int numVertices, Vector3[] vertexBase, int vertexStride)
+        {
+            IndexedMesh mesh = new IndexedMesh();
+            mesh.TriangleCount = numTriangleIndices;
+            mesh.TriangleIndexBase = triangleIndexBase;
+            mesh.TriangleIndexStride = triangleIndexStride;
+            mesh.VertexBase = vertexBase;
+            mesh.VertexCount = numVertices;
+            mesh.VertexStride = vertexStride;
+
+            AddIndexedMesh(mesh);
+        }
+
+        public TriangleIndexVertexArray(int[] triangleIndexBase, Vector3[] vertexBase)
+            : this(triangleIndexBase.Length, triangleIndexBase, 32, vertexBase.Length, vertexBase, 24) { }
+
+        public void AddIndexedMesh(IndexedMesh indexedMesh)
+        {
+            _indexedMeshes.Add(indexedMesh);
+        }
+
+        public override void GetLockedVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public override void GetLockedReadOnlyVertexIndexBase(out List<Vector3> verts, out List<int> indicies, out int numfaces, int subpart)
+        {
+            IndexedMesh m = _indexedMeshes[0];
+            Vector3[] vertexBase = m.VertexBase;
+            verts = new List<Vector3>();
+            foreach (Vector3 v in vertexBase)
+            {
+                verts.Add(v);
+            }
+            int[] indexBase = m.TriangleIndexBase;
+            indicies = new List<int>();
+            foreach (int i in indexBase)
+            {
+                indicies.Add(i);
+            }
+            numfaces = vertexBase.GetLength(0);
+        }
+
+        public override void UnLockVertexBase(int subpart)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public override void UnLockReadOnlyVertexBase(int subpart)
+        {
+        }
+
+        public override int SubPartsCount()
+        {
+            return _indexedMeshes.Count;
+        }
+
+        public override void PreallocateVertices(int numverts)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+
+        public override void PreallocateIndices(int numindices)
+        {
+            throw new Exception("The method or operation is not implemented.");
+        }
+    }
+}
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs
new file mode 100644
index 0000000..037616c
--- /dev/null
+++ b/OpenSim/Region/Physics/Manager/IMesher.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenSim.Framework;
+
+namespace OpenSim.Region.Physics.Manager
+{
+    public interface IMesher
+    {
+        IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size);
+    }
+
+    public interface IVertex {
+    }
+
+    public interface IMesh
+    {
+        List<PhysicsVector> getVertexList();
+        int[] getIndexListAsInt();
+        int[] getIndexListAsIntLocked();
+        float[] getVertexListAsFloatLocked();
+
+
+    }
+}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
index 09ebf29..47c8ae0 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
 using OpenSim.Framework.Console;
+using Nini.Config;
 
 namespace OpenSim.Region.Physics.Manager
 {
@@ -38,28 +39,50 @@ namespace OpenSim.Region.Physics.Manager
     /// </summary>
     public class PhysicsPluginManager
     {
-        private Dictionary<string, IPhysicsPlugin> _plugins = new Dictionary<string, IPhysicsPlugin>();
+        private Dictionary<string, IPhysicsPlugin> _PhysPlugins = new Dictionary<string, IPhysicsPlugin>();
+        private Dictionary<string, IMeshingPlugin> _MeshPlugins = new Dictionary<string, IMeshingPlugin>();
 
         public PhysicsPluginManager()
         {
         }
 
-        public PhysicsScene GetPhysicsScene(string engineName)
+        public PhysicsScene GetPhysicsScene(string physEngineName, string meshEngineName)
         {
-            if (String.IsNullOrEmpty(engineName))
+
+            if (String.IsNullOrEmpty(physEngineName))
+            {
+                return PhysicsScene.Null;
+            }
+
+            if (String.IsNullOrEmpty(meshEngineName))
             {
                 return PhysicsScene.Null;
             }
 
-            if (_plugins.ContainsKey(engineName))
+
+            IMesher meshEngine = null;
+            if (_MeshPlugins.ContainsKey(meshEngineName))
             {
-                MainLog.Instance.Verbose("PHYSICS", "creating " + engineName);
-                return _plugins[engineName].GetScene();
+                MainLog.Instance.Verbose("PHYSICS", "creating meshing engine " + meshEngineName);
+                meshEngine = _MeshPlugins[meshEngineName].GetMesher();
             }
             else
             {
-                MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", engineName);
-                throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", engineName));
+                MainLog.Instance.Warn("PHYSICS", "couldn't find meshingEngine: {0}", meshEngineName);
+                throw new ArgumentException(String.Format("couldn't find meshingEngine: {0}", meshEngineName));
+            }
+
+            if (_PhysPlugins.ContainsKey(physEngineName))
+            {
+                MainLog.Instance.Verbose("PHYSICS", "creating " + physEngineName);
+                PhysicsScene result = _PhysPlugins[physEngineName].GetScene();
+                result.Initialise(meshEngine);
+                return result;
+            }
+            else
+            {
+                MainLog.Instance.Warn("PHYSICS", "couldn't find physicsEngine: {0}", physEngineName);
+                throw new ArgumentException(String.Format("couldn't find physicsEngine: {0}", physEngineName));
             }
         }
 
@@ -85,18 +108,29 @@ namespace OpenSim.Region.Physics.Manager
                 {
                     if (!pluginType.IsAbstract)
                     {
-                        Type typeInterface = pluginType.GetInterface("IPhysicsPlugin", true);
+                        Type physTypeInterface = pluginType.GetInterface("IPhysicsPlugin", true);
 
-                        if (typeInterface != null)
+                        if (physTypeInterface != null)
                         {
                             IPhysicsPlugin plug =
                                 (IPhysicsPlugin) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
                             plug.Init();
-                            _plugins.Add(plug.GetName(), plug);
+                            _PhysPlugins.Add(plug.GetName(), plug);
                             MainLog.Instance.Verbose("PHYSICS", "Added physics engine: " + plug.GetName());
                         }
 
-                        typeInterface = null;
+                        Type meshTypeInterface = pluginType.GetInterface("IMeshingPlugin", true);
+
+                        if (meshTypeInterface != null)
+                        {
+                            IMeshingPlugin plug =
+                                (IMeshingPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
+                            _MeshPlugins.Add(plug.GetName(), plug);
+                            MainLog.Instance.Verbose("PHYSICS", "Added meshing engine: " + plug.GetName());
+                        }
+
+                        physTypeInterface = null;
+                        meshTypeInterface = null;
                     }
                 }
             }
@@ -127,4 +161,11 @@ namespace OpenSim.Region.Physics.Manager
         string GetName();
         void Dispose();
     }
-}
\ No newline at end of file
+
+    public interface IMeshingPlugin
+    {
+        string GetName();
+        IMesher GetMesher();
+    }
+
+}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 13591ea..6f19e72 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -28,6 +28,7 @@
 using Axiom.Math;
 using OpenSim.Framework;
 using OpenSim.Framework.Console;
+using OpenSim.Region.Physics.Manager;
 
 namespace OpenSim.Region.Physics.Manager
 {
@@ -38,6 +39,8 @@ namespace OpenSim.Region.Physics.Manager
             get { return new NullPhysicsScene(); }
         }
 
+        public abstract void Initialise(IMesher meshmerizer);
+
         public abstract PhysicsActor AddAvatar(string avName, PhysicsVector position);
 
         public abstract void RemoveAvatar(PhysicsActor actor);
@@ -63,6 +66,12 @@ namespace OpenSim.Region.Physics.Manager
         {
             private static int m_workIndicator;
 
+
+            public override void Initialise(IMesher meshmerizer)
+            {
+                // Does nothing right now
+            }
+
             public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
             {
                 MainLog.Instance.Verbose("NullPhysicsScene : AddAvatar({0})", position);
@@ -123,4 +132,4 @@ namespace OpenSim.Region.Physics.Manager
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Physics/Meshing/Extruder.cs b/OpenSim/Region/Physics/Meshing/Extruder.cs
new file mode 100644
index 0000000..63d727f
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/Extruder.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenSim.Region.Physics.Meshing
+{
+    class Extruder
+    {
+        public float startParameter;
+        public float stopParameter;
+        public Manager.PhysicsVector size;
+
+        public Mesh Extrude(Mesh m)
+        {
+            // Currently only works for iSteps=1;
+            Mesh result = new Mesh();
+
+            Mesh workingPlus  = m.Clone();
+            Mesh workingMinus = m.Clone();
+
+            foreach (Vertex v in workingPlus.vertices)
+            {
+                if (v == null)
+                    continue;
+
+                v.Z = +.5f;
+                v.X *= size.X;
+                v.Y *= size.Y;
+                v.Z *= size.Z;
+            }
+
+            foreach (Vertex v in workingMinus.vertices)
+            {
+                if (v == null)
+                    continue;
+
+                v.Z = -.5f;
+                v.X *= size.X;
+                v.Y *= size.Y;
+                v.Z *= size.Z;
+            }
+
+            foreach (Triangle t in workingMinus.triangles)
+            {
+                t.invertNormal();
+            }
+
+            result.Append(workingMinus);
+            result.Append(workingPlus);
+
+            int iLastNull = 0;
+            for (int i = 0; i < workingPlus.vertices.Count; i++)
+            {
+                int iNext = (i + 1);
+                
+                if (workingPlus.vertices[i] == null) // Can't make a simplex here
+                {
+                    iLastNull = i+1;
+                    continue;
+                }
+
+                if (i == workingPlus.vertices.Count-1) // End of list
+                {
+                    iNext = iLastNull;
+                }
+
+                if (workingPlus.vertices[iNext] == null) // Null means wrap to begin of last segment
+                {
+                    iNext = iLastNull;
+                }
+
+                Triangle tSide;
+                tSide = new Triangle(workingPlus.vertices[i], workingMinus.vertices[i], workingPlus.vertices[iNext]);
+                result.Add(tSide);
+
+                tSide = new Triangle(workingPlus.vertices[iNext], workingMinus.vertices[i], workingMinus.vertices[iNext]);
+                result.Add(tSide);
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/OpenSim/Region/Physics/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/Meshing/HelperTypes.cs
new file mode 100644
index 0000000..9e75826
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/HelperTypes.cs
@@ -0,0 +1,306 @@
+/*
+* Copyright (c) Contributors, http://opensimulator.org/
+* See CONTRIBUTORS.TXT for a full list of copyright holders.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the OpenSim Project nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* 
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using OpenSim.Framework.Console;
+using OpenSim.Region.Physics.Manager;
+
+using OpenSim.Region.Physics.Meshing;
+
+public class Vertex : PhysicsVector, IComparable<Vertex>
+{
+    public Vertex(float x, float y, float z)
+        : base(x, y, z)
+    {
+    }
+
+    public Vertex(PhysicsVector v)
+        : base(v.X, v.Y, v.Z)
+    {
+    }
+
+    public Vertex Clone()
+    {
+        return new Vertex(X, Y, Z);
+    }
+
+    public static Vertex FromAngle(double angle)
+    {
+        return new Vertex((float)Math.Cos(angle), (float)Math.Sin(angle), 0.0f);
+    }
+
+
+    public virtual bool Equals(Vertex v, float tolerance)
+    {
+        PhysicsVector diff = this - v;
+        float d = diff.length();
+        if (d < tolerance)
+            return true;
+
+        return false;
+    }
+
+
+    public int CompareTo(Vertex other)
+    {
+        if (X < other.X)
+            return -1;
+
+        if (X > other.X)
+            return 1;
+
+        if (Y < other.Y)
+            return -1;
+
+        if (Y > other.Y)
+            return 1;
+
+        if (Z < other.Z)
+            return -1;
+
+        if (Z > other.Z)
+            return 1;
+
+        return 0;
+    }
+
+    public static bool operator >(Vertex me, Vertex other)
+    {
+        return me.CompareTo(other) > 0;
+    }
+
+    public static bool operator <(Vertex me, Vertex other)
+    {
+        return me.CompareTo(other) < 0;
+    }
+    public String ToRaw()
+    {
+        // Why this stuff with the number formatter?
+        // Well, the raw format uses the english/US notation of numbers
+        // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
+        // The german notation uses these characters exactly vice versa!
+        // The Float.ToString() routine is a localized one, giving different results depending on the country
+        // settings your machine works with. Unusable for a machine readable file format :-(
+        NumberFormatInfo nfi = new NumberFormatInfo();
+        nfi.NumberDecimalSeparator = ".";
+        nfi.NumberDecimalDigits = 3;
+
+        String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
+
+        return s1;
+    }
+
+}
+
+public class Triangle
+{
+    public Vertex v1;
+    public Vertex v2;
+    public Vertex v3;
+
+    private float radius_square;
+    private float cx;
+    private float cy;
+
+    public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
+    {
+        v1 = _v1;
+        v2 = _v2;
+        v3 = _v3;
+
+        CalcCircle();
+    }
+
+    public bool isInCircle(float x, float y)
+    {
+        float dx, dy;
+        float dd;
+
+        dx = x - cx;
+        dy = y - cy;
+
+        dd = dx*dx + dy*dy;
+        if (dd < radius_square)
+            return true;
+        else
+            return false;
+    }
+
+    public bool isDegraded()
+    {
+        // This means, the vertices of this triangle are somewhat strange.
+        // They either line up or at least two of them are identical
+        return (radius_square == 0.0);
+    }
+
+    private void CalcCircle()
+    {
+        // Calculate the center and the radius of a circle given by three points p1, p2, p3
+        // It is assumed, that the triangles vertices are already set correctly
+        double p1x, p2x, p1y, p2y, p3x, p3y;
+
+        // Deviation of this routine: 
+        // A circle has the general equation (M-p)^2=r^2, where M and p are vectors
+        // this gives us three equations f(p)=r^2, each for one point p1, p2, p3
+        // putting respectively two equations together gives two equations
+        // f(p1)=f(p2) and f(p1)=f(p3)
+        // bringing all constant terms to one side brings them to the form
+        // M*v1=c1 resp.M*v2=c2 where v1=(p1-p2) and v2=(p1-p3) (still vectors)
+        // and c1, c2 are scalars (Naming conventions like the variables below)
+        // Now using the equations that are formed by the components of the vectors
+        // and isolate Mx lets you make one equation that only holds My
+        // The rest is straight forward and eaasy :-)
+        // 
+
+        /* helping variables for temporary results */
+        double c1, c2;
+        double v1x, v1y, v2x, v2y;
+
+        double z, n;
+
+        double rx, ry;
+
+        // Readout the three points, the triangle consists of
+        p1x = v1.X;
+        p1y = v1.Y;
+
+        p2x = v2.X;
+        p2y = v2.Y;
+
+        p3x = v3.X;
+        p3y = v3.Y;
+
+        /* calc helping values first */
+        c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
+        c2 = (p1x*p1x + p1y*p1y - p3x*p3x - p3y*p3y)/2;
+
+        v1x = p1x - p2x;
+        v1y = p1y - p2y;
+
+        v2x = p1x - p3x;
+        v2y = p1y - p3y;
+
+        z = (c1*v2x - c2*v1x);
+        n = (v1y*v2x - v2y*v1x);
+
+        if (n == 0.0) // This is no triangle, i.e there are (at least) two points at the same location
+        {
+            radius_square = 0.0f;
+            return;
+        }
+
+        cy = (float) (z/n);
+
+        if (v2x != 0.0)
+        {
+            cx = (float) ((c2 - v2y*cy)/v2x);
+        }
+        else if (v1x != 0.0)
+        {
+            cx = (float) ((c1 - v1y*cy)/v1x);
+        }
+        else
+        {
+            Debug.Assert(false, "Malformed triangle"); /* Both terms zero means nothing good */
+        }
+
+        rx = (p1x - cx);
+        ry = (p1y - cy);
+
+        radius_square = (float) (rx*rx + ry*ry);
+    }
+
+    public List<Simplex> GetSimplices()
+    {
+        List<Simplex> result = new List<Simplex>();
+        Simplex s1 = new Simplex(v1, v2);
+        Simplex s2 = new Simplex(v2, v3);
+        Simplex s3 = new Simplex(v3, v1);
+
+        result.Add(s1);
+        result.Add(s2);
+        result.Add(s3);
+
+        return result;
+    }
+
+    public override String ToString()
+    {
+        NumberFormatInfo nfi = new NumberFormatInfo();
+        nfi.CurrencyDecimalDigits = 2;
+        nfi.CurrencyDecimalSeparator = ".";
+
+        String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
+        String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
+        String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
+
+        return s1 + ";" + s2 + ";" + s3;
+    }
+
+    public PhysicsVector getNormal()
+    {
+        // Vertices
+
+        // Vectors for edges
+        PhysicsVector e1;
+        PhysicsVector e2;
+
+        e1 = new PhysicsVector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
+        e2 = new PhysicsVector(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
+
+        // Cross product for normal
+        PhysicsVector n = PhysicsVector.cross(e1, e2);
+
+        // Length
+        float l = n.length();
+
+        // Normalized "normal"
+        n = n / l;
+
+        return n;
+    }
+
+    public void invertNormal()
+    {
+        Vertex vt;
+        vt = v1;
+        v1 = v2;
+        v2 = vt;
+    }
+
+    // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and 
+    // debugging purposes
+    public String ToStringRaw()
+    {
+        String output = v1.ToRaw() + " " + v2.ToRaw() + " " +v3.ToRaw();
+        return output;
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs
new file mode 100644
index 0000000..fd4ce4e
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/Mesh.cs
@@ -0,0 +1,213 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Text;
+
+using System.Runtime.InteropServices;
+
+
+using OpenSim.Region.Physics.Manager;
+
+namespace OpenSim.Region.Physics.Meshing
+{
+    public class Mesh : IMesh
+    {
+        public List<Vertex> vertices;
+        public List<Triangle> triangles;
+
+        public float[] normals;
+
+        public Mesh()
+        {
+            vertices = new List<Vertex>();
+            triangles = new List<Triangle>();
+        }
+
+        public Mesh Clone()
+        {
+            Mesh result = new Mesh();
+
+            foreach (Vertex v in vertices)
+            {
+                if (v == null)
+                    result.vertices.Add(null);
+                else
+                    result.vertices.Add(v.Clone());
+            }
+
+            foreach (Triangle t in triangles)
+            {
+                int iV1, iV2, iV3;
+                iV1 = this.vertices.IndexOf(t.v1);
+                iV2 = this.vertices.IndexOf(t.v2);
+                iV3 = this.vertices.IndexOf(t.v3);
+
+                Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]);
+                result.Add(newT);
+            }
+
+            return result;
+        }
+
+        
+        
+        public void Add(Triangle triangle)
+        {
+            int i;
+            i = vertices.IndexOf(triangle.v1);
+            if (i < 0)
+                throw new ArgumentException("Vertex v1 not known to mesh");
+            i = vertices.IndexOf(triangle.v2);
+            if (i < 0)
+                throw new ArgumentException("Vertex v2 not known to mesh");
+            i = vertices.IndexOf(triangle.v3);
+            if (i < 0)
+                throw new ArgumentException("Vertex v3 not known to mesh");
+
+            triangles.Add(triangle);
+        }
+
+        public void Add(Vertex v)
+        {
+            vertices.Add(v);
+        }
+
+        public void Remove(Vertex v)
+        {
+            int i;
+
+            // First, remove all triangles that are build on v
+            for (i = 0; i < triangles.Count; i++)
+            {
+                Triangle t = triangles[i];
+                if (t.v1 == v || t.v2 == v || t.v3 == v)
+                {
+                    triangles.RemoveAt(i);
+                    i--;
+                }
+            }
+
+            // Second remove v itself
+            vertices.Remove(v);
+        }
+
+        public void RemoveTrianglesOutside(SimpleHull hull)
+        {
+            int i;
+
+            for (i = 0; i < triangles.Count; i++)
+            {
+                Triangle t = triangles[i];
+                Vertex v1 = t.v1;
+                Vertex v2 = t.v2;
+                Vertex v3 = t.v3;
+                PhysicsVector m = v1 + v2 + v3;
+                m /= 3.0f;
+                if (!hull.IsPointIn(new Vertex(m)))
+                {
+                    triangles.RemoveAt(i);
+                    i--;
+                }
+            }
+        }
+
+
+        public void Add(List<Vertex> lv)
+        {
+            foreach (Vertex v in lv)
+            {
+                vertices.Add(v);
+            }
+        }
+
+        public List<PhysicsVector> getVertexList()
+        {
+            List<PhysicsVector> result = new List<PhysicsVector>();
+            foreach (Vertex v in vertices)
+            {
+                result.Add(v);
+            }
+            return result;
+        }
+
+        public float[] getVertexListAsFloatLocked()
+        {
+            float[] result = new float[vertices.Count * 3];
+            for (int i = 0; i < vertices.Count; i++)
+            {
+                Vertex v = vertices[i];
+                if (v == null)
+                    continue;
+                result[3 * i + 0] = v.X;
+                result[3 * i + 1] = v.Y;
+                result[3 * i + 2] = v.Z;
+            }
+            GCHandle.Alloc(result, GCHandleType.Pinned);
+            return result;
+        }
+
+        public int[] getIndexListAsInt()
+        {
+            int[] result = new int[triangles.Count * 3];
+            for (int i = 0; i < triangles.Count; i++)
+            {
+                Triangle t = triangles[i];
+                result[3 * i + 0] = vertices.IndexOf(t.v1);
+                result[3 * i + 1] = vertices.IndexOf(t.v2);
+                result[3 * i + 2] = vertices.IndexOf(t.v3);
+            }
+            return result;
+        }
+
+        public int[] getIndexListAsIntLocked()
+        {
+            int[] result = getIndexListAsInt();
+            GCHandle.Alloc(result, GCHandleType.Pinned);
+            return result;
+        }
+
+
+        public void Append(Mesh newMesh)
+        {
+            foreach (Vertex v in newMesh.vertices)
+                vertices.Add(v);
+
+            foreach (Triangle t in newMesh.triangles)
+                Add(t);
+
+        }
+
+        // Do a linear transformation of  mesh.
+        public void TransformLinear(float[,] matrix, float[] offset)
+        {
+            foreach (Vertex v in vertices)
+            {
+                if (v == null)
+                    continue;
+                float x, y, z;
+                x = v.X * matrix[0, 0] + v.Y * matrix[1, 0] + v.Z * matrix[2, 0];
+                y = v.X * matrix[0, 1] + v.Y * matrix[1, 1] + v.Z * matrix[2, 1];
+                z = v.X * matrix[0, 2] + v.Y * matrix[1, 2] + v.Z * matrix[2, 2];
+                v.X = x + offset[0];
+                v.Y = y + offset[1];
+                v.Z = z + offset[2];
+            }
+        }
+
+        public void DumpRaw(String path, String name, String title)
+        {
+            if (path == null)
+                return;
+            String fileName = name + "_" + title + ".raw";
+            String completePath = Path.Combine(path, fileName);
+            StreamWriter sw = new StreamWriter(completePath);
+            foreach (Triangle t in triangles)
+            {
+                String s = t.ToStringRaw();
+                sw.WriteLine(s);
+            }
+            sw.Close();
+        }
+    }
+
+}
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
new file mode 100644
index 0000000..da4ee58
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -0,0 +1,393 @@
+/*
+* Copyright (c) Contributors, http://opensimulator.org/
+* See CONTRIBUTORS.TXT for a full list of copyright holders.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the OpenSim Project nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+* 
+*/
+
+using System;
+using System.IO;
+using System.Globalization;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using OpenSim.Framework;
+using OpenSim.Framework.Console;
+using OpenSim.Region.Physics.Manager;
+
+namespace OpenSim.Region.Physics.Meshing
+{
+
+    public class MeshmerizerPlugin : IMeshingPlugin
+    {
+        public MeshmerizerPlugin()
+        {
+        }
+
+        public string GetName()
+        {
+            return "Meshmerizer";
+        }
+
+        public IMesher GetMesher()
+        {
+            return new Meshmerizer();
+        }
+    }
+
+    public class Meshmerizer : IMesher
+    {
+        // 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
+        //        const string baseDir = "rawFiles";
+                const string baseDir = null;
+
+        static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
+        { 
+            // p1, p2, points on the straight
+            // r1, r2, directional vectors of the straight. Not necessarily of length 1!
+            // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
+            // thus allowing to decide whether an intersection is between two points
+
+            float r1x = r1.X;
+            float r1y = r1.Y;
+            float r2x = r2.X;
+            float r2y = r2.Y;
+
+            float denom = r1y*r2x - r1x*r2y;
+
+            if (denom == 0.0)
+            {
+                lambda = Single.NaN;
+                mu = Single.NaN;
+                return;
+            }
+
+            float p1x = p1.X;
+            float p1y = p1.Y;
+            float p2x = p2.X;
+            float p2y = p2.Y;
+            lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
+            mu     = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
+        
+        }
+
+        private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
+        {
+            List<Triangle> influenced = new List<Triangle>();
+            foreach (Triangle t in triangles)
+            {
+                if (t.isInCircle(v.X, v.Y))
+                {
+                    influenced.Add(t);
+                }
+            }
+            return influenced;
+        }
+        
+        
+        private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
+        {
+            // This is a variant of the delaunay algorithm
+            // each time a new vertex is inserted, all triangles that are influenced by it are deleted
+            // and replaced by new ones including the new vertex
+            // It is not very time efficient but easy to implement.
+
+            int iCurrentVertex;
+            int iMaxVertex = vertices.Count;
+            for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
+            {
+                // Background: A triangle mesh fulfills the delaunay condition if (iff!)
+                // each circumlocutory circle (i.e. the circle that touches all three corners) 
+                // of each triangle is empty of other vertices.
+                // Obviously a single (seeding) triangle fulfills this condition.
+                // If we now add one vertex, we need to reconstruct all triangles, that
+                // do not fulfill this condition with respect to the new triangle
+
+                // Find the triangles that are influenced by the new vertex
+                Vertex v=vertices[iCurrentVertex];
+                if (v == null)
+                    continue;   // Null is polygon stop marker. Ignore it
+                List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
+
+                List<Simplex> simplices = new List<Simplex>();
+
+                // Reconstruction phase. First step, dissolve each triangle into it's simplices,
+                // i.e. it's "border lines"
+                // Goal is to find "inner" borders and delete them, while the hull gets conserved.
+                // Inner borders are special in the way that they always come twice, which is how we detect them 
+                foreach (Triangle t in influencedTriangles)
+                {
+                    List<Simplex> newSimplices = t.GetSimplices();
+                    simplices.AddRange(newSimplices);
+                    triangles.Remove(t);
+                }
+                // Now sort the simplices. That will make identical ones reside side by side in the list
+                simplices.Sort();
+
+                // Look for duplicate simplices here. 
+                // Remember, they are directly side by side in the list right now, 
+                // So we only check directly neighbours
+                int iSimplex;
+                List<Simplex> innerSimplices = new List<Simplex>();
+                for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
+                {
+                    if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
+                    {
+                        innerSimplices.Add(simplices[iSimplex - 1]);
+                        innerSimplices.Add(simplices[iSimplex]);
+                    }
+                }
+
+                foreach (Simplex s in innerSimplices)
+                {
+                    simplices.Remove(s);
+                }
+
+                // each simplex still in the list belongs to the hull of the region in question
+                // The new vertex (yes, we still deal with verices here :-) ) forms a triangle 
+                // with each of these simplices. Build the new triangles and add them to the list
+                foreach (Simplex s in simplices)
+                {
+                    Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
+                    if (!t.isDegraded())
+                    {
+                        triangles.Add(t);
+                    }
+                }
+            }
+
+        }
+
+            
+        static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
+        // Builds the z (+ and -) surfaces of a box shaped prim
+        {
+            UInt16 hollowFactor = primShape.ProfileHollow;
+            UInt16 profileBegin = primShape.ProfileBegin;
+            UInt16 profileEnd = primShape.ProfileEnd;
+
+            // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
+            // of a block are basically the same
+            // They may be warped differently but the shape is identical
+            // So we only create one surface as a model and derive both plus and minus surface of the block from it
+            // This is done in a model space where the block spans from -.5 to +.5 in X and Y
+            // The mapping to Scene space is done later during the "extrusion" phase
+
+            // Base
+            Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
+            Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
+            Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
+            Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
+
+            Meshing.SimpleHull outerHull = new SimpleHull();
+            outerHull.AddVertex(MM);
+            outerHull.AddVertex(PM);
+            outerHull.AddVertex(PP);
+            outerHull.AddVertex(MP);
+
+            // Deal with cuts now
+            if ((profileBegin != 0) || (profileEnd != 0))
+            {
+                double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
+                fProfileBeginAngle -= (90.0 + 45.0);   // for some reasons, the SL client counts from the corner -X/-Y
+                double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
+                fProfileEndAngle -= (90.0 + 45.0);
+                if (fProfileBeginAngle < fProfileEndAngle)
+                    fProfileEndAngle -= 360.0;
+
+                // Note, that we don't want to cut out a triangle, even if this is a 
+                // good approximation for small cuts. Indeed we want to cut out an arc
+                // and we approximate this arc by a polygon chain
+                // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
+                // So it can easily be subtracted from the outer hull
+                int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
+                double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
+
+                Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
+
+                // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
+                SimpleHull cutHull = new SimpleHull();
+                cutHull.AddVertex(origin);
+                for (int i=0; i<iSteps; i++) {
+                    double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
+                    Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
+                    cutHull.AddVertex(v);
+                }
+                Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
+                cutHull.AddVertex(legEnd);
+
+                MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
+                SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
+
+                outerHull = cuttedHull;
+            }
+
+            // Deal with the hole here
+            if (hollowFactor > 0)
+            {
+                float hollowFactorF = (float) hollowFactor/(float) 50000;
+                Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
+                Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
+                Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
+                Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
+
+                SimpleHull holeHull = new SimpleHull();
+
+                holeHull.AddVertex(IMM);
+                holeHull.AddVertex(IMP);
+                holeHull.AddVertex(IPP);
+                holeHull.AddVertex(IPM);
+
+                SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
+
+                outerHull = hollowedHull;
+
+            }
+
+            Mesh m = new Mesh();
+
+            Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
+            Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
+            Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
+
+            m.Add(Seed1);
+            m.Add(Seed2);
+            m.Add(Seed3);
+
+            m.Add(new Triangle(Seed1, Seed2, Seed3));
+            m.Add(outerHull.getVertices());
+
+            InsertVertices(m.vertices, 3, m.triangles);
+            m.DumpRaw(baseDir, primName, "Proto first Mesh");
+
+            m.Remove(Seed1);
+            m.Remove(Seed2);
+            m.Remove(Seed3);
+            m.DumpRaw(baseDir, primName, "Proto seeds removed");
+            
+            m.RemoveTrianglesOutside(outerHull);
+            m.DumpRaw(baseDir, primName, "Proto outsides removed");
+
+            foreach (Triangle t in m.triangles)
+            {
+                PhysicsVector n = t.getNormal();
+                if (n.Z < 0.0)
+                    t.invertNormal();
+            }
+
+            Extruder extr = new Extruder();
+
+            extr.size = size;
+
+            Mesh result = extr.Extrude(m);
+            result.DumpRaw(baseDir, primName, "Z extruded");
+            return result;
+        }
+
+        public static void CalcNormals(Mesh mesh)
+        {
+            int iTriangles = mesh.triangles.Count;
+
+            mesh.normals = new float[iTriangles*3];
+
+            int i = 0;
+            foreach (Triangle t in mesh.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);
+
+                // Normalized "normal"
+                nx /= l;
+                ny /= l;
+                nz /= l;
+
+                mesh.normals[i] = nx;
+                mesh.normals[i + 1] = ny;
+                mesh.normals[i + 2] = nz;
+
+                i += 3;
+            }
+        }
+
+        public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
+        {
+            Mesh mesh = null;
+
+            switch (primShape.ProfileShape)
+            {
+                case ProfileShape.Square:
+                    mesh=CreateBoxMesh(primName, primShape, size);
+                    CalcNormals(mesh);
+                    break;
+                default:
+                    mesh = CreateBoxMesh(primName, primShape, size);
+                    CalcNormals(mesh);
+                    //Set default mesh to cube otherwise it'll return 
+                    // null and crash on the 'setMesh' method in the physics plugins.
+                    //mesh = null;
+                    break;
+            }
+
+            return mesh;
+        }
+    }
+
+}
diff --git a/OpenSim/Region/Physics/Meshing/SimpleHull.cs b/OpenSim/Region/Physics/Meshing/SimpleHull.cs
new file mode 100644
index 0000000..c199949
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/SimpleHull.cs
@@ -0,0 +1,363 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenSim.Framework.Console;
+
+namespace OpenSim.Region.Physics.Meshing
+{
+    // A simple hull is a set of vertices building up to simplices that border a region
+    // The word simple referes to the fact, that this class assumes, that all simplices
+    // do not intersect
+    // Simple hulls can be added and subtracted.
+    // Vertices can be checked to lie inside a hull
+    // Also note, that the sequence of the vertices is important and defines if the region that
+    // is defined by the hull lies inside or outside the simplex chain
+    public class SimpleHull
+    {
+        List<Vertex> vertices = new List<Vertex>();
+        List<Vertex> holeVertices = new List<Vertex>(); // Only used, when the hull is hollow
+
+        // Adds a vertex to the end of the list
+        public void AddVertex(Vertex v) {
+            vertices.Add(v);
+        }
+
+        override public String ToString()
+        {
+            String result="";
+            foreach (Vertex v in vertices)
+            {
+                result += "b:" + v.ToString() + "\n";
+            }
+
+            return result;
+        }
+
+
+        public List<Vertex> getVertices() {
+            List<Vertex> newVertices = new List<Vertex>();
+
+            newVertices.AddRange(vertices);
+            newVertices.Add(null);
+            newVertices.AddRange(holeVertices);
+
+            return newVertices;
+        }
+
+        public SimpleHull Clone()
+        {
+            SimpleHull result = new SimpleHull();
+            foreach (Vertex v in vertices)
+            {
+                result.AddVertex(v.Clone());
+            }
+
+            foreach (Vertex v in this.holeVertices)
+            {
+                result.holeVertices.Add(v.Clone());
+            }
+            
+            return result;
+        }
+
+        public bool IsPointIn(Vertex v1)
+        {
+            int iCounter=0;
+            List<Simplex> simplices=buildSimplexList();
+            foreach (Simplex s in simplices)
+            {
+                // Send a ray along the positive X-Direction
+                // Note, that this direction must correlate with the "below" interpretation
+                // of handling for the special cases below
+                Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true);
+
+                if (intersection == null)
+                    continue;   // No intersection. Done. More tests to follow otherwise
+
+                // Did we hit the end of a simplex?
+                // Then this can be one of two special cases:
+                // 1. we go through a border exactly at a joint
+                // 2. we have just marginally touched a corner
+                // 3. we can slide along a border
+                // Solution: If the other vertex is "below" the ray, we don't count it
+                // Thus corners pointing down are counted twice, corners pointing up are not counted
+                // borders are counted once
+                if (intersection.IsIdentical(s.v1, 0.001f)) {
+                    if (s.v2.Y < v1.Y)
+                        continue;
+                }
+                // Do this for the other vertex two
+                if (intersection.IsIdentical(s.v2, 0.001f)) {
+                    if (s.v1.Y<v1.Y)
+                        continue;
+                }
+                iCounter++;
+            }
+
+            return iCounter % 2 == 1; // Point is inside if the number of intersections is odd
+        }
+
+        public bool containsPointsFrom(SimpleHull otherHull)
+        {
+            foreach (Vertex v in otherHull.vertices)
+            {
+                if (IsPointIn(v))
+                    return true;
+            }
+
+            return false;
+        }
+
+
+        List<Simplex> buildSimplexList() {
+
+            List<Simplex> result = new List<Simplex>();
+
+            // Not asserted but assumed: at least three vertices
+            for (int i=0; i<vertices.Count-1; i++) {
+                Simplex s=new Simplex(vertices[i], vertices[i+1]);
+                result.Add(s);
+            }
+            Simplex s1=new Simplex(vertices[vertices.Count-1], vertices[0]);
+            result.Add(s1);
+
+            if (holeVertices.Count==0)
+                return result;
+
+            // Same here. At least three vertices in hole assumed
+            for (int i = 0; i < holeVertices.Count - 1; i++)
+            {
+                Simplex s = new Simplex(holeVertices[i], holeVertices[i + 1]);
+                result.Add(s);
+            }
+            
+            s1 = new Simplex(holeVertices[holeVertices.Count - 1], holeVertices[0]);
+            result.Add(s1);
+            return result;
+        }
+
+        bool InsertVertex(Vertex v, int iAfter)
+        {
+            vertices.Insert(iAfter + 1, v);
+            return true;
+        }
+
+        Vertex getNextVertex(Vertex currentVertex)
+        {
+            int iCurrentIndex;
+            iCurrentIndex = vertices.IndexOf(currentVertex);
+
+            // Error handling for iCurrentIndex==-1 should go here (and probably never will)
+
+            iCurrentIndex++;
+            if (iCurrentIndex == vertices.Count)
+                iCurrentIndex = 0;
+
+            return vertices[iCurrentIndex];
+        }
+
+        public Vertex FindVertex(Vertex vBase, float tolerance) {
+            foreach (Vertex v in vertices) {
+                if (v.IsIdentical(vBase, tolerance))
+                    return v;
+            }
+
+            return null;
+        }
+
+        public void FindIntersection(Simplex s, ref Vertex Intersection, ref Vertex nextVertex)
+        {
+            Vertex bestIntersection=null;
+            float distToV1=Single.PositiveInfinity;
+            Simplex bestIntersectingSimplex=null;
+
+            List<Simplex> simple = buildSimplexList();
+            foreach (Simplex sTest in simple)
+            {
+                Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f);
+                
+                Vertex vTemp=null;
+                if (vvTemp != null)
+                    vTemp = new Vertex(vvTemp);
+
+                if (vTemp!=null) {
+
+                    Manager.PhysicsVector diff=(s.v1-vTemp);
+                    float distTemp=diff.length();
+
+                    if (bestIntersection==null || distTemp<distToV1) {
+                        bestIntersection=vTemp;
+                        distToV1=distTemp;
+                        bestIntersectingSimplex = sTest;
+                    }
+
+                } // end if vTemp
+
+            } // end foreach
+
+            Intersection = bestIntersection;
+            if (bestIntersectingSimplex != null)
+                nextVertex = bestIntersectingSimplex.v2;
+            else
+                nextVertex = null;
+        }
+
+
+        public static SimpleHull SubtractHull(SimpleHull baseHull, SimpleHull otherHull)
+        {
+
+            SimpleHull baseHullClone = baseHull.Clone();
+            SimpleHull otherHullClone = otherHull.Clone();
+            bool intersects = false;
+
+            MainLog.Instance.Debug("State before intersection detection");
+            MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
+            MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
+
+            {
+                int iBase, iOther;
+
+                // Insert into baseHull
+                for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
+                {
+                    int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
+                    Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
+
+                    for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
+                    {
+                        int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
+                        Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
+
+                        Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, 0.001f, -.001f, 0.999f, 1.001f);
+                        if (intersect != null)
+                        {
+                            Vertex vIntersect = new Vertex(intersect);
+                            baseHullClone.vertices.Insert(iBase + 1, vIntersect);
+                            sBase.v2 = vIntersect;
+                            intersects = true;
+                        }
+                    }
+                }
+            }
+
+            MainLog.Instance.Debug("State after intersection detection for the base hull");
+            MainLog.Instance.Debug("The baseHull is:\n{1}", 0, baseHullClone.ToString());
+
+            {
+                int iOther, iBase;
+
+                // Insert into otherHull
+                for (iOther = 0; iOther < otherHullClone.vertices.Count; iOther++)
+                {
+                    int iOtherNext = (iOther + 1) % otherHullClone.vertices.Count;
+                    Simplex sOther = new Simplex(otherHullClone.vertices[iOther], otherHullClone.vertices[iOtherNext]);
+
+                    for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
+                    {
+                        int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
+                        Simplex sBase = new Simplex(baseHullClone.vertices[iBase], baseHullClone.vertices[iBaseNext]);
+
+                        Manager.PhysicsVector intersect = Simplex.Intersect(sBase, sOther, -.001f, 0.001f, 1.001f, 0.999f);
+                        if (intersect != null)
+                        {
+                            Vertex vIntersect = new Vertex(intersect);
+                            otherHullClone.vertices.Insert(iOther + 1, vIntersect);
+                            sOther.v2 = vIntersect;
+                            intersects = true;
+                        }
+                    }
+                }
+            }
+
+            MainLog.Instance.Debug("State after intersection detection for the base hull");
+            MainLog.Instance.Debug("The otherHull is:\n{1}", 0, otherHullClone.ToString());
+
+
+            bool otherIsInBase = baseHullClone.containsPointsFrom(otherHullClone);
+            if (!intersects && otherIsInBase)
+            {
+                // We have a hole here
+                baseHullClone.holeVertices = otherHullClone.vertices;
+                return baseHullClone;
+            }
+
+
+            SimpleHull result = new SimpleHull();
+
+            // Find a good starting Simplex from baseHull
+            // A good starting simplex is one that is outside otherHull
+            // Such a simplex must exist, otherwise the result will be empty
+            Vertex baseStartVertex = null;
+            {
+                int iBase;
+                for (iBase = 0; iBase < baseHullClone.vertices.Count; iBase++)
+                {
+                    int iBaseNext = (iBase + 1) % baseHullClone.vertices.Count;
+                    Vertex center = new Vertex((baseHullClone.vertices[iBase] + baseHullClone.vertices[iBaseNext]) / 2.0f);
+                    bool isOutside = !otherHullClone.IsPointIn(center);
+                    if (isOutside)
+                    {
+                        baseStartVertex = baseHullClone.vertices[iBaseNext];
+                        break;
+                    }
+                }
+            }
+
+
+            if (baseStartVertex == null) // i.e. no simplex fulfilled the "outside" condition. 
+            // In otherwords, subtractHull completely embraces baseHull
+            {
+                return result;
+            }
+
+            // The simplex that *starts* with baseStartVertex is outside the cutting hull,
+            // so we can start our walk with the next vertex without loosing a branch
+            Vertex V1 = baseStartVertex;
+            bool onBase = true;
+
+            // And here is how we do the magic :-)
+            // Start on the base hull.
+            // Walk the vertices in the positive direction
+            // For each vertex check, whether it is a vertex shared with the other hull
+            // if this is the case, switch over to walking the other vertex list.
+            // Note: The other hull *must* go backwards to our starting point (via several orther vertices)
+            // Thus it is important that the cutting hull has the inverse directional sense than the
+            // base hull!!!!!!!!! (means if base goes CW around it's center cutting hull must go CCW)
+
+            bool done = false;
+            while (!done)
+            {
+                result.AddVertex(V1);
+                Vertex nextVertex = null;
+                if (onBase)
+                {
+                    nextVertex = otherHullClone.FindVertex(V1, 0.001f);
+                }
+                else
+                {
+                    nextVertex = baseHullClone.FindVertex(V1, 0.001f);
+                }
+
+                if (nextVertex != null) // A node that represents an intersection
+                {
+                    V1 = nextVertex;    // Needed to find the next vertex on the other hull
+                    onBase = !onBase;
+                }
+
+                if (onBase)
+                    V1 = baseHullClone.getNextVertex(V1);
+                else
+                    V1 = otherHullClone.getNextVertex(V1);
+
+                if (V1 == baseStartVertex)
+                    done = true;
+            }
+
+            MainLog.Instance.Debug("The resulting Hull is:\n{1}", 0, result.ToString());
+
+            return result;
+
+        }
+    }
+}
diff --git a/OpenSim/Region/Physics/Meshing/Simplex.cs b/OpenSim/Region/Physics/Meshing/Simplex.cs
new file mode 100644
index 0000000..4944f22
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/Simplex.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using OpenSim.Region.Physics.Manager;
+
+namespace OpenSim.Region.Physics.Meshing
+{
+    // A simplex is a section of a straight line.
+    // It is defined by its endpoints, i.e. by two vertices
+    // Operation on vertices are
+    public class Simplex : IComparable<Simplex>
+    {
+        public Vertex v1;
+        public Vertex v2;
+
+        public Simplex(Vertex _v1, Vertex _v2)
+        {
+            v1 = _v1;
+            v2 = _v2;
+        }
+
+        public int CompareTo(Simplex other)
+        {
+
+            Vertex lv1, lv2, ov1, ov2, temp;
+
+            lv1 = v1;
+            lv2 = v2;
+            ov1 = other.v1;
+            ov2 = other.v2;
+
+            if (lv1 > lv2)
+            {
+                temp = lv1;
+                lv1 = lv2;
+                lv2 = temp;
+            }
+
+            if (ov1 > ov2)
+            {
+                temp = ov1;
+                ov1 = ov2;
+                ov2 = temp;
+            }
+
+            if (lv1 > ov1)
+            {
+                return 1;
+            }
+            if (lv1 < ov1)
+            {
+                return -1;
+            }
+
+            if (lv2 > ov2)
+            {
+                return 1;
+            }
+            if (lv2 < ov2)
+            {
+                return -1;
+            }
+
+            return 0;
+        }
+
+        private static void intersectParameter(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
+        { 
+            // Intersects two straights
+            // p1, p2, points on the straight
+            // r1, r2, directional vectors of the straight. Not necessarily of length 1!
+            // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
+            // thus allowing to decide whether an intersection is between two points
+
+            float r1x = r1.X;
+            float r1y = r1.Y;
+            float r2x = r2.X;
+            float r2y = r2.Y;
+
+            float denom = r1y*r2x - r1x*r2y;
+
+            float p1x = p1.X;
+            float p1y = p1.Y;
+            float p2x = p2.X;
+            float p2y = p2.Y;
+
+            float z1=-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x;
+            float z2=-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x;
+
+            if (denom == 0.0f) // Means the straights are parallel. Either no intersection or an infinite number of them
+            {
+                if (z1==0.0f) {// Means they are identical -> many, many intersections
+                    lambda = Single.NaN;
+                    mu = Single.NaN;
+                } else {
+                    lambda = Single.PositiveInfinity;
+                    mu = Single.PositiveInfinity;
+                }
+                return;
+
+            }
+
+
+
+            lambda = z1 / denom;
+            mu     = z2 / denom;
+        
+        }
+
+
+        // Intersects the simplex with another one.
+        // the borders are used to deal with float inaccuracies
+        // As a rule of thumb, the borders are
+        // lowerBorder1 : 0.0
+        // lowerBorder2 : 0.0
+        // upperBorder1 : 1.0
+        // upperBorder2 : 1.0
+        // Set these to values near the given parameters (e.g. 0.001 instead of 1 to exclude simplex starts safely, or to -0.001 to include them safely)
+        public static PhysicsVector Intersect(
+                                        Simplex s1, 
+                                        Simplex s2, 
+                                        float lowerBorder1, 
+                                        float lowerBorder2, 
+                                        float upperBorder1, 
+                                        float upperBorder2)
+        {
+            PhysicsVector firstSimplexDirection = s1.v2 - s1.v1;
+            PhysicsVector secondSimplexDirection = s2.v2 - s2.v1;
+
+            float lambda = 0.0f;
+            float mu = 0.0f;
+
+            // Give us the parameters of an intersection. This subroutine does *not* take the constraints
+            // (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
+            // into account. We do that afterwards.
+            intersectParameter(s1.v1, firstSimplexDirection, s2.v1, secondSimplexDirection, ref lambda, ref mu);
+
+            if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
+                return null;
+
+            if (Single.IsNaN(lambda)) // Special case. many, many intersections.
+                return null;
+
+            if (lambda > upperBorder1) // We're behind v2
+                return null;
+
+            if (lambda < lowerBorder1)
+                return null;
+
+            if (mu < lowerBorder2) // outside simplex 2
+                return null;
+
+            if (mu > upperBorder2) // outside simplex 2
+                return null;
+
+            return s1.v1 + lambda * firstSimplexDirection;
+
+        }
+
+        // Intersects the simplex with a ray. The ray is defined as all p=origin + lambda*direction
+        // where lambda >= 0
+        public PhysicsVector RayIntersect(Vertex origin, PhysicsVector direction, bool bEndsIncluded)
+        {
+            PhysicsVector simplexDirection = v2 - v1;
+
+            float lambda = 0.0f;
+            float mu = 0.0f;
+
+            // Give us the parameters of an intersection. This subroutine does *not* take the constraints
+            // (intersection must be between v1 and v2 and it must be in the positive direction of the ray)
+            // into account. We do that afterwards.
+            intersectParameter(v1, simplexDirection, origin, direction, ref lambda, ref mu);
+
+            if (Single.IsInfinity(lambda)) // Special case. No intersection at all. directions parallel.
+                return null;
+
+            if (Single.IsNaN(lambda)) // Special case. many, many intersections.
+                return null;
+
+            if (mu < 0.0) // We're on the wrong side of the ray
+                return null;
+
+            if (lambda > 1.0) // We're behind v2
+                return null;
+
+            if (lambda == 1.0 && !bEndsIncluded)
+                return null;    // The end of the simplices are not included
+
+            if (lambda < 0.0f) // we're before v1;
+                return null;
+
+            return this.v1 + lambda * simplexDirection;
+
+        }
+
+
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 4e69175..646ccb5 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -32,7 +32,7 @@ using Axiom.Math;
 using Ode.NET;
 using OpenSim.Framework;
 using OpenSim.Region.Physics.Manager;
-using OpenSim.Region.Physics.OdePlugin.Meshing;
+//using OpenSim.Region.Physics.OdePlugin.Meshing;
 
 namespace OpenSim.Region.Physics.OdePlugin
 {
@@ -98,6 +98,8 @@ namespace OpenSim.Region.Physics.OdePlugin
         public IntPtr space;
         public static Object OdeLock = new Object();
 
+        public IMesher mesher;
+
         public OdeScene()
         {
             nearCallback = near;
@@ -137,6 +139,12 @@ namespace OpenSim.Region.Physics.OdePlugin
             
         }
 
+        public override void Initialise(IMesher meshmerizer)
+        {
+            mesher = meshmerizer;
+        }
+
+
         // This function blatantly ripped off from BoxStack.cs
         private void near(IntPtr space, IntPtr g1, IntPtr g2)
         {
@@ -308,7 +316,7 @@ namespace OpenSim.Region.Physics.OdePlugin
         }
 
         private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
-                                     Mesh mesh, PrimitiveBaseShape pbs, bool isphysical)
+                                     IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
         {
             PhysicsVector pos = new PhysicsVector();
             pos.X = position.X;
@@ -409,11 +417,12 @@ namespace OpenSim.Region.Physics.OdePlugin
         {
             return this.AddPrimShape(primName, pbs, position, size, rotation, false);
         }
+
         public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
                                                   PhysicsVector size, Quaternion rotation, bool isPhysical)
         {
             PhysicsActor result;
-            Mesh mesh = null;
+            IMesh mesh = null;
 
             switch (pbs.ProfileShape)
             {
@@ -421,7 +430,7 @@ namespace OpenSim.Region.Physics.OdePlugin
                     /// support simple box & hollow box now; later, more shapes
                     if (needsMeshing(pbs))
                     {
-                         mesh = Meshmerizer.CreateMesh(primName, pbs, size);
+                         mesh = mesher.CreateMesh(primName, pbs, size);
                     }
                    
                     break;
@@ -931,7 +940,7 @@ namespace OpenSim.Region.Physics.OdePlugin
         private PhysicsVector _acceleration;
         public Quaternion _orientation;
 
-        private Mesh _mesh;
+        private IMesh _mesh;
         private PrimitiveBaseShape _pbs;
         private OdeScene _parent_scene;
         public IntPtr prim_geom;
@@ -953,7 +962,7 @@ namespace OpenSim.Region.Physics.OdePlugin
 
 
         public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
-                       Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
+                       Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
         {
             
 
@@ -1036,15 +1045,15 @@ namespace OpenSim.Region.Physics.OdePlugin
                 Body = (IntPtr)0;
             }
         }
-        public void setMesh(OdeScene parent_scene, Mesh mesh)
+        public void setMesh(OdeScene parent_scene, IMesh mesh)
         {
             //Kill Body so that mesh can re-make the geom
             if (IsPhysical && Body != (IntPtr)0)
             {
                 disableBody();
             }
-            float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
-            int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage
+            float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
+            int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
             int VertexCount = vertexList.GetLength(0)/3;
             int IndexCount = indexList.GetLength(0);
 
@@ -1169,7 +1178,7 @@ namespace OpenSim.Region.Physics.OdePlugin
 
                         
                         // Don't need to re-enable body..   it's done in SetMesh
-                        Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
+                        IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
                         // createmesh returns null when it's a shape that isn't a cube.
                         if (mesh != null)
                         setMesh(_parent_scene, mesh);
@@ -1218,7 +1227,7 @@ namespace OpenSim.Region.Physics.OdePlugin
                     // Construction of new prim
                     if (this._parent_scene.needsMeshing(_pbs))
                     {
-                        Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
+                        IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
                         setMesh(_parent_scene, mesh);
                     } else {
                         prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
index 76121ae..7652372 100644
--- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
+++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs
@@ -84,6 +84,12 @@ namespace OpenSim.Region.Physics.PhysXPlugin
             scene = mySdk.CreateScene();
         }
 
+        public override void Initialise(IMesher meshmerizer)
+        {
+            // Does nothing right now
+        }
+
+
         public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
         {
             Vec3 pos = new Vec3();
diff --git a/prebuild.xml b/prebuild.xml
index 404a750..58ec667 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -251,7 +251,8 @@
       <Reference name="Axiom.MathLib.dll" localCopy="false"/>
       <Reference name="OpenSim.Framework" localCopy="false"/>
       <Reference name="OpenSim.Framework.Console" localCopy="false"/>
-      <Files>
+	  <Reference name="Nini.dll" />
+	  <Files>
         <Match pattern="*.cs" recurse="false"/>
       </Files>
     </Project>
@@ -346,8 +347,9 @@
       <Reference name="System" localCopy="false"/>
       <Reference name="libsecondlife.dll"/>
       <Reference name="Axiom.MathLib.dll" localCopy="false"/>
-      <Reference name="OpenSim.Framework"/>
-      <Reference name="OpenSim.Region.Physics.Manager" localCopy="false"/>
+	  <Reference name="OpenSim.Framework"/>
+	  <Reference name="OpenSim.Framework.Console" localCopy="false"/>
+	  <Reference name="OpenSim.Region.Physics.Manager" localCopy="false"/>
       <Reference name="Modified.XnaDevRu.BulletX.dll" localCopy="false" />
       <Reference name="MonoXnaCompactMaths.dll" localCopy="false" />
 
@@ -356,6 +358,30 @@
       </Files>
     </Project>
 
+    <Project name="OpenSim.Region.Physics.Meshing" path="OpenSim/Region/Physics/Meshing" type="Library">
+      <Configuration name="Debug">
+        <Options>
+          <OutputPath>../../../../bin/Physics/</OutputPath>
+        </Options>
+      </Configuration>
+      <Configuration name="Release">
+        <Options>
+          <OutputPath>../../../../bin/Physics/</OutputPath>
+        </Options>
+      </Configuration>
+
+      <ReferencePath>../../../../bin/</ReferencePath>
+      <Reference name="System" localCopy="false"/>
+      <Reference name="libsecondlife.dll"/>
+      <Reference name="OpenSim.Framework"/>
+      <Reference name="OpenSim.Framework.Console"/>
+	  <Reference name="OpenSim.Region.Physics.Manager" localCopy="false"/>
+
+	  <Files>
+        <Match pattern="*.cs" recurse="true"/>
+      </Files>
+    </Project>
+
     
     <!-- Terrain engine -->
     <Project name="OpenSim.Region.Terrain.BasicTerrain" path="OpenSim/Region/Terrain.BasicTerrain" type="Library">
@@ -564,8 +590,10 @@
       <Reference name="OpenSim.Region.Communications.Local"/>      
       <Reference name="OpenSim.Region.Physics.Manager"/>
       <Reference name="XMLRPC.dll"/>
+      <Reference name="Nini.dll" />
 
-      <Files>
+
+	  <Files>
         <Match pattern="*.cs" recurse="true"/>
       </Files>
     </Project>
@@ -1108,3 +1136,4 @@
 
 
 
+
-- 
cgit v1.1