From f415256e0b0d4b0191d52cb84090a0f1b0044ae9 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 11 Feb 2012 03:25:17 +0000 Subject: [PATCH] Use mesh to estimate real center of prims if avaiable. Let sculpt map textures with alpha channel work. On linux J2DecodeCache folder must be deleted to remove bad entries. Corrently this can't be cached on linux (mono/ cairo/? problem) --- OpenSim/Region/Physics/Manager/IMesher.cs | 1 + OpenSim/Region/Physics/Meshing/Mesh.cs | 72 ++++++++++++++++++- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 21 +++++- OpenSim/Region/Physics/Meshing/SculptMap.cs | 62 +++++++++------- .../Region/Physics/UbitOdePlugin/ODEPrim.cs | 6 +- 5 files changed, 129 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index 3a9ca1bd34..cc9248450a 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs @@ -65,5 +65,6 @@ namespace OpenSim.Region.Physics.Manager void releasePinned(); void Append(IMesh newMesh); void TransformLinear(float[,] matrix, float[] offset); + Vector3 GetCentroid(); } } diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs index f781ff9bd0..c715642bac 100644 --- a/OpenSim/Region/Physics/Meshing/Mesh.cs +++ b/OpenSim/Region/Physics/Meshing/Mesh.cs @@ -46,11 +46,36 @@ namespace OpenSim.Region.Physics.Meshing IntPtr m_indicesPtr = IntPtr.Zero; int m_indexCount = 0; public float[] m_normals; + Vector3 _centroid; + int _centroidDiv; + + private class vertexcomp : IEqualityComparer + { + public bool Equals(Vertex v1, Vertex v2) + { + if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z) + return true; + else + return false; + } + public int GetHashCode(Vertex v) + { + int a = v.X.GetHashCode(); + int b = v.Y.GetHashCode(); + int c = v.Z.GetHashCode(); + return (a << 16) ^ (b << 8) ^ c; + } + + } public Mesh() { - m_vertices = new Dictionary(); + vertexcomp vcomp = new vertexcomp(); + + m_vertices = new Dictionary(vcomp); m_triangles = new List(); + _centroid = Vector3.Zero; + _centroidDiv = 0; } public Mesh Clone() @@ -61,7 +86,8 @@ namespace OpenSim.Region.Physics.Meshing { result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); } - + result._centroid = _centroid; + result._centroidDiv = _centroidDiv; return result; } @@ -71,15 +97,57 @@ namespace OpenSim.Region.Physics.Meshing throw new NotSupportedException("Attempt to Add to a pinned Mesh"); // If a vertex of the triangle is not yet in the vertices list, // add it and set its index to the current index count + // vertex == seems broken + // skip colapsed triangles + if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) + || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) + || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) + ) + { + return; + } + + if (m_vertices.Count == 0) + { + _centroidDiv = 0; + _centroid = Vector3.Zero; + } + if (!m_vertices.ContainsKey(triangle.v1)) + { m_vertices[triangle.v1] = m_vertices.Count; + _centroid.X += triangle.v1.X; + _centroid.Y += triangle.v1.Y; + _centroid.Z += triangle.v1.Z; + _centroidDiv++; + } if (!m_vertices.ContainsKey(triangle.v2)) + { m_vertices[triangle.v2] = m_vertices.Count; + _centroid.X += triangle.v2.X; + _centroid.Y += triangle.v2.Y; + _centroid.Z += triangle.v2.Z; + _centroidDiv++; + } if (!m_vertices.ContainsKey(triangle.v3)) + { m_vertices[triangle.v3] = m_vertices.Count; + _centroid.X += triangle.v3.X; + _centroid.Y += triangle.v3.Y; + _centroid.Z += triangle.v3.Z; + _centroidDiv++; + } m_triangles.Add(triangle); } + public Vector3 GetCentroid() + { + if (_centroidDiv > 0) + return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv); + else + return Vector3.Zero; + } + public void CalcNormals() { int iTriangles = m_triangles.Count; diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index f15e81ba8e..ba461f7b67 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -74,6 +74,8 @@ namespace OpenSim.Region.Physics.Meshing #endif private bool cacheSculptMaps = true; + private bool cacheSculptAlphaMaps = true; + private string decodedSculptMapPath = null; private bool useMeshiesPhysicsMesh = false; @@ -87,7 +89,16 @@ namespace OpenSim.Region.Physics.Meshing IConfig mesh_config = config.Configs["Mesh"]; decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); + cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + cacheSculptAlphaMaps = false; + } + else + cacheSculptAlphaMaps = cacheSculptMaps; + if(mesh_config != null) useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); @@ -268,15 +279,18 @@ namespace OpenSim.Region.Physics.Meshing { if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces)) return null; + // Remove the reference to any JPEG2000 sculpt data so it can be GCed + // don't loose it + // primShape.SculptData = Utils.EmptyBytes; } +// primShape.SculptDataLoaded = true; } else { if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) return null; } - - // Remove the reference to any JPEG2000 sculpt data so it can be GCed + // keep compatible primShape.SculptData = Utils.EmptyBytes; int numCoords = coords.Count; @@ -482,7 +496,8 @@ namespace OpenSim.Region.Physics.Meshing //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); - if (cacheSculptMaps) + if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0))) + // don't cache images with alpha channel in linux since mono can't load them correctly) { try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); } diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs index 740424ef91..b3d9cb62f3 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMap.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMap.cs @@ -58,28 +58,24 @@ namespace PrimMesher if (bmW == 0 || bmH == 0) throw new Exception("SculptMap: bitmap has no data"); - int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image + int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image + bool smallMap = bmW * bmH <= numLodPixels; bool needsScaling = false; - bool smallMap = bmW * bmH <= lod * lod; - width = bmW; height = bmH; - while (width * height > numLodPixels) + while (width * height > numLodPixels * 4) { width >>= 1; height >>= 1; needsScaling = true; } - - try { if (needsScaling) - bm = ScaleImage(bm, width, height, - System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); + bm = ScaleImage(bm, width, height); } catch (Exception e) @@ -87,7 +83,7 @@ namespace PrimMesher throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); } - if (width * height > lod * lod) + if (width * height > numLodPixels) { width >>= 1; height >>= 1; @@ -144,15 +140,17 @@ namespace PrimMesher int rowNdx, colNdx; int smNdx = 0; + for (rowNdx = 0; rowNdx < numRows; rowNdx++) { List row = new List(numCols); for (colNdx = 0; colNdx < numCols; colNdx++) { + if (mirror) - row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); + row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f)); else - row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); + row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f)); ++smNdx; } @@ -161,23 +159,39 @@ namespace PrimMesher return rows; } - private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, - System.Drawing.Drawing2D.InterpolationMode interpMode) + private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight) { - Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight); - scaledImage.SetResolution(96.0f, 96.0f); - Graphics grPhoto = Graphics.FromImage(scaledImage); - grPhoto.InterpolationMode = interpMode; + Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); + + Color c; + float xscale = srcImage.Width / destWidth; + float yscale = srcImage.Height / destHeight; + + float sy = 0.5f; + for (int y = 0; y < destHeight; y++) + { + float sx = 0.5f; + for (int x = 0; x < destWidth; x++) + { + try + { + c = srcImage.GetPixel((int)(sx), (int)(sy)); + scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B)); + } + catch (IndexOutOfRangeException) + { + } - grPhoto.DrawImage(srcImage, - new Rectangle(0, 0, destWidth, destHeight), - new Rectangle(0, 0, srcImage.Width, srcImage.Height), - GraphicsUnit.Pixel); - - grPhoto.Dispose(); + sx += xscale; + } + sy += yscale; + } + srcImage.Dispose(); return scaledImage; } + + } + } -} #endif diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index b0dbe504bf..073c37fa65 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -1,4 +1,3 @@ - /* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. @@ -1056,9 +1055,8 @@ namespace OpenSim.Region.Physics.OdePlugin return false; } -// primOOBoffset = mesh.GetCentroid(); -// hasOOBoffsetFromMesh = true; - hasOOBoffsetFromMesh = false; + primOOBoffset = mesh.GetCentroid(); + hasOOBoffsetFromMesh = true; _triMeshData = d.GeomTriMeshDataCreate();