diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index cc9248450a..c32cf38e5d 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs @@ -36,6 +36,7 @@ namespace OpenSim.Region.Physics.Manager { IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); + IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex); } // Values for level of detail to be passed to the mesher. diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index ba19db6c18..8a3b50bdad 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs @@ -67,6 +67,11 @@ namespace OpenSim.Region.Physics.Manager return CreateMesh(primName, primShape, size, lod, false); } + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) + { + return CreateMesh(primName, primShape, size, lod, false); + } + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) { // Remove the reference to the encoded JPEG2000 data so it can be GCed diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 79e50d29af..75fa1efd45 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -717,6 +717,11 @@ namespace OpenSim.Region.Physics.Meshing return CreateMesh(primName, primShape, size, lod, false); } + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) + { + return CreateMesh(primName, primShape, size, lod, false); + } + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) { #if SPAM diff --git a/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs b/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs index 8cd8dcf6ff..293825779e 100644 --- a/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs +++ b/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs @@ -270,116 +270,20 @@ public class Triangle 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) + public Triangle(float _v1x,float _v1y,float _v1z, + float _v2x,float _v2y,float _v2z, + float _v3x,float _v3y,float _v3z) { - 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); + v1 = new Vertex(_v1x, _v1y, _v1z); + v2 = new Vertex(_v2x, _v2y, _v2z); + v3 = new Vertex(_v3x, _v3y, _v3z); } public override String ToString() diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index c9c52c0fba..7667e91f62 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs @@ -41,6 +41,7 @@ using Nini.Config; using System.Reflection; using System.IO; using ComponentAce.Compression.Libs.zlib; +using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.Meshing { @@ -256,7 +257,7 @@ namespace OpenSim.Region.Physics.Meshing /// /// /// - private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) + private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex) { // m_log.DebugFormat( // "[MESH]: Creating physics proxy for {0}, shape {1}", @@ -272,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing if (!useMeshiesPhysicsMesh) return null; - if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces)) + if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex)) return null; } else @@ -296,22 +297,20 @@ namespace OpenSim.Region.Physics.Meshing int numCoords = coords.Count; int numFaces = faces.Count; - // Create the list of vertices - List vertices = new List(); - for (int i = 0; i < numCoords; i++) - { - Coord c = coords[i]; - vertices.Add(new Vertex(c.X, c.Y, c.Z)); - } - Mesh mesh = new Mesh(); // Add the corresponding triangles to the mesh for (int i = 0; i < numFaces; i++) { Face f = faces[i]; - mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); + mesh.Add(new Triangle(coords[f.v1].X, coords[f.v1].Y, coords[f.v1].Z, + coords[f.v2].X, coords[f.v2].Y, coords[f.v2].Z, + coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z)); } + +// mesh.DumpRaw("c:\\lixo", "lixo", "lixo"); + mesh.DumpRaw(".", "lixo", "lixo"); + return mesh; } @@ -325,10 +324,12 @@ namespace OpenSim.Region.Physics.Meshing /// Faces are added to this list by the method. /// true if coords and faces were successfully generated, false if not private bool GenerateCoordsAndFacesFromPrimMeshData( - string primName, PrimitiveBaseShape primShape, Vector3 size, out List coords, out List faces) + string primName, PrimitiveBaseShape primShape, Vector3 size, out List coords, out List faces, bool convex) { // m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); + bool usemesh = false; + coords = new List(); faces = new List(); OSD meshOsd = null; @@ -365,14 +366,25 @@ namespace OpenSim.Region.Physics.Meshing { OSDMap physicsParms = null; OSDMap map = (OSDMap)meshOsd; - if (map.ContainsKey("physics_shape")) - physicsParms = (OSDMap)map["physics_shape"]; // old asset format - else if (map.ContainsKey("physics_mesh")) - physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + + if (!convex) + { + if (map.ContainsKey("physics_shape")) + physicsParms = (OSDMap)map["physics_shape"]; // old asset format + else if (map.ContainsKey("physics_mesh")) + physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + + if (physicsParms != null) + usemesh = true; + } + + if(!usemesh && (map.ContainsKey("physics_convex"))) + physicsParms = (OSDMap)map["physics_convex"]; + if (physicsParms == null) { - m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); + m_log.Warn("[MESH]: unknown mesh type"); return false; } @@ -416,20 +428,270 @@ namespace OpenSim.Region.Physics.Meshing return false; } - OSDArray decodedMeshOsdArray = null; - - // physics_shape is an array of OSDMaps, one for each submesh - if (decodedMeshOsd is OSDArray) + if (usemesh) { -// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); + OSDArray decodedMeshOsdArray = null; - decodedMeshOsdArray = (OSDArray)decodedMeshOsd; - foreach (OSD subMeshOsd in decodedMeshOsdArray) + // physics_shape is an array of OSDMaps, one for each submesh + if (decodedMeshOsd is OSDArray) { - if (subMeshOsd is OSDMap) - AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); + // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); + + decodedMeshOsdArray = (OSDArray)decodedMeshOsd; + foreach (OSD subMeshOsd in decodedMeshOsdArray) + { + if (subMeshOsd is OSDMap) + AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); + } } } + else + { + OSDMap cmap = (OSDMap)decodedMeshOsd; + if (cmap == null) + return false; + + byte[] data; + const float invMaxU16 = 1.0f / 65535f; + int t1; + int t2; + int t3; + int i; + + List vs = new List(); + + float3 f3; + PHullResult hullr = new PHullResult(); + + Coord c; + Face f; + + Vector3 range; + Vector3 min; + int nverts; + int nindexs; + + if (cmap.ContainsKey("Max")) + range = cmap["Max"].AsVector3(); + else + range = new Vector3(0.5f, 0.5f, 0.5f); + + if (cmap.ContainsKey("Min")) + min = cmap["Min"].AsVector3(); + else + min = new Vector3(-0.5f, -0.5f, -0.5f); + + range = range - min; + range *= invMaxU16; + + if (!convex && cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions")) + { + List hsizes = new List(); + int totalpoints = 0; + data = cmap["HullList"].AsBinary(); + for (i = 0; i < data.Length; i++) + { + t1 = data[i]; + if (t1 == 0) + t1 = 256; + totalpoints += t1; + hsizes.Add(t1); + } + + data = cmap["Positions"].AsBinary(); + int ptr = 0; + int vertsoffset = 0; + + if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point + { + foreach (int hullsize in hsizes) + { + for (i = 0; i < hullsize; i++ ) + { + t1 = data[ptr++]; + t1 += data[ptr++] << 8; + t2 = data[ptr++]; + t2 += data[ptr++] << 8; + t3 = data[ptr++]; + t3 += data[ptr++] << 8; + + f3 = new float3((t1 * range.X + min.X) * size.X, + (t2 * range.Y + min.Y) * size.Y, + (t3 * range.Z + min.Z) * size.Z); + vs.Add(f3); + } + + if(hullsize <3) + { + vs.Clear(); + continue; + } + + if (hullsize <5) + { + foreach (float3 point in vs) + { + c.X = point.x; + c.Y = point.y; + c.Z = point.z; + coords.Add(c); + } + f = new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2); + faces.Add(f); + + if (hullsize == 4) + { + // not sure about orientation.. + f = new Face(vertsoffset, vertsoffset + 2, vertsoffset + 3); + faces.Add(f); + f = new Face(vertsoffset, vertsoffset + 3, vertsoffset + 1); + faces.Add(f); + f = new Face(vertsoffset + 3, vertsoffset + 2, vertsoffset + 1); + faces.Add(f); + } + vertsoffset += vs.Count; + vs.Clear(); + continue; + } + + if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) + { + vs.Clear(); + continue; + } + + nverts = hullr.Vertices.Count; + nindexs = hullr.Indices.Count; + + if (nindexs % 3 != 0) + { + vs.Clear(); + continue; + } + + for (i = 0; i < nverts; i++) + { + c.X = hullr.Vertices[i].x; + c.Y = hullr.Vertices[i].y; + c.Z = hullr.Vertices[i].z; + coords.Add(c); + } + + + for (i = 0; i < nindexs; i += 3) + { + t1 = hullr.Indices[i]; + if (t1 > nverts) + break; + t2 = hullr.Indices[i + 1]; + if (t2 > nverts) + break; + t3 = hullr.Indices[i + 2]; + if (t3 > nverts) + break; + f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3); + faces.Add(f); + } + vertsoffset += nverts; + vs.Clear(); + } + } + if (coords.Count > 0 && faces.Count > 0) + return true; + + } + + vs.Clear(); + + if (cmap.ContainsKey("BoundingVerts")) + { + data = cmap["BoundingVerts"].AsBinary(); + + for (i = 0; i < data.Length; ) + { + t1 = data[i++]; + t1 += data[i++] << 8; + t2 = data[i++]; + t2 += data[i++] << 8; + t3 = data[i++]; + t3 += data[i++] << 8; + + f3 = new float3((t1 * range.X + min.X) * size.X, + (t2 * range.Y + min.Y) * size.Y, + (t3 * range.Z + min.Z) * size.Z); + vs.Add(f3); + } + + if (vs.Count < 3) + { + vs.Clear(); + return false; + } + + if (vs.Count < 5) + { + foreach (float3 point in vs) + { + c.X = point.x; + c.Y = point.y; + c.Z = point.z; + coords.Add(c); + } + f = new Face(0, 1, 2); + faces.Add(f); + + if (vs.Count == 4) + { + // not sure about orientation.. + f = new Face(0, 2, 3); + faces.Add(f); + f = new Face(0, 3, 1); + faces.Add(f); + f = new Face( 3, 2, 1); + faces.Add(f); + } + vs.Clear(); + return true; + } + + if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) + return false; + + nverts = hullr.Vertices.Count; + nindexs = hullr.Indices.Count; + + if (nindexs % 3 != 0) + return false; + + for (i = 0; i < nverts; i++) + { + c.X = hullr.Vertices[i].x; + c.Y = hullr.Vertices[i].y; + c.Z = hullr.Vertices[i].z; + coords.Add(c); + } + for (i = 0; i < nindexs; i += 3) + { + t1 = hullr.Indices[i]; + if (t1 > nverts) + break; + t2 = hullr.Indices[i + 1]; + if (t2 > nverts) + break; + t3 = hullr.Indices[i + 2]; + if (t3 > nverts) + break; + f = new Face(t1, t2, t3); + faces.Add(f); + } + + if (coords.Count > 0 && faces.Count > 0) + return true; + } + else + return false; + + } } return true; @@ -714,11 +976,16 @@ namespace OpenSim.Region.Physics.Meshing public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) { - return CreateMesh(primName, primShape, size, lod, false); + return CreateMesh(primName, primShape, size, lod, false,false); } public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) { + return CreateMesh(primName, primShape, size, lod, false,false); + } + + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) + { #if SPAM m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); #endif @@ -736,7 +1003,7 @@ namespace OpenSim.Region.Physics.Meshing if (size.Y < 0.01f) size.Y = 0.01f; if (size.Z < 0.01f) size.Z = 0.01f; - mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); + mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); if (mesh != null) {