Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork

avinationmerge
ubit 2012-10-13 00:40:07 +02:00
commit 77b170f1f6
3 changed files with 532 additions and 282 deletions

View File

@ -32,30 +32,49 @@ using System.Runtime.InteropServices;
using OpenSim.Region.Physics.Manager;
using PrimMesher;
using OpenMetaverse;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace OpenSim.Region.Physics.Meshing
{
public class MeshBuildingData
{
public Dictionary<Vertex, int> m_vertices;
public List<Triangle> m_triangles;
public float m_obbXmin;
public float m_obbXmax;
public float m_obbYmin;
public float m_obbYmax;
public float m_obbZmin;
public float m_obbZmax;
public Vector3 m_centroid;
public int m_centroidDiv;
}
[Serializable()]
public class Mesh : IMesh
{
private Dictionary<Vertex, int> m_vertices;
private List<Triangle> m_triangles;
GCHandle m_pinnedVertexes;
GCHandle m_pinnedIndex;
float[] vertices;
int[] indexes;
Vector3 m_obb;
Vector3 m_obboffset;
[NonSerialized()]
MeshBuildingData m_bdata;
[NonSerialized()]
GCHandle vhandler;
[NonSerialized()]
GCHandle ihandler;
[NonSerialized()]
IntPtr m_verticesPtr = IntPtr.Zero;
int m_vertexCount = 0;
[NonSerialized()]
IntPtr m_indicesPtr = IntPtr.Zero;
[NonSerialized()]
int m_vertexCount = 0;
[NonSerialized()]
int m_indexCount = 0;
public float[] m_normals;
Vector3 m_centroid;
float m_obbXmin;
float m_obbXmax;
float m_obbYmin;
float m_obbYmax;
float m_obbZmin;
float m_obbZmax;
int m_centroidDiv;
public int RefCount { get; set; }
public AMeshKey Key { get; set; }
private class vertexcomp : IEqualityComparer<Vertex>
{
@ -79,42 +98,82 @@ namespace OpenSim.Region.Physics.Meshing
{
vertexcomp vcomp = new vertexcomp();
m_vertices = new Dictionary<Vertex, int>(vcomp);
m_triangles = new List<Triangle>();
m_centroid = Vector3.Zero;
m_centroidDiv = 0;
m_obbXmin = float.MaxValue;
m_obbXmax = float.MinValue;
m_obbYmin = float.MaxValue;
m_obbYmax = float.MinValue;
m_obbZmin = float.MaxValue;
m_obbZmax = float.MinValue;
m_bdata = new MeshBuildingData();
m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
m_bdata.m_triangles = new List<Triangle>();
m_bdata.m_centroid = Vector3.Zero;
m_bdata.m_centroidDiv = 0;
m_bdata.m_obbXmin = float.MaxValue;
m_bdata.m_obbXmax = float.MinValue;
m_bdata.m_obbYmin = float.MaxValue;
m_bdata.m_obbYmax = float.MinValue;
m_bdata.m_obbZmin = float.MaxValue;
m_bdata.m_obbZmax = float.MinValue;
m_obb = new Vector3(0.5f, 0.5f, 0.5f);
m_obboffset = Vector3.Zero;
}
public int RefCount { get; set; }
public AMeshKey Key { get; set; }
public void Scale(Vector3 scale)
public Mesh Scale(Vector3 scale)
{
if (m_verticesPtr == null || m_indicesPtr == null)
return null;
Mesh result = new Mesh();
float x = scale.X;
float y = scale.Y;
float z = scale.Z;
result.m_obb.X = m_obb.X * x;
result.m_obb.Y = m_obb.Y * y;
result.m_obb.Z = m_obb.Z * z;
result.m_obboffset.X = m_obboffset.X * x;
result.m_obboffset.Y = m_obboffset.Y * y;
result.m_obboffset.Z = m_obboffset.Z * z;
result.vertices = new float[vertices.Length];
int j = 0;
for (int i = 0; i < m_vertexCount; i++)
{
result.vertices[j] = vertices[j] * x;
j++;
result.vertices[j] = vertices[j] * y;
j++;
result.vertices[j] = vertices[j] * z;
j++;
}
result.indexes = new int[indexes.Length];
indexes.CopyTo(result.indexes,0);
result.pinMemory();
return result;
}
public Mesh Clone()
{
Mesh result = new Mesh();
foreach (Triangle t in m_triangles)
if (m_bdata != null)
{
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
result.m_bdata = new MeshBuildingData();
foreach (Triangle t in m_bdata.m_triangles)
{
result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
}
result.m_bdata.m_centroid = m_bdata.m_centroid;
result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
}
result.m_centroid = m_centroid;
result.m_centroidDiv = m_centroidDiv;
result.m_obbXmin = m_obbXmin;
result.m_obbXmax = m_obbXmax;
result.m_obbYmin = m_obbYmin;
result.m_obbYmax = m_obbYmax;
result.m_obbZmin = m_obbZmin;
result.m_obbZmax = m_obbZmax;
result.m_obb = m_obb;
result.m_obboffset = m_obboffset;
return result;
}
@ -124,37 +183,34 @@ namespace OpenSim.Region.Physics.Meshing
float y = v.Y;
float z = v.Z;
m_centroid.X += x;
m_centroid.Y += y;
m_centroid.Z += z;
m_centroidDiv++;
m_bdata.m_centroid.X += x;
m_bdata.m_centroid.Y += y;
m_bdata.m_centroid.Z += z;
m_bdata.m_centroidDiv++;
if (x > m_obbXmax)
m_obbXmax = x;
else if (x < m_obbXmin)
m_obbXmin = x;
if (x > m_bdata.m_obbXmax)
m_bdata.m_obbXmax = x;
else if (x < m_bdata.m_obbXmin)
m_bdata.m_obbXmin = x;
if (y > m_obbYmax)
m_obbYmax = y;
else if (y < m_obbYmin)
m_obbYmin = y;
if (y > m_bdata.m_obbYmax)
m_bdata.m_obbYmax = y;
else if (y < m_bdata.m_obbYmin)
m_bdata.m_obbYmin = y;
if (z > m_obbZmax)
m_obbZmax = z;
else if (z < m_obbZmin)
m_obbZmin = z;
if (z > m_bdata.m_obbZmax)
m_bdata.m_obbZmax = z;
else if (z < m_bdata.m_obbZmin)
m_bdata.m_obbZmin = z;
}
public void Add(Triangle triangle)
{
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
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)
@ -163,46 +219,45 @@ namespace OpenSim.Region.Physics.Meshing
return;
}
if (m_vertices.Count == 0)
if (m_bdata.m_vertices.Count == 0)
{
m_centroidDiv = 0;
m_centroid = Vector3.Zero;
m_bdata.m_centroidDiv = 0;
m_bdata.m_centroid = Vector3.Zero;
}
if (!m_vertices.ContainsKey(triangle.v1))
if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
{
m_vertices[triangle.v1] = m_vertices.Count;
m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
addVertexLStats(triangle.v1);
}
if (!m_vertices.ContainsKey(triangle.v2))
if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
{
m_vertices[triangle.v2] = m_vertices.Count;
m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
addVertexLStats(triangle.v2);
}
if (!m_vertices.ContainsKey(triangle.v3))
if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
{
m_vertices[triangle.v3] = m_vertices.Count;
m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
addVertexLStats(triangle.v3);
}
m_triangles.Add(triangle);
m_bdata.m_triangles.Add(triangle);
}
public Vector3 GetCentroid()
{
if (m_centroidDiv > 0)
return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
else
return Vector3.Zero;
return m_obboffset;
}
public Vector3 GetOBB()
{
return m_obb;
float x, y, z;
if (m_centroidDiv > 0)
if (m_bdata.m_centroidDiv > 0)
{
x = (m_obbXmax - m_obbXmin) * 0.5f;
y = (m_obbYmax - m_obbYmin) * 0.5f;
z = (m_obbZmax - m_obbZmin) * 0.5f;
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
}
else // ??
{
@ -213,72 +268,10 @@ namespace OpenSim.Region.Physics.Meshing
return new Vector3(x, y, z);
}
public void CalcNormals()
{
int iTriangles = m_triangles.Count;
this.m_normals = new float[iTriangles * 3];
int i = 0;
foreach (Triangle t in m_triangles)
{
float ux, uy, uz;
float vx, vy, vz;
float wx, wy, wz;
ux = t.v1.X;
uy = t.v1.Y;
uz = t.v1.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;
// Vectors for edges
float e1x, e1y, e1z;
float e2x, e2y, e2z;
e1x = ux - vx;
e1y = uy - vy;
e1z = uz - vz;
e2x = ux - wx;
e2y = uy - wy;
e2z = uz - wz;
// Cross product for normal
float nx, ny, nz;
nx = e1y * e2z - e1z * e2y;
ny = e1z * e2x - e1x * e2z;
nz = e1x * e2y - e1y * e2x;
// Length
float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
float lReciprocal = 1.0f / l;
// Normalized "normal"
//nx /= l;
//ny /= l;
//nz /= l;
m_normals[i] = nx * lReciprocal;
m_normals[i + 1] = ny * lReciprocal;
m_normals[i + 2] = nz * lReciprocal;
i += 3;
}
}
public List<Vector3> getVertexList()
{
List<Vector3> result = new List<Vector3>();
foreach (Vertex v in m_vertices.Keys)
foreach (Vertex v in m_bdata.m_vertices.Keys)
{
result.Add(new Vector3(v.X, v.Y, v.Z));
}
@ -287,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
private float[] getVertexListAsFloat()
{
if (m_vertices == null)
if (m_bdata.m_vertices == null)
throw new NotSupportedException();
float[] result = new float[m_vertices.Count * 3];
foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
float[] result = new float[m_bdata.m_vertices.Count * 3];
foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
{
Vertex v = kvp.Key;
int i = kvp.Value;
@ -303,74 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
public float[] getVertexListAsFloatLocked()
{
if (m_pinnedVertexes.IsAllocated)
return (float[])(m_pinnedVertexes.Target);
float[] result = getVertexListAsFloat();
m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
// Inform the garbage collector of this unmanaged allocation so it can schedule
// the next GC round more intelligently
GC.AddMemoryPressure(Buffer.ByteLength(result));
return result;
return null;
}
public void PrepForOde()
{
// If there isn't an unmanaged array allocated yet, do it now
if (m_verticesPtr == IntPtr.Zero)
{
float[] vertexList = getVertexListAsFloat();
// Each vertex is 3 elements (floats)
m_vertexCount = vertexList.Length / 3;
int byteCount = m_vertexCount * 3 * sizeof(float);
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
}
// If there isn't an unmanaged array allocated yet, do it now
if (m_indicesPtr == IntPtr.Zero)
{
int[] indexList = getIndexListAsInt();
m_indexCount = indexList.Length;
int byteCount = m_indexCount * sizeof(int);
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
}
releaseSourceMeshData();
}
public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
{
// A vertex is 3 floats
vertexStride = 3 * sizeof(float);
// If there isn't an unmanaged array allocated yet, do it now
if (m_verticesPtr == IntPtr.Zero)
if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
{
float[] vertexList = getVertexListAsFloat();
vertices = getVertexListAsFloat();
// Each vertex is 3 elements (floats)
m_vertexCount = vertexList.Length / 3;
int byteCount = m_vertexCount * vertexStride;
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
m_vertexCount = vertices.Length / 3;
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
m_verticesPtr = vhandler.AddrOfPinnedObject();
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
}
vertices = m_verticesPtr;
_vertices = m_verticesPtr;
vertexCount = m_vertexCount;
}
public int[] getIndexListAsInt()
{
if (m_triangles == null)
if (m_bdata.m_triangles == null)
throw new NotSupportedException();
int[] result = new int[m_triangles.Count * 3];
for (int i = 0; i < m_triangles.Count; i++)
int[] result = new int[m_bdata.m_triangles.Count * 3];
for (int i = 0; i < m_bdata.m_triangles.Count; i++)
{
Triangle t = m_triangles[i];
result[3 * i + 0] = m_vertices[t.v1];
result[3 * i + 1] = m_vertices[t.v2];
result[3 * i + 2] = m_vertices[t.v3];
Triangle t = m_bdata.m_triangles[i];
result[3 * i + 0] = m_bdata.m_vertices[t.v1];
result[3 * i + 1] = m_bdata.m_vertices[t.v2];
result[3 * i + 2] = m_bdata.m_vertices[t.v3];
}
return result;
}
@ -381,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
/// <returns></returns>
public int[] getIndexListAsIntLocked()
{
if (m_pinnedIndex.IsAllocated)
return (int[])(m_pinnedIndex.Target);
int[] result = getIndexListAsInt();
m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
// Inform the garbage collector of this unmanaged allocation so it can schedule
// the next GC round more intelligently
GC.AddMemoryPressure(Buffer.ByteLength(result));
return result;
return null;
}
public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
{
// If there isn't an unmanaged array allocated yet, do it now
if (m_indicesPtr == IntPtr.Zero)
if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
{
int[] indexList = getIndexListAsInt();
m_indexCount = indexList.Length;
int byteCount = m_indexCount * sizeof(int);
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
indexes = getIndexListAsInt();
m_indexCount = indexes.Length;
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
m_indicesPtr = ihandler.AddrOfPinnedObject();
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
}
// A triangle is 3 ints (indices)
triStride = 3 * sizeof(int);
@ -412,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
public void releasePinned()
{
if (m_pinnedVertexes.IsAllocated)
m_pinnedVertexes.Free();
if (m_pinnedIndex.IsAllocated)
m_pinnedIndex.Free();
if (m_verticesPtr != IntPtr.Zero)
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
vhandler.Free();
vertices = null;
m_verticesPtr = IntPtr.Zero;
}
if (m_indicesPtr != IntPtr.Zero)
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
ihandler.Free();
indexes = null;
m_indicesPtr = IntPtr.Zero;
}
}
@ -433,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
/// </summary>
public void releaseSourceMeshData()
{
m_triangles = null;
m_vertices = null;
if (m_bdata != null)
{
m_bdata.m_triangles = null;
m_bdata.m_vertices = null;
}
}
public void releaseBuildingMeshData()
{
if (m_bdata != null)
{
m_bdata.m_triangles = null;
m_bdata.m_vertices = null;
m_bdata = null;
}
}
public void Append(IMesh newMesh)
{
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
throw new NotSupportedException("Attempt to Append to a pinned Mesh");
if (!(newMesh is Mesh))
return;
foreach (Triangle t in ((Mesh)newMesh).m_triangles)
foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
Add(t);
}
// Do a linear transformation of mesh.
public void TransformLinear(float[,] matrix, float[] offset)
{
if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
foreach (Vertex v in m_vertices.Keys)
foreach (Vertex v in m_bdata.m_vertices.Keys)
{
if (v == null)
continue;
@ -473,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
{
if (path == null)
return;
if (m_bdata == null)
return;
String fileName = name + "_" + title + ".raw";
String completePath = System.IO.Path.Combine(path, fileName);
StreamWriter sw = new StreamWriter(completePath);
foreach (Triangle t in m_triangles)
foreach (Triangle t in m_bdata.m_triangles)
{
String s = t.ToStringRaw();
sw.WriteLine(s);
@ -486,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
public void TrimExcess()
{
m_triangles.TrimExcess();
m_bdata.m_triangles.TrimExcess();
}
public void pinMemory()
{
m_vertexCount = vertices.Length / 3;
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
m_verticesPtr = vhandler.AddrOfPinnedObject();
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
m_indexCount = indexes.Length;
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
m_indicesPtr = ihandler.AddrOfPinnedObject();
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
}
public void PrepForOde()
{
// If there isn't an unmanaged array allocated yet, do it now
if (m_verticesPtr == IntPtr.Zero)
vertices = getVertexListAsFloat();
// If there isn't an unmanaged array allocated yet, do it now
if (m_indicesPtr == IntPtr.Zero)
indexes = getIndexListAsInt();
pinMemory();
float x, y, z;
if (m_bdata.m_centroidDiv > 0)
{
m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
}
else
{
m_obboffset = Vector3.Zero;
x = 0.5f;
y = 0.5f;
z = 0.5f;
}
m_obb = new Vector3(x, y, z);
releaseBuildingMeshData();
}
public bool ToStream(Stream st)
{
if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
return false;
BinaryWriter bw = new BinaryWriter(st);
bool ok = true;
try
{
bw.Write(m_vertexCount);
bw.Write(m_indexCount);
for (int i = 0; i < 3 * m_vertexCount; i++)
bw.Write(vertices[i]);
for (int i = 0; i < m_indexCount; i++)
bw.Write(indexes[i]);
bw.Write(m_obb.X);
bw.Write(m_obb.Y);
bw.Write(m_obb.Z);
bw.Write(m_obboffset.X);
bw.Write(m_obboffset.Y);
bw.Write(m_obboffset.Z);
}
catch
{
ok = false;
}
if (bw != null)
{
bw.Flush();
bw.Close();
}
return ok;
}
public static Mesh FromStream(Stream st, AMeshKey key)
{
Mesh mesh = new Mesh();
mesh.releaseBuildingMeshData();
BinaryReader br = new BinaryReader(st);
bool ok = true;
try
{
mesh.m_vertexCount = br.ReadInt32();
mesh.m_indexCount = br.ReadInt32();
int n = 3 * mesh.m_vertexCount;
mesh.vertices = new float[n];
for (int i = 0; i < n; i++)
mesh.vertices[i] = br.ReadSingle();
mesh.indexes = new int[mesh.m_indexCount];
for (int i = 0; i < mesh.m_indexCount; i++)
mesh.indexes[i] = br.ReadInt32();
mesh.m_obb.X = br.ReadSingle();
mesh.m_obb.Y = br.ReadSingle();
mesh.m_obb.Z = br.ReadSingle();
mesh.m_obboffset.X = br.ReadSingle();
mesh.m_obboffset.Y = br.ReadSingle();
mesh.m_obboffset.Z = br.ReadSingle();
}
catch
{
ok = false;
}
br.Close();
if (ok)
{
mesh.pinMemory();
mesh.Key = key;
mesh.RefCount = 1;
return mesh;
}
mesh.vertices = null;
mesh.indexes = null;
return null;
}
}
}

View File

@ -42,6 +42,8 @@ using System.Reflection;
using System.IO;
using ComponentAce.Compression.Libs.zlib;
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace OpenSim.Region.Physics.Meshing
{
@ -68,18 +70,20 @@ namespace OpenSim.Region.Physics.Meshing
// 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
#if SPAM
const string baseDir = "rawFiles";
#else
public object diskLock = new object();
public bool doMeshFileCache = true;
public string cachePath = "MeshCache";
// const string baseDir = "rawFiles";
private const string baseDir = null; //"rawFiles";
#endif
private bool useMeshiesPhysicsMesh = false;
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
// private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
// private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>();
private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
@ -89,8 +93,16 @@ namespace OpenSim.Region.Physics.Meshing
IConfig mesh_config = config.Configs["Mesh"];
if(mesh_config != null)
{
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
if(useMeshiesPhysicsMesh)
{
doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
}
else
doMeshFileCache = false;
}
}
/// <summary>
@ -188,7 +200,7 @@ namespace OpenSim.Region.Physics.Meshing
/// <param name="size">Size of entire object</param>
/// <param name="coords"></param>
/// <param name="faces"></param>
private void AddSubMesh(OSDMap subMeshData, Vector3 size, List<Coord> coords, List<Face> faces)
private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
{
// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
@ -221,9 +233,9 @@ namespace OpenSim.Region.Physics.Meshing
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
Coord c = new Coord(
Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
coords.Add(c);
}
@ -247,7 +259,7 @@ namespace OpenSim.Region.Physics.Meshing
/// <param name="size"></param>
/// <param name="lod"></param>
/// <returns></returns>
private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex)
private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
{
// m_log.DebugFormat(
// "[MESH]: Creating physics proxy for {0}, shape {1}",
@ -263,18 +275,18 @@ namespace OpenSim.Region.Physics.Meshing
if (!useMeshiesPhysicsMesh)
return null;
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
return null;
}
else
{
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
return null;
}
}
else
{
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
return null;
}
@ -309,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
/// <param name="faces">Faces are added to this list by the method.</param>
/// <returns>true if coords and faces were successfully generated, false if not</returns>
private bool GenerateCoordsAndFacesFromPrimMeshData(
string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces, bool convex)
string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
{
// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
@ -382,7 +394,7 @@ namespace OpenSim.Region.Physics.Meshing
OSD decodedMeshOsd = new OSD();
byte[] meshBytes = new byte[physSize];
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
// byte[] decompressed = new byte[physSize * 5];
try
{
using (MemoryStream inMs = new MemoryStream(meshBytes))
@ -420,13 +432,13 @@ namespace OpenSim.Region.Physics.Meshing
// physics_shape is an array of OSDMaps, one for each submesh
if (decodedMeshOsd is OSDArray)
{
// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
// 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);
AddSubMesh(subMeshOsd as OSDMap, coords, faces);
}
}
}
@ -498,9 +510,9 @@ namespace OpenSim.Region.Physics.Meshing
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);
f3 = new float3((t1 * range.X + min.X),
(t2 * range.Y + min.Y),
(t3 * range.Z + min.Z));
vs.Add(f3);
}
@ -597,9 +609,9 @@ namespace OpenSim.Region.Physics.Meshing
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);
f3 = new float3((t1 * range.X + min.X),
(t2 * range.Y + min.Y),
(t3 * range.Z + min.Z));
vs.Add(f3);
}
@ -687,7 +699,7 @@ namespace OpenSim.Region.Physics.Meshing
/// <param name="faces">Faces are added to this list by the method.</param>
/// <returns>true if coords and faces were successfully generated, false if not</returns>
private bool GenerateCoordsAndFacesFromPrimSculptData(
string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
{
coords = new List<Coord>();
faces = new List<Face>();
@ -757,9 +769,7 @@ namespace OpenSim.Region.Physics.Meshing
idata.Dispose();
sculptMesh.DumpRaw(baseDir, primName, "primMesh");
sculptMesh.Scale(size.X, size.Y, size.Z);
// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
coords = sculptMesh.coords;
faces = sculptMesh.faces;
@ -777,7 +787,7 @@ namespace OpenSim.Region.Physics.Meshing
/// <param name="faces">Faces are added to this list by the method.</param>
/// <returns>true if coords and faces were successfully generated, false if not</returns>
private bool GenerateCoordsAndFacesFromPrimShapeData(
string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
{
PrimMesh primMesh;
coords = new List<Coord>();
@ -912,9 +922,7 @@ namespace OpenSim.Region.Physics.Meshing
}
}
primMesh.DumpRaw(baseDir, primName, "primMesh");
primMesh.Scale(size.X, size.Y, size.Z);
// primMesh.DumpRaw(baseDir, primName, "primMesh");
coords = primMesh.coords;
faces = primMesh.faces;
@ -934,6 +942,7 @@ namespace OpenSim.Region.Physics.Meshing
{
key.uuid = primShape.SculptTexture;
key.hashB = mdjb2(key.hashB, primShape.SculptType);
key.hashB = mdjb2(key.hashB, primShape.PCode);
}
else
{
@ -956,6 +965,7 @@ namespace OpenSim.Region.Physics.Meshing
hash = mdjb2(hash, primShape.ProfileBegin);
hash = mdjb2(hash, primShape.ProfileEnd);
hash = mdjb2(hash, primShape.ProfileHollow);
hash = mdjb2(hash, primShape.PCode);
key.hashA = hash;
}
@ -1001,8 +1011,6 @@ namespace OpenSim.Region.Physics.Meshing
return CreateMesh(primName, primShape, size, lod, false,false,false);
}
private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f);
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
{
Mesh mesh = null;
@ -1031,7 +1039,13 @@ namespace OpenSim.Region.Physics.Meshing
{
m_uniqueReleasedMeshes.Remove(key);
lock (m_uniqueMeshes)
m_uniqueMeshes.Add(key, mesh);
{
try
{
m_uniqueMeshes.Add(key, mesh);
}
catch { }
}
mesh.RefCount = 1;
return mesh;
}
@ -1039,6 +1053,8 @@ namespace OpenSim.Region.Physics.Meshing
return null;
}
private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
{
#if SPAM
@ -1074,41 +1090,78 @@ namespace OpenSim.Region.Physics.Meshing
{
m_uniqueReleasedMeshes.Remove(key);
lock (m_uniqueMeshes)
m_uniqueMeshes.Add(key, mesh);
{
try
{
m_uniqueMeshes.Add(key, mesh);
}
catch { }
}
mesh.RefCount = 1;
return mesh;
}
}
mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex);
Mesh UnitMesh = null;
AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
if (mesh != null)
lock (m_uniqueReleasedMeshes)
{
if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
if (UnitMesh != null)
{
#if SPAM
m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " +
minSizeForComplexMesh.ToString() + " - creating simple bounding box");
#endif
mesh = CreateBoundingBoxMesh(mesh);
mesh.DumpRaw(baseDir, primName, "Z extruded");
UnitMesh.RefCount = 1;
}
}
if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
UnitMesh = GetFromFileCache(unitKey);
if (UnitMesh == null)
{
UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
if (UnitMesh == null)
return null;
UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
if (forOde)
{
// force pinned mem allocation
mesh.PrepForOde();
UnitMesh.PrepForOde();
}
else
mesh.TrimExcess();
UnitMesh.TrimExcess();
mesh.Key = key;
mesh.RefCount = 1;
UnitMesh.Key = unitKey;
UnitMesh.RefCount = 1;
lock(m_uniqueMeshes)
m_uniqueMeshes.Add(key, mesh);
if (doMeshFileCache && primShape.SculptEntry)
StoreToFileCache(unitKey, UnitMesh);
lock (m_uniqueReleasedMeshes)
{
try
{
m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
}
catch { }
}
}
mesh = UnitMesh.Scale(size);
mesh.Key = key;
mesh.RefCount = 1;
lock (m_uniqueMeshes)
{
try
{
m_uniqueMeshes.Add(key, mesh);
}
catch { }
}
return mesh;
}
@ -1133,7 +1186,13 @@ namespace OpenSim.Region.Physics.Meshing
mesh.RefCount = 0;
m_uniqueMeshes.Remove(mesh.Key);
lock (m_uniqueReleasedMeshes)
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
{
try
{
m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
}
catch { }
}
}
}
@ -1160,10 +1219,102 @@ namespace OpenSim.Region.Physics.Meshing
foreach (Mesh m in meshstodelete)
{
m_uniqueReleasedMeshes.Remove(m.Key);
m.releaseSourceMeshData();
m.releaseBuildingMeshData();
m.releasePinned();
}
}
}
public void FileNames(AMeshKey key, out string dir,out string fullFileName)
{
string id = key.ToString();
string init = id.Substring(0, 1);
dir = System.IO.Path.Combine(cachePath, init);
fullFileName = System.IO.Path.Combine(dir, id);
}
public string FullFileName(AMeshKey key)
{
string id = key.ToString();
string init = id.Substring(0,1);
id = System.IO.Path.Combine(init, id);
id = System.IO.Path.Combine(cachePath, id);
return id;
}
private Mesh GetFromFileCache(AMeshKey key)
{
Mesh mesh = null;
string filename = FullFileName(key);
bool ok = true;
lock (diskLock)
{
if (File.Exists(filename))
{
FileStream stream = null;
try
{
stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryFormatter bformatter = new BinaryFormatter();
mesh = Mesh.FromStream(stream, key);
}
catch (Exception e)
{
ok = false;
m_log.ErrorFormat(
"[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
filename, e.Message, e.StackTrace);
}
if (stream != null)
stream.Close();
if (mesh == null || !ok)
File.Delete(filename);
}
}
return mesh;
}
private void StoreToFileCache(AMeshKey key, Mesh mesh)
{
Stream stream = null;
bool ok = false;
// Make sure the target cache directory exists
string dir = String.Empty;
string filename = String.Empty;
FileNames(key, out dir, out filename);
lock (diskLock)
{
try
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
stream = File.Open(filename, FileMode.Create);
ok = mesh.ToStream(stream);
}
catch (IOException e)
{
m_log.ErrorFormat(
"[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.",
filename, e.Message, e.StackTrace);
ok = false;
}
if (stream != null)
stream.Close();
if (!ok && File.Exists(filename))
File.Delete(filename);
}
}
}
}

View File

@ -718,7 +718,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
return;
/*
// debug
PhysicsActor dp2;
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
@ -742,7 +742,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
//
*/
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||