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 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;
} }
} }
} }

View File

@ -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);
}
}
} }
} }

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)) 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 ||