From daffb691741250dae9e3f767580f0349bd2c5c4f Mon Sep 17 00:00:00 2001 From: dahlia Date: Thu, 24 Sep 2009 18:16:29 -0700 Subject: modify BulletDotNETPrim.cs in preparation for Mantis #4181 --- .../Physics/BulletDotNETPlugin/BulletDotNETPrim.cs | 234 +++++++++++---------- 1 file changed, 122 insertions(+), 112 deletions(-) (limited to 'OpenSim/Region/Physics') diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs index 7ab8b98..f22ea71 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs @@ -204,7 +204,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin tempAngularVelocity2 = new btVector3(0, 0, 0); tempInertia1 = new btVector3(0, 0, 0); tempInertia2 = new btVector3(0, 0, 0); - tempOrientation1 = new btQuaternion(0,0,0,1); + tempOrientation1 = new btQuaternion(0, 0, 0, 1); tempOrientation2 = new btQuaternion(0, 0, 0, 1); _parent_scene = parent_scene; tempTransform1 = new btTransform(_parent_scene.QuatIdentity, _parent_scene.VectorZero); @@ -216,10 +216,10 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin tempMotionState2 = new btDefaultMotionState(_parent_scene.TransZero); tempMotionState3 = new btDefaultMotionState(_parent_scene.TransZero); - + AxisLockLinearLow = new btVector3(-1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize, -1 * (int)Constants.RegionSize); - int regionsize = (int) Constants.RegionSize; - + int regionsize = (int)Constants.RegionSize; + if (regionsize == 256) regionsize = 512; @@ -611,7 +611,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin DisableAxisMotor(); DisposeOfBody(); SetCollisionShape(null); - + if (tempMotionState3 != null && tempMotionState3.Handle != IntPtr.Zero) { tempMotionState3.Dispose(); @@ -677,8 +677,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin tempInertia2.Dispose(); tempInertia1 = null; } - - + + if (tempAngularVelocity2 != null && tempAngularVelocity2.Handle != IntPtr.Zero) { tempAngularVelocity2.Dispose(); @@ -802,7 +802,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin changesize(timestep); } - // + // if (m_taintshape) { @@ -1001,7 +1001,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin else SetBody(0); changeSelectedStatus(timestep); - + resetCollisionAccounting(); m_taintPhysics = m_isphysical; } @@ -1012,7 +1012,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (_parent_scene.needsMeshing(_pbs)) { - ProcessGeomCreationAsTriMesh(PhysicsVector.Zero,Quaternion.Identity); + ProcessGeomCreationAsTriMesh(PhysicsVector.Zero, Quaternion.Identity); // createmesh returns null when it doesn't mesh. CreateGeom(IntPtr.Zero, _mesh); } @@ -1038,32 +1038,32 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin meshlod = _parent_scene.MeshSculptphysicalLOD; IMesh mesh = _parent_scene.mesher.CreateMesh(SOPName, _pbs, _size, meshlod, IsPhysical); - if (!positionOffset.IsIdentical(PhysicsVector.Zero,0.001f) || orientation != Quaternion.Identity) + if (!positionOffset.IsIdentical(PhysicsVector.Zero, 0.001f) || orientation != Quaternion.Identity) { - - float[] xyz = new float[3]; - xyz[0] = positionOffset.X; - xyz[1] = positionOffset.Y; - xyz[2] = positionOffset.Z; - - Matrix4 m4 = Matrix4.CreateFromQuaternion(orientation); - - float[,] matrix = new float[3,3]; - - matrix[0, 0] = m4.M11; - matrix[0, 1] = m4.M12; - matrix[0, 2] = m4.M13; - matrix[1, 0] = m4.M21; - matrix[1, 1] = m4.M22; - matrix[1, 2] = m4.M23; - matrix[2, 0] = m4.M31; - matrix[2, 1] = m4.M32; - matrix[2, 2] = m4.M33; - - - mesh.TransformLinear(matrix, xyz); - - + + float[] xyz = new float[3]; + xyz[0] = positionOffset.X; + xyz[1] = positionOffset.Y; + xyz[2] = positionOffset.Z; + + Matrix4 m4 = Matrix4.CreateFromQuaternion(orientation); + + float[,] matrix = new float[3, 3]; + + matrix[0, 0] = m4.M11; + matrix[0, 1] = m4.M12; + matrix[0, 2] = m4.M13; + matrix[1, 0] = m4.M21; + matrix[1, 1] = m4.M22; + matrix[1, 2] = m4.M23; + matrix[2, 0] = m4.M31; + matrix[2, 1] = m4.M32; + matrix[2, 2] = m4.M33; + + + mesh.TransformLinear(matrix, xyz); + + } @@ -1088,12 +1088,12 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin SetCollisionShape(null); // Construction of new prim ProcessGeomCreation(); - + if (IsPhysical) SetBody(Mass); else SetBody(0); - + m_taintsize = _size; } @@ -1136,7 +1136,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin //prim_geom = IntPtr.Zero; m_log.Error("[PHYSICS]: PrimGeom dead"); } - + // we don't need to do space calculation because the client sends a position update also. if (_size.X <= 0) _size.X = 0.01f; if (_size.Y <= 0) _size.Y = 0.01f; @@ -1153,8 +1153,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin tempTransform1.Dispose(); tempTransform1 = new btTransform(tempOrientation1, tempPosition1); - - + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); if (IsPhysical) @@ -1162,7 +1162,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin SetBody(Mass); // Re creates body on size. // EnableBody also does setMass() - + } else { @@ -1179,7 +1179,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } } resetCollisionAccounting(); - + m_taintshape = false; } @@ -1291,7 +1291,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { Body.setCollisionFlags((int)ContactFlags.CF_NO_CONTACT_RESPONSE); disableBodySoft(); - + } else { @@ -1299,7 +1299,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin enableBodySoft(); } m_isSelected = m_taintselected; - + } private void changevelocity(float timestep) @@ -1368,7 +1368,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin _parent = m_taintparent; m_taintPhysics = m_isphysical; - + } private void changefloatonwater(float timestep) @@ -1627,7 +1627,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (m_zeroPosition == null) m_zeroPosition = new PhysicsVector(0, 0, 0); - m_zeroPosition.setValues(_position.X,_position.Y,_position.Z); + m_zeroPosition.setValues(_position.X, _position.Y, _position.Z); return; } } @@ -1981,7 +1981,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin //_mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); _mesh = p_mesh; setMesh(_parent_scene, _mesh); - + } else { @@ -1994,15 +1994,15 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin //SetGeom to a Regular Sphere if (tempSize1 == null) tempSize1 = new btVector3(0, 0, 0); - tempSize1.setValue(_size.X * 0.5f,_size.Y * 0.5f, _size.Z * 0.5f); - SetCollisionShape(new btSphereShape(_size.X*0.5f)); + tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f); + SetCollisionShape(new btSphereShape(_size.X * 0.5f)); } else { // uses halfextents if (tempSize1 == null) tempSize1 = new btVector3(0, 0, 0); - tempSize1.setValue(_size.X*0.5f, _size.Y*0.5f, _size.Z*0.5f); + tempSize1.setValue(_size.X * 0.5f, _size.Y * 0.5f, _size.Z * 0.5f); SetCollisionShape(new btBoxShape(tempSize1)); } } @@ -2052,14 +2052,24 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } } + //IMesh oldMesh = primMesh; + + //primMesh = mesh; + + //float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + //int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage + ////Array.Reverse(indexList); + //primMesh.releaseSourceMeshData(); // free up the original mesh data to save memory + IMesh oldMesh = primMesh; primMesh = mesh; - - float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory - int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage + + float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage //Array.Reverse(indexList); - primMesh.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); @@ -2068,17 +2078,17 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin btshapeArray.Dispose(); //Array.Reverse(indexList); btshapeArray = new btTriangleIndexVertexArray(IndexCount / 3, indexList, (3 * sizeof(int)), - VertexCount, vertexList, 3*sizeof (float)); + VertexCount, vertexList, 3 * sizeof(float)); SetCollisionShape(new btGImpactMeshShape(btshapeArray)); //((btGImpactMeshShape) prim_geom).updateBound(); - ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1,1, 1)); + ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1)); ((btGImpactMeshShape)prim_geom).updateBound(); _parent_scene.SetUsingGImpact(); - if (oldMesh != null) - { - oldMesh.releasePinned(); - oldMesh = null; - } + //if (oldMesh != null) + //{ + // oldMesh.releasePinned(); + // oldMesh = null; + //} } @@ -2102,7 +2112,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } */ prim_geom = shape; - + //Body.set } @@ -2143,8 +2153,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin if (prim_geom is btGImpactMeshShape) { - ((btGImpactMeshShape) prim_geom).setLocalScaling(new btVector3(1, 1, 1)); - ((btGImpactMeshShape) prim_geom).updateBound(); + ((btGImpactMeshShape)prim_geom).setLocalScaling(new btVector3(1, 1, 1)); + ((btGImpactMeshShape)prim_geom).updateBound(); } //Body.setCollisionFlags(Body.getCollisionFlags() | (int)ContactFlags.CF_CUSTOM_MATERIAL_CALLBACK); //Body.setUserPointer((IntPtr) (int)m_localID); @@ -2159,7 +2169,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { if (chld == null) continue; - + // if (chld.NeedsMeshing()) // hasTrimesh = true; } @@ -2167,40 +2177,40 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin //if (hasTrimesh) //{ - ProcessGeomCreationAsTriMesh(PhysicsVector.Zero, Quaternion.Identity); - // createmesh returns null when it doesn't mesh. - - /* - if (_mesh is Mesh) - { - } - else - { - m_log.Warn("[PHYSICS]: Can't link a OpenSim.Region.Physics.Meshing.Mesh object"); - return; - } - */ + ProcessGeomCreationAsTriMesh(PhysicsVector.Zero, Quaternion.Identity); + // createmesh returns null when it doesn't mesh. - - - foreach (BulletDotNETPrim chld in childrenPrim) - { - if (chld == null) - continue; - PhysicsVector offset = chld.Position - Position; - Vector3 pos = new Vector3(offset.X, offset.Y, offset.Z); - pos *= Quaternion.Inverse(Orientation); - //pos *= Orientation; - offset.setValues(pos.X, pos.Y, pos.Z); - chld.ProcessGeomCreationAsTriMesh(offset, chld.Orientation); - - _mesh.Append(chld._mesh); - + /* + if (_mesh is Mesh) + { + } + else + { + m_log.Warn("[PHYSICS]: Can't link a OpenSim.Region.Physics.Meshing.Mesh object"); + return; + } + */ - } - setMesh(_parent_scene, _mesh); - - //} + + + foreach (BulletDotNETPrim chld in childrenPrim) + { + if (chld == null) + continue; + PhysicsVector offset = chld.Position - Position; + Vector3 pos = new Vector3(offset.X, offset.Y, offset.Z); + pos *= Quaternion.Inverse(Orientation); + //pos *= Orientation; + offset.setValues(pos.X, pos.Y, pos.Z); + chld.ProcessGeomCreationAsTriMesh(offset, chld.Orientation); + + _mesh.Append(chld._mesh); + + + } + setMesh(_parent_scene, _mesh); + + //} if (tempMotionState1 != null && tempMotionState1.Handle != IntPtr.Zero) tempMotionState1.Dispose(); @@ -2238,7 +2248,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin ((btGImpactMeshShape)prim_geom).updateBound(); } _parent_scene.AddPrimToScene(this); - + } if (IsPhysical) @@ -2252,7 +2262,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin if (Body.Handle != IntPtr.Zero) { DisableAxisMotor(); - _parent_scene.removeFromWorld(this,Body); + _parent_scene.removeFromWorld(this, Body); Body.Dispose(); } Body = null; @@ -2305,7 +2315,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin return; - + lock (childrenPrim) { if (!childrenPrim.Contains(prm)) @@ -2313,8 +2323,8 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin childrenPrim.Add(prm); } } - - + + } public void disableBody() @@ -2386,7 +2396,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { Body.clearForces(); Body.forceActivationState(0); - + } } @@ -2400,7 +2410,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin Body.clearForces(); Body.forceActivationState(4); forceenable = true; - + } m_disabled = false; } @@ -2415,7 +2425,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin SetBody(Mass); else SetBody(0); - + // TODO: Set Collision Category Bits and Flags // TODO: Set Auto Disable data @@ -2587,10 +2597,10 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin _velocity.Y = tempLinearVelocity1.getY(); _velocity.Z = tempLinearVelocity1.getZ(); - _acceleration = ((_velocity - m_lastVelocity)/0.1f); - _acceleration = new PhysicsVector(_velocity.X - m_lastVelocity.X/0.1f, - _velocity.Y - m_lastVelocity.Y/0.1f, - _velocity.Z - m_lastVelocity.Z/0.1f); + _acceleration = ((_velocity - m_lastVelocity) / 0.1f); + _acceleration = new PhysicsVector(_velocity.X - m_lastVelocity.X / 0.1f, + _velocity.Y - m_lastVelocity.Y / 0.1f, + _velocity.Z - m_lastVelocity.Z / 0.1f); //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); if (_velocity.IsIdentical(pv, 0.5f)) @@ -2669,7 +2679,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin if (AxisLockAngleHigh != null && AxisLockAngleHigh.Handle != IntPtr.Zero) AxisLockAngleHigh.Dispose(); - + m_aMotor = new btGeneric6DofConstraint(Body, _parent_scene.TerrainBody, _parent_scene.TransZero, _parent_scene.TransZero, false); @@ -2683,7 +2693,7 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin m_aMotor.setLinearUpperLimit(AxisLockLinearHigh); _parent_scene.getBulletWorld().addConstraint((btTypedConstraint)m_aMotor); //m_aMotor. - + } internal void DisableAxisMotor() @@ -2698,4 +2708,4 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin } } - + -- cgit v1.1 From 1b2828f5d859d2941167b0457158142e683efe39 Mon Sep 17 00:00:00 2001 From: Dan Lake Date: Thu, 24 Sep 2009 10:00:31 -0700 Subject: Meshmerizer stores dictionary of unique Meshes keyed on construction parameters. CreateMesh() returns a Mesh from the dictionary or creates a new Mesh if it has not been created before. Meshes are never purged from the dictionary. The raw Mesh data is discarded once the memory is pinned for ODE use. All copies of the same prim/mesh use the same pinned memory. ONLY IMPLEMENTED AND TESTED WITH MESHMERIZER AND ODE Signed-off-by: dahlia --- OpenSim/Region/Physics/Meshing/Mesh.cs | 87 +++++++++------------------ OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 69 +++++++++++++++++++-- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 17 +----- 3 files changed, 95 insertions(+), 78 deletions(-) (limited to 'OpenSim/Region/Physics') diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs index ceafaad..7567556 100644 --- a/OpenSim/Region/Physics/Meshing/Mesh.cs +++ b/OpenSim/Region/Physics/Meshing/Mesh.cs @@ -40,7 +40,6 @@ namespace OpenSim.Region.Physics.Meshing private List triangles; GCHandle pinnedVirtexes; GCHandle pinnedIndex; - public PrimMesh primMesh = null; public float[] normals; public Mesh() @@ -63,6 +62,8 @@ namespace OpenSim.Region.Physics.Meshing public void Add(Triangle triangle) { + if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) + 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 if (!vertices.ContainsKey(triangle.v1)) @@ -148,40 +149,22 @@ namespace OpenSim.Region.Physics.Meshing public float[] getVertexListAsFloatLocked() { + if( pinnedVirtexes.IsAllocated ) + return (float[])(pinnedVirtexes.Target); float[] result; - if (primMesh == null) + //m_log.WarnFormat("vertices.Count = {0}", vertices.Count); + result = new float[vertices.Count * 3]; + foreach (KeyValuePair kvp in vertices) { - //m_log.WarnFormat("vertices.Count = {0}", vertices.Count); - result = new float[vertices.Count * 3]; - foreach (KeyValuePair kvp in vertices) - { - Vertex v = kvp.Key; - int i = kvp.Value; - //m_log.WarnFormat("kvp.Value = {0}", i); - result[3 * i + 0] = v.X; - result[3 * i + 1] = v.Y; - result[3 * i + 2] = v.Z; - } - pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned); - } - else - { - int count = primMesh.coords.Count; - result = new float[count * 3]; - for (int i = 0; i < count; i++) - { - Coord c = primMesh.coords[i]; - { - int resultIndex = 3 * i; - result[resultIndex] = c.X; - result[resultIndex + 1] = c.Y; - result[resultIndex + 2] = c.Z; - } - - } - pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned); + Vertex v = kvp.Key; + int i = kvp.Value; + //m_log.WarnFormat("kvp.Value = {0}", i); + result[3 * i + 0] = v.X; + result[3 * i + 1] = v.Y; + result[3 * i + 2] = v.Z; } + pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned); return result; } @@ -189,33 +172,13 @@ namespace OpenSim.Region.Physics.Meshing { int[] result; - if (primMesh == null) - { - result = new int[triangles.Count * 3]; - for (int i = 0; i < triangles.Count; i++) - { - Triangle t = triangles[i]; - result[3 * i + 0] = vertices[t.v1]; - result[3 * i + 1] = vertices[t.v2]; - result[3 * i + 2] = vertices[t.v3]; - } - } - else + result = new int[triangles.Count * 3]; + for (int i = 0; i < triangles.Count; i++) { - int numFaces = primMesh.faces.Count; - result = new int[numFaces * 3]; - for (int i = 0; i < numFaces; i++) - { - Face f = primMesh.faces[i]; -// Coord c1 = primMesh.coords[f.v1]; -// Coord c2 = primMesh.coords[f.v2]; -// Coord c3 = primMesh.coords[f.v3]; - - int resultIndex = i * 3; - result[resultIndex] = f.v1; - result[resultIndex + 1] = f.v2; - result[resultIndex + 2] = f.v3; - } + Triangle t = triangles[i]; + result[3 * i + 0] = vertices[t.v1]; + result[3 * i + 1] = vertices[t.v2]; + result[3 * i + 2] = vertices[t.v3]; } return result; } @@ -226,6 +189,9 @@ namespace OpenSim.Region.Physics.Meshing /// public int[] getIndexListAsIntLocked() { + if (pinnedIndex.IsAllocated) + return (int[])(pinnedIndex.Target); + int[] result = getIndexListAsInt(); pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); @@ -245,11 +211,13 @@ namespace OpenSim.Region.Physics.Meshing { triangles = null; vertices = null; - primMesh = null; } public void Append(IMesh newMesh) { + if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) + throw new NotSupportedException("Attempt to Append to a pinned Mesh"); + if (!(newMesh is Mesh)) return; @@ -260,6 +228,9 @@ namespace OpenSim.Region.Physics.Meshing // Do a linear transformation of mesh. public void TransformLinear(float[,] matrix, float[] offset) { + if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) + throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); + foreach (Vertex v in vertices.Keys) { if (v == null) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index f469ad6..0873035 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -76,6 +76,7 @@ namespace OpenSim.Region.Physics.Meshing private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh + private Dictionary m_uniqueMeshes = new Dictionary(); /// /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may @@ -170,9 +171,62 @@ namespace OpenSim.Region.Physics.Meshing } - public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) + private ulong GetMeshKey( PrimitiveBaseShape pbs, PhysicsVector size, float lod ) + { + ulong hash = 5381; + + hash = djb2(hash, pbs.PathCurve); + hash = djb2(hash, (byte)((byte)pbs.HollowShape | (byte)pbs.ProfileShape)); + hash = djb2(hash, pbs.PathBegin); + hash = djb2(hash, pbs.PathEnd); + hash = djb2(hash, pbs.PathScaleX); + hash = djb2(hash, pbs.PathScaleY); + hash = djb2(hash, pbs.PathShearX); + hash = djb2(hash, pbs.PathShearY); + hash = djb2(hash, (byte)pbs.PathTwist); + hash = djb2(hash, (byte)pbs.PathTwistBegin); + hash = djb2(hash, (byte)pbs.PathRadiusOffset); + hash = djb2(hash, (byte)pbs.PathTaperX); + hash = djb2(hash, (byte)pbs.PathTaperY); + hash = djb2(hash, pbs.PathRevolutions); + hash = djb2(hash, (byte)pbs.PathSkew); + hash = djb2(hash, pbs.ProfileBegin); + hash = djb2(hash, pbs.ProfileEnd); + hash = djb2(hash, pbs.ProfileHollow); + + // TODO: Separate scale out from the primitive shape data (after + // scaling is supported at the physics engine level) + byte[] scaleBytes = size.GetBytes(); + for (int i = 0; i < scaleBytes.Length; i++) + hash = djb2(hash, scaleBytes[i]); + + // Include LOD in hash, accounting for endianness + byte[] lodBytes = new byte[4]; + Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4); + if (!BitConverter.IsLittleEndian) + { + Array.Reverse(lodBytes, 0, 4); + } + for (int i = 0; i < lodBytes.Length; i++) + hash = djb2(hash, lodBytes[i]); + + return hash; + } + + private ulong djb2(ulong hash, byte c) + { + return ((hash << 5) + hash) + (ulong)c; + } + + private ulong djb2(ulong hash, ushort c) + { + hash = ((hash << 5) + hash) + (ulong)((byte)c); + return ((hash << 5) + hash) + (ulong)(c >> 8); + } + + + private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) { - Mesh mesh = new Mesh(); PrimMesh primMesh; PrimMesher.SculptMesh sculptMesh; @@ -385,8 +439,6 @@ namespace OpenSim.Region.Physics.Meshing coords = primMesh.coords; faces = primMesh.faces; - - } @@ -401,13 +453,13 @@ namespace OpenSim.Region.Physics.Meshing vertices.Add(new Vertex(c.X, c.Y, c.Z)); } + Mesh mesh = new Mesh(); // Add the corresponding triangles to the mesh for (int i = 0; i < numFaces; i++) { Face f = faces[i]; mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); } - return mesh; } @@ -418,7 +470,12 @@ namespace OpenSim.Region.Physics.Meshing public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical) { + // 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 + ulong key = GetMeshKey(primShape, size, lod); Mesh mesh = null; + if (m_uniqueMeshes.TryGetValue(key, out mesh)) + return mesh; if (size.X < 0.01f) size.X = 0.01f; if (size.Y < 0.01f) size.Y = 0.01f; @@ -441,7 +498,7 @@ namespace OpenSim.Region.Physics.Meshing // trim the vertex and triangle lists to free up memory mesh.TrimExcess(); } - + m_uniqueMeshes.Add(key, mesh); return mesh; } } diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 673ae39..032b5df 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -82,7 +82,6 @@ namespace OpenSim.Region.Physics.OdePlugin // private float m_tensor = 5f; private int body_autodisable_frames = 20; - private IMesh primMesh = null; private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom @@ -814,14 +813,10 @@ namespace OpenSim.Region.Physics.OdePlugin } } - IMesh oldMesh = primMesh; + float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory + int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage - primMesh = mesh; - - float[] vertexList = primMesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory - int[] indexList = primMesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage - - primMesh.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); @@ -847,12 +842,6 @@ namespace OpenSim.Region.Physics.OdePlugin return; } - if (oldMesh != null) - { - oldMesh.releasePinned(); - oldMesh = null; - } - // if (IsPhysical && Body == (IntPtr) 0) // { // Recreate the body -- cgit v1.1