From fdb57b28b164f239de0f976b967b79dc2ca5f6ae Mon Sep 17 00:00:00 2001 From: dan miller Date: Mon, 5 Nov 2007 12:25:53 +0000 Subject: [PATCH] prim cuts in ODE Much thanks to Gerhard! Merged with Darok's recent changes re: physical prims --- .../BasicPhysicsPlugin/BasicPhysicsPlugin.cs | 8 + .../Physics/BulletXPlugin/BulletXPlugin.cs | 9 + .../Region/Physics/Manager/PhysicsActor.cs | 14 + .../Region/Physics/Manager/PhysicsVector.cs | 50 ++ .../Physics/OdePlugin/Meshing/HelperTypes.cs | 166 +++--- .../Physics/OdePlugin/Meshing/Meshmerizer.cs | 516 ++++++------------ OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 121 +++- .../Region/Physics/PhysXPlugin/PhysXPlugin.cs | 139 +++-- 8 files changed, 507 insertions(+), 516 deletions(-) diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs index 7c2bbf4cfa..46037df466 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs @@ -221,6 +221,14 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin set { } } + public override PrimitiveBaseShape Shape + { + set + { + return; + } + } + public override PhysicsVector Velocity { get { return _velocity; } diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index 5b8b0e8cfa..0a868ea073 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -686,6 +686,15 @@ namespace OpenSim.Region.Physics.BulletXPlugin get { return _size; } set { lock (BulletXScene.BulletXLock) { _size = value; } } } + + public override PrimitiveBaseShape Shape + { + set + { + return; + } + } + public override PhysicsVector Acceleration { get { return _acceleration; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index bfe1d0bbd2..b151e16b04 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -26,6 +26,7 @@ * */ using Axiom.Math; +using OpenSim.Framework; namespace OpenSim.Region.Physics.Manager { @@ -50,6 +51,11 @@ namespace OpenSim.Region.Physics.Manager public abstract PhysicsVector Size { get; set; } + public abstract PrimitiveBaseShape Shape + { + set; + } + public abstract PhysicsVector Position { get; set; } public abstract PhysicsVector Velocity { get; set; } @@ -85,6 +91,14 @@ namespace OpenSim.Region.Physics.Manager set { return; } } + public override PrimitiveBaseShape Shape + { + set + { + return; + } + } + public override PhysicsVector Velocity { get { return PhysicsVector.Zero; } diff --git a/OpenSim/Region/Physics/Manager/PhysicsVector.cs b/OpenSim/Region/Physics/Manager/PhysicsVector.cs index 7de37e4206..ada2297fd8 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsVector.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsVector.cs @@ -25,6 +25,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ + +using System; + + namespace OpenSim.Region.Physics.Manager { public class PhysicsVector @@ -50,5 +54,51 @@ namespace OpenSim.Region.Physics.Manager { return "<" + X + "," + Y + "," + Z + ">"; } + + // Operations + public static PhysicsVector operator +(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + public static PhysicsVector operator -(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + public static PhysicsVector cross(PhysicsVector a, PhysicsVector b) + { + return new PhysicsVector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); + } + + public float length() + { + return (float)Math.Sqrt(X*X + Y*Y + Z*Z); + } + + public static PhysicsVector operator / (PhysicsVector v, float f) + { + return new PhysicsVector(v.X / f, v.Y / f, v.Z / f); + } + + public static PhysicsVector operator *(PhysicsVector v, float f) + { + return new PhysicsVector(v.X * f, v.Y * f, v.Z * f); + } + + public static PhysicsVector operator *(float f, PhysicsVector v) + { + return v * f; + } + + public virtual bool IsIdentical(PhysicsVector v, float tolerance) + { + PhysicsVector diff = this - v; + float d = diff.length(); + if (d < tolerance) + return true; + + return false; + } } } \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/HelperTypes.cs index 13184e2ffb..3b20af77bc 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 -{ - public String name; - public PhysicsVector point; +using OpenSim.Region.Physics.OdePlugin.Meshing; - public Vertex(String name, float x, float y, float z) +public class Vertex : PhysicsVector, IComparable +{ + public Vertex(float x, float y, float z) + : base(x, y, z) { - this.name = name; - point = new PhysicsVector(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 (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,52 +101,25 @@ public class Vertex : IComparable { 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 Simplex : IComparable -{ - 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) - { - if (v1 > other.v1) - { - return 1; - } - if (v1 < other.v1) - { - return -1; - } - - if (v2 > other.v2) - { - return 1; - } - if (v2 < other.v2) - { - return -1; - } - - return 0; - } -} ; - public class Triangle { public Vertex v1; @@ -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 46de15e88c..2a304cbac6 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 vertices; - public List triangles; - - public float[] normals; - - public Mesh() - { - vertices = new List(); - triangles = new List(); - } - - 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++) - { - 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); - } - 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); - } - } - 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) + { + 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 FindInfluencedTriangles(List triangles, Vertex v) { List influenced = new List(); 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 vertices, int usedForSeed, List triangles, - List innerBorders) + + + private static void InsertVertices(List vertices, int usedForSeed, List 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 influencedTriangles = FindInfluencedTriangles(triangles, v); + Vertex v=vertices[iCurrentVertex]; + if (v == null) + continue; // Null is polygon stop marker. Ignore it + List influencedTriangles=FindInfluencedTriangles(triangles, v); List simplices = new List(); @@ -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 innerSimplices = new List(); 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 innerTriangles = new List(); - 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(); + 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 - // 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)); + // 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); - 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])); + 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; - 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)); + // 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); - 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])); + // 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 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); - meshMX.Add(IPP); - meshMX.Add(IPM); - meshMX.Add(IMP); - meshMX.Add(IMM); + SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); - meshMX.Add(new Triangle(IPP, IMP, IPM)); - meshMX.Add(new Triangle(IPM, IMP, IMM)); + outerHull = hollowedHull; - foreach (Triangle t in meshMX.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); - - 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(); - } } - Mesh result = new Mesh(); - result.Append(meshMX); - result.Append(meshPX); + Mesh m = new Mesh(); - return result; - } + 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); - private static Mesh CreateBoxMeshY(PrimitiveBaseShape primShape, PhysicsVector size) - // Builds the y (+ and -) surfaces of a box shaped prim - { - UInt16 hollowFactor = primShape.ProfileHollow; + m.Add(new Triangle(Seed1, Seed2, Seed3)); + m.Add(outerHull.getVertices()); - // (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)); + InsertVertices(m.vertices, 3, m.triangles); + m.DumpRaw(baseDir, primName, "Proto first Mesh"); - 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])); + 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"); - // (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])); - - if (hollowFactor > 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); - - MeshMY.Add(IPP); - MeshMY.Add(IPM); - MeshMY.Add(IMP); - MeshMY.Add(IMM); - - MeshMY.Add(new Triangle(IPP, IPM, IMP)); - MeshMY.Add(new Triangle(IMP, IPM, IMM)); - - 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 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)); - - - 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])); - - // (P)lus Z - Mesh PZ = new 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)); - - // 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 innerBorders = new List(); - 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(); - 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(); + extr.size = size; + + Mesh result = extr.Extrude(m); + result.DumpRaw(baseDir, primName, "Z extruded"); 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); - - 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.point.X; - vy = t.v2.point.Y; - vz = t.v2.point.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; - 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 f1db034c4a..9ac43bf50e 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) + if (needsMeshing(pbs)) { - result = AddPrim(primName, position, size, rotation, null, null); + mesh = Meshmerizer.CreateMesh(primName, pbs, size); } - else - { - Mesh mesh = Meshmerizer.CreateMesh(pbs, size); - result = AddPrim(primName, position, size, rotation, mesh, pbs); - } - 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); } - else + _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) { - d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + // Cleanup meshing here } + + // Construction of new prim + if (this._parent_scene.needsMeshing(_pbs)) + { + 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); + } } } diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index 7a43a0a0ff..5483703387 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -291,15 +291,23 @@ namespace OpenSim.Region.Physics.PhysXPlugin gravityAccel = 0; } } - - public void UpdatePosition() + public override PrimitiveBaseShape Shape { - Vec3 vec = _character.Position; - _position.X = vec.X; - _position.Y = vec.Y; - _position.Z = vec.Z; + set + { + return; + } } - } + + public void UpdatePosition() + { + Vec3 vec = this._character.Position; + this._position.X = vec.X; + this._position.Y = vec.Y; + this._position.Z = vec.Z; + } + } + public class PhysXPrim : PhysicsActor { @@ -358,55 +366,84 @@ namespace OpenSim.Region.Physics.PhysXPlugin } } + public override PrimitiveBaseShape Shape + { + set + { + return; + } + } + + public override PhysicsVector Velocity + { + get + { + return _velocity; + } + set + { + _velocity = value; + } + } + + public override bool Kinematic + { + get + { + return this._prim.Kinematic; + } + set + { + this._prim.Kinematic = value; + } + } + + public override Quaternion Orientation + { + get + { + Quaternion res = new Quaternion(); + PhysXWrapper.Quaternion quat = this._prim.GetOrientation(); + res.w = quat.W; + res.x = quat.X; + res.y = quat.Y; + res.z = quat.Z; + return res; + } + set + { + + } + } + + public override PhysicsVector Acceleration + { + get + { + return _acceleration; + } + + } + public void SetAcceleration (PhysicsVector accel) + { + this._acceleration = accel; + } + + public override void AddForce(PhysicsVector force) + { + + } + + public override void SetMomentum(PhysicsVector momentum) + { + + } + public override PhysicsVector Size { get { return new PhysicsVector(0, 0, 0); } set { } } - public override PhysicsVector Velocity - { - get { return _velocity; } - set { _velocity = value; } - } - - public override bool Kinematic - { - get { return _prim.Kinematic; } - set { _prim.Kinematic = value; } - } - - public override Quaternion Orientation - { - get - { - Quaternion res = new Quaternion(); - PhysXWrapper.Quaternion quat = _prim.GetOrientation(); - res.w = quat.W; - res.x = quat.X; - res.y = quat.Y; - res.z = quat.Z; - return res; - } - set { } - } - - public override PhysicsVector Acceleration - { - get { return _acceleration; } - } - - public void SetAcceleration(PhysicsVector accel) - { - _acceleration = accel; - } - - public override void AddForce(PhysicsVector force) - { - } - - public override void SetMomentum(PhysicsVector momentum) - { - } } }