[TEST] disk cache meshs
parent
a91be67a6e
commit
6e21796584
|
@ -32,30 +32,49 @@ using System.Runtime.InteropServices;
|
||||||
using OpenSim.Region.Physics.Manager;
|
using OpenSim.Region.Physics.Manager;
|
||||||
using PrimMesher;
|
using PrimMesher;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Meshing
|
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
|
public class Mesh : IMesh
|
||||||
{
|
{
|
||||||
|
float[] vertices;
|
||||||
private Dictionary<Vertex, int> m_vertices;
|
int[] indexes;
|
||||||
private List<Triangle> m_triangles;
|
Vector3 m_obb;
|
||||||
GCHandle m_pinnedVertexes;
|
Vector3 m_obboffset;
|
||||||
GCHandle m_pinnedIndex;
|
[NonSerialized()]
|
||||||
|
MeshBuildingData m_bdata;
|
||||||
|
[NonSerialized()]
|
||||||
|
GCHandle vhandler;
|
||||||
|
[NonSerialized()]
|
||||||
|
GCHandle ihandler;
|
||||||
|
[NonSerialized()]
|
||||||
IntPtr m_verticesPtr = IntPtr.Zero;
|
IntPtr m_verticesPtr = IntPtr.Zero;
|
||||||
int m_vertexCount = 0;
|
[NonSerialized()]
|
||||||
IntPtr m_indicesPtr = IntPtr.Zero;
|
IntPtr m_indicesPtr = IntPtr.Zero;
|
||||||
|
[NonSerialized()]
|
||||||
|
int m_vertexCount = 0;
|
||||||
|
[NonSerialized()]
|
||||||
int m_indexCount = 0;
|
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>
|
private class vertexcomp : IEqualityComparer<Vertex>
|
||||||
{
|
{
|
||||||
|
@ -79,42 +98,82 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
vertexcomp vcomp = new vertexcomp();
|
vertexcomp vcomp = new vertexcomp();
|
||||||
|
|
||||||
m_vertices = new Dictionary<Vertex, int>(vcomp);
|
m_bdata = new MeshBuildingData();
|
||||||
m_triangles = new List<Triangle>();
|
m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
|
||||||
m_centroid = Vector3.Zero;
|
m_bdata.m_triangles = new List<Triangle>();
|
||||||
m_centroidDiv = 0;
|
m_bdata.m_centroid = Vector3.Zero;
|
||||||
m_obbXmin = float.MaxValue;
|
m_bdata.m_centroidDiv = 0;
|
||||||
m_obbXmax = float.MinValue;
|
m_bdata.m_obbXmin = float.MaxValue;
|
||||||
m_obbYmin = float.MaxValue;
|
m_bdata.m_obbXmax = float.MinValue;
|
||||||
m_obbYmax = float.MinValue;
|
m_bdata.m_obbYmin = float.MaxValue;
|
||||||
m_obbZmin = float.MaxValue;
|
m_bdata.m_obbYmax = float.MinValue;
|
||||||
m_obbZmax = 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 Mesh Scale(Vector3 scale)
|
||||||
|
|
||||||
public void 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()
|
public Mesh Clone()
|
||||||
{
|
{
|
||||||
Mesh result = new Mesh();
|
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_obb = m_obb;
|
||||||
result.m_centroidDiv = m_centroidDiv;
|
result.m_obboffset = m_obboffset;
|
||||||
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;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,37 +183,34 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
float y = v.Y;
|
float y = v.Y;
|
||||||
float z = v.Z;
|
float z = v.Z;
|
||||||
|
|
||||||
m_centroid.X += x;
|
m_bdata.m_centroid.X += x;
|
||||||
m_centroid.Y += y;
|
m_bdata.m_centroid.Y += y;
|
||||||
m_centroid.Z += z;
|
m_bdata.m_centroid.Z += z;
|
||||||
m_centroidDiv++;
|
m_bdata.m_centroidDiv++;
|
||||||
|
|
||||||
if (x > m_obbXmax)
|
if (x > m_bdata.m_obbXmax)
|
||||||
m_obbXmax = x;
|
m_bdata.m_obbXmax = x;
|
||||||
else if (x < m_obbXmin)
|
else if (x < m_bdata.m_obbXmin)
|
||||||
m_obbXmin = x;
|
m_bdata.m_obbXmin = x;
|
||||||
|
|
||||||
if (y > m_obbYmax)
|
if (y > m_bdata.m_obbYmax)
|
||||||
m_obbYmax = y;
|
m_bdata.m_obbYmax = y;
|
||||||
else if (y < m_obbYmin)
|
else if (y < m_bdata.m_obbYmin)
|
||||||
m_obbYmin = y;
|
m_bdata.m_obbYmin = y;
|
||||||
|
|
||||||
if (z > m_obbZmax)
|
if (z > m_bdata.m_obbZmax)
|
||||||
m_obbZmax = z;
|
m_bdata.m_obbZmax = z;
|
||||||
else if (z < m_obbZmin)
|
else if (z < m_bdata.m_obbZmin)
|
||||||
m_obbZmin = z;
|
m_bdata.m_obbZmin = z;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Add(Triangle triangle)
|
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");
|
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)
|
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.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)
|
|| (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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vertices.Count == 0)
|
if (m_bdata.m_vertices.Count == 0)
|
||||||
{
|
{
|
||||||
m_centroidDiv = 0;
|
m_bdata.m_centroidDiv = 0;
|
||||||
m_centroid = Vector3.Zero;
|
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);
|
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);
|
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);
|
addVertexLStats(triangle.v3);
|
||||||
}
|
}
|
||||||
m_triangles.Add(triangle);
|
m_bdata.m_triangles.Add(triangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetCentroid()
|
public Vector3 GetCentroid()
|
||||||
{
|
{
|
||||||
if (m_centroidDiv > 0)
|
return m_obboffset;
|
||||||
return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
|
|
||||||
else
|
|
||||||
return Vector3.Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 GetOBB()
|
public Vector3 GetOBB()
|
||||||
{
|
{
|
||||||
|
return m_obb;
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
if (m_centroidDiv > 0)
|
if (m_bdata.m_centroidDiv > 0)
|
||||||
{
|
{
|
||||||
x = (m_obbXmax - m_obbXmin) * 0.5f;
|
x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
|
||||||
y = (m_obbYmax - m_obbYmin) * 0.5f;
|
y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
|
||||||
z = (m_obbZmax - m_obbZmin) * 0.5f;
|
z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
|
||||||
}
|
}
|
||||||
else // ??
|
else // ??
|
||||||
{
|
{
|
||||||
|
@ -213,72 +268,10 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return new Vector3(x, y, z);
|
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()
|
public List<Vector3> getVertexList()
|
||||||
{
|
{
|
||||||
List<Vector3> result = new List<Vector3>();
|
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));
|
result.Add(new Vector3(v.X, v.Y, v.Z));
|
||||||
}
|
}
|
||||||
|
@ -287,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
private float[] getVertexListAsFloat()
|
private float[] getVertexListAsFloat()
|
||||||
{
|
{
|
||||||
if (m_vertices == null)
|
if (m_bdata.m_vertices == null)
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
float[] result = new float[m_vertices.Count * 3];
|
float[] result = new float[m_bdata.m_vertices.Count * 3];
|
||||||
foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
|
foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
|
||||||
{
|
{
|
||||||
Vertex v = kvp.Key;
|
Vertex v = kvp.Key;
|
||||||
int i = kvp.Value;
|
int i = kvp.Value;
|
||||||
|
@ -303,74 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public float[] getVertexListAsFloatLocked()
|
public float[] getVertexListAsFloatLocked()
|
||||||
{
|
{
|
||||||
if (m_pinnedVertexes.IsAllocated)
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrepForOde()
|
public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
// A vertex is 3 floats
|
// A vertex is 3 floats
|
||||||
vertexStride = 3 * sizeof(float);
|
vertexStride = 3 * sizeof(float);
|
||||||
|
|
||||||
// If there isn't an unmanaged array allocated yet, do it now
|
// 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)
|
// Each vertex is 3 elements (floats)
|
||||||
m_vertexCount = vertexList.Length / 3;
|
m_vertexCount = vertices.Length / 3;
|
||||||
int byteCount = m_vertexCount * vertexStride;
|
vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
|
||||||
m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
m_verticesPtr = vhandler.AddrOfPinnedObject();
|
||||||
System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
|
GC.AddMemoryPressure(Buffer.ByteLength(vertices));
|
||||||
}
|
}
|
||||||
vertices = m_verticesPtr;
|
_vertices = m_verticesPtr;
|
||||||
vertexCount = m_vertexCount;
|
vertexCount = m_vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] getIndexListAsInt()
|
public int[] getIndexListAsInt()
|
||||||
{
|
{
|
||||||
if (m_triangles == null)
|
if (m_bdata.m_triangles == null)
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
int[] result = new int[m_triangles.Count * 3];
|
int[] result = new int[m_bdata.m_triangles.Count * 3];
|
||||||
for (int i = 0; i < m_triangles.Count; i++)
|
for (int i = 0; i < m_bdata.m_triangles.Count; i++)
|
||||||
{
|
{
|
||||||
Triangle t = m_triangles[i];
|
Triangle t = m_bdata.m_triangles[i];
|
||||||
result[3 * i + 0] = m_vertices[t.v1];
|
result[3 * i + 0] = m_bdata.m_vertices[t.v1];
|
||||||
result[3 * i + 1] = m_vertices[t.v2];
|
result[3 * i + 1] = m_bdata.m_vertices[t.v2];
|
||||||
result[3 * i + 2] = m_vertices[t.v3];
|
result[3 * i + 2] = m_bdata.m_vertices[t.v3];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -381,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public int[] getIndexListAsIntLocked()
|
public int[] getIndexListAsIntLocked()
|
||||||
{
|
{
|
||||||
if (m_pinnedIndex.IsAllocated)
|
return null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
|
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 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();
|
indexes = getIndexListAsInt();
|
||||||
m_indexCount = indexList.Length;
|
m_indexCount = indexes.Length;
|
||||||
int byteCount = m_indexCount * sizeof(int);
|
ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
|
||||||
m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
|
m_indicesPtr = ihandler.AddrOfPinnedObject();
|
||||||
System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
|
GC.AddMemoryPressure(Buffer.ByteLength(indexes));
|
||||||
}
|
}
|
||||||
// A triangle is 3 ints (indices)
|
// A triangle is 3 ints (indices)
|
||||||
triStride = 3 * sizeof(int);
|
triStride = 3 * sizeof(int);
|
||||||
|
@ -412,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public void releasePinned()
|
public void releasePinned()
|
||||||
{
|
{
|
||||||
if (m_pinnedVertexes.IsAllocated)
|
|
||||||
m_pinnedVertexes.Free();
|
|
||||||
if (m_pinnedIndex.IsAllocated)
|
|
||||||
m_pinnedIndex.Free();
|
|
||||||
if (m_verticesPtr != IntPtr.Zero)
|
if (m_verticesPtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
|
vhandler.Free();
|
||||||
|
vertices = null;
|
||||||
m_verticesPtr = IntPtr.Zero;
|
m_verticesPtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
if (m_indicesPtr != IntPtr.Zero)
|
if (m_indicesPtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
|
ihandler.Free();
|
||||||
|
indexes = null;
|
||||||
m_indicesPtr = IntPtr.Zero;
|
m_indicesPtr = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void releaseSourceMeshData()
|
public void releaseSourceMeshData()
|
||||||
{
|
{
|
||||||
m_triangles = null;
|
if (m_bdata != null)
|
||||||
m_vertices = 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)
|
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");
|
throw new NotSupportedException("Attempt to Append to a pinned Mesh");
|
||||||
|
|
||||||
if (!(newMesh is Mesh))
|
if (!(newMesh is Mesh))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (Triangle t in ((Mesh)newMesh).m_triangles)
|
foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
|
||||||
Add(t);
|
Add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a linear transformation of mesh.
|
// Do a linear transformation of mesh.
|
||||||
public void TransformLinear(float[,] matrix, float[] offset)
|
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");
|
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)
|
if (v == null)
|
||||||
continue;
|
continue;
|
||||||
|
@ -473,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
if (path == null)
|
if (path == null)
|
||||||
return;
|
return;
|
||||||
|
if (m_bdata == null)
|
||||||
|
return;
|
||||||
String fileName = name + "_" + title + ".raw";
|
String fileName = name + "_" + title + ".raw";
|
||||||
String completePath = System.IO.Path.Combine(path, fileName);
|
String completePath = System.IO.Path.Combine(path, fileName);
|
||||||
StreamWriter sw = new StreamWriter(completePath);
|
StreamWriter sw = new StreamWriter(completePath);
|
||||||
foreach (Triangle t in m_triangles)
|
foreach (Triangle t in m_bdata.m_triangles)
|
||||||
{
|
{
|
||||||
String s = t.ToStringRaw();
|
String s = t.ToStringRaw();
|
||||||
sw.WriteLine(s);
|
sw.WriteLine(s);
|
||||||
|
@ -486,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
public void TrimExcess()
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ using System.Reflection;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using ComponentAce.Compression.Libs.zlib;
|
using ComponentAce.Compression.Libs.zlib;
|
||||||
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.Meshing
|
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
|
// 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
|
// raw files can be imported by blender so a visual inspection of the results can be done
|
||||||
#if SPAM
|
|
||||||
const string baseDir = "rawFiles";
|
public object diskLock = new object();
|
||||||
#else
|
|
||||||
|
public bool doMeshFileCache = true;
|
||||||
|
|
||||||
|
public string cachePath = "MeshCache";
|
||||||
|
|
||||||
|
// const string baseDir = "rawFiles";
|
||||||
private const string baseDir = null; //"rawFiles";
|
private const string baseDir = null; //"rawFiles";
|
||||||
#endif
|
|
||||||
|
|
||||||
private bool useMeshiesPhysicsMesh = false;
|
private bool useMeshiesPhysicsMesh = false;
|
||||||
|
|
||||||
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
|
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_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
|
||||||
private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = 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"];
|
IConfig mesh_config = config.Configs["Mesh"];
|
||||||
|
|
||||||
if(mesh_config != null)
|
if(mesh_config != null)
|
||||||
|
{
|
||||||
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
|
||||||
|
if(useMeshiesPhysicsMesh)
|
||||||
|
{
|
||||||
|
doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
|
||||||
|
cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
doMeshFileCache = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -188,7 +200,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="size">Size of entire object</param>
|
/// <param name="size">Size of entire object</param>
|
||||||
/// <param name="coords"></param>
|
/// <param name="coords"></param>
|
||||||
/// <param name="faces"></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));
|
// 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);
|
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
|
||||||
|
|
||||||
Coord c = new Coord(
|
Coord c = new Coord(
|
||||||
Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
|
Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
|
||||||
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
|
Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
|
||||||
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
|
Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
|
||||||
|
|
||||||
coords.Add(c);
|
coords.Add(c);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +259,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="size"></param>
|
/// <param name="size"></param>
|
||||||
/// <param name="lod"></param>
|
/// <param name="lod"></param>
|
||||||
/// <returns></returns>
|
/// <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(
|
// m_log.DebugFormat(
|
||||||
// "[MESH]: Creating physics proxy for {0}, shape {1}",
|
// "[MESH]: Creating physics proxy for {0}, shape {1}",
|
||||||
|
@ -263,18 +275,18 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
if (!useMeshiesPhysicsMesh)
|
if (!useMeshiesPhysicsMesh)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
|
if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
|
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
/// <param name="faces">Faces are added to this list by the method.</param>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimMeshData(
|
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);
|
// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
|
||||||
|
|
||||||
|
@ -382,7 +394,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
OSD decodedMeshOsd = new OSD();
|
OSD decodedMeshOsd = new OSD();
|
||||||
byte[] meshBytes = new byte[physSize];
|
byte[] meshBytes = new byte[physSize];
|
||||||
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
|
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
|
||||||
// byte[] decompressed = new byte[physSize * 5];
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (MemoryStream inMs = new MemoryStream(meshBytes))
|
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
|
// physics_shape is an array of OSDMaps, one for each submesh
|
||||||
if (decodedMeshOsd is OSDArray)
|
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;
|
decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
|
||||||
foreach (OSD subMeshOsd in decodedMeshOsdArray)
|
foreach (OSD subMeshOsd in decodedMeshOsdArray)
|
||||||
{
|
{
|
||||||
if (subMeshOsd is OSDMap)
|
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++];
|
||||||
t3 += data[ptr++] << 8;
|
t3 += data[ptr++] << 8;
|
||||||
|
|
||||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
f3 = new float3((t1 * range.X + min.X),
|
||||||
(t2 * range.Y + min.Y) * size.Y,
|
(t2 * range.Y + min.Y),
|
||||||
(t3 * range.Z + min.Z) * size.Z);
|
(t3 * range.Z + min.Z));
|
||||||
vs.Add(f3);
|
vs.Add(f3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,9 +609,9 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
t3 = data[i++];
|
t3 = data[i++];
|
||||||
t3 += data[i++] << 8;
|
t3 += data[i++] << 8;
|
||||||
|
|
||||||
f3 = new float3((t1 * range.X + min.X) * size.X,
|
f3 = new float3((t1 * range.X + min.X),
|
||||||
(t2 * range.Y + min.Y) * size.Y,
|
(t2 * range.Y + min.Y),
|
||||||
(t3 * range.Z + min.Z) * size.Z);
|
(t3 * range.Z + min.Z));
|
||||||
vs.Add(f3);
|
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>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimSculptData(
|
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>();
|
coords = new List<Coord>();
|
||||||
faces = new List<Face>();
|
faces = new List<Face>();
|
||||||
|
@ -757,9 +769,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
|
|
||||||
idata.Dispose();
|
idata.Dispose();
|
||||||
|
|
||||||
sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||||
|
|
||||||
sculptMesh.Scale(size.X, size.Y, size.Z);
|
|
||||||
|
|
||||||
coords = sculptMesh.coords;
|
coords = sculptMesh.coords;
|
||||||
faces = sculptMesh.faces;
|
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>
|
/// <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>
|
/// <returns>true if coords and faces were successfully generated, false if not</returns>
|
||||||
private bool GenerateCoordsAndFacesFromPrimShapeData(
|
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;
|
PrimMesh primMesh;
|
||||||
coords = new List<Coord>();
|
coords = new List<Coord>();
|
||||||
|
@ -912,9 +922,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
primMesh.DumpRaw(baseDir, primName, "primMesh");
|
// primMesh.DumpRaw(baseDir, primName, "primMesh");
|
||||||
|
|
||||||
primMesh.Scale(size.X, size.Y, size.Z);
|
|
||||||
|
|
||||||
coords = primMesh.coords;
|
coords = primMesh.coords;
|
||||||
faces = primMesh.faces;
|
faces = primMesh.faces;
|
||||||
|
@ -934,6 +942,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
key.uuid = primShape.SculptTexture;
|
key.uuid = primShape.SculptTexture;
|
||||||
key.hashB = mdjb2(key.hashB, primShape.SculptType);
|
key.hashB = mdjb2(key.hashB, primShape.SculptType);
|
||||||
|
key.hashB = mdjb2(key.hashB, primShape.PCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -956,6 +965,7 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
hash = mdjb2(hash, primShape.ProfileBegin);
|
hash = mdjb2(hash, primShape.ProfileBegin);
|
||||||
hash = mdjb2(hash, primShape.ProfileEnd);
|
hash = mdjb2(hash, primShape.ProfileEnd);
|
||||||
hash = mdjb2(hash, primShape.ProfileHollow);
|
hash = mdjb2(hash, primShape.ProfileHollow);
|
||||||
|
hash = mdjb2(hash, primShape.PCode);
|
||||||
key.hashA = hash;
|
key.hashA = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,8 +1011,6 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return CreateMesh(primName, primShape, size, lod, false,false,false);
|
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)
|
public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
|
||||||
{
|
{
|
||||||
Mesh mesh = null;
|
Mesh mesh = null;
|
||||||
|
@ -1031,7 +1039,13 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
m_uniqueReleasedMeshes.Remove(key);
|
m_uniqueReleasedMeshes.Remove(key);
|
||||||
lock (m_uniqueMeshes)
|
lock (m_uniqueMeshes)
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
mesh.RefCount = 1;
|
mesh.RefCount = 1;
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
@ -1039,6 +1053,8 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
return null;
|
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)
|
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
|
||||||
{
|
{
|
||||||
#if SPAM
|
#if SPAM
|
||||||
|
@ -1074,41 +1090,78 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
{
|
{
|
||||||
m_uniqueReleasedMeshes.Remove(key);
|
m_uniqueReleasedMeshes.Remove(key);
|
||||||
lock (m_uniqueMeshes)
|
lock (m_uniqueMeshes)
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_uniqueMeshes.Add(key, mesh);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
mesh.RefCount = 1;
|
mesh.RefCount = 1;
|
||||||
return mesh;
|
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
|
UnitMesh.RefCount = 1;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
if (forOde)
|
||||||
{
|
{
|
||||||
// force pinned mem allocation
|
// force pinned mem allocation
|
||||||
mesh.PrepForOde();
|
UnitMesh.PrepForOde();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mesh.TrimExcess();
|
UnitMesh.TrimExcess();
|
||||||
|
|
||||||
mesh.Key = key;
|
UnitMesh.Key = unitKey;
|
||||||
mesh.RefCount = 1;
|
UnitMesh.RefCount = 1;
|
||||||
|
|
||||||
lock(m_uniqueMeshes)
|
if (doMeshFileCache && primShape.SculptEntry)
|
||||||
m_uniqueMeshes.Add(key, mesh);
|
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;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1133,7 +1186,13 @@ namespace OpenSim.Region.Physics.Meshing
|
||||||
mesh.RefCount = 0;
|
mesh.RefCount = 0;
|
||||||
m_uniqueMeshes.Remove(mesh.Key);
|
m_uniqueMeshes.Remove(mesh.Key);
|
||||||
lock (m_uniqueReleasedMeshes)
|
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)
|
foreach (Mesh m in meshstodelete)
|
||||||
{
|
{
|
||||||
m_uniqueReleasedMeshes.Remove(m.Key);
|
m_uniqueReleasedMeshes.Remove(m.Key);
|
||||||
m.releaseSourceMeshData();
|
m.releaseBuildingMeshData();
|
||||||
m.releasePinned();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -718,7 +718,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
|
|
||||||
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
|
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
|
||||||
return;
|
return;
|
||||||
|
/*
|
||||||
// debug
|
// debug
|
||||||
PhysicsActor dp2;
|
PhysicsActor dp2;
|
||||||
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
|
if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
|
||||||
|
@ -742,7 +742,7 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
|
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
|
||||||
|
|
Loading…
Reference in New Issue