From fdb57b28b164f239de0f976b967b79dc2ca5f6ae Mon Sep 17 00:00:00 2001
From: dan miller
Date: Mon, 5 Nov 2007 12:25:53 +0000
Subject: prim cuts in ODE Much thanks to Gerhard! Merged with Darok's recent
 changes re: physical prims

---
 .../Physics/OdePlugin/Meshing/HelperTypes.cs       | 158 ++++---
 .../Physics/OdePlugin/Meshing/Meshmerizer.cs       | 514 +++++++--------------
 OpenSim/Region/Physics/OdePlugin/OdePlugin.cs      | 121 +++--
 3 files changed, 333 insertions(+), 460 deletions(-)

(limited to 'OpenSim/Region/Physics/OdePlugin')

diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
index 13184e2..3b20af7 100644
--- a/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs
@@ -30,37 +30,63 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Globalization;
+using OpenSim.Framework.Console;
 using OpenSim.Region.Physics.Manager;
 
-public class Vertex : IComparable<Vertex>
+using OpenSim.Region.Physics.OdePlugin.Meshing;
+
+public class Vertex : PhysicsVector, IComparable<Vertex>
 {
-    public String name;
-    public PhysicsVector point;
+    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 Vertex(String name, float x, float y, float z)
+    public virtual bool Equals(Vertex v, float tolerance)
     {
-        this.name = name;
-        point = new PhysicsVector(x, y, z);
+        PhysicsVector diff = this - v;
+        float d = diff.length();
+        if (d < tolerance)
+            return true;
+
+        return false;
     }
 
+
     public int CompareTo(Vertex other)
     {
-        if (point.X < other.point.X)
+        if (X < other.X)
             return -1;
 
-        if (point.X > other.point.X)
+        if (X > other.X)
             return 1;
 
-        if (point.Y < other.point.Y)
+        if (Y < other.Y)
             return -1;
 
-        if (point.Y > other.point.Y)
+        if (Y > other.Y)
             return 1;
 
-        if (point.Z < other.point.Z)
+        if (Z < other.Z)
             return -1;
 
-        if (point.Z > other.point.Z)
+        if (Z > other.Z)
             return 1;
 
         return 0;
@@ -75,51 +101,24 @@ public class Vertex : IComparable<Vertex>
     {
         return me.CompareTo(other) < 0;
     }
-}
-
-public class Simplex : IComparable<Simplex>
-{
-    public Vertex v1;
-    public Vertex v2;
-
-    public Simplex(Vertex _v1, Vertex _v2)
-    {
-        // Presort indices to make sorting (comparing) easier
-        if (_v1 > _v2)
-        {
-            v1 = _v1;
-            v2 = _v2;
-        }
-        else
-        {
-            v1 = _v2;
-            v2 = _v1;
-        }
-    }
-
-    public int CompareTo(Simplex other)
+    public String ToRaw()
     {
-        if (v1 > other.v1)
-        {
-            return 1;
-        }
-        if (v1 < other.v1)
-        {
-            return -1;
-        }
+        // 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;
 
-        if (v2 > other.v2)
-        {
-            return 1;
-        }
-        if (v2 < other.v2)
-        {
-            return -1;
-        }
+        String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi);
 
-        return 0;
+        return s1;
     }
-} ;
+
+}
 
 public class Triangle
 {
@@ -155,6 +154,12 @@ public class Triangle
             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()
     {
@@ -184,14 +189,14 @@ public class Triangle
         double rx, ry;
 
         // Readout the three points, the triangle consists of
-        p1x = v1.point.X;
-        p1y = v1.point.Y;
+        p1x = v1.X;
+        p1y = v1.Y;
 
-        p2x = v2.point.X;
-        p2y = v2.point.Y;
+        p2x = v2.X;
+        p2y = v2.Y;
 
-        p3x = v3.point.X;
-        p3y = v3.point.Y;
+        p3x = v3.X;
+        p3y = v3.Y;
 
         /* calc helping values first */
         c1 = (p1x*p1x + p1y*p1y - p2x*p2x - p2y*p2y)/2;
@@ -253,12 +258,9 @@ public class Triangle
         nfi.CurrencyDecimalDigits = 2;
         nfi.CurrencyDecimalSeparator = ".";
 
-        String s1 = "<" + v1.point.X.ToString(nfi) + "," + v1.point.Y.ToString(nfi) + "," + v1.point.Z.ToString(nfi) +
-                    ">";
-        String s2 = "<" + v2.point.X.ToString(nfi) + "," + v2.point.Y.ToString(nfi) + "," + v2.point.Z.ToString(nfi) +
-                    ">";
-        String s3 = "<" + v3.point.X.ToString(nfi) + "," + v3.point.Y.ToString(nfi) + "," + v3.point.Z.ToString(nfi) +
-                    ">";
+        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;
     }
@@ -271,23 +273,17 @@ public class Triangle
         PhysicsVector e1;
         PhysicsVector e2;
 
-        e1 = new PhysicsVector(v1.point.X - v2.point.X, v1.point.Y - v2.point.Y, v1.point.Z - v2.point.Z);
-        e2 = new PhysicsVector(v1.point.X - v3.point.X, v1.point.Y - v3.point.Y, v1.point.Z - v3.point.Z);
+        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 = new PhysicsVector();
-        float nx, ny, nz;
-        n.X = e1.Y*e2.Z - e1.Z*e2.Y;
-        n.Y = e1.Z*e2.X - e1.X*e2.Z;
-        n.Z = e1.X*e2.Y - e1.Y*e2.X;
+        PhysicsVector n = PhysicsVector.cross(e1, e2);
 
         // Length
-        float l = (float) Math.Sqrt(n.X*n.X + n.Y*n.Y + n.Z*n.Z);
+        float l = n.length();
 
         // Normalized "normal"
-        n.X /= l;
-        n.Y /= l;
-        n.Z /= l;
+        n = n / l;
 
         return n;
     }
@@ -299,4 +295,12 @@ public class Triangle
         v1 = v2;
         v2 = vt;
     }
-}
\ No newline at end of file
+
+    // 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;
+    }
+}
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
index 46de15e..2a304cb 100644
--- a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
@@ -27,109 +27,70 @@
 */
 
 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.OdePlugin
+namespace OpenSim.Region.Physics.OdePlugin.Meshing
 {
-    public class Mesh
-    {
-        public List<Vertex> vertices;
-        public List<Triangle> triangles;
-
-        public float[] normals;
-
-        public Mesh()
-        {
-            vertices = new List<Vertex>();
-            triangles = new List<Triangle>();
-        }
-
-        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 float[] getVertexListAsFloat()
-        {
-            float[] result = new float[vertices.Count*3];
-            for (int i = 0; i < vertices.Count; i++)
-            {
-                Vertex v = vertices[i];
-                PhysicsVector point = v.point;
-                result[3*i + 0] = point.X;
-                result[3*i + 1] = point.Y;
-                result[3*i + 2] = point.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++)
+    public class Meshmerizer
+    {
+        // 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)
             {
-                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);
+                lambda = Single.NaN;
+                mu = Single.NaN;
+                return;
             }
-            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);
+            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;
+        
         }
-    }
-
 
-    public class Meshmerizer
-    {
         private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
         {
             List<Triangle> influenced = new List<Triangle>();
             foreach (Triangle t in triangles)
             {
-                float dx, dy;
-
-                if (t.isInCircle(v.point.X, v.point.Y))
+                if (t.isInCircle(v.X, v.Y))
                 {
                     influenced.Add(t);
                 }
             }
             return influenced;
         }
-
-
-        private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles,
-                                           List<int> innerBorders)
+        
+        
+        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
@@ -148,8 +109,10 @@ namespace OpenSim.Region.Physics.OdePlugin
                 // 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];
-                List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v);
+                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>();
 
@@ -163,11 +126,12 @@ namespace OpenSim.Region.Physics.OdePlugin
                     simplices.AddRange(newSimplices);
                     triangles.Remove(t);
                 }
-                // Now sort the simplices. That will make identical ones side by side in the list
+                // 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
+                // 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
@@ -186,310 +150,145 @@ namespace OpenSim.Region.Physics.OdePlugin
 
                 // 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
+                // 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]);
-                    triangles.Add(t);
+                    if (!t.isDegraded())
+                    {
+                        triangles.Add(t);
+                    }
                 }
             }
 
-            // At this point all vertices should be inserted into the mesh
-            // But the areas, that should be kept free still are filled with triangles
-            // We have to remove them. For this we have a list of indices to vertices.
-            // Each triangle that solemnly constists of vertices from the inner border
-            // are deleted
-
-            List<Triangle> innerTriangles = new List<Triangle>();
-            foreach (Triangle t in triangles)
-            {
-                if (
-                    innerBorders.Contains(vertices.IndexOf(t.v1))
-                    && innerBorders.Contains(vertices.IndexOf(t.v2))
-                    && innerBorders.Contains(vertices.IndexOf(t.v3))
-                    )
-                    innerTriangles.Add(t);
-            }
-            foreach (Triangle t in innerTriangles)
-            {
-                triangles.Remove(t);
-            }
         }
 
-
-        private static Mesh CreateBoxMeshX(PrimitiveBaseShape primShape, PhysicsVector size)
-            // Builds the x (+ and -) surfaces of a box shaped prim
+            
+        static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
+        // Builds the z (+ and -) surfaces of a box shaped prim
         {
             UInt16 hollowFactor = primShape.ProfileHollow;
-            Mesh meshMX = new Mesh();
-
-
-            // Surface 0, -X
-            meshMX.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            meshMX.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
-            meshMX.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
-            meshMX.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
-
-            meshMX.Add(new Triangle(meshMX.vertices[0], meshMX.vertices[2], meshMX.vertices[1]));
-            meshMX.Add(new Triangle(meshMX.vertices[1], meshMX.vertices[2], meshMX.vertices[3]));
-
-
-            Mesh meshPX = new Mesh();
-            // Surface 1, +X
-            meshPX.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            meshPX.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
-            meshPX.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
-            meshPX.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
-
-
-            meshPX.Add(new Triangle(meshPX.vertices[0], meshPX.vertices[1], meshPX.vertices[2]));
-            meshPX.Add(new Triangle(meshPX.vertices[2], meshPX.vertices[1], meshPX.vertices[3]));
-
-
-            if (hollowFactor > 0)
+            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))
             {
-                float hollowFactorF = (float) hollowFactor/(float) 50000;
-
-                Vertex IPP;
-                Vertex IPM;
-                Vertex IMP;
-                Vertex IMM;
-
-                IPP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IPM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-                IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-
-                meshMX.Add(IPP);
-                meshMX.Add(IPM);
-                meshMX.Add(IMP);
-                meshMX.Add(IMM);
-
-                meshMX.Add(new Triangle(IPP, IMP, IPM));
-                meshMX.Add(new Triangle(IPM, IMP, IMM));
-
-                foreach (Triangle t in meshMX.triangles)
-                {
-                    PhysicsVector n = t.getNormal();
+                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);
 
-                IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-                IMP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IMM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-
-                meshPX.Add(IPP);
-                meshPX.Add(IPM);
-                meshPX.Add(IMP);
-                meshPX.Add(IMM);
-
-                meshPX.Add(new Triangle(IPP, IPM, IMP));
-                meshPX.Add(new Triangle(IMP, IPM, IMM));
-
-                foreach (Triangle t in meshPX.triangles)
-                {
-                    PhysicsVector n = t.getNormal();
-                }
+                outerHull = cuttedHull;
             }
 
-            Mesh result = new Mesh();
-            result.Append(meshMX);
-            result.Append(meshPX);
-
-            return result;
-        }
-
-
-        private static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size)
-            // Builds the y (+ and -) surfaces of a box shaped prim
-        {
-            UInt16 hollowFactor = primShape.ProfileHollow;
-
-            // (M)inus Y
-            Mesh MeshMY = new Mesh();
-            MeshMY.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            MeshMY.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            MeshMY.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
-            MeshMY.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, +size.Z/2.0f));
-
-            MeshMY.Add(new Triangle(MeshMY.vertices[0], MeshMY.vertices[1], MeshMY.vertices[2]));
-            MeshMY.Add(new Triangle(MeshMY.vertices[2], MeshMY.vertices[1], MeshMY.vertices[3]));
-
-            // (P)lus Y
-            Mesh MeshPY = new Mesh();
-
-            MeshPY.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
-            MeshPY.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
-            MeshPY.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
-            MeshPY.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, +size.Z/2.0f));
-
-            MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[0], MeshPY.vertices[2]));
-            MeshPY.Add(new Triangle(MeshPY.vertices[1], MeshPY.vertices[2], MeshPY.vertices[3]));
-
+            // 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);
 
-                Vertex IPP;
-                Vertex IPM;
-                Vertex IMP;
-                Vertex IMM;
+                SimpleHull holeHull = new SimpleHull();
 
-                IPP = new Vertex("Inner+X-Y+Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IPM = new Vertex("Inner+X-Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-                IMP = new Vertex("Inner-X-Y+Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IMM = new Vertex("Inner-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
+                holeHull.AddVertex(IMM);
+                holeHull.AddVertex(IMP);
+                holeHull.AddVertex(IPP);
+                holeHull.AddVertex(IPM);
 
-                MeshMY.Add(IPP);
-                MeshMY.Add(IPM);
-                MeshMY.Add(IMP);
-                MeshMY.Add(IMM);
+                SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
 
-                MeshMY.Add(new Triangle(IPP, IPM, IMP));
-                MeshMY.Add(new Triangle(IMP, IPM, IMM));
+                outerHull = hollowedHull;
 
-                foreach (Triangle t in MeshMY.triangles)
-                {
-                    PhysicsVector n = t.getNormal();
-                }
-
-
-                IPP = new Vertex("Inner+X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IPM = new Vertex("Inner+X+Y-Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-                IMP = new Vertex("Inner-X+Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, +size.Z/2.0f);
-                IMM = new Vertex("Inner-X+Y-Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, -size.Z/2.0f);
-
-                MeshPY.Add(IPP);
-                MeshPY.Add(IPM);
-                MeshPY.Add(IMP);
-                MeshPY.Add(IMM);
-
-                MeshPY.Add(new Triangle(IPM, IPP, IMP));
-                MeshPY.Add(new Triangle(IMP, IMM, IPM));
-
-                foreach (Triangle t in MeshPY.triangles)
-                {
-                    PhysicsVector n = t.getNormal();
-                }
             }
 
+            Mesh m = new Mesh();
 
-            Mesh result = new Mesh();
-            result.Append(MeshMY);
-            result.Append(MeshPY);
-
-            return result;
-        }
-
-        private static Mesh CreateBoxMeshZ(PrimitiveBaseShape primShape, PhysicsVector size)
-            // Builds the z (+ and -) surfaces of a box shaped prim
-        {
-            UInt16 hollowFactor = primShape.ProfileHollow;
-
-            // Base, i.e. outer shape
-            // (M)inus Z
-            Mesh MZ = new Mesh();
-
-            MZ.Add(new Vertex("-X-Y-Z", -size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            MZ.Add(new Vertex("+X-Y-Z", +size.X/2.0f, -size.Y/2.0f, -size.Z/2.0f));
-            MZ.Add(new Vertex("-X+Y-Z", -size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
-            MZ.Add(new Vertex("+X+Y-Z", +size.X/2.0f, +size.Y/2.0f, -size.Z/2.0f));
+            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);
 
-            MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[0], MZ.vertices[2]));
-            MZ.Add(new Triangle(MZ.vertices[1], MZ.vertices[2], MZ.vertices[3]));
+            m.Add(new Triangle(Seed1, Seed2, Seed3));
+            m.Add(outerHull.getVertices());
 
-            // (P)lus Z
-            Mesh PZ = new Mesh();
+            InsertVertices(m.vertices, 3, m.triangles);
+            m.DumpRaw(baseDir, primName, "Proto first Mesh");
 
-            PZ.Add(new Vertex("-X-Y+Z", -size.X/2.0f, -size.Y/2.0f, 0.0f));
-            PZ.Add(new Vertex("+X-Y+Z", +size.X/2.0f, -size.Y/2.0f, 0.0f));
-            PZ.Add(new Vertex("-X+Y+Z", -size.X/2.0f, +size.Y/2.0f, 0.0f));
-            PZ.Add(new Vertex("+X+Y+Z", +size.X/2.0f, +size.Y/2.0f, 0.0f));
+            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");
 
-            // Surface 5, +Z
-            PZ.Add(new Triangle(PZ.vertices[0], PZ.vertices[1], PZ.vertices[2]));
-            PZ.Add(new Triangle(PZ.vertices[2], PZ.vertices[1], PZ.vertices[3]));
-
-            if (hollowFactor > 0)
-            {
-                float hollowFactorF = (float) hollowFactor/(float) 50000;
-
-                MZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
-                MZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
-                MZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
-                MZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
-
-                List<int> innerBorders = new List<int>();
-                innerBorders.Add(4);
-                innerBorders.Add(5);
-                innerBorders.Add(6);
-                innerBorders.Add(7);
-
-                InsertVertices(MZ.vertices, 4, MZ.triangles, innerBorders);
-
-                PZ.Add(new Vertex("-X-Y-Z", -size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
-                PZ.Add(new Vertex("-X+Y-Z", +size.X*hollowFactorF/2.0f, -size.Y*hollowFactorF/2.0f, 0.0f));
-                PZ.Add(new Vertex("-X-Y+Z", -size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
-                PZ.Add(new Vertex("-X+Y+Z", +size.X*hollowFactorF/2.0f, +size.Y*hollowFactorF/2.0f, 0.0f));
-
-                innerBorders = new List<int>();
-                innerBorders.Add(4);
-                innerBorders.Add(5);
-                innerBorders.Add(6);
-                innerBorders.Add(7);
-
-                InsertVertices(PZ.vertices, 4, PZ.triangles, innerBorders);
-            }
-
-            foreach (Vertex v in PZ.vertices)
-            {
-                v.point.Z = size.Z/2.0f;
-            }
-            foreach (Vertex v in MZ.vertices)
-            {
-                v.point.Z = -size.Z/2.0f;
-            }
-
-            foreach (Triangle t in MZ.triangles)
-            {
-                PhysicsVector n = t.getNormal();
-                if (n.Z > 0.0)
-                    t.invertNormal();
-            }
-
-            foreach (Triangle t in PZ.triangles)
+            foreach (Triangle t in m.triangles)
             {
                 PhysicsVector n = t.getNormal();
                 if (n.Z < 0.0)
                     t.invertNormal();
             }
 
-            Mesh result = new Mesh();
-            result.Append(MZ);
-            result.Append(PZ);
+            Extruder extr = new Extruder();
 
-            return result;
-        }
-
-        private static Mesh CreateBoxMesh(PrimitiveBaseShape primShape, PhysicsVector size)
-        {
-            Mesh result = new Mesh();
-
-
-            Mesh MeshX = CreateBoxMeshX(primShape, size);
-            Mesh MeshY = CreateBoxMeshY(primShape, size);
-            Mesh MeshZ = CreateBoxMeshZ(primShape, size);
-
-            result.Append(MeshX);
-            result.Append(MeshY);
-            result.Append(MeshZ);
+            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;
@@ -503,17 +302,18 @@ namespace OpenSim.Region.Physics.OdePlugin
                 float vx, vy, vz;
                 float wx, wy, wz;
 
-                ux = t.v1.point.X;
-                uy = t.v1.point.Y;
-                uz = t.v1.point.Z;
+                ux = t.v1.X;
+                uy = t.v1.Y;
+                uz = t.v1.Z;
+
+                vx = t.v2.X;
+                vy = t.v2.Y;
+                vz = t.v2.Z;
 
-                vx = t.v2.point.X;
-                vy = t.v2.point.Y;
-                vz = t.v2.point.Z;
+                wx = t.v3.X;
+                wy = t.v3.Y;
+                wz = t.v3.Z;
 
-                wx = t.v3.point.X;
-                wy = t.v3.point.Y;
-                wz = t.v3.point.Z;
 
                 // Vectors for edges
                 float e1x, e1y, e1z;
@@ -550,14 +350,14 @@ namespace OpenSim.Region.Physics.OdePlugin
             }
         }
 
-        public static Mesh CreateMesh(PrimitiveBaseShape primShape, PhysicsVector size)
+        public static Mesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
         {
             Mesh mesh = null;
 
             switch (primShape.ProfileShape)
             {
                 case ProfileShape.Square:
-                    mesh = CreateBoxMesh(primShape, size);
+                    mesh=CreateBoxMesh(primName, primShape, size);
                     CalcNormals(mesh);
                     break;
                 default:
@@ -568,4 +368,4 @@ namespace OpenSim.Region.Physics.OdePlugin
             return mesh;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index f1db034..9ac43bf 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -32,6 +32,8 @@ using Axiom.Math;
 using Ode.NET;
 using OpenSim.Framework;
 using OpenSim.Region.Physics.Manager;
+using OpenSim.Region.Physics.OdePlugin.Meshing;
+
 
 namespace OpenSim.Region.Physics.OdePlugin
 {
@@ -274,6 +276,7 @@ namespace OpenSim.Region.Physics.OdePlugin
 
         public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
         {
+/*
             String name1 = null;
             String name2 = null;
 
@@ -294,45 +297,52 @@ namespace OpenSim.Region.Physics.OdePlugin
 
             d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
 //            MainLog.Instance.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
-
+*/
             return 1;
         }
 
+        
+        public bool needsMeshing(PrimitiveBaseShape pbs)
+        {
+            if (pbs.ProfileHollow != 0)
+                return true;
+
+            if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
+                return true;
+
+            return false;
+        }
 
         public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
                                                   PhysicsVector size, Quaternion rotation) //To be removed
         {
             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;
 
             switch (pbs.ProfileShape)
             {
                 case ProfileShape.Square:
                     /// support simple box & hollow box now; later, more shapes
-                    if (pbs.ProfileHollow == 0)
-                    {
-                        result = AddPrim(primName, position, size, rotation, null, null);
-                    }
-                    else
+                    if (needsMeshing(pbs))
                     {
-                        Mesh mesh = Meshmerizer.CreateMesh(pbs, size);
-                        result = AddPrim(primName, position, size, rotation, mesh, pbs);
+                         mesh = Meshmerizer.CreateMesh(primName, pbs, size);
                     }
-                    break;
-
-                default:
-                    result = AddPrim(primName, position, size, rotation, null, null);
+                   
                     break;
             }
+           
+            result = AddPrim(primName, position, size, rotation, mesh, pbs);
+
 
             return result;
         }
 
-
         public override void Simulate(float timeStep)
         {
             step_time += timeStep;
@@ -551,6 +561,13 @@ namespace OpenSim.Region.Physics.OdePlugin
             set { }
         }
 
+        public override PrimitiveBaseShape Shape
+        {
+            set
+            {
+                return;
+            }
+        }
 
         public override PhysicsVector Velocity
         {
@@ -753,6 +770,12 @@ namespace OpenSim.Region.Physics.OdePlugin
             }
         }
 
+        public override bool IsPhysical
+        {
+            get { return false; }
+            set { return; }
+        }
+
         public void setMesh(OdeScene parent_scene, Mesh mesh)
         {
             float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
@@ -769,12 +792,6 @@ namespace OpenSim.Region.Physics.OdePlugin
             prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, null, null);
         }
 
-        public override bool IsPhysical
-        {
-            get { return false; }
-            set { return; }
-        }
-
         public override bool Flying
         {
             get { return false; //no flying prims for you
@@ -810,18 +827,70 @@ namespace OpenSim.Region.Physics.OdePlugin
                 _size = value;
                 lock (OdeScene.OdeLock)
                 {
-                    if (_mesh != null) // We deal with a mesh here
+                    string oldname = _parent_scene.geom_name_map[prim_geom];
+
+                    // Cleanup of old prim geometry
+                    d.GeomDestroy(prim_geom);
+                    if (_mesh != null)
                     {
-                        string oldname = _parent_scene.geom_name_map[prim_geom];
-                        d.GeomDestroy(prim_geom);
-                        Mesh mesh = Meshmerizer.CreateMesh(_pbs, _size);
+                        // Cleanup meshing here
+                    }
+
+                    // Construction of new prim
+                    if (this._parent_scene.needsMeshing(_pbs))
+                    {
+                        Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
                         setMesh(_parent_scene, mesh);
-                        _parent_scene.geom_name_map[prim_geom] = oldname;
+                    } else {
+                        prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
+                    }
+                    _parent_scene.geom_name_map[prim_geom] = oldname;
+
+                    d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+                    d.Quaternion myrot = new d.Quaternion();
+                    myrot.W = _orientation.w;
+                    myrot.X = _orientation.x;
+                    myrot.Y = _orientation.y;
+                    myrot.Z = _orientation.z;
+                    d.GeomSetQuaternion(prim_geom, ref myrot);
+                }
+            }
+        }
+
+        public override PrimitiveBaseShape Shape
+        {
+            set
+            {
+                _pbs = value;
+                lock (OdeScene.OdeLock)
+                {
+                    string oldname = _parent_scene.geom_name_map[prim_geom];
+
+                    // Cleanup of old prim geometry
+                    d.GeomDestroy(prim_geom);
+                    if (_mesh != null)
+                    {
+                        // Cleanup meshing here
                     }
-                    else
+
+                    // Construction of new prim
+                    if (this._parent_scene.needsMeshing(_pbs))
                     {
-                        d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
+                        Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
+                        setMesh(_parent_scene, mesh);
+                    } else {
+                        prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
                     }
+                    _parent_scene.geom_name_map[prim_geom] = oldname;
+
+                    d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+                    d.Quaternion myrot = new d.Quaternion();
+                    myrot.W = _orientation.w;
+                    myrot.X = _orientation.x;
+                    myrot.Y = _orientation.y;
+                    myrot.Z = _orientation.z;
+                    d.GeomSetQuaternion(prim_geom, ref myrot);
+
                 }
             }
         }
-- 
cgit v1.1