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)
parent
b617411b97
commit
f415256e0b
|
@ -65,5 +65,6 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
void releasePinned();
|
void releasePinned();
|
||||||
void Append(IMesh newMesh);
|
void Append(IMesh newMesh);
|
||||||
void TransformLinear(float[,] matrix, float[] offset);
|
void TransformLinear(float[,] matrix, float[] offset);
|
||||||
|
Vector3 GetCentroid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,36 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
IntPtr m_indicesPtr = IntPtr.Zero;
|
IntPtr m_indicesPtr = IntPtr.Zero;
|
||||||
int m_indexCount = 0;
|
int m_indexCount = 0;
|
||||||
public float[] m_normals;
|
public float[] m_normals;
|
||||||
|
Vector3 _centroid;
|
||||||
|
int _centroidDiv;
|
||||||
|
|
||||||
|
private class vertexcomp : IEqualityComparer<Vertex>
|
||||||
|
{
|
||||||
|
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()
|
public Mesh()
|
||||||
{
|
{
|
||||||
m_vertices = new Dictionary<Vertex, int>();
|
vertexcomp vcomp = new vertexcomp();
|
||||||
|
|
||||||
|
m_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||||
m_triangles = new List<Triangle>();
|
m_triangles = new List<Triangle>();
|
||||||
|
_centroid = Vector3.Zero;
|
||||||
|
_centroidDiv = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mesh Clone()
|
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.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
|
||||||
}
|
}
|
||||||
|
result._centroid = _centroid;
|
||||||
|
result._centroidDiv = _centroidDiv;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,15 +97,57 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
|
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
|
||||||
// If a vertex of the triangle is not yet in the vertices list,
|
// If a vertex of the triangle is not yet in the vertices list,
|
||||||
// add it and set its index to the current index count
|
// 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))
|
if (!m_vertices.ContainsKey(triangle.v1))
|
||||||
|
{
|
||||||
m_vertices[triangle.v1] = m_vertices.Count;
|
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))
|
if (!m_vertices.ContainsKey(triangle.v2))
|
||||||
|
{
|
||||||
m_vertices[triangle.v2] = m_vertices.Count;
|
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))
|
if (!m_vertices.ContainsKey(triangle.v3))
|
||||||
|
{
|
||||||
m_vertices[triangle.v3] = m_vertices.Count;
|
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);
|
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()
|
public void CalcNormals()
|
||||||
{
|
{
|
||||||
int iTriangles = m_triangles.Count;
|
int iTriangles = m_triangles.Count;
|
||||||
|
|
|
@ -74,6 +74,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private bool cacheSculptMaps = true;
|
private bool cacheSculptMaps = true;
|
||||||
|
private bool cacheSculptAlphaMaps = true;
|
||||||
|
|
||||||
private string decodedSculptMapPath = null;
|
private string decodedSculptMapPath = null;
|
||||||
private bool useMeshiesPhysicsMesh = false;
|
private bool useMeshiesPhysicsMesh = false;
|
||||||
|
|
||||||
|
@ -87,7 +89,16 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
IConfig mesh_config = config.Configs["Mesh"];
|
IConfig mesh_config = config.Configs["Mesh"];
|
||||||
|
|
||||||
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
|
||||||
|
|
||||||
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
|
||||||
|
|
||||||
|
if (Environment.OSVersion.Platform == PlatformID.Unix)
|
||||||
|
{
|
||||||
|
cacheSculptAlphaMaps = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cacheSculptAlphaMaps = cacheSculptMaps;
|
||||||
|
|
||||||
if(mesh_config != null)
|
if(mesh_config != null)
|
||||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
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))
|
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
||||||
return null;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// keep compatible
|
||||||
// Remove the reference to any JPEG2000 sculpt data so it can be GCed
|
|
||||||
primShape.SculptData = Utils.EmptyBytes;
|
primShape.SculptData = Utils.EmptyBytes;
|
||||||
|
|
||||||
int numCoords = coords.Count;
|
int numCoords = coords.Count;
|
||||||
|
@ -482,7 +496,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
|
//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); }
|
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
|
||||||
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
|
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
|
||||||
|
|
|
@ -58,28 +58,24 @@ namespace PrimMesher
|
||||||
if (bmW == 0 || bmH == 0)
|
if (bmW == 0 || bmH == 0)
|
||||||
throw new Exception("SculptMap: bitmap has no data");
|
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 needsScaling = false;
|
||||||
|
|
||||||
bool smallMap = bmW * bmH <= lod * lod;
|
|
||||||
|
|
||||||
width = bmW;
|
width = bmW;
|
||||||
height = bmH;
|
height = bmH;
|
||||||
while (width * height > numLodPixels)
|
while (width * height > numLodPixels * 4)
|
||||||
{
|
{
|
||||||
width >>= 1;
|
width >>= 1;
|
||||||
height >>= 1;
|
height >>= 1;
|
||||||
needsScaling = true;
|
needsScaling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (needsScaling)
|
if (needsScaling)
|
||||||
bm = ScaleImage(bm, width, height,
|
bm = ScaleImage(bm, width, height);
|
||||||
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -87,7 +83,7 @@ namespace PrimMesher
|
||||||
throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
|
throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width * height > lod * lod)
|
if (width * height > numLodPixels)
|
||||||
{
|
{
|
||||||
width >>= 1;
|
width >>= 1;
|
||||||
height >>= 1;
|
height >>= 1;
|
||||||
|
@ -144,15 +140,17 @@ namespace PrimMesher
|
||||||
int rowNdx, colNdx;
|
int rowNdx, colNdx;
|
||||||
int smNdx = 0;
|
int smNdx = 0;
|
||||||
|
|
||||||
|
|
||||||
for (rowNdx = 0; rowNdx < numRows; rowNdx++)
|
for (rowNdx = 0; rowNdx < numRows; rowNdx++)
|
||||||
{
|
{
|
||||||
List<Coord> row = new List<Coord>(numCols);
|
List<Coord> row = new List<Coord>(numCols);
|
||||||
for (colNdx = 0; colNdx < numCols; colNdx++)
|
for (colNdx = 0; colNdx < numCols; colNdx++)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (mirror)
|
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
|
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;
|
++smNdx;
|
||||||
}
|
}
|
||||||
|
@ -161,23 +159,39 @@ namespace PrimMesher
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight,
|
private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
|
||||||
System.Drawing.Drawing2D.InterpolationMode interpMode)
|
|
||||||
{
|
{
|
||||||
Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight);
|
|
||||||
scaledImage.SetResolution(96.0f, 96.0f);
|
|
||||||
|
|
||||||
Graphics grPhoto = Graphics.FromImage(scaledImage);
|
Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
|
||||||
grPhoto.InterpolationMode = interpMode;
|
|
||||||
|
|
||||||
grPhoto.DrawImage(srcImage,
|
Color c;
|
||||||
new Rectangle(0, 0, destWidth, destHeight),
|
float xscale = srcImage.Width / destWidth;
|
||||||
new Rectangle(0, 0, srcImage.Width, srcImage.Height),
|
float yscale = srcImage.Height / destHeight;
|
||||||
GraphicsUnit.Pixel);
|
|
||||||
|
|
||||||
grPhoto.Dispose();
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
sx += xscale;
|
||||||
|
}
|
||||||
|
sy += yscale;
|
||||||
|
}
|
||||||
|
srcImage.Dispose();
|
||||||
return scaledImage;
|
return scaledImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
@ -1056,9 +1055,8 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// primOOBoffset = mesh.GetCentroid();
|
primOOBoffset = mesh.GetCentroid();
|
||||||
// hasOOBoffsetFromMesh = true;
|
hasOOBoffsetFromMesh = true;
|
||||||
hasOOBoffsetFromMesh = false;
|
|
||||||
|
|
||||||
_triMeshData = d.GeomTriMeshDataCreate();
|
_triMeshData = d.GeomTriMeshDataCreate();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue