Merge branch 'master' into vehicles

0.6.8-post-fixes
Melanie 2009-10-05 12:58:52 +01:00
commit 8d5a40aad0
4 changed files with 124 additions and 69 deletions

View File

@ -47,6 +47,8 @@ namespace OpenSim.Region.Physics.Manager
int[] getIndexListAsInt(); int[] getIndexListAsInt();
int[] getIndexListAsIntLocked(); int[] getIndexListAsIntLocked();
float[] getVertexListAsFloatLocked(); float[] getVertexListAsFloatLocked();
void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount);
void getVertexListAsPtrToFloatArray( out IntPtr vertexList, out int vertexStride, out int vertexCount );
void releaseSourceMeshData(); void releaseSourceMeshData();
void releasePinned(); void releasePinned();
void Append(IMesh newMesh); void Append(IMesh newMesh);

View File

@ -36,23 +36,27 @@ namespace OpenSim.Region.Physics.Meshing
{ {
public class Mesh : IMesh public class Mesh : IMesh
{ {
private Dictionary<Vertex, int> vertices; private Dictionary<Vertex, int> m_vertices;
private List<Triangle> triangles; private List<Triangle> m_triangles;
GCHandle pinnedVirtexes; GCHandle m_pinnedVertexes;
GCHandle pinnedIndex; GCHandle m_pinnedIndex;
public float[] normals; IntPtr m_verticesPtr = IntPtr.Zero;
int m_vertexCount = 0;
IntPtr m_indicesPtr = IntPtr.Zero;
int m_indexCount = 0;
public float[] m_normals;
public Mesh() public Mesh()
{ {
vertices = new Dictionary<Vertex, int>(); m_vertices = new Dictionary<Vertex, int>();
triangles = new List<Triangle>(); m_triangles = new List<Triangle>();
} }
public Mesh Clone() public Mesh Clone()
{ {
Mesh result = new Mesh(); Mesh result = new Mesh();
foreach (Triangle t in triangles) foreach (Triangle t in m_triangles)
{ {
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()));
} }
@ -62,27 +66,27 @@ namespace OpenSim.Region.Physics.Meshing
public void Add(Triangle triangle) public void Add(Triangle triangle)
{ {
if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || 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, // 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
if (!vertices.ContainsKey(triangle.v1)) if( !m_vertices.ContainsKey(triangle.v1) )
vertices[triangle.v1] = vertices.Count; m_vertices[triangle.v1] = m_vertices.Count;
if (!vertices.ContainsKey(triangle.v2)) if (!m_vertices.ContainsKey(triangle.v2))
vertices[triangle.v2] = vertices.Count; m_vertices[triangle.v2] = m_vertices.Count;
if (!vertices.ContainsKey(triangle.v3)) if (!m_vertices.ContainsKey(triangle.v3))
vertices[triangle.v3] = vertices.Count; m_vertices[triangle.v3] = m_vertices.Count;
triangles.Add(triangle); m_triangles.Add(triangle);
} }
public void CalcNormals() public void CalcNormals()
{ {
int iTriangles = triangles.Count; int iTriangles = m_triangles.Count;
this.normals = new float[iTriangles * 3]; this.m_normals = new float[iTriangles * 3];
int i = 0; int i = 0;
foreach (Triangle t in triangles) foreach (Triangle t in m_triangles)
{ {
float ux, uy, uz; float ux, uy, uz;
float vx, vy, vz; float vx, vy, vz;
@ -129,9 +133,9 @@ namespace OpenSim.Region.Physics.Meshing
//ny /= l; //ny /= l;
//nz /= l; //nz /= l;
normals[i] = nx * lReciprocal; m_normals[i] = nx * lReciprocal;
normals[i + 1] = ny * lReciprocal; m_normals[i + 1] = ny * lReciprocal;
normals[i + 2] = nz * lReciprocal; m_normals[i + 2] = nz * lReciprocal;
i += 3; i += 3;
} }
@ -140,45 +144,70 @@ namespace OpenSim.Region.Physics.Meshing
public List<PhysicsVector> getVertexList() public List<PhysicsVector> getVertexList()
{ {
List<PhysicsVector> result = new List<PhysicsVector>(); List<PhysicsVector> result = new List<PhysicsVector>();
foreach (Vertex v in vertices.Keys) foreach (Vertex v in m_vertices.Keys)
{ {
result.Add(v); result.Add(v);
} }
return result; return result;
} }
public float[] getVertexListAsFloatLocked() private float[] getVertexListAsFloat()
{ {
if (pinnedVirtexes.IsAllocated) if(m_vertices == null)
return (float[])(pinnedVirtexes.Target); throw new NotSupportedException();
float[] result; float[] result = new float[m_vertices.Count * 3];
foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
//m_log.WarnFormat("vertices.Count = {0}", vertices.Count);
result = new float[vertices.Count * 3];
foreach (KeyValuePair<Vertex, int> kvp in vertices)
{ {
Vertex v = kvp.Key; Vertex v = kvp.Key;
int i = kvp.Value; int i = kvp.Value;
//m_log.WarnFormat("kvp.Value = {0}", i);
result[3 * i + 0] = v.X; result[3 * i + 0] = v.X;
result[3 * i + 1] = v.Y; result[3 * i + 1] = v.Y;
result[3 * i + 2] = v.Z; result[3 * i + 2] = v.Z;
} }
pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned);
return result; return result;
} }
public float[] getVertexListAsFloatLocked()
{
if( m_pinnedVertexes.IsAllocated )
return (float[])(m_pinnedVertexes.Target);
float[] result = getVertexListAsFloat();
m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
return result;
}
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)
{
float[] vertexList = 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);
}
vertices = m_verticesPtr;
vertexCount = m_vertexCount;
}
public int[] getIndexListAsInt() public int[] getIndexListAsInt()
{ {
int[] result; if (m_triangles == null)
throw new NotSupportedException();
result = new int[triangles.Count * 3]; int[] result = new int[m_triangles.Count * 3];
for (int i = 0; i < triangles.Count; i++) for (int i = 0; i < m_triangles.Count; i++)
{ {
Triangle t = triangles[i]; Triangle t = m_triangles[i];
result[3 * i + 0] = vertices[t.v1]; result[3 * i + 0] = m_vertices[t.v1];
result[3 * i + 1] = vertices[t.v2]; result[3 * i + 1] = m_vertices[t.v2];
result[3 * i + 2] = vertices[t.v3]; result[3 * i + 2] = m_vertices[t.v3];
} }
return result; return result;
} }
@ -189,19 +218,48 @@ namespace OpenSim.Region.Physics.Meshing
/// <returns></returns> /// <returns></returns>
public int[] getIndexListAsIntLocked() public int[] getIndexListAsIntLocked()
{ {
if (pinnedIndex.IsAllocated) if (m_pinnedIndex.IsAllocated)
return (int[])(pinnedIndex.Target); return (int[])(m_pinnedIndex.Target);
int[] result = getIndexListAsInt(); int[] result = getIndexListAsInt();
pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
return result; return result;
} }
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)
{
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);
}
// A triangle is 3 ints (indices)
triStride = 3 * sizeof(int);
indices = m_indicesPtr;
indexCount = m_indexCount;
}
public void releasePinned() public void releasePinned()
{ {
pinnedVirtexes.Free(); if (m_pinnedVertexes.IsAllocated)
pinnedIndex.Free(); m_pinnedVertexes.Free();
if (m_pinnedIndex.IsAllocated)
m_pinnedIndex.Free();
if (m_verticesPtr != IntPtr.Zero)
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
m_verticesPtr = IntPtr.Zero;
}
if (m_indicesPtr != IntPtr.Zero)
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
m_indicesPtr = IntPtr.Zero;
}
} }
/// <summary> /// <summary>
@ -209,29 +267,29 @@ namespace OpenSim.Region.Physics.Meshing
/// </summary> /// </summary>
public void releaseSourceMeshData() public void releaseSourceMeshData()
{ {
triangles = null; m_triangles = null;
vertices = null; m_vertices = null;
} }
public void Append(IMesh newMesh) public void Append(IMesh newMesh)
{ {
if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || 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).triangles) foreach (Triangle t in ((Mesh)newMesh).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 (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || 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 vertices.Keys) foreach (Vertex v in m_vertices.Keys)
{ {
if (v == null) if (v == null)
continue; continue;
@ -252,7 +310,7 @@ namespace OpenSim.Region.Physics.Meshing
String fileName = name + "_" + title + ".raw"; String fileName = name + "_" + title + ".raw";
String completePath = Path.Combine(path, fileName); String completePath = Path.Combine(path, fileName);
StreamWriter sw = new StreamWriter(completePath); StreamWriter sw = new StreamWriter(completePath);
foreach (Triangle t in triangles) foreach (Triangle t in m_triangles)
{ {
String s = t.ToStringRaw(); String s = t.ToStringRaw();
sw.WriteLine(s); sw.WriteLine(s);
@ -262,7 +320,7 @@ namespace OpenSim.Region.Physics.Meshing
public void TrimExcess() public void TrimExcess()
{ {
triangles.TrimExcess(); m_triangles.TrimExcess();
} }
} }
} }

View File

@ -498,12 +498,9 @@ namespace OpenSim.Region.Physics.Meshing
// If this mesh has been created already, return it instead of creating another copy // If this mesh has been created already, return it instead of creating another copy
// For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
if (! primShape.SculptEntry) key = GetMeshKey(primShape, size, lod);
{ if (m_uniqueMeshes.TryGetValue(key, out mesh))
key = GetMeshKey(primShape, size, lod); return mesh;
if (m_uniqueMeshes.TryGetValue(key, out mesh))
return mesh;
}
if (size.X < 0.01f) size.X = 0.01f; if (size.X < 0.01f) size.X = 0.01f;
if (size.Y < 0.01f) size.Y = 0.01f; if (size.Y < 0.01f) size.Y = 0.01f;
@ -525,10 +522,9 @@ namespace OpenSim.Region.Physics.Meshing
// trim the vertex and triangle lists to free up memory // trim the vertex and triangle lists to free up memory
mesh.TrimExcess(); mesh.TrimExcess();
}
if (!primShape.SculptEntry)
m_uniqueMeshes.Add(key, mesh); m_uniqueMeshes.Add(key, mesh);
}
return mesh; return mesh;
} }

View File

@ -824,18 +824,17 @@ namespace OpenSim.Region.Physics.OdePlugin
} }
} }
float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory IntPtr vertices, indices;
int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage int vertexCount, indexCount;
int vertexStride, triStride;
mesh.getVertexListAsPtrToFloatArray( out vertices, out vertexStride, out vertexCount ); // Note, that vertices are fixed in unmanaged heap
mesh.getIndexListAsPtrToIntArray( out indices, out triStride, out indexCount ); // Also fixed, needs release after usage
mesh.releaseSourceMeshData(); // free up the original mesh data to save memory mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
int VertexCount = vertexList.GetLength(0)/3;
int IndexCount = indexList.GetLength(0);
_triMeshData = d.GeomTriMeshDataCreate(); _triMeshData = d.GeomTriMeshDataCreate();
d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount, d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
3*sizeof (int));
d.GeomTriMeshDataPreprocess(_triMeshData); d.GeomTriMeshDataPreprocess(_triMeshData);
_parent_scene.waitForSpaceUnlock(m_targetSpace); _parent_scene.waitForSpaceUnlock(m_targetSpace);