diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index a03d62697a..b85d93d53a 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -733,7 +733,8 @@ namespace OpenSim.Framework
reqnum, verb, requestUrl);
int tickstart = Util.EnvironmentTickCount();
- int tickdata = 0;
+// int tickdata = 0;
+ int tickdiff = 0;
Type type = typeof(TRequest);
@@ -776,8 +777,8 @@ namespace OpenSim.Framework
requestStream.Close();
// capture how much time was spent writing
- tickdata = Util.EnvironmentTickCountSubtract(tickstart);
-
+ // useless in this async
+// tickdata = Util.EnvironmentTickCountSubtract(tickstart);
request.BeginGetResponse(delegate(IAsyncResult ar)
{
response = request.EndGetResponse(ar);
@@ -794,7 +795,8 @@ namespace OpenSim.Framework
finally
{
// Let's not close this
- //buffer.Close();
+ // yes do close it
+ buffer.Close();
respStream.Close();
response.Close();
}
@@ -862,7 +864,6 @@ namespace OpenSim.Framework
}
// m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
-
try
{
action(deserial);
@@ -877,9 +878,10 @@ namespace OpenSim.Framework
}, null);
}
- int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
+ tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
if (tickdiff > WebUtil.LongCallTime)
{
+/*
string originalRequest = null;
if (buffer != null)
@@ -898,12 +900,19 @@ namespace OpenSim.Framework
tickdiff,
tickdata,
originalRequest);
+*/
+ m_log.InfoFormat(
+ "[ASYNC REQUEST]: Slow WebRequest SETUP <{0}> {1} {2} took {3}ms",
+ reqnum,
+ verb,
+ requestUrl,
+ tickdiff);
}
else if (WebUtil.DebugLevel >= 4)
{
m_log.DebugFormat(
- "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
- reqnum, tickdiff, tickdata);
+ "[WEB UTIL]: HTTP OUT {0} took {1}ms",
+ reqnum, tickdiff);
}
}
}
@@ -938,6 +947,8 @@ namespace OpenSim.Framework
request.Method = verb;
string respstring = String.Empty;
+ int tickset = Util.EnvironmentTickCountSubtract(tickstart);
+
using (MemoryStream buffer = new MemoryStream())
{
if ((verb == "POST") || (verb == "PUT"))
@@ -1019,6 +1030,7 @@ namespace OpenSim.Framework
verb,
requestUrl,
tickdiff,
+ tickset,
tickdata,
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
else if (WebUtil.DebugLevel >= 4)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index f509d94c03..f6146a9171 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -1117,17 +1117,17 @@ namespace OpenSim.Region.ClientStack.Linden
else
{
AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
- if (client != null)
- {
- // let users see anything.. i don't so far
- string str;
- if (cost > 0)
- // dont remember where is money unit name to put here
- str = "Upload complete. charged " + cost.ToString() + "$";
- else
- str = "Upload complete";
- client.SendAgentAlertMessage(str, true);
- }
+// if (client != null)
+// {
+// // let users see anything.. i don't so far
+// string str;
+// if (cost > 0)
+// // dont remember where is money unit name to put here
+// str = "Upload complete. charged " + cost.ToString() + "$";
+// else
+// str = "Upload complete";
+// client.SendAgentAlertMessage(str, true);
+// }
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index bac71b0175..fcac182f45 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
public void RegisterCaps(UUID agentID, Caps caps)
{
- if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID))
+ if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID) && !m_scene.Permissions.IsGod(agentID))
return;
UUID capID = UUID.Random();
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 233e559c13..edf2befc0d 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -575,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion current = m_group.GroupRotation;
Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
+ step.Normalize();
/* use simpler change detection
* float angle = 0;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 985f0a0ba9..782a1af138 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -4386,8 +4386,8 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart[] parts = m_parts.GetArray();
- for (int i = 0; i < parts.Length; i++)
- parts[i].CheckSculptAndLoad();
+// for (int i = 0; i < parts.Length; i++)
+// parts[i].CheckSculptAndLoad();
}
///
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 2d90a22367..248679bdef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1095,9 +1095,9 @@ namespace OpenSim.Region.Framework.Scenes
{
actor.Size = m_shape.Scale;
- if (Shape.SculptEntry)
- CheckSculptAndLoad();
- else
+// if (Shape.SculptEntry)
+// CheckSculptAndLoad();
+// else
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
}
}
@@ -1583,7 +1583,9 @@ namespace OpenSim.Region.Framework.Scenes
float cost = 0.1f;
if (PhysActor != null)
-// cost += PhysActor.Cost;
+ cost = PhysActor.PhysicsCost;
+ else
+ cost = 0.1f;
if ((Flags & PrimFlags.Physics) != 0)
cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
@@ -1596,9 +1598,12 @@ namespace OpenSim.Region.Framework.Scenes
{
get
{
-
-
- return 0.1f;
+ float cost;
+ if (PhysActor != null)
+ cost = PhysActor.StreamCost;
+ else
+ cost = 1.0f;
+ return 1.0f;
}
}
@@ -1654,8 +1659,8 @@ namespace OpenSim.Region.Framework.Scenes
else
{
PhysActor.PhysicsShapeType = m_physicsShapeType;
- if (Shape.SculptEntry)
- CheckSculptAndLoad();
+// if (Shape.SculptEntry)
+// CheckSculptAndLoad();
}
if (ParentGroup != null)
@@ -2115,12 +2120,13 @@ namespace OpenSim.Region.Framework.Scenes
if (userExposed)
{
+/*
if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
{
ParentGroup.Scene.AssetService.Get(
dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
}
-
+*/
bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
@@ -2142,6 +2148,7 @@ namespace OpenSim.Region.Framework.Scenes
/// ID of asset received
/// Register
///
+/*
protected void AssetReceived(string id, Object sender, AssetBase asset)
{
if (asset != null)
@@ -2151,7 +2158,7 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
// Name, UUID, id);
}
-
+*/
///
/// Do a physics property update for a NINJA joint.
///
@@ -2341,9 +2348,9 @@ namespace OpenSim.Region.Framework.Scenes
// If this part is a sculpt then delay the physics update until we've asynchronously loaded the
// mesh data.
- if (Shape.SculptEntry)
- CheckSculptAndLoad();
- else
+// if (Shape.SculptEntry)
+// CheckSculptAndLoad();
+// else
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
}
}
@@ -3128,6 +3135,7 @@ namespace OpenSim.Region.Framework.Scenes
/// Set sculpt and mesh data, and tell the physics engine to process the change.
///
/// The mesh itself.
+/*
public void SculptTextureCallback(AssetBase texture)
{
if (m_shape.SculptEntry)
@@ -3155,7 +3163,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
-
+*/
///
/// Send a full update to the client for the given part
///
@@ -4397,7 +4405,7 @@ namespace OpenSim.Region.Framework.Scenes
public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
{
m_shape.ReadInUpdateExtraParam(type, inUse, data);
-
+/*
if (type == 0x30)
{
if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
@@ -4405,7 +4413,7 @@ namespace OpenSim.Region.Framework.Scenes
ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
}
}
-
+*/
if (ParentGroup != null)
{
ParentGroup.HasGroupChanged = true;
@@ -4813,9 +4821,9 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- if (Shape.SculptEntry)
- CheckSculptAndLoad();
- else
+// if (Shape.SculptEntry)
+// CheckSculptAndLoad();
+// else
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
if (!building)
@@ -4969,10 +4977,13 @@ namespace OpenSim.Region.Framework.Scenes
///
/// When the physics engine has finished with it, the sculpt data is discarded to save memory.
///
+/*
public void CheckSculptAndLoad()
{
// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
+ return;
+
if (ParentGroup.IsDeleted)
return;
@@ -4994,7 +5005,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
-
+*/
///
/// Update the texture entry for this part.
///
@@ -5262,6 +5273,7 @@ namespace OpenSim.Region.Framework.Scenes
}
Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations);
+ rot.Normalize();
UpdateRotation(rot);
m_APIDIterations--;
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
index 5b743e8a02..8de70efaca 100644
--- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs
@@ -2190,7 +2190,7 @@ namespace OpenSim.Region.Physics.OdePlugin
convex = false;
try
{
- _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex);
+ _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true,convex,false);
}
catch
{
@@ -2557,7 +2557,7 @@ namespace OpenSim.Region.Physics.OdePlugin
try
{
- mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex);
+ mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true, convex,false);
}
catch
{
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs
index a8c99f7e67..ecc2918862 100644
--- a/OpenSim/Region/Physics/Manager/IMesher.cs
+++ b/OpenSim/Region/Physics/Manager/IMesher.cs
@@ -37,9 +37,11 @@ namespace OpenSim.Region.Physics.Manager
{
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
- IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex);
+ IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde);
+ IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex);
void ReleaseMesh(IMesh mesh);
void ExpireReleaseMeshs();
+ void ExpireFileCache();
}
// Values for level of detail to be passed to the mesher.
@@ -57,6 +59,7 @@ namespace OpenSim.Region.Physics.Manager
{
}
+ [Serializable()]
[StructLayout(LayoutKind.Explicit)]
public struct AMeshKey
{
@@ -66,6 +69,13 @@ namespace OpenSim.Region.Physics.Manager
public ulong hashA;
[FieldOffset(8)]
public ulong hashB;
+ [FieldOffset(16)]
+ public ulong hashC;
+
+ public override string ToString()
+ {
+ return uuid.ToString() + "-" + hashC.ToString("x") ;
+ }
}
public interface IMesh
@@ -81,5 +91,6 @@ namespace OpenSim.Region.Physics.Manager
void Append(IMesh newMesh);
void TransformLinear(float[,] matrix, float[] offset);
Vector3 GetCentroid();
+ Vector3 GetOBB();
}
}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index a2c72c30fb..14f65b8e14 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -315,6 +315,23 @@ namespace OpenSim.Region.Physics.Manager
}
}
+
+ public virtual float PhysicsCost
+ {
+ get
+ {
+ return 0.1f;
+ }
+ }
+
+ public virtual float StreamCost
+ {
+ get
+ {
+ return 1.0f;
+ }
+ }
+
///
/// Velocity of this actor.
///
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 5274f3b471..ce269fabc1 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Physics.Manager
get { return new NullPhysicsScene(); }
}
- public RequestAssetDelegate RequestAssetMethod { private get; set; }
+ public RequestAssetDelegate RequestAssetMethod { get; set; }
public virtual void TriggerPhysicsBasedRestart()
{
@@ -246,6 +246,9 @@ namespace OpenSim.Region.Physics.Manager
public abstract void AddPhysicsActorTaint(PhysicsActor prim);
+
+ public virtual void PrepareSimulation() { }
+
///
/// Perform a simulation of the current physics scene over the given timestep.
///
diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
index f555cb9253..16846e612f 100644
--- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs
+++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Physics.Manager
return CreateMesh(primName, primShape, size, lod, false);
}
- public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
+ public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde)
{
return CreateMesh(primName, primShape, size, lod, false);
}
@@ -79,7 +79,14 @@ namespace OpenSim.Region.Physics.Manager
return null;
}
+
+ public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
+ {
+ return null;
+ }
+
public void ReleaseMesh(IMesh mesh) { }
public void ExpireReleaseMeshs() { }
+ public void ExpireFileCache() { }
}
}
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs
index c715642bac..6970553818 100644
--- a/OpenSim/Region/Physics/Meshing/Mesh.cs
+++ b/OpenSim/Region/Physics/Meshing/Mesh.cs
@@ -148,6 +148,12 @@ namespace OpenSim.Region.Physics.Meshing
return Vector3.Zero;
}
+ // not functional
+ public Vector3 GetOBB()
+ {
+ return new Vector3(0.5f, 0.5f, 0.5f);
+ }
+
public void CalcNormals()
{
int iTriangles = m_triangles.Count;
@@ -253,6 +259,7 @@ namespace OpenSim.Region.Physics.Meshing
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
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 3c4f737f9e..f629c4d60b 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -74,8 +74,6 @@ namespace OpenSim.Region.Physics.Meshing
#endif
private bool cacheSculptMaps = true;
- private bool cacheSculptAlphaMaps = true;
-
private string decodedSculptMapPath = null;
private bool useMeshiesPhysicsMesh = false;
@@ -89,16 +87,7 @@ namespace OpenSim.Region.Physics.Meshing
IConfig mesh_config = config.Configs["Mesh"];
decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
-
cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
-
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- {
- cacheSculptAlphaMaps = false;
- }
- else
- cacheSculptAlphaMaps = cacheSculptMaps;
-
if(mesh_config != null)
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
@@ -279,18 +268,15 @@ namespace OpenSim.Region.Physics.Meshing
{
if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
return null;
- // Remove the reference to any JPEG2000 sculpt data so it can be GCed
- // don't loose it
- // primShape.SculptData = Utils.EmptyBytes;
}
-// primShape.SculptDataLoaded = true;
}
else
{
if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
return null;
}
- // keep compatible
+
+ // Remove the reference to any JPEG2000 sculpt data so it can be GCed
primShape.SculptData = Utils.EmptyBytes;
int numCoords = coords.Count;
@@ -335,7 +321,7 @@ namespace OpenSim.Region.Physics.Meshing
if (primShape.SculptData.Length <= 0)
{
- m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
+// m_log.ErrorFormat("[MESH]: asset data for {0} is zero length", primName);
return false;
}
@@ -496,8 +482,7 @@ namespace OpenSim.Region.Physics.Meshing
//idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
- if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
- // don't cache images with alpha channel in linux since mono can't load them correctly)
+ if (cacheSculptMaps)
{
try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
@@ -717,7 +702,7 @@ namespace OpenSim.Region.Physics.Meshing
return CreateMesh(primName, primShape, size, lod, false);
}
- public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
+ public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
{
return CreateMesh(primName, primShape, size, lod, false);
}
@@ -763,7 +748,13 @@ namespace OpenSim.Region.Physics.Meshing
return mesh;
}
+ public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
+ {
+ return null;
+ }
+
public void ReleaseMesh(IMesh imesh) { }
public void ExpireReleaseMeshs() { }
+ public void ExpireFileCache() { }
}
}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index eb02536907..7a0857faaf 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -100,6 +100,9 @@ namespace OpenSim.Region.Physics.OdePlugin
private Vector3 m_taintAngularLock = Vector3.One;
private IntPtr Amotor = IntPtr.Zero;
+ private object m_assetsLock = new object();
+ private bool m_assetFailed = false;
+
private Vector3 m_PIDTarget;
private float m_PIDTau;
private float PID_D = 35f;
@@ -282,6 +285,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
m_taintadd = true;
+ m_assetFailed = false;
_parent_scene.AddPhysicsActorTaint(this);
}
@@ -604,8 +608,8 @@ namespace OpenSim.Region.Physics.OdePlugin
break;
case HollowShape.Circle:
- // Hollow shape is a perfect cylinder in respect to the cube's scale
- // Cylinder hollow volume calculation
+ // Hollow shape is a perfect cyllinder in respect to the cube's scale
+ // Cyllinder hollow volume calculation
hollowVolume *= 0.1963495f * 3.07920140172638f;
break;
@@ -1498,6 +1502,8 @@ Console.WriteLine("CreateGeom:");
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
// createmesh returns null when it's a shape that isn't a cube.
// m_log.Debug(m_localID);
+ if (mesh == null)
+ CheckMeshAsset();
}
#if SPAM
@@ -1997,7 +2003,12 @@ Console.WriteLine(" JointCreateFixed");
// Don't need to re-enable body.. it's done in SetMesh
if (_parent_scene.needsMeshing(_pbs))
+ {
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
+ if (mesh == null)
+ CheckMeshAsset();
+ }
+
}
CreateGeom(m_targetSpace, mesh);
@@ -2057,6 +2068,8 @@ Console.WriteLine(" JointCreateFixed");
///
private void changeshape()
{
+ m_taintshape = false;
+
// Cleanup of old prim geometry and Bodies
if (IsPhysical && Body != IntPtr.Zero)
{
@@ -2084,6 +2097,7 @@ Console.WriteLine(" JointCreateFixed");
IMesh mesh = null;
+
if (_parent_scene.needsMeshing(_pbs))
{
// Don't need to re-enable body.. it's done in CreateMesh
@@ -2094,6 +2108,8 @@ Console.WriteLine(" JointCreateFixed");
// createmesh returns null when it doesn't mesh.
mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
+ if (mesh == null)
+ CheckMeshAsset();
}
CreateGeom(m_targetSpace, mesh);
@@ -2130,7 +2146,7 @@ Console.WriteLine(" JointCreateFixed");
}
resetCollisionAccounting();
- m_taintshape = false;
+// m_taintshape = false;
}
///
@@ -2396,6 +2412,7 @@ Console.WriteLine(" JointCreateFixed");
set
{
_pbs = value;
+ m_assetFailed = false;
m_taintshape = true;
}
}
@@ -3234,5 +3251,37 @@ Console.WriteLine(" JointCreateFixed");
{
m_material = pMaterial;
}
+
+
+ private void CheckMeshAsset()
+ {
+ if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
+ {
+ m_assetFailed = true;
+ Util.FireAndForget(delegate
+ {
+ RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
+ if (assetProvider != null)
+ assetProvider(_pbs.SculptTexture, MeshAssetReveived);
+ });
+ }
+ }
+
+ void MeshAssetReveived(AssetBase asset)
+ {
+ if (asset.Data != null && asset.Data.Length > 0)
+ {
+ if (!_pbs.SculptEntry)
+ return;
+ if (_pbs.SculptTexture.ToString() != asset.ID)
+ return;
+
+ _pbs.SculptData = new byte[asset.Data.Length];
+ asset.Data.CopyTo(_pbs.SculptData, 0);
+ m_assetFailed = false;
+ m_taintshape = true;
+ _parent_scene.AddPhysicsActorTaint(this);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
index 7e3ec63d23..8d7d3b3ae9 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODERayCastRequestManager.cs
@@ -137,15 +137,8 @@ namespace OpenSim.Region.Physics.OdePlugin
ODERayCastRequest[] reqs = m_PendingRequests.ToArray();
for (int i = 0; i < reqs.Length; i++)
{
- try
- {
- if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
- RayCast(reqs[i]); // if there isn't anyone to send results
- }
- catch
- {
- //Fail silently
- }
+ if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast
+ RayCast(reqs[i]); // if there isn't anyone to send results
}
m_PendingRequests.Clear();
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index cbe21e20f9..d53bd90b61 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -4320,4 +4320,4 @@ namespace OpenSim.Region.Physics.OdePlugin
m_stats[ODEPrimUpdateFrameMsStatName] = 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index 98c0f0b458..1e9b8bc895 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -32,24 +32,49 @@ using System.Runtime.InteropServices;
using OpenSim.Region.Physics.Manager;
using PrimMesher;
using OpenMetaverse;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
namespace OpenSim.Region.Physics.Meshing
{
+ public class MeshBuildingData
+ {
+ public Dictionary m_vertices;
+ public List m_triangles;
+ public float m_obbXmin;
+ public float m_obbXmax;
+ public float m_obbYmin;
+ public float m_obbYmax;
+ public float m_obbZmin;
+ public float m_obbZmax;
+ public Vector3 m_centroid;
+ public int m_centroidDiv;
+ }
+
+ [Serializable()]
public class Mesh : IMesh
{
-
- private Dictionary m_vertices;
- private List m_triangles;
- GCHandle m_pinnedVertexes;
- GCHandle m_pinnedIndex;
+ float[] vertices;
+ int[] indexes;
+ Vector3 m_obb;
+ Vector3 m_obboffset;
+ [NonSerialized()]
+ MeshBuildingData m_bdata;
+ [NonSerialized()]
+ GCHandle vhandler;
+ [NonSerialized()]
+ GCHandle ihandler;
+ [NonSerialized()]
IntPtr m_verticesPtr = IntPtr.Zero;
- int m_vertexCount = 0;
+ [NonSerialized()]
IntPtr m_indicesPtr = IntPtr.Zero;
+ [NonSerialized()]
+ int m_vertexCount = 0;
+ [NonSerialized()]
int m_indexCount = 0;
- public float[] m_normals;
- Vector3 m_centroid;
- int m_centroidDiv;
+ public int RefCount { get; set; }
+ public AMeshKey Key { get; set; }
private class vertexcomp : IEqualityComparer
{
@@ -73,43 +98,119 @@ namespace OpenSim.Region.Physics.Meshing
{
vertexcomp vcomp = new vertexcomp();
- m_vertices = new Dictionary(vcomp);
- m_triangles = new List();
- m_centroid = Vector3.Zero;
- m_centroidDiv = 0;
+ m_bdata = new MeshBuildingData();
+ m_bdata.m_vertices = new Dictionary(vcomp);
+ m_bdata.m_triangles = new List();
+ m_bdata.m_centroid = Vector3.Zero;
+ m_bdata.m_centroidDiv = 0;
+ m_bdata.m_obbXmin = float.MaxValue;
+ m_bdata.m_obbXmax = float.MinValue;
+ m_bdata.m_obbYmin = float.MaxValue;
+ m_bdata.m_obbYmax = float.MinValue;
+ m_bdata.m_obbZmin = float.MaxValue;
+ m_bdata.m_obbZmax = float.MinValue;
+ m_obb = new Vector3(0.5f, 0.5f, 0.5f);
+ m_obboffset = Vector3.Zero;
}
- public int RefCount { get; set; }
- public AMeshKey Key { get; set; }
-
- public void Scale(Vector3 scale)
+ public Mesh Scale(Vector3 scale)
{
+ if (m_verticesPtr == null || m_indicesPtr == null)
+ return null;
+ Mesh result = new Mesh();
+ float x = scale.X;
+ float y = scale.Y;
+ float z = scale.Z;
+
+ result.m_obb.X = m_obb.X * x;
+ result.m_obb.Y = m_obb.Y * y;
+ result.m_obb.Z = m_obb.Z * z;
+ result.m_obboffset.X = m_obboffset.X * x;
+ result.m_obboffset.Y = m_obboffset.Y * y;
+ result.m_obboffset.Z = m_obboffset.Z * z;
+
+ result.vertices = new float[vertices.Length];
+ int j = 0;
+ for (int i = 0; i < m_vertexCount; i++)
+ {
+ result.vertices[j] = vertices[j] * x;
+ j++;
+ result.vertices[j] = vertices[j] * y;
+ j++;
+ result.vertices[j] = vertices[j] * z;
+ j++;
+ }
+
+ result.indexes = new int[indexes.Length];
+ indexes.CopyTo(result.indexes,0);
+
+ result.pinMemory();
+
+ return result;
}
public Mesh Clone()
{
Mesh result = new Mesh();
- foreach (Triangle t in m_triangles)
+ if (m_bdata != null)
{
- result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
+ result.m_bdata = new MeshBuildingData();
+ foreach (Triangle t in m_bdata.m_triangles)
+ {
+ result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
+ }
+ result.m_bdata.m_centroid = m_bdata.m_centroid;
+ result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
+ result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
+ result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
+ result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
+ result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
+ result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
+ result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
}
- result.m_centroid = m_centroid;
- result.m_centroidDiv = m_centroidDiv;
+ result.m_obb = m_obb;
+ result.m_obboffset = m_obboffset;
return result;
}
+ public void addVertexLStats(Vertex v)
+ {
+ float x = v.X;
+ float y = v.Y;
+ float z = v.Z;
+
+ m_bdata.m_centroid.X += x;
+ m_bdata.m_centroid.Y += y;
+ m_bdata.m_centroid.Z += z;
+ m_bdata.m_centroidDiv++;
+
+ if (x > m_bdata.m_obbXmax)
+ m_bdata.m_obbXmax = x;
+ else if (x < m_bdata.m_obbXmin)
+ m_bdata.m_obbXmin = x;
+
+ if (y > m_bdata.m_obbYmax)
+ m_bdata.m_obbYmax = y;
+ else if (y < m_bdata.m_obbYmin)
+ m_bdata.m_obbYmin = y;
+
+ if (z > m_bdata.m_obbZmax)
+ m_bdata.m_obbZmax = z;
+ else if (z < m_bdata.m_obbZmin)
+ m_bdata.m_obbZmin = z;
+
+ }
+
+
public void Add(Triangle triangle)
{
- if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+ if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
throw new NotSupportedException("Attempt to Add to a pinned Mesh");
- // If a vertex of the triangle is not yet in the vertices list,
- // add it and set its index to the current index count
- // vertex == seems broken
- // skip colapsed triangles
+
if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
|| (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
|| (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
@@ -118,113 +219,59 @@ namespace OpenSim.Region.Physics.Meshing
return;
}
- if (m_vertices.Count == 0)
+ if (m_bdata.m_vertices.Count == 0)
{
- m_centroidDiv = 0;
- m_centroid = Vector3.Zero;
+ m_bdata.m_centroidDiv = 0;
+ m_bdata.m_centroid = Vector3.Zero;
}
- if (!m_vertices.ContainsKey(triangle.v1))
+ if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
{
- m_vertices[triangle.v1] = m_vertices.Count;
- m_centroid.X += triangle.v1.X;
- m_centroid.Y += triangle.v1.Y;
- m_centroid.Z += triangle.v1.Z;
- m_centroidDiv++;
+ m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
+ addVertexLStats(triangle.v1);
}
- if (!m_vertices.ContainsKey(triangle.v2))
+ if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
{
- m_vertices[triangle.v2] = m_vertices.Count;
- m_centroid.X += triangle.v2.X;
- m_centroid.Y += triangle.v2.Y;
- m_centroid.Z += triangle.v2.Z;
- m_centroidDiv++;
+ m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
+ addVertexLStats(triangle.v2);
}
- if (!m_vertices.ContainsKey(triangle.v3))
+ if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
{
- m_vertices[triangle.v3] = m_vertices.Count;
- m_centroid.X += triangle.v3.X;
- m_centroid.Y += triangle.v3.Y;
- m_centroid.Z += triangle.v3.Z;
- m_centroidDiv++;
+ m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
+ addVertexLStats(triangle.v3);
}
- m_triangles.Add(triangle);
+ m_bdata.m_triangles.Add(triangle);
}
public Vector3 GetCentroid()
{
- if (m_centroidDiv > 0)
- return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv);
- else
- return Vector3.Zero;
+ return m_obboffset;
+
}
- public void CalcNormals()
+ public Vector3 GetOBB()
{
- int iTriangles = m_triangles.Count;
-
- this.m_normals = new float[iTriangles * 3];
-
- int i = 0;
- foreach (Triangle t in m_triangles)
+ return m_obb;
+ float x, y, z;
+ if (m_bdata.m_centroidDiv > 0)
{
- 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;
+ 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 // ??
+ {
+ x = 0.5f;
+ y = 0.5f;
+ z = 0.5f;
+ }
+ return new Vector3(x, y, z);
}
public List getVertexList()
{
List result = new List();
- 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));
}
@@ -233,10 +280,10 @@ namespace OpenSim.Region.Physics.Meshing
private float[] getVertexListAsFloat()
{
- if (m_vertices == null)
+ if (m_bdata.m_vertices == null)
throw new NotSupportedException();
- float[] result = new float[m_vertices.Count * 3];
- foreach (KeyValuePair kvp in m_vertices)
+ float[] result = new float[m_bdata.m_vertices.Count * 3];
+ foreach (KeyValuePair kvp in m_bdata.m_vertices)
{
Vertex v = kvp.Key;
int i = kvp.Value;
@@ -249,48 +296,39 @@ namespace OpenSim.Region.Physics.Meshing
public float[] getVertexListAsFloatLocked()
{
- if (m_pinnedVertexes.IsAllocated)
- return (float[])(m_pinnedVertexes.Target);
-
- float[] result = getVertexListAsFloat();
- m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
- // Inform the garbage collector of this unmanaged allocation so it can schedule
- // the next GC round more intelligently
- GC.AddMemoryPressure(Buffer.ByteLength(result));
-
- return result;
+ return null;
}
- public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
+ public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
{
// A vertex is 3 floats
vertexStride = 3 * sizeof(float);
// If there isn't an unmanaged array allocated yet, do it now
- if (m_verticesPtr == IntPtr.Zero)
+ if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
{
- float[] vertexList = getVertexListAsFloat();
+ vertices = getVertexListAsFloat();
// Each vertex is 3 elements (floats)
- m_vertexCount = vertexList.Length / 3;
- int byteCount = m_vertexCount * vertexStride;
- m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
- System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
+ m_vertexCount = vertices.Length / 3;
+ vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
+ m_verticesPtr = vhandler.AddrOfPinnedObject();
+ GC.AddMemoryPressure(Buffer.ByteLength(vertices));
}
- vertices = m_verticesPtr;
+ _vertices = m_verticesPtr;
vertexCount = m_vertexCount;
}
public int[] getIndexListAsInt()
{
- if (m_triangles == null)
+ if (m_bdata.m_triangles == null)
throw new NotSupportedException();
- int[] result = new int[m_triangles.Count * 3];
- for (int i = 0; i < m_triangles.Count; i++)
+ int[] result = new int[m_bdata.m_triangles.Count * 3];
+ for (int i = 0; i < m_bdata.m_triangles.Count; i++)
{
- Triangle t = m_triangles[i];
- result[3 * i + 0] = m_vertices[t.v1];
- result[3 * i + 1] = m_vertices[t.v2];
- result[3 * i + 2] = m_vertices[t.v3];
+ Triangle t = m_bdata.m_triangles[i];
+ result[3 * i + 0] = m_bdata.m_vertices[t.v1];
+ result[3 * i + 1] = m_bdata.m_vertices[t.v2];
+ result[3 * i + 2] = m_bdata.m_vertices[t.v3];
}
return result;
}
@@ -301,28 +339,19 @@ namespace OpenSim.Region.Physics.Meshing
///
public int[] getIndexListAsIntLocked()
{
- if (m_pinnedIndex.IsAllocated)
- return (int[])(m_pinnedIndex.Target);
-
- int[] result = getIndexListAsInt();
- m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
- // Inform the garbage collector of this unmanaged allocation so it can schedule
- // the next GC round more intelligently
- GC.AddMemoryPressure(Buffer.ByteLength(result));
-
- return result;
+ return null;
}
public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
{
// If there isn't an unmanaged array allocated yet, do it now
- if (m_indicesPtr == IntPtr.Zero)
+ if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
{
- int[] indexList = getIndexListAsInt();
- m_indexCount = indexList.Length;
- int byteCount = m_indexCount * sizeof(int);
- m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
- System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
+ indexes = getIndexListAsInt();
+ m_indexCount = indexes.Length;
+ ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
+ m_indicesPtr = ihandler.AddrOfPinnedObject();
+ GC.AddMemoryPressure(Buffer.ByteLength(indexes));
}
// A triangle is 3 ints (indices)
triStride = 3 * sizeof(int);
@@ -332,18 +361,16 @@ namespace OpenSim.Region.Physics.Meshing
public void releasePinned()
{
- if (m_pinnedVertexes.IsAllocated)
- m_pinnedVertexes.Free();
- if (m_pinnedIndex.IsAllocated)
- m_pinnedIndex.Free();
if (m_verticesPtr != IntPtr.Zero)
{
- System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
+ vhandler.Free();
+ vertices = null;
m_verticesPtr = IntPtr.Zero;
}
if (m_indicesPtr != IntPtr.Zero)
{
- System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
+ ihandler.Free();
+ indexes = null;
m_indicesPtr = IntPtr.Zero;
}
}
@@ -353,29 +380,42 @@ namespace OpenSim.Region.Physics.Meshing
///
public void releaseSourceMeshData()
{
- m_triangles = null;
- m_vertices = null;
+ if (m_bdata != null)
+ {
+ m_bdata.m_triangles = null;
+ m_bdata.m_vertices = null;
+ }
+ }
+
+ public void releaseBuildingMeshData()
+ {
+ if (m_bdata != null)
+ {
+ m_bdata.m_triangles = null;
+ m_bdata.m_vertices = null;
+ m_bdata = null;
+ }
}
public void Append(IMesh newMesh)
{
- if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+ if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
throw new NotSupportedException("Attempt to Append to a pinned Mesh");
if (!(newMesh is Mesh))
return;
- foreach (Triangle t in ((Mesh)newMesh).m_triangles)
+ foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
Add(t);
}
// Do a linear transformation of mesh.
public void TransformLinear(float[,] matrix, float[] offset)
{
- if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
+ if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
-
- foreach (Vertex v in m_vertices.Keys)
+
+ foreach (Vertex v in m_bdata.m_vertices.Keys)
{
if (v == null)
continue;
@@ -393,10 +433,12 @@ namespace OpenSim.Region.Physics.Meshing
{
if (path == null)
return;
+ if (m_bdata == null)
+ return;
String fileName = name + "_" + title + ".raw";
String completePath = System.IO.Path.Combine(path, fileName);
StreamWriter sw = new StreamWriter(completePath);
- foreach (Triangle t in m_triangles)
+ foreach (Triangle t in m_bdata.m_triangles)
{
String s = t.ToStringRaw();
sw.WriteLine(s);
@@ -406,7 +448,144 @@ namespace OpenSim.Region.Physics.Meshing
public void TrimExcess()
{
- m_triangles.TrimExcess();
+ m_bdata.m_triangles.TrimExcess();
+ }
+
+ public void pinMemory()
+ {
+ m_vertexCount = vertices.Length / 3;
+ vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
+ m_verticesPtr = vhandler.AddrOfPinnedObject();
+ GC.AddMemoryPressure(Buffer.ByteLength(vertices));
+
+ m_indexCount = indexes.Length;
+ ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
+ m_indicesPtr = ihandler.AddrOfPinnedObject();
+ GC.AddMemoryPressure(Buffer.ByteLength(indexes));
+ }
+
+ public void PrepForOde()
+ {
+ // If there isn't an unmanaged array allocated yet, do it now
+ if (m_verticesPtr == IntPtr.Zero)
+ vertices = getVertexListAsFloat();
+
+ // If there isn't an unmanaged array allocated yet, do it now
+ if (m_indicesPtr == IntPtr.Zero)
+ indexes = getIndexListAsInt();
+
+ pinMemory();
+
+ float x, y, z;
+
+ if (m_bdata.m_centroidDiv > 0)
+ {
+ m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
+ x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
+ y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
+ z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
+ }
+
+ else
+ {
+ m_obboffset = Vector3.Zero;
+ x = 0.5f;
+ y = 0.5f;
+ z = 0.5f;
+ }
+ m_obb = new Vector3(x, y, z);
+
+ releaseBuildingMeshData();
+ }
+ public bool ToStream(Stream st)
+ {
+ if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
+ return false;
+
+ BinaryWriter bw = new BinaryWriter(st);
+ bool ok = true;
+
+ try
+ {
+
+ bw.Write(m_vertexCount);
+ bw.Write(m_indexCount);
+
+ for (int i = 0; i < 3 * m_vertexCount; i++)
+ bw.Write(vertices[i]);
+ for (int i = 0; i < m_indexCount; i++)
+ bw.Write(indexes[i]);
+ bw.Write(m_obb.X);
+ bw.Write(m_obb.Y);
+ bw.Write(m_obb.Z);
+ bw.Write(m_obboffset.X);
+ bw.Write(m_obboffset.Y);
+ bw.Write(m_obboffset.Z);
+ }
+ catch
+ {
+ ok = false;
+ }
+
+ if (bw != null)
+ {
+ bw.Flush();
+ bw.Close();
+ }
+
+ return ok;
+ }
+
+ public static Mesh FromStream(Stream st, AMeshKey key)
+ {
+ Mesh mesh = new Mesh();
+ mesh.releaseBuildingMeshData();
+
+ BinaryReader br = new BinaryReader(st);
+
+ bool ok = true;
+ try
+ {
+ mesh.m_vertexCount = br.ReadInt32();
+ mesh.m_indexCount = br.ReadInt32();
+
+ int n = 3 * mesh.m_vertexCount;
+ mesh.vertices = new float[n];
+ for (int i = 0; i < n; i++)
+ mesh.vertices[i] = br.ReadSingle();
+
+ mesh.indexes = new int[mesh.m_indexCount];
+ for (int i = 0; i < mesh.m_indexCount; i++)
+ mesh.indexes[i] = br.ReadInt32();
+
+ mesh.m_obb.X = br.ReadSingle();
+ mesh.m_obb.Y = br.ReadSingle();
+ mesh.m_obb.Z = br.ReadSingle();
+
+ mesh.m_obboffset.X = br.ReadSingle();
+ mesh.m_obboffset.Y = br.ReadSingle();
+ mesh.m_obboffset.Z = br.ReadSingle();
+ }
+ catch
+ {
+ ok = false;
+ }
+
+ br.Close();
+
+ if (ok)
+ {
+ mesh.pinMemory();
+
+ mesh.Key = key;
+ mesh.RefCount = 1;
+
+ return mesh;
+ }
+
+ mesh.vertices = null;
+ mesh.indexes = null;
+ return null;
}
}
}
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index 4c40175b76..29fdda4af6 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -42,6 +42,8 @@ using System.Reflection;
using System.IO;
using ComponentAce.Compression.Libs.zlib;
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
namespace OpenSim.Region.Physics.Meshing
{
@@ -68,22 +70,22 @@ namespace OpenSim.Region.Physics.Meshing
// Setting baseDir to a path will enable the dumping of raw files
// raw files can be imported by blender so a visual inspection of the results can be done
-#if SPAM
- const string baseDir = "rawFiles";
-#else
+
+ public object diskLock = new object();
+
+ public bool doMeshFileCache = true;
+
+ public string cachePath = "MeshCache";
+ public TimeSpan CacheExpire;
+ public bool doCacheExpire = true;
+
+// const string baseDir = "rawFiles";
private const string baseDir = null; //"rawFiles";
-#endif
- private bool cacheSculptMaps = true;
- private bool cacheSculptAlphaMaps = true;
-
- private string decodedSculptMapPath = null;
private bool useMeshiesPhysicsMesh = false;
private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
-// private Dictionary m_uniqueMeshes = new Dictionary();
-// private Dictionary m_uniqueReleasedMeshes = new Dictionary();
private Dictionary m_uniqueMeshes = new Dictionary();
private Dictionary m_uniqueReleasedMeshes = new Dictionary();
@@ -92,29 +94,29 @@ namespace OpenSim.Region.Physics.Meshing
IConfig start_config = config.Configs["Startup"];
IConfig mesh_config = config.Configs["Mesh"];
- decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
- cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
-
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- {
- cacheSculptAlphaMaps = false;
- }
- else
- cacheSculptAlphaMaps = cacheSculptMaps;
+ float fcache = 48.0f;
+// float fcache = 0.02f;
if(mesh_config != null)
+ {
useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
+ if (useMeshiesPhysicsMesh)
+ {
+ doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
+ cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
+ fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
+ doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
+ }
+ else
+ {
+ doMeshFileCache = false;
+ doCacheExpire = false;
+ }
+ }
+
+ CacheExpire = TimeSpan.FromHours(fcache);
- try
- {
- if (!Directory.Exists(decodedSculptMapPath))
- Directory.CreateDirectory(decodedSculptMapPath);
- }
- catch (Exception e)
- {
- m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message);
- }
}
///
@@ -212,7 +214,7 @@ namespace OpenSim.Region.Physics.Meshing
/// Size of entire object
///
///
- private void AddSubMesh(OSDMap subMeshData, Vector3 size, List coords, List faces)
+ private void AddSubMesh(OSDMap subMeshData, List coords, List faces)
{
// Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
@@ -245,9 +247,9 @@ namespace OpenSim.Region.Physics.Meshing
ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
Coord c = new Coord(
- Utils.UInt16ToFloat(uX, posMin.X, posMax.X) * size.X,
- Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y) * size.Y,
- Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z) * size.Z);
+ Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
+ Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
+ Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
coords.Add(c);
}
@@ -271,7 +273,7 @@ namespace OpenSim.Region.Physics.Meshing
///
///
///
- private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool convex)
+ private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
{
// m_log.DebugFormat(
// "[MESH]: Creating physics proxy for {0}, shape {1}",
@@ -287,18 +289,18 @@ namespace OpenSim.Region.Physics.Meshing
if (!useMeshiesPhysicsMesh)
return null;
- if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces, convex))
+ if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
return null;
}
else
{
- if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
+ if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
return null;
}
}
else
{
- if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces))
+ if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
return null;
}
@@ -333,7 +335,7 @@ namespace OpenSim.Region.Physics.Meshing
/// Faces are added to this list by the method.
/// true if coords and faces were successfully generated, false if not
private bool GenerateCoordsAndFacesFromPrimMeshData(
- string primName, PrimitiveBaseShape primShape, Vector3 size, out List coords, out List faces, bool convex)
+ string primName, PrimitiveBaseShape primShape, out List coords, out List faces, bool convex)
{
// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
@@ -345,7 +347,7 @@ namespace OpenSim.Region.Physics.Meshing
if (primShape.SculptData.Length <= 0)
{
- m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
+// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
return false;
}
@@ -406,7 +408,7 @@ namespace OpenSim.Region.Physics.Meshing
OSD decodedMeshOsd = new OSD();
byte[] meshBytes = new byte[physSize];
System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
-// byte[] decompressed = new byte[physSize * 5];
+
try
{
using (MemoryStream inMs = new MemoryStream(meshBytes))
@@ -444,13 +446,13 @@ namespace OpenSim.Region.Physics.Meshing
// physics_shape is an array of OSDMaps, one for each submesh
if (decodedMeshOsd is OSDArray)
{
- // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
+// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
foreach (OSD subMeshOsd in decodedMeshOsdArray)
{
if (subMeshOsd is OSDMap)
- AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
+ AddSubMesh(subMeshOsd as OSDMap, coords, faces);
}
}
}
@@ -522,9 +524,9 @@ namespace OpenSim.Region.Physics.Meshing
t3 = data[ptr++];
t3 += data[ptr++] << 8;
- f3 = new float3((t1 * range.X + min.X) * size.X,
- (t2 * range.Y + min.Y) * size.Y,
- (t3 * range.Z + min.Z) * size.Z);
+ f3 = new float3((t1 * range.X + min.X),
+ (t2 * range.Y + min.Y),
+ (t3 * range.Z + min.Z));
vs.Add(f3);
}
@@ -621,9 +623,9 @@ namespace OpenSim.Region.Physics.Meshing
t3 = data[i++];
t3 += data[i++] << 8;
- f3 = new float3((t1 * range.X + min.X) * size.X,
- (t2 * range.Y + min.Y) * size.Y,
- (t3 * range.Z + min.Z) * size.Z);
+ f3 = new float3((t1 * range.X + min.X),
+ (t2 * range.Y + min.Y),
+ (t3 * range.Z + min.Z));
vs.Add(f3);
}
@@ -711,35 +713,13 @@ namespace OpenSim.Region.Physics.Meshing
/// Faces are added to this list by the method.
/// true if coords and faces were successfully generated, false if not
private bool GenerateCoordsAndFacesFromPrimSculptData(
- string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List coords, out List faces)
+ string primName, PrimitiveBaseShape primShape, float lod, out List coords, out List faces)
{
coords = new List();
faces = new List();
PrimMesher.SculptMesh sculptMesh;
Image idata = null;
- string decodedSculptFileName = "";
- if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
- {
- decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
- try
- {
- if (File.Exists(decodedSculptFileName))
- {
- idata = Image.FromFile(decodedSculptFileName);
- }
- }
- catch (Exception e)
- {
- m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
-
- }
- //if (idata != null)
- // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
- }
-
- if (idata == null)
- {
if (primShape.SculptData == null || primShape.SculptData.Length == 0)
return false;
@@ -748,25 +728,15 @@ namespace OpenSim.Region.Physics.Meshing
OpenMetaverse.Imaging.ManagedImage unusedData;
OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
+ unusedData = null;
+
if (idata == null)
{
// In some cases it seems that the decode can return a null bitmap without throwing
// an exception
m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
-
return false;
}
-
- unusedData = null;
-
- //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
-
- if (cacheSculptMaps && (cacheSculptAlphaMaps || (((ImageFlags)(idata.Flags) & ImageFlags.HasAlpha) ==0)))
- // don't cache images with alpha channel in linux since mono can't load them correctly)
- {
- try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
- catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
- }
}
catch (DllNotFoundException)
{
@@ -783,7 +753,6 @@ namespace OpenSim.Region.Physics.Meshing
m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
return false;
}
- }
PrimMesher.SculptMesh.SculptType sculptType;
// remove mirror and invert bits
@@ -814,9 +783,7 @@ namespace OpenSim.Region.Physics.Meshing
idata.Dispose();
- sculptMesh.DumpRaw(baseDir, primName, "primMesh");
-
- sculptMesh.Scale(size.X, size.Y, size.Z);
+// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
coords = sculptMesh.coords;
faces = sculptMesh.faces;
@@ -834,7 +801,7 @@ namespace OpenSim.Region.Physics.Meshing
/// Faces are added to this list by the method.
/// true if coords and faces were successfully generated, false if not
private bool GenerateCoordsAndFacesFromPrimShapeData(
- string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List coords, out List faces)
+ string primName, PrimitiveBaseShape primShape, float lod, out List coords, out List faces)
{
PrimMesh primMesh;
coords = new List();
@@ -969,9 +936,7 @@ namespace OpenSim.Region.Physics.Meshing
}
}
- primMesh.DumpRaw(baseDir, primName, "primMesh");
-
- primMesh.Scale(size.X, size.Y, size.Z);
+// primMesh.DumpRaw(baseDir, primName, "primMesh");
coords = primMesh.coords;
faces = primMesh.faces;
@@ -985,12 +950,14 @@ namespace OpenSim.Region.Physics.Meshing
Byte[] someBytes;
key.hashB = 5181;
+ key.hashC = 5181;
ulong hash = 5381;
if (primShape.SculptEntry)
{
key.uuid = primShape.SculptTexture;
- key.hashB = mdjb2(key.hashB, primShape.SculptType);
+ key.hashC = mdjb2(key.hashC, primShape.SculptType);
+ key.hashC = mdjb2(key.hashC, primShape.PCode);
}
else
{
@@ -1002,6 +969,8 @@ namespace OpenSim.Region.Physics.Meshing
hash = mdjb2(hash, primShape.PathScaleX);
hash = mdjb2(hash, primShape.PathScaleY);
hash = mdjb2(hash, primShape.PathShearX);
+ key.hashA = hash;
+ hash = key.hashB;
hash = mdjb2(hash, primShape.PathShearY);
hash = mdjb2(hash, (byte)primShape.PathTwist);
hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
@@ -1013,26 +982,38 @@ namespace OpenSim.Region.Physics.Meshing
hash = mdjb2(hash, primShape.ProfileBegin);
hash = mdjb2(hash, primShape.ProfileEnd);
hash = mdjb2(hash, primShape.ProfileHollow);
- key.hashA = hash;
+ hash = mdjb2(hash, primShape.PCode);
+ key.hashB = hash;
}
- hash = key.hashB;
-
- someBytes = size.GetBytes();
- for (int i = 0; i < someBytes.Length; i++)
- hash = mdjb2(hash, someBytes[i]);
+ hash = key.hashC;
hash = mdjb2(hash, lod);
-
- hash &= 0x3fffffffffffffff;
+
+ if (size == m_MeshUnitSize)
+ {
+ hash = hash << 8;
+ hash |= 8;
+ }
+ else
+ {
+ someBytes = size.GetBytes();
+ for (int i = 0; i < someBytes.Length; i++)
+ hash = mdjb2(hash, someBytes[i]);
+ hash = hash << 8;
+ }
if (convex)
- hash |= 0x4000000000000000;
+ hash |= 4;
if (primShape.SculptEntry)
- hash |= 0x8000000000000000;
+ {
+ hash |= 1;
+ if (primShape.SculptType == (byte)SculptType.Mesh)
+ hash |= 2;
+ }
- key.hashB = hash;
+ key.hashC = hash;
return key;
}
@@ -1048,35 +1029,74 @@ namespace OpenSim.Region.Physics.Meshing
return ((hash << 5) + hash) + (ulong)(c >> 8);
}
-
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
{
- return CreateMesh(primName, primShape, size, lod, false,false);
+ return CreateMesh(primName, primShape, size, lod, false,false,false);
}
public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
{
- return CreateMesh(primName, primShape, size, lod, 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)
+ {
+ Mesh mesh = null;
- public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
+ if (size.X < 0.01f) size.X = 0.01f;
+ if (size.Y < 0.01f) size.Y = 0.01f;
+ if (size.Z < 0.01f) size.Z = 0.01f;
+
+ AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex);
+ lock (m_uniqueMeshes)
+ {
+ m_uniqueMeshes.TryGetValue(key, out mesh);
+
+ if (mesh != null)
+ {
+ mesh.RefCount++;
+ return mesh;
+ }
+ }
+
+ // try to find a identical mesh on meshs recently released
+ lock (m_uniqueReleasedMeshes)
+ {
+ m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
+ if (mesh != null)
+ {
+ m_uniqueReleasedMeshes.Remove(key);
+ lock (m_uniqueMeshes)
+ {
+ try
+ {
+ m_uniqueMeshes.Add(key, mesh);
+ }
+ catch { }
+ }
+ mesh.RefCount = 1;
+ return mesh;
+ }
+ }
+ return null;
+ }
+
+ private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
+
+ public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
{
#if SPAM
m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
#endif
Mesh mesh = null;
-// ulong key = 0;
-
if (size.X < 0.01f) size.X = 0.01f;
if (size.Y < 0.01f) size.Y = 0.01f;
if (size.Z < 0.01f) size.Z = 0.01f;
// try to find a identical mesh on meshs in use
-// key = primShape.GetMeshKey(size, lod, convex);
+
AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
lock (m_uniqueMeshes)
@@ -1098,35 +1118,78 @@ namespace OpenSim.Region.Physics.Meshing
{
m_uniqueReleasedMeshes.Remove(key);
lock (m_uniqueMeshes)
- m_uniqueMeshes.Add(key, mesh);
+ {
+ try
+ {
+ m_uniqueMeshes.Add(key, mesh);
+ }
+ catch { }
+ }
mesh.RefCount = 1;
return mesh;
}
}
- mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex);
+ Mesh UnitMesh = null;
+ AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
- if (mesh != null)
+ lock (m_uniqueReleasedMeshes)
{
- if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh)
+ m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
+ if (UnitMesh != null)
{
-#if SPAM
- m_log.Debug("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " +
- minSizeForComplexMesh.ToString() + " - creating simple bounding box");
-#endif
- mesh = CreateBoundingBoxMesh(mesh);
- mesh.DumpRaw(baseDir, primName, "Z extruded");
+ UnitMesh.RefCount = 1;
}
-
- // trim the vertex and triangle lists to free up memory
- mesh.TrimExcess();
- mesh.Key = key;
- mesh.RefCount = 1;
-
- lock(m_uniqueMeshes)
- m_uniqueMeshes.Add(key, mesh);
}
+ if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
+ UnitMesh = GetFromFileCache(unitKey);
+
+ if (UnitMesh == null)
+ {
+ UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
+
+ if (UnitMesh == null)
+ return null;
+
+ UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
+
+ if (forOde)
+ {
+ // force pinned mem allocation
+ UnitMesh.PrepForOde();
+ }
+ else
+ UnitMesh.TrimExcess();
+
+ UnitMesh.Key = unitKey;
+ UnitMesh.RefCount = 1;
+
+ if (doMeshFileCache && primShape.SculptEntry)
+ StoreToFileCache(unitKey, UnitMesh);
+
+ lock (m_uniqueReleasedMeshes)
+ {
+ try
+ {
+ m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
+ }
+ catch { }
+ }
+ }
+
+ mesh = UnitMesh.Scale(size);
+ mesh.Key = key;
+ mesh.RefCount = 1;
+ lock (m_uniqueMeshes)
+ {
+ try
+ {
+ m_uniqueMeshes.Add(key, mesh);
+ }
+ catch { }
+ }
+
return mesh;
}
@@ -1137,21 +1200,27 @@ namespace OpenSim.Region.Physics.Meshing
Mesh mesh = (Mesh)imesh;
- int curRefCount = mesh.RefCount;
- curRefCount--;
-
- if (curRefCount > 0)
- {
- mesh.RefCount = curRefCount;
- return;
- }
-
lock (m_uniqueMeshes)
{
+ int curRefCount = mesh.RefCount;
+ curRefCount--;
+
+ if (curRefCount > 0)
+ {
+ mesh.RefCount = curRefCount;
+ return;
+ }
+
mesh.RefCount = 0;
m_uniqueMeshes.Remove(mesh.Key);
lock (m_uniqueReleasedMeshes)
- m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
+ {
+ try
+ {
+ m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
+ }
+ catch { }
+ }
}
}
@@ -1178,10 +1247,170 @@ namespace OpenSim.Region.Physics.Meshing
foreach (Mesh m in meshstodelete)
{
m_uniqueReleasedMeshes.Remove(m.Key);
- m.releaseSourceMeshData();
+ m.releaseBuildingMeshData();
m.releasePinned();
}
}
}
+
+ public void FileNames(AMeshKey key, out string dir,out string fullFileName)
+ {
+ string id = key.ToString();
+ string init = id.Substring(0, 1);
+ dir = System.IO.Path.Combine(cachePath, init);
+ fullFileName = System.IO.Path.Combine(dir, id);
+ }
+
+ public string FullFileName(AMeshKey key)
+ {
+ string id = key.ToString();
+ string init = id.Substring(0,1);
+ id = System.IO.Path.Combine(init, id);
+ id = System.IO.Path.Combine(cachePath, id);
+ return id;
+ }
+
+ private Mesh GetFromFileCache(AMeshKey key)
+ {
+ Mesh mesh = null;
+ string filename = FullFileName(key);
+ bool ok = true;
+
+ lock (diskLock)
+ {
+ if (File.Exists(filename))
+ {
+ FileStream stream = null;
+ try
+ {
+ stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ BinaryFormatter bformatter = new BinaryFormatter();
+
+ mesh = Mesh.FromStream(stream, key);
+
+ }
+ catch (Exception e)
+ {
+ ok = false;
+ m_log.ErrorFormat(
+ "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
+ filename, e.Message, e.StackTrace);
+ }
+
+ if (stream != null)
+ stream.Close();
+
+ if (mesh == null || !ok)
+ File.Delete(filename);
+ else
+ File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
+ }
+ }
+
+ 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 (File.Exists(filename))
+ {
+ if (ok)
+ File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
+ else
+ File.Delete(filename);
+ }
+ }
+ }
+
+ public void ExpireFileCache()
+ {
+ if (!doCacheExpire)
+ return;
+
+ string controlfile = System.IO.Path.Combine(cachePath, "cntr");
+
+ lock (diskLock)
+ {
+ try
+ {
+ if (File.Exists(controlfile))
+ {
+ int ndeleted = 0;
+ int totalfiles = 0;
+ int ndirs = 0;
+ DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
+ File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
+
+ foreach (string dir in Directory.GetDirectories(cachePath))
+ {
+ try
+ {
+ foreach (string file in Directory.GetFiles(dir))
+ {
+ try
+ {
+ if (File.GetLastAccessTimeUtc(file) < OlderTime)
+ {
+ File.Delete(file);
+ ndeleted++;
+ }
+ }
+ catch { }
+ totalfiles++;
+ }
+ }
+ catch { }
+ ndirs++;
+ }
+
+ if (ndeleted == 0)
+ m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires",
+ totalfiles,ndirs);
+ else
+ m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}",
+ totalfiles,ndirs, ndeleted, OlderTime.ToString());
+ }
+ else
+ {
+ m_log.Info("[MESH CACHE]: Expire delayed to next startup");
+ FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough);
+ fs.Close();
+ }
+ }
+ catch { }
+ }
+ }
}
}
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index c363310b16..f5bf05d1a0 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -172,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin
// force lower density for testing
m_density = 3.0f;
-
mu = parent_scene.AvatarFriction;
walkDivisor = walk_divisor;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
new file mode 100644
index 0000000000..73dd2fd49b
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
@@ -0,0 +1,931 @@
+/*
+ * AJLDuarte 2012
+ */
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using OpenSim.Framework;
+using OpenSim.Region.Physics.Manager;
+using OdeAPI;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+
+namespace OpenSim.Region.Physics.OdePlugin
+{
+ public enum MeshState : byte
+ {
+ noNeed = 0,
+
+ loadingAsset = 1,
+
+ AssetOK = 0x0f, // 00001111
+
+ NeedMask = 0x30, // 00110000
+ needMesh = 0x10, // 00010000
+ needAsset = 0x20, // 00100000
+
+ FailMask = 0xC0, // 11000000
+ AssetFailed = 0x40, // 01000000
+ MeshFailed = 0x80, // 10000000
+
+ MeshNoColide = FailMask | needAsset
+ }
+
+ public enum meshWorkerCmnds : byte
+ {
+ nop = 0,
+ addnew,
+ changefull,
+ changesize,
+ changeshapetype,
+ getmesh,
+ }
+
+ public class ODEPhysRepData
+ {
+ public PhysicsActor actor;
+ public PrimitiveBaseShape pbs;
+ public IMesh mesh;
+
+ public Vector3 size;
+ public Vector3 OBB;
+ public Vector3 OBBOffset;
+
+ public float volume;
+
+ public byte shapetype;
+ public bool hasOBB;
+ public bool hasMeshVolume;
+ public MeshState meshState;
+ public UUID? assetID;
+ public meshWorkerCmnds comand;
+ }
+
+ public class ODEMeshWorker
+ {
+
+ private ILog m_log;
+ private OdeScene m_scene;
+ private IMesher m_mesher;
+
+ public bool meshSculptedPrim = true;
+ public bool forceSimplePrimMeshing = false;
+ public float meshSculptLOD = 32;
+ public float MeshSculptphysicalLOD = 32;
+
+
+ private OpenSim.Framework.BlockingQueue createqueue = new OpenSim.Framework.BlockingQueue();
+ private bool m_running;
+
+ private Thread m_thread;
+
+ public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
+ {
+ m_scene = pScene;
+ m_log = pLog;
+ m_mesher = pMesher;
+
+ if (pConfig != null)
+ {
+ forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
+ meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
+ meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
+ MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
+ }
+ m_running = true;
+ m_thread = new Thread(DoWork);
+ m_thread.Start();
+ }
+
+ private void DoWork()
+ {
+ m_mesher.ExpireFileCache();
+
+ while(m_running)
+ {
+ ODEPhysRepData nextRep = createqueue.Dequeue();
+ if(!m_running)
+ return;
+ if (nextRep == null)
+ continue;
+ if (m_scene.haveActor(nextRep.actor))
+ {
+ switch (nextRep.comand)
+ {
+ case meshWorkerCmnds.changefull:
+ case meshWorkerCmnds.changeshapetype:
+ case meshWorkerCmnds.changesize:
+ GetMesh(nextRep);
+ if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
+ m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
+ break;
+ case meshWorkerCmnds.getmesh:
+ DoRepDataGetMesh(nextRep);
+ break;
+ }
+ }
+ }
+ }
+
+ public void Stop()
+ {
+ try
+ {
+ m_thread.Abort();
+ createqueue.Clear();
+ }
+ catch
+ {
+ }
+ }
+
+ public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
+ Vector3 size, byte shapetype)
+ {
+ ODEPhysRepData repData = new ODEPhysRepData();
+ repData.actor = actor;
+ repData.pbs = pbs;
+ repData.size = size;
+ repData.shapetype = shapetype;
+
+ CheckMesh(repData);
+ CalcVolumeData(repData);
+ m_scene.AddChange(actor, changes.PhysRepData, repData);
+ return;
+ }
+
+ public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
+ Vector3 size, byte shapetype)
+ {
+ ODEPhysRepData repData = new ODEPhysRepData();
+ repData.actor = actor;
+ repData.pbs = pbs;
+ repData.size = size;
+ repData.shapetype = shapetype;
+
+ CheckMesh(repData);
+ CalcVolumeData(repData);
+ m_scene.AddChange(actor, changes.AddPhysRep, repData);
+ return repData;
+ }
+
+ public void RequestMesh(ODEPhysRepData repData)
+ {
+ repData.mesh = null;
+
+ if (repData.meshState == MeshState.needAsset)
+ {
+ PrimitiveBaseShape pbs = repData.pbs;
+
+ // check if we got outdated
+
+ if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
+ {
+ repData.meshState = MeshState.noNeed;
+ return;
+ }
+
+ repData.assetID = pbs.SculptTexture;
+ repData.meshState = MeshState.loadingAsset;
+
+ repData.comand = meshWorkerCmnds.getmesh;
+ createqueue.Enqueue(repData);
+ }
+ }
+
+ // creates and prepares a mesh to use and calls parameters estimation
+ public bool CreateActorPhysRep(ODEPhysRepData repData)
+ {
+ IMesh mesh = repData.mesh;
+
+ if (mesh != null)
+ {
+ IntPtr vertices, indices;
+ int vertexCount, indexCount;
+ int vertexStride, triStride;
+
+ mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
+ mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
+
+ if (vertexCount == 0 || indexCount == 0)
+ {
+ m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
+ repData.actor.Name, repData.pbs.SculptTexture.ToString());
+ repData.meshState = MeshState.MeshFailed;
+ repData.hasOBB = false;
+ repData.mesh = null;
+ m_scene.mesher.ReleaseMesh(mesh);
+ }
+ else
+ {
+ repData.OBBOffset = mesh.GetCentroid();
+ repData.OBB = mesh.GetOBB();
+ repData.hasOBB = true;
+ mesh.releaseSourceMeshData();
+ }
+ }
+ CalcVolumeData(repData);
+ return true;
+ }
+
+ public void AssetLoaded(ODEPhysRepData repData)
+ {
+ if (m_scene.haveActor(repData.actor))
+ {
+ if (needsMeshing(repData.pbs)) // no need for pbs now?
+ {
+ repData.comand = meshWorkerCmnds.changefull;
+ createqueue.Enqueue(repData);
+ }
+ }
+ else
+ repData.pbs.SculptData = Utils.EmptyBytes;
+ }
+
+ public void DoRepDataGetMesh(ODEPhysRepData repData)
+ {
+ if (!repData.pbs.SculptEntry)
+ return;
+
+ if (repData.meshState != MeshState.loadingAsset)
+ return;
+
+ if (repData.assetID == null || repData.assetID == UUID.Zero)
+ return;
+
+ if (repData.assetID != repData.pbs.SculptTexture)
+ return;
+
+ // check if it is in cache
+ GetMesh(repData);
+ if (repData.meshState != MeshState.needAsset)
+ {
+ CreateActorPhysRep(repData);
+ m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
+ return;
+ }
+
+ RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
+ if (assetProvider == null)
+ return;
+ ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
+ }
+
+
+ ///
+ /// Routine to figure out if we need to mesh this prim with our mesher
+ ///
+ ///
+ ///
+ public bool needsMeshing(PrimitiveBaseShape pbs)
+ {
+ // check sculpts or meshs
+ if (pbs.SculptEntry)
+ {
+ if (meshSculptedPrim)
+ return true;
+
+ if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
+ return true;
+
+ return false;
+ }
+
+ if (forceSimplePrimMeshing)
+ return true;
+
+ // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
+
+ if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
+ || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
+ && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
+ {
+
+ if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
+ && pbs.ProfileHollow == 0
+ && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
+ && pbs.PathBegin == 0 && pbs.PathEnd == 0
+ && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
+ && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
+ && pbs.PathShearX == 0 && pbs.PathShearY == 0)
+ {
+ return false;
+ }
+ }
+
+ // following code doesn't give meshs to boxes and spheres ever
+ // and it's odd.. so for now just return true if asked to force meshs
+ // hopefully mesher will fail if doesn't suport so things still get basic boxes
+
+ int iPropertiesNotSupportedDefault = 0;
+
+ if (pbs.ProfileHollow != 0)
+ iPropertiesNotSupportedDefault++;
+
+ if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
+ iPropertiesNotSupportedDefault++;
+
+ if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
+ iPropertiesNotSupportedDefault++;
+
+ if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
+ iPropertiesNotSupportedDefault++;
+
+ if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
+ iPropertiesNotSupportedDefault++;
+
+ if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
+ iPropertiesNotSupportedDefault++;
+
+ if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
+ iPropertiesNotSupportedDefault++;
+
+ if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
+ iPropertiesNotSupportedDefault++;
+
+ if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
+ iPropertiesNotSupportedDefault++;
+
+ // test for torus
+ if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
+ {
+ if (pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+ }
+ else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
+ {
+ if (pbs.PathCurve == (byte)Extrusion.Straight)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+
+ // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
+ else if (pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+ }
+ else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
+ {
+ if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+ }
+ else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
+ {
+ if (pbs.PathCurve == (byte)Extrusion.Straight)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+ else if (pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ iPropertiesNotSupportedDefault++;
+ }
+ }
+
+ if (iPropertiesNotSupportedDefault == 0)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ // see if we need a mesh and if so if we have a cached one
+ // called with a new repData
+ public void CheckMesh(ODEPhysRepData repData)
+ {
+ PhysicsActor actor = repData.actor;
+ PrimitiveBaseShape pbs = repData.pbs;
+
+ if (!needsMeshing(pbs))
+ {
+ repData.meshState = MeshState.noNeed;
+ return;
+ }
+
+ IMesh mesh = null;
+
+ Vector3 size = repData.size;
+ byte shapetype = repData.shapetype;
+
+ bool convex;
+
+ int clod = (int)LevelOfDetail.High;
+ if (shapetype == 0)
+ convex = false;
+ else
+ {
+ convex = true;
+ if (pbs.SculptType != (byte)SculptType.Mesh)
+ clod = (int)LevelOfDetail.Low;
+ }
+
+ mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
+
+ if (mesh == null)
+ {
+ if (pbs.SculptEntry)
+ {
+ if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
+ {
+ repData.assetID = pbs.SculptTexture;
+ repData.meshState = MeshState.needAsset;
+ }
+ else
+ repData.meshState = MeshState.MeshFailed;
+
+ return;
+ }
+ else
+ {
+ repData.meshState = MeshState.needMesh;
+ mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
+ if (mesh == null)
+ {
+ repData.meshState = MeshState.MeshFailed;
+ return;
+ }
+ }
+ }
+
+ repData.meshState = MeshState.AssetOK;
+ repData.mesh = mesh;
+
+ if (pbs.SculptEntry)
+ {
+ repData.assetID = pbs.SculptTexture;
+ }
+
+ pbs.SculptData = Utils.EmptyBytes;
+ return ;
+ }
+
+ public void GetMesh(ODEPhysRepData repData)
+ {
+ PhysicsActor actor = repData.actor;
+
+ PrimitiveBaseShape pbs = repData.pbs;
+
+ repData.mesh = null;
+ repData.hasOBB = false;
+
+ if (!needsMeshing(pbs))
+ {
+ repData.meshState = MeshState.noNeed;
+ return;
+ }
+
+ if (repData.meshState == MeshState.MeshFailed)
+ return;
+
+ if (pbs.SculptEntry)
+ {
+ if (repData.meshState == MeshState.AssetFailed)
+ {
+ if (pbs.SculptTexture == repData.assetID)
+ return;
+ }
+ }
+
+ repData.meshState = MeshState.noNeed;
+
+ IMesh mesh = null;
+ Vector3 size = repData.size;
+ byte shapetype = repData.shapetype;
+
+ bool convex;
+ int clod = (int)LevelOfDetail.High;
+ if (shapetype == 0)
+ convex = false;
+ else
+ {
+ convex = true;
+ if (pbs.SculptType != (byte)SculptType.Mesh)
+ clod = (int)LevelOfDetail.Low;
+ }
+
+ mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
+
+ if (mesh == null)
+ {
+ if (pbs.SculptEntry)
+ {
+ if (pbs.SculptTexture == UUID.Zero)
+ return;
+
+ repData.assetID = pbs.SculptTexture;
+
+ if (pbs.SculptData == null || pbs.SculptData.Length == 0)
+ {
+ repData.meshState = MeshState.needAsset;
+ return;
+ }
+ }
+ }
+
+ repData.mesh = mesh;
+ repData.pbs.SculptData = Utils.EmptyBytes;
+
+ if (mesh == null)
+ {
+ if (pbs.SculptEntry)
+ repData.meshState = MeshState.AssetFailed;
+ else
+ repData.meshState = MeshState.MeshFailed;
+
+ return;
+ }
+
+ repData.meshState = MeshState.AssetOK;
+
+ return;
+ }
+
+ private void CalculateBasicPrimVolume(ODEPhysRepData repData)
+ {
+ PrimitiveBaseShape _pbs = repData.pbs;
+ Vector3 _size = repData.size;
+
+ float volume = _size.X * _size.Y * _size.Z; // default
+ float tmp;
+
+ float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
+ float hollowVolume = hollowAmount * hollowAmount;
+
+ switch (_pbs.ProfileShape)
+ {
+ case ProfileShape.Square:
+ // default box
+
+ if (_pbs.PathCurve == (byte)Extrusion.Straight)
+ {
+ if (hollowAmount > 0.0)
+ {
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Square:
+ case HollowShape.Same:
+ break;
+
+ case HollowShape.Circle:
+
+ hollowVolume *= 0.78539816339f;
+ break;
+
+ case HollowShape.Triangle:
+
+ hollowVolume *= (0.5f * .5f);
+ break;
+
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+
+ else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ //a tube
+
+ volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
+ tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
+ volume -= volume * tmp * tmp;
+
+ if (hollowAmount > 0.0)
+ {
+ hollowVolume *= hollowAmount;
+
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Square:
+ case HollowShape.Same:
+ break;
+
+ case HollowShape.Circle:
+ hollowVolume *= 0.78539816339f;
+ break;
+
+ case HollowShape.Triangle:
+ hollowVolume *= 0.5f * 0.5f;
+ break;
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+
+ break;
+
+ case ProfileShape.Circle:
+
+ if (_pbs.PathCurve == (byte)Extrusion.Straight)
+ {
+ volume *= 0.78539816339f; // elipse base
+
+ if (hollowAmount > 0.0)
+ {
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Same:
+ case HollowShape.Circle:
+ break;
+
+ case HollowShape.Square:
+ hollowVolume *= 0.5f * 2.5984480504799f;
+ break;
+
+ case HollowShape.Triangle:
+ hollowVolume *= .5f * 1.27323954473516f;
+ break;
+
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+
+ else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
+ tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
+ volume *= (1.0f - tmp * tmp);
+
+ if (hollowAmount > 0.0)
+ {
+
+ // calculate the hollow volume by it's shape compared to the prim shape
+ hollowVolume *= hollowAmount;
+
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Same:
+ case HollowShape.Circle:
+ break;
+
+ case HollowShape.Square:
+ hollowVolume *= 0.5f * 2.5984480504799f;
+ break;
+
+ case HollowShape.Triangle:
+ hollowVolume *= .5f * 1.27323954473516f;
+ break;
+
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+ break;
+
+ case ProfileShape.HalfCircle:
+ if (_pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ volume *= 0.5236f;
+
+ if (hollowAmount > 0.0)
+ {
+ hollowVolume *= hollowAmount;
+
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Circle:
+ case HollowShape.Triangle: // diference in sl is minor and odd
+ case HollowShape.Same:
+ break;
+
+ case HollowShape.Square:
+ hollowVolume *= 0.909f;
+ break;
+
+ // case HollowShape.Triangle:
+ // hollowVolume *= .827f;
+ // break;
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+
+ }
+ break;
+
+ case ProfileShape.EquilateralTriangle:
+
+ if (_pbs.PathCurve == (byte)Extrusion.Straight)
+ {
+ volume *= 0.32475953f;
+
+ if (hollowAmount > 0.0)
+ {
+
+ // calculate the hollow volume by it's shape compared to the prim shape
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Same:
+ case HollowShape.Triangle:
+ hollowVolume *= .25f;
+ break;
+
+ case HollowShape.Square:
+ hollowVolume *= 0.499849f * 3.07920140172638f;
+ break;
+
+ case HollowShape.Circle:
+ // Hollow shape is a perfect cyllinder in respect to the cube's scale
+ // Cyllinder hollow volume calculation
+
+ hollowVolume *= 0.1963495f * 3.07920140172638f;
+ break;
+
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+ else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
+ {
+ volume *= 0.32475953f;
+ volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
+ tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
+ volume *= (1.0f - tmp * tmp);
+
+ if (hollowAmount > 0.0)
+ {
+
+ hollowVolume *= hollowAmount;
+
+ switch (_pbs.HollowShape)
+ {
+ case HollowShape.Same:
+ case HollowShape.Triangle:
+ hollowVolume *= .25f;
+ break;
+
+ case HollowShape.Square:
+ hollowVolume *= 0.499849f * 3.07920140172638f;
+ break;
+
+ case HollowShape.Circle:
+
+ hollowVolume *= 0.1963495f * 3.07920140172638f;
+ break;
+
+ default:
+ hollowVolume = 0;
+ break;
+ }
+ volume *= (1.0f - hollowVolume);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ float taperX1;
+ float taperY1;
+ float taperX;
+ float taperY;
+ float pathBegin;
+ float pathEnd;
+ float profileBegin;
+ float profileEnd;
+
+ if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
+ {
+ taperX1 = _pbs.PathScaleX * 0.01f;
+ if (taperX1 > 1.0f)
+ taperX1 = 2.0f - taperX1;
+ taperX = 1.0f - taperX1;
+
+ taperY1 = _pbs.PathScaleY * 0.01f;
+ if (taperY1 > 1.0f)
+ taperY1 = 2.0f - taperY1;
+ taperY = 1.0f - taperY1;
+ }
+ else
+ {
+ taperX = _pbs.PathTaperX * 0.01f;
+ if (taperX < 0.0f)
+ taperX = -taperX;
+ taperX1 = 1.0f - taperX;
+
+ taperY = _pbs.PathTaperY * 0.01f;
+ if (taperY < 0.0f)
+ taperY = -taperY;
+ taperY1 = 1.0f - taperY;
+ }
+
+ volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
+
+ pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
+ pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
+ volume *= (pathEnd - pathBegin);
+
+ // this is crude aproximation
+ profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
+ profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
+ volume *= (profileEnd - profileBegin);
+
+ repData.volume = volume;
+ }
+
+ private void CalcVolumeData(ODEPhysRepData repData)
+ {
+ if (repData.hasOBB)
+ {
+ Vector3 OBB = repData.OBB;
+ }
+ else
+ {
+ Vector3 OBB = repData.size;
+ OBB.X *= 0.5f;
+ OBB.Y *= 0.5f;
+ OBB.Z *= 0.5f;
+
+ repData.OBB = OBB;
+ repData.OBBOffset = Vector3.Zero;
+ }
+
+ CalculateBasicPrimVolume(repData);
+ }
+ }
+
+ public class ODEAssetRequest
+ {
+ ODEMeshWorker m_worker;
+ private ILog m_log;
+ ODEPhysRepData repData;
+
+ public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
+ ODEPhysRepData pRepData, ILog plog)
+ {
+ m_worker = pWorker;
+ m_log = plog;
+ repData = pRepData;
+
+ repData.meshState = MeshState.AssetFailed;
+ if (provider == null)
+ return;
+
+ if (repData.assetID == null)
+ return;
+
+ UUID assetID = (UUID) repData.assetID;
+ if (assetID == UUID.Zero)
+ return;
+
+ repData.meshState = MeshState.loadingAsset;
+ provider(assetID, ODEassetReceived);
+ }
+
+ void ODEassetReceived(AssetBase asset)
+ {
+ repData.meshState = MeshState.AssetFailed;
+ if (asset != null)
+ {
+ if (asset.Data != null && asset.Data.Length > 0)
+ {
+ repData.meshState = MeshState.noNeed;
+
+ if (!repData.pbs.SculptEntry)
+ return;
+ if (repData.pbs.SculptTexture != repData.assetID)
+ return;
+
+ repData.pbs.SculptData = new byte[asset.Data.Length];
+ asset.Data.CopyTo(repData.pbs.SculptData,0);
+ repData.meshState = MeshState.AssetOK;
+ m_worker.AssetLoaded(repData);
+ }
+ else
+ m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
+ repData.actor.Name, asset.ID.ToString());
+ }
+ else
+ m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
+ repData.actor.Name);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index f2f4725900..ce67cc469e 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_lastdoneSelected;
internal bool m_outbounds;
- private Quaternion m_lastorientation = new Quaternion();
+ private Quaternion m_lastorientation;
private Quaternion _orientation;
private Vector3 _position;
@@ -91,33 +91,30 @@ namespace OpenSim.Region.Physics.OdePlugin
private Vector3 _size;
private Vector3 _acceleration;
private Vector3 m_angularlock = Vector3.One;
- private IntPtr Amotor = IntPtr.Zero;
+ private IntPtr Amotor;
private Vector3 m_force;
private Vector3 m_forceacc;
private Vector3 m_angularForceacc;
- private float m_invTimeStep = 50.0f;
- private float m_timeStep = .02f;
+ private float m_invTimeStep;
+ private float m_timeStep;
private Vector3 m_PIDTarget;
private float m_PIDTau;
private bool m_usePID;
- // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
- // and are for non-VEHICLES only.
-
private float m_PIDHoverHeight;
private float m_PIDHoverTau;
private bool m_useHoverPID;
- private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
+ private PIDHoverType m_PIDHoverType;
private float m_targetHoverHeight;
private float m_groundHeight;
private float m_waterHeight;
private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
- private int body_autodisable_frames = 5;
- public int bodydisablecontrol = 0;
+ private int body_autodisable_frames;
+ public int bodydisablecontrol;
// Default we're a Geometry
@@ -147,12 +144,16 @@ namespace OpenSim.Region.Physics.OdePlugin
private IMesh m_mesh;
private object m_meshlock = new object();
private PrimitiveBaseShape _pbs;
+
+ private UUID? m_assetID;
+ private MeshState m_meshState;
+
public OdeScene _parent_scene;
///
/// The physics space which contains prim geometry
///
- public IntPtr m_targetSpace = IntPtr.Zero;
+ public IntPtr m_targetSpace;
public IntPtr prim_geom;
public IntPtr _triMeshData;
@@ -166,27 +167,32 @@ namespace OpenSim.Region.Physics.OdePlugin
public IntPtr collide_geom; // for objects: geom if single prim space it linkset
- private float m_density = 10.000006836f; // Aluminum g/cm3;
+ private float m_density;
private byte m_shapetype;
public bool _zeroFlag;
private bool m_lastUpdateSent;
- public IntPtr Body = IntPtr.Zero;
+ public IntPtr Body;
private Vector3 _target_velocity;
- public Vector3 primOOBsize; // prim real dimensions from mesh
- public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb
+ public Vector3 m_OBBOffset;
+ public Vector3 m_OBB;
public float primOOBradiusSQ;
+
+ private bool m_hasOBB = true;
+
+ private float m_physCost;
+ private float m_streamCost;
+
public d.Mass primdMass; // prim inertia information on it's own referencial
float primMass; // prim own mass
float primVolume; // prim own volume;
float _mass; // object mass acording to case
- private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
- public int givefakepos = 0;
+ public int givefakepos;
private Vector3 fakepos;
- public int givefakeori = 0;
+ public int givefakeori;
private Quaternion fakeori;
private int m_eventsubscription;
@@ -271,7 +277,23 @@ namespace OpenSim.Region.Physics.OdePlugin
cdata.mu *= veh.FrictionFactor;
// cdata.mu *= 0;
}
- }
+ }
+
+ public override float PhysicsCost
+ {
+ get
+ {
+ return m_physCost;
+ }
+ }
+
+ public override float StreamCost
+ {
+ get
+ {
+ return m_streamCost;
+ }
+ }
public override int PhysicsActorType
{
@@ -394,7 +416,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (value.IsFinite())
{
- AddChange(changes.Size, value);
+ _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype);
}
else
{
@@ -464,7 +486,7 @@ namespace OpenSim.Region.Physics.OdePlugin
q.Z = dq.Z;
q.W = dq.W;
- Vector3 Ptot = primOOBoffset * q;
+ Vector3 Ptot = m_OBBOffset * q;
dtmp = d.GeomGetPosition(prim_geom);
Ptot.X += dtmp.X;
Ptot.Y += dtmp.Y;
@@ -504,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
get
{
- return primOOBsize;
+ return m_OBB;
}
}
@@ -512,7 +534,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{
get
{
- return primOOBoffset;
+ return m_OBBOffset;
}
}
@@ -528,7 +550,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{
set
{
- AddChange(changes.Shape, value);
+// AddChange(changes.Shape, value);
+ _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype);
}
}
@@ -541,11 +564,10 @@ namespace OpenSim.Region.Physics.OdePlugin
set
{
m_shapetype = value;
- AddChange(changes.Shape, null);
+ _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
}
}
-
public override Vector3 Velocity
{
get
@@ -619,6 +641,9 @@ namespace OpenSim.Region.Physics.OdePlugin
{
fakeori = value;
givefakeori++;
+
+ value.Normalize();
+
AddChange(changes.Orientation, value);
}
else
@@ -1012,7 +1037,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_invTimeStep = 1f / m_timeStep;
m_density = parent_scene.geomDefaultDensity;
- // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
prim_geom = IntPtr.Zero;
@@ -1064,7 +1088,6 @@ namespace OpenSim.Region.Physics.OdePlugin
m_colliderfilter = 0;
m_NoColide = false;
- hasOOBoffsetFromMesh = false;
_triMeshData = IntPtr.Zero;
m_shapetype = _shapeType;
@@ -1079,27 +1102,14 @@ namespace OpenSim.Region.Physics.OdePlugin
mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
- CalcPrimBodyData();
-
- m_mesh = null;
- if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0))
- {
- bool convex;
- int clod = (int)LevelOfDetail.High;
- if (m_shapetype == 0)
- convex = false;
- else
- {
- convex = true;
- if (_pbs.SculptType != (byte)SculptType.Mesh)
- clod = (int)LevelOfDetail.Low;
- }
- m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex);
- }
-
m_building = true; // control must set this to false when done
- AddChange(changes.Add, null);
+ // get basic mass parameters
+ ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype);
+
+ primVolume = repData.volume;
+
+ UpdatePrimBodyData();
}
private void resetCollisionAccounting()
@@ -1323,105 +1333,6 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
- private bool setMesh(OdeScene parent_scene)
- {
- IntPtr vertices, indices;
- int vertexCount, indexCount;
- int vertexStride, triStride;
-
- if (Body != IntPtr.Zero)
- {
- if (childPrim)
- {
- if (_parent != null)
- {
- OdePrim parent = (OdePrim)_parent;
- parent.ChildDelink(this, false);
- }
- }
- else
- {
- DestroyBody();
- }
- }
-
- IMesh mesh = null;
-
- lock (m_meshlock)
- {
- if (m_mesh == null)
- {
- bool convex;
- int clod = (int)LevelOfDetail.High;
-
- if (m_shapetype == 0)
- convex = false;
- else
- {
- convex = true;
- if (_pbs.SculptType != (byte)SculptType.Mesh)
- clod = (int)LevelOfDetail.Low;
- }
-
- mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex);
- }
- else
- {
- mesh = m_mesh;
- }
-
- if (mesh == null)
- {
- m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
- return false;
- }
-
-
- 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
-
- if (vertexCount == 0 || indexCount == 0)
- {
- m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}",
- Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
- mesh.releaseSourceMeshData();
- return false;
- }
-
- primOOBoffset = mesh.GetCentroid();
- hasOOBoffsetFromMesh = true;
-
- mesh.releaseSourceMeshData();
- m_mesh = mesh;
- }
-
- IntPtr geo = IntPtr.Zero;
-
- try
- {
- _triMeshData = d.GeomTriMeshDataCreate();
-
- d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
- d.GeomTriMeshDataPreprocess(_triMeshData);
-
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
- geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
- }
-
- catch (Exception e)
- {
- m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
- if (_triMeshData != IntPtr.Zero)
- {
- d.GeomTriMeshDataDestroy(_triMeshData);
- _triMeshData = IntPtr.Zero;
- }
- return false;
- }
-
- SetGeom(geo);
- return true;
- }
private void SetGeom(IntPtr geom)
{
@@ -1449,49 +1360,139 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
}
- CalcPrimBodyData();
-
+ UpdatePrimBodyData();
_parent_scene.actor_name_map[prim_geom] = this;
+/*
+// debug
+ d.AABB aabb;
+ d.GeomGetAABB(prim_geom, out aabb);
+ float x = aabb.MaxX - aabb.MinX;
+ float y = aabb.MaxY - aabb.MinY;
+ float z = aabb.MaxZ - aabb.MinZ;
+ if( x > 60.0f || y > 60.0f || z > 60.0f)
+ m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
+ Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
+ else if (x < 0.001f || y < 0.001f || z < 0.001f)
+ m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
+ Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
+
+//
+*/
+
}
else
m_log.Warn("Setting bad Geom");
}
-
- ///
- /// Create a geometry for the given mesh in the given target space.
- ///
- ///
- /// If null, then a mesh is used that is based on the profile shape data.
- private void CreateGeom()
+ private bool GetMeshGeom()
{
- if (_triMeshData != IntPtr.Zero)
+ IntPtr vertices, indices;
+ int vertexCount, indexCount;
+ int vertexStride, triStride;
+
+ IMesh mesh = m_mesh;
+
+ if (mesh == null)
+ return false;
+
+ mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
+ mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
+
+ if (vertexCount == 0 || indexCount == 0)
{
- d.GeomTriMeshDataDestroy(_triMeshData);
- _triMeshData = IntPtr.Zero;
+ m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1}",
+ Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh");
+
+ m_hasOBB = false;
+ m_OBBOffset = Vector3.Zero;
+ m_OBB = _size * 0.5f;
+
+ m_physCost = 0.1f;
+ m_streamCost = 1.0f;
+
+ _parent_scene.mesher.ReleaseMesh(mesh);
+ m_meshState = MeshState.MeshFailed;
+ m_mesh = null;
+ return false;
}
- bool haveMesh = false;
- hasOOBoffsetFromMesh = false;
+ IntPtr geo = IntPtr.Zero;
+
+ try
+ {
+ _triMeshData = d.GeomTriMeshDataCreate();
+
+ d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
+ d.GeomTriMeshDataPreprocess(_triMeshData);
+
+ geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
+ }
+
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
+ if (_triMeshData != IntPtr.Zero)
+ {
+ try
+ {
+ d.GeomTriMeshDataDestroy(_triMeshData);
+ }
+ catch
+ {
+ }
+ }
+ _triMeshData = IntPtr.Zero;
+
+ m_hasOBB = false;
+ m_OBBOffset = Vector3.Zero;
+ m_OBB = _size * 0.5f;
+ m_physCost = 0.1f;
+ m_streamCost = 1.0f;
+
+ _parent_scene.mesher.ReleaseMesh(mesh);
+ m_meshState = MeshState.MeshFailed;
+ m_mesh = null;
+ return false;
+ }
+
+ m_physCost = 0.0013f * (float)indexCount;
+ // todo
+ m_streamCost = 1.0f;
+
+ SetGeom(geo);
+
+ return true;
+ }
+
+ private void CreateGeom()
+ {
+ bool hasMesh = false;
+
m_NoColide = false;
- if (_parent_scene.needsMeshing(_pbs))
+ if ((m_meshState & MeshState.MeshNoColide) != 0)
+ m_NoColide = true;
+
+ else if(m_mesh != null)
{
- haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
- if (!haveMesh)
+ if (GetMeshGeom())
+ hasMesh = true;
+ else
m_NoColide = true;
}
- if (!haveMesh)
+
+ if (!hasMesh)
{
+ IntPtr geo = IntPtr.Zero;
+
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
&& _size.X == _size.Y && _size.Y == _size.Z)
{ // it's a sphere
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
+ geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
}
catch (Exception e)
{
@@ -1501,11 +1502,9 @@ namespace OpenSim.Region.Physics.OdePlugin
}
else
{// do it as a box
- _parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- //Console.WriteLine(" CreateGeom 4");
- SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
+ geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
}
catch (Exception e)
{
@@ -1513,19 +1512,18 @@ namespace OpenSim.Region.Physics.OdePlugin
return;
}
}
+ m_physCost = 0.1f;
+ m_streamCost = 1.0f;
+ SetGeom(geo);
}
}
- ///
- /// Set a new geometry for this prim.
- ///
- ///
private void RemoveGeom()
{
if (prim_geom != IntPtr.Zero)
{
-// _parent_scene.geom_name_map.Remove(prim_geom);
_parent_scene.actor_name_map.Remove(prim_geom);
+
try
{
d.GeomDestroy(prim_geom);
@@ -1534,11 +1532,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomTriMeshDataDestroy(_triMeshData);
_triMeshData = IntPtr.Zero;
}
-
}
-
-
- // catch (System.AccessViolationException)
catch (Exception e)
{
m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
@@ -1546,29 +1540,26 @@ namespace OpenSim.Region.Physics.OdePlugin
prim_geom = IntPtr.Zero;
collide_geom = IntPtr.Zero;
+ m_targetSpace = IntPtr.Zero;
}
else
{
m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
}
- if (m_mesh != null)
+ lock (m_meshlock)
{
- _parent_scene.mesher.ReleaseMesh(m_mesh);
- m_mesh = null;
+ if (m_mesh != null)
+ {
+ _parent_scene.mesher.ReleaseMesh(m_mesh);
+ m_mesh = null;
+ }
}
Body = IntPtr.Zero;
- hasOOBoffsetFromMesh = false;
+ m_hasOBB = false;
}
-/*
- private void ChildSetGeom(OdePrim odePrim)
- {
- // well..
- DestroyBody();
- MakeBody();
- }
-*/
+
//sets non physical prim m_targetSpace to right space in spaces grid for static prims
// should only be called for non physical prims unless they are becoming non physical
private void SetInStaticSpace(OdePrim prim)
@@ -1631,9 +1622,6 @@ namespace OpenSim.Region.Physics.OdePlugin
if (Body != IntPtr.Zero)
{
-// d.BodyDestroy(Body);
-// Body = IntPtr.Zero;
- // do a more complet destruction
DestroyBody();
m_log.Warn("[PHYSICS]: MakeBody called having a body");
}
@@ -2143,339 +2131,9 @@ namespace OpenSim.Region.Physics.OdePlugin
#region Mass Calculation
- private float CalculatePrimVolume()
+ private void UpdatePrimBodyData()
{
- float volume = _size.X * _size.Y * _size.Z; // default
- float tmp;
-
- float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
- float hollowVolume = hollowAmount * hollowAmount;
-
- switch (_pbs.ProfileShape)
- {
- case ProfileShape.Square:
- // default box
-
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- if (hollowAmount > 0.0)
- {
- switch (_pbs.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
-
- case HollowShape.Circle:
-
- hollowVolume *= 0.78539816339f;
- break;
-
- case HollowShape.Triangle:
-
- hollowVolume *= (0.5f * .5f);
- break;
-
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
-
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- //a tube
-
- volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
- volume -= volume * tmp * tmp;
-
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
-
- switch (_pbs.HollowShape)
- {
- case HollowShape.Square:
- case HollowShape.Same:
- break;
-
- case HollowShape.Circle:
- hollowVolume *= 0.78539816339f;
- break;
-
- case HollowShape.Triangle:
- hollowVolume *= 0.5f * 0.5f;
- break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
-
- break;
-
- case ProfileShape.Circle:
-
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.78539816339f; // elipse base
-
- if (hollowAmount > 0.0)
- {
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
-
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
-
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
-
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
-
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
- volume *= (1.0f - tmp * tmp);
-
- if (hollowAmount > 0.0)
- {
-
- // calculate the hollow volume by it's shape compared to the prim shape
- hollowVolume *= hollowAmount;
-
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Circle:
- break;
-
- case HollowShape.Square:
- hollowVolume *= 0.5f * 2.5984480504799f;
- break;
-
- case HollowShape.Triangle:
- hollowVolume *= .5f * 1.27323954473516f;
- break;
-
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
-
- case ProfileShape.HalfCircle:
- if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.5236f;
-
- if (hollowAmount > 0.0)
- {
- hollowVolume *= hollowAmount;
-
- switch (_pbs.HollowShape)
- {
- case HollowShape.Circle:
- case HollowShape.Triangle: // diference in sl is minor and odd
- case HollowShape.Same:
- break;
-
- case HollowShape.Square:
- hollowVolume *= 0.909f;
- break;
-
- // case HollowShape.Triangle:
- // hollowVolume *= .827f;
- // break;
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
-
- }
- break;
-
- case ProfileShape.EquilateralTriangle:
-
- if (_pbs.PathCurve == (byte)Extrusion.Straight)
- {
- volume *= 0.32475953f;
-
- if (hollowAmount > 0.0)
- {
-
- // calculate the hollow volume by it's shape compared to the prim shape
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
-
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
-
- case HollowShape.Circle:
- // Hollow shape is a perfect cyllinder in respect to the cube's scale
- // Cyllinder hollow volume calculation
-
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
-
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- volume *= 0.32475953f;
- volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
- tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
- volume *= (1.0f - tmp * tmp);
-
- if (hollowAmount > 0.0)
- {
-
- hollowVolume *= hollowAmount;
-
- switch (_pbs.HollowShape)
- {
- case HollowShape.Same:
- case HollowShape.Triangle:
- hollowVolume *= .25f;
- break;
-
- case HollowShape.Square:
- hollowVolume *= 0.499849f * 3.07920140172638f;
- break;
-
- case HollowShape.Circle:
-
- hollowVolume *= 0.1963495f * 3.07920140172638f;
- break;
-
- default:
- hollowVolume = 0;
- break;
- }
- volume *= (1.0f - hollowVolume);
- }
- }
- break;
-
- default:
- break;
- }
-
- float taperX1;
- float taperY1;
- float taperX;
- float taperY;
- float pathBegin;
- float pathEnd;
- float profileBegin;
- float profileEnd;
-
- if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
- {
- taperX1 = _pbs.PathScaleX * 0.01f;
- if (taperX1 > 1.0f)
- taperX1 = 2.0f - taperX1;
- taperX = 1.0f - taperX1;
-
- taperY1 = _pbs.PathScaleY * 0.01f;
- if (taperY1 > 1.0f)
- taperY1 = 2.0f - taperY1;
- taperY = 1.0f - taperY1;
- }
- else
- {
- taperX = _pbs.PathTaperX * 0.01f;
- if (taperX < 0.0f)
- taperX = -taperX;
- taperX1 = 1.0f - taperX;
-
- taperY = _pbs.PathTaperY * 0.01f;
- if (taperY < 0.0f)
- taperY = -taperY;
- taperY1 = 1.0f - taperY;
- }
-
- volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
-
- pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
- pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
- volume *= (pathEnd - pathBegin);
-
- // this is crude aproximation
- profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
- profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
- volume *= (profileEnd - profileBegin);
-
- return volume;
- }
-
-
- private void CalcPrimBodyData()
- {
- float volume;
-
- if (prim_geom == IntPtr.Zero)
- {
- // Ubit let's have a initial basic OOB
- primOOBsize.X = _size.X;
- primOOBsize.Y = _size.Y;
- primOOBsize.Z = _size.Z;
- primOOBoffset = Vector3.Zero;
- }
- else
- {
- d.AABB AABB;
- d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
-
- primOOBsize.X = (AABB.MaxX - AABB.MinX);
- primOOBsize.Y = (AABB.MaxY - AABB.MinY);
- primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
- if (!hasOOBoffsetFromMesh)
- {
- primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
- primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
- primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
- }
- }
-
- // also its own inertia and mass
- // keep using basic shape mass for now
- volume = CalculatePrimVolume();
-
- primVolume = volume;
- primMass = m_density * volume;
+ primMass = m_density * primVolume;
if (primMass <= 0)
primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
@@ -2484,18 +2142,32 @@ namespace OpenSim.Region.Physics.OdePlugin
_mass = primMass; // just in case
- d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
+ d.MassSetBoxTotal(out primdMass, primMass, m_OBB.X, m_OBB.Y, m_OBB.Z);
d.MassTranslate(ref primdMass,
- primOOBoffset.X,
- primOOBoffset.Y,
- primOOBoffset.Z);
+ m_OBBOffset.X,
+ m_OBBOffset.Y,
+ m_OBBOffset.Z);
- primOOBsize *= 0.5f; // let obb size be a corner coords
- primOOBradiusSQ = primOOBsize.LengthSquared();
+ primOOBradiusSQ = m_OBB.LengthSquared();
+
+ if (_triMeshData != IntPtr.Zero)
+ {
+ float pc = m_physCost;
+ float psf = primOOBradiusSQ;
+ psf *= 1.33f * .2f;
+ pc *= psf;
+ if (pc < 0.1f)
+ pc = 0.1f;
+
+ m_physCost = pc;
+ }
+ else
+ m_physCost = 0.1f;
+
+ m_streamCost = 1.0f;
}
-
#endregion
@@ -2575,6 +2247,14 @@ namespace OpenSim.Region.Physics.OdePlugin
_orientation.Y = qtmp.Y;
_orientation.Z = qtmp.Z;
_orientation.W = qtmp.W;
+/*
+// Debug
+ float qlen = _orientation.Length();
+ if (qlen > 1.01f || qlen < 0.99)
+ m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
+//
+*/
+ _orientation.Normalize();
d.Vector3 lpos = d.GeomGetPosition(prim_geom);
_position.X = lpos.X;
@@ -2684,27 +2364,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private void changeadd()
{
- CreateGeom();
-
- if (prim_geom != IntPtr.Zero)
- {
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.X = _orientation.X;
- myrot.Y = _orientation.Y;
- myrot.Z = _orientation.Z;
- myrot.W = _orientation.W;
- d.GeomSetQuaternion(prim_geom, ref myrot);
-
- if (!m_isphysical)
- {
- SetInStaticSpace(this);
- UpdateCollisionCatFlags();
- ApplyCollisionCatFlags();
- }
- else
- MakeBody();
- }
}
private void changeAngularLock(Vector3 newLock)
@@ -2774,6 +2433,9 @@ namespace OpenSim.Region.Physics.OdePlugin
_target_velocity = Vector3.Zero;
if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
m_vehicle.Stop();
+
+ _zeroFlag = false;
+ base.RequestPhysicsterseUpdate();
}
if (Body != IntPtr.Zero)
@@ -3148,7 +2810,63 @@ namespace OpenSim.Region.Physics.OdePlugin
resetCollisionAccounting();
}
- private void changeprimsizeshape()
+ private void changeSize(Vector3 newSize)
+ {
+ }
+
+ private void changeShape(PrimitiveBaseShape newShape)
+ {
+ }
+
+ private void changeAddPhysRep(ODEPhysRepData repData)
+ {
+ _size = repData.size; //??
+ _pbs = repData.pbs;
+ m_shapetype = repData.shapetype;
+
+ m_mesh = repData.mesh;
+
+ m_assetID = repData.assetID;
+ m_meshState = repData.meshState;
+
+ m_hasOBB = repData.hasOBB;
+ m_OBBOffset = repData.OBBOffset;
+ m_OBB = repData.OBB;
+
+ primVolume = repData.volume;
+
+ CreateGeom();
+
+ if (prim_geom != IntPtr.Zero)
+ {
+ d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+ d.Quaternion myrot = new d.Quaternion();
+ myrot.X = _orientation.X;
+ myrot.Y = _orientation.Y;
+ myrot.Z = _orientation.Z;
+ myrot.W = _orientation.W;
+ d.GeomSetQuaternion(prim_geom, ref myrot);
+ }
+
+ if (!m_isphysical)
+ {
+ SetInStaticSpace(this);
+ UpdateCollisionCatFlags();
+ ApplyCollisionCatFlags();
+ }
+ else
+ MakeBody();
+
+ if ((m_meshState & MeshState.NeedMask) != 0)
+ {
+ repData.size = _size;
+ repData.pbs = _pbs;
+ repData.shapetype = m_shapetype;
+ _parent_scene.m_meshWorker.RequestMesh(repData);
+ }
+ }
+
+ private void changePhysRepData(ODEPhysRepData repData)
{
CheckDelaySelect();
@@ -3170,16 +2888,22 @@ namespace OpenSim.Region.Physics.OdePlugin
RemoveGeom();
- // 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;
- if (_size.Z <= 0)
- _size.Z = 0.01f;
- // Construction of new prim
+ _size = repData.size;
+ _pbs = repData.pbs;
+ m_shapetype = repData.shapetype;
- CreateGeom();
+ m_mesh = repData.mesh;
+
+ m_assetID = repData.assetID;
+ m_meshState = repData.meshState;
+
+ m_hasOBB = repData.hasOBB;
+ m_OBBOffset = repData.OBBOffset;
+ m_OBB = repData.OBB;
+
+ primVolume = repData.volume;
+
+ CreateGeom();
if (prim_geom != IntPtr.Zero)
{
@@ -3202,29 +2926,24 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
else
- MakeBody();
+ MakeBody();
}
-
else
{
+ SetInStaticSpace(this);
UpdateCollisionCatFlags();
ApplyCollisionCatFlags();
}
resetCollisionAccounting();
- }
- private void changeSize(Vector3 newSize)
- {
- _size = newSize;
- changeprimsizeshape();
- }
-
- private void changeShape(PrimitiveBaseShape newShape)
- {
- if(newShape != null)
- _pbs = newShape;
- changeprimsizeshape();
+ if ((m_meshState & MeshState.NeedMask) != 0)
+ {
+ repData.size = _size;
+ repData.pbs = _pbs;
+ repData.shapetype = m_shapetype;
+ _parent_scene.m_meshWorker.RequestMesh(repData);
+ }
}
private void changeFloatOnWater(bool newval)
@@ -3891,7 +3610,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public bool DoAChange(changes what, object arg)
{
- if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
+ if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
{
return false;
}
@@ -3902,6 +3621,11 @@ namespace OpenSim.Region.Physics.OdePlugin
case changes.Add:
changeadd();
break;
+
+ case changes.AddPhysRep:
+ changeAddPhysRep((ODEPhysRepData)arg);
+ break;
+
case changes.Remove:
//If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
//When we return true, it destroys all of the prims in the linkset anyway
@@ -3984,6 +3708,10 @@ namespace OpenSim.Region.Physics.OdePlugin
changeShape((PrimitiveBaseShape)arg);
break;
+ case changes.PhysRepData:
+ changePhysRepData((ODEPhysRepData) arg);
+ break;
+
case changes.CollidesWater:
changeFloatOnWater((bool)arg);
break;
@@ -4072,6 +3800,8 @@ namespace OpenSim.Region.Physics.OdePlugin
donullchange();
break;
+
+
default:
donullchange();
break;
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
index 21fe9c08f7..799a324f4b 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODERayCastRequestManager.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Region.Physics.OdePlugin
req.length = length;
req.Normal = direction;
req.Origin = position;
- req.filter = RayFilterFlags.AllPrims;
+ req.filter = RayFilterFlags.AllPrims | RayFilterFlags.land;
m_PendingRequests.Enqueue(req);
}
@@ -288,7 +288,10 @@ namespace OpenSim.Region.Physics.OdePlugin
catflags |= CollisionCategories.Water;
if (catflags != 0)
+ {
+ d.GeomSetCollideBits(ray, (uint)catflags);
doSpaceRay(req);
+ }
}
else
{
@@ -314,7 +317,8 @@ namespace OpenSim.Region.Physics.OdePlugin
///
private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhanton;
- private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
+// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
+ private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
private void doSpaceRay(ODERayRequest req)
{
@@ -323,6 +327,16 @@ namespace OpenSim.Region.Physics.OdePlugin
d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
+ if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
+ {
+ // current ode land to ray collisions is very bad
+ // so for now limit its range badly
+
+ if (req.length > 30.0f)
+ d.GeomRaySetLength(ray, 30.0f);
+
+ d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
+ }
if (req.callbackMethod is RaycastCallback)
{
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index f126644d8b..b98f177e86 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public int lastframe;
}
+
// colision flags of things others can colide with
// rays, sensors, probes removed since can't be colided with
// The top space where things are placed provided further selection
@@ -109,7 +110,7 @@ namespace OpenSim.Region.Physics.OdePlugin
light = 7 // compatibility with old viewers
}
-
+
public enum changes : int
{
Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
@@ -147,6 +148,8 @@ namespace OpenSim.Region.Physics.OdePlugin
Size,
Shape,
+ PhysRepData,
+ AddPhysRep,
CollidesWater,
VolumeDtc,
@@ -230,11 +233,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private float minimumGroundFlightOffset = 3f;
public float maximumMassObject = 10000.01f;
- public bool meshSculptedPrim = true;
- public bool forceSimplePrimMeshing = false;
-
- public float meshSculptLOD = 32;
- public float MeshSculptphysicalLOD = 32;
public float geomDefaultDensity = 10.000006836f;
@@ -302,6 +300,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public IntPtr TopSpace; // the global space
public IntPtr ActiveSpace; // space for active prims
public IntPtr StaticSpace; // space for the static things around
+ public IntPtr GroundSpace; // space for ground
// some speedup variables
private int spaceGridMaxX;
@@ -313,7 +312,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private IntPtr[] staticPrimspaceOffRegion;
public Object OdeLock;
- private static Object SimulationLock;
+ public static Object SimulationLock;
public IMesher mesher;
@@ -328,7 +327,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private PhysicsScene m_parentScene = null;
private ODERayCastRequestManager m_rayCastManager;
-
+ public ODEMeshWorker m_meshWorker;
/* maybe needed if ode uses tls
private void checkThread()
@@ -361,6 +360,8 @@ namespace OpenSim.Region.Physics.OdePlugin
nearCallback = near;
m_rayCastManager = new ODERayCastRequestManager(this);
+
+
lock (OdeLock)
{
// Create the world and the first space
@@ -372,6 +373,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// now the major subspaces
ActiveSpace = d.HashSpaceCreate(TopSpace);
StaticSpace = d.HashSpaceCreate(TopSpace);
+ GroundSpace = d.HashSpaceCreate(TopSpace);
}
catch
{
@@ -381,10 +383,12 @@ namespace OpenSim.Region.Physics.OdePlugin
d.HashSpaceSetLevels(TopSpace, -2, 8);
d.HashSpaceSetLevels(ActiveSpace, -2, 8);
d.HashSpaceSetLevels(StaticSpace, -2, 8);
+ d.HashSpaceSetLevels(GroundSpace, 0, 8);
// demote to second level
d.SpaceSetSublevel(ActiveSpace, 1);
d.SpaceSetSublevel(StaticSpace, 1);
+ d.SpaceSetSublevel(GroundSpace, 1);
d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
CollisionCategories.Geom |
@@ -402,6 +406,9 @@ namespace OpenSim.Region.Physics.OdePlugin
));
d.GeomSetCollideBits(StaticSpace, 0);
+ d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
+ d.GeomSetCollideBits(GroundSpace, 0);
+
contactgroup = d.JointGroupCreate(0);
//contactgroup
@@ -440,9 +447,11 @@ namespace OpenSim.Region.Physics.OdePlugin
int contactsPerCollision = 80;
+ IConfig physicsconfig = null;
+
if (m_config != null)
{
- IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
+ physicsconfig = m_config.Configs["ODEPhysicsSettings"];
if (physicsconfig != null)
{
gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
@@ -469,27 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin
geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
-/*
- bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD);
- bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG);
-*/
- forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
- meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
- meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD);
- MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
-/*
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- {
- avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD);
- avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP);
- }
- else
- {
-
- avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD);
- avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP);
- }
-*/
+
physics_logging = physicsconfig.GetBoolean("physics_logging", false);
physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
@@ -499,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
+ m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, physicsconfig);
+
HalfOdeStep = ODE_STEPSIZE * 0.5f;
odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f);
@@ -727,6 +718,32 @@ namespace OpenSim.Region.Physics.OdePlugin
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
return;
+/*
+// debug
+ PhysicsActor dp2;
+ if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
+ {
+ d.AABB aabb;
+ d.GeomGetAABB(g2, out aabb);
+ float x = aabb.MaxX - aabb.MinX;
+ float y = aabb.MaxY - aabb.MinY;
+ float z = aabb.MaxZ - aabb.MinZ;
+ if (x > 60.0f || y > 60.0f || z > 60.0f)
+ {
+ if (!actor_name_map.TryGetValue(g2, out dp2))
+ m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
+ else
+ m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
+ dp2.Name, dp2.Size, x, y, z,
+ dp2.Position.ToString(),
+ dp2.Orientation.ToString(),
+ dp2.Orientation.Length());
+ return;
+ }
+ }
+//
+*/
+
if(d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc)
@@ -1225,6 +1242,7 @@ namespace OpenSim.Region.Physics.OdePlugin
chr.CollidingObj = false;
// do colisions with static space
d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback);
+ // no coll with gnd
}
}
catch (AccessViolationException)
@@ -1253,7 +1271,10 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!prm.m_outbounds)
{
if (d.BodyIsEnabled(prm.Body))
+ {
d.SpaceCollide2(StaticSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
+ d.SpaceCollide2(GroundSpace, prm.collide_geom, IntPtr.Zero, nearCallback);
+ }
}
}
}
@@ -1295,6 +1316,15 @@ namespace OpenSim.Region.Physics.OdePlugin
_collisionEventPrimRemove.Add(obj);
}
+ public override float TimeDilation
+ {
+ get { return m_timeDilation; }
+ }
+
+ public override bool SupportsNINJAJoints
+ {
+ get { return false; }
+ }
#region Add/Remove Entities
@@ -1350,59 +1380,6 @@ namespace OpenSim.Region.Physics.OdePlugin
((OdeCharacter) actor).Destroy();
}
- private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
- PrimitiveBaseShape pbs, bool isphysical, uint localID)
- {
- Vector3 pos = position;
- Vector3 siz = size;
- Quaternion rot = rotation;
-
- OdePrim newPrim;
- lock (OdeLock)
- {
- newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical,false,0,localID);
-
- lock (_prims)
- _prims.Add(newPrim);
- }
- return newPrim;
- }
-
- private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
- PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, uint localID)
- {
- Vector3 pos = position;
- Vector3 siz = size;
- Quaternion rot = rotation;
-
- OdePrim newPrim;
- lock (OdeLock)
- {
- newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, 0, localID);
-
- lock (_prims)
- _prims.Add(newPrim);
- }
- return newPrim;
- }
-
- private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
- PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
- {
- Vector3 pos = position;
- Vector3 siz = size;
- Quaternion rot = rotation;
-
- OdePrim newPrim;
- lock (OdeLock)
- {
- newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, isPhantom, shapeType, localID);
-
- lock (_prims)
- _prims.Add(newPrim);
- }
- return newPrim;
- }
public void addActivePrim(OdePrim activatePrim)
{
@@ -1423,44 +1400,39 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
+ private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
+ PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
+ {
+ OdePrim newPrim;
+ lock (OdeLock)
+ {
+ newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
+ lock (_prims)
+ _prims.Add(newPrim);
+ }
+ return newPrim;
+ }
+
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
{
- return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, localid);
+ return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
}
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
{
-#if SPAM
- m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
-#endif
-
- return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
+ return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
}
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
{
-#if SPAM
- m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
-#endif
return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
}
- public override float TimeDilation
- {
- get { return m_timeDilation; }
- }
-
- public override bool SupportsNINJAJoints
- {
- get { return false; }
- }
-
-
public void remActivePrim(OdePrim deactivatePrim)
{
lock (_activeprims)
@@ -1513,6 +1485,28 @@ namespace OpenSim.Region.Physics.OdePlugin
}
}
+
+ public bool havePrim(OdePrim prm)
+ {
+ lock (_prims)
+ return _prims.Contains(prm);
+ }
+
+ public bool haveActor(PhysicsActor actor)
+ {
+ if (actor is OdePrim)
+ {
+ lock (_prims)
+ return _prims.Contains((OdePrim)actor);
+ }
+ else if (actor is OdeCharacter)
+ {
+ lock (_characters)
+ return _characters.Contains((OdeCharacter)actor);
+ }
+ return false;
+ }
+
#endregion
#region Space Separation Calculation
@@ -1615,135 +1609,6 @@ namespace OpenSim.Region.Physics.OdePlugin
#endregion
- ///
- /// Routine to figure out if we need to mesh this prim with our mesher
- ///
- ///
- ///
- public bool needsMeshing(PrimitiveBaseShape pbs)
- {
- // check sculpts or meshs
- if (pbs.SculptEntry)
- {
- if (meshSculptedPrim)
- return true;
-
- if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
- return true;
-
- return false;
- }
-
- if (forceSimplePrimMeshing)
- return true;
-
- // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
-
- if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
- || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
- && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
- {
-
- if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
- && pbs.ProfileHollow == 0
- && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
- && pbs.PathBegin == 0 && pbs.PathEnd == 0
- && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
- && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
- && pbs.PathShearX == 0 && pbs.PathShearY == 0)
- {
-#if SPAM
- m_log.Warn("NonMesh");
-#endif
- return false;
- }
- }
-
- // following code doesn't give meshs to boxes and spheres ever
- // and it's odd.. so for now just return true if asked to force meshs
- // hopefully mesher will fail if doesn't suport so things still get basic boxes
-
- int iPropertiesNotSupportedDefault = 0;
-
- if (pbs.ProfileHollow != 0)
- iPropertiesNotSupportedDefault++;
-
- if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
- iPropertiesNotSupportedDefault++;
-
- if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
- iPropertiesNotSupportedDefault++;
-
- if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
- iPropertiesNotSupportedDefault++;
-
- if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
- iPropertiesNotSupportedDefault++;
-
- if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
- iPropertiesNotSupportedDefault++;
-
- if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
- iPropertiesNotSupportedDefault++;
-
- if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
- iPropertiesNotSupportedDefault++;
-
- if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
- iPropertiesNotSupportedDefault++;
-
- // test for torus
- if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
- {
- if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Straight)
- {
- iPropertiesNotSupportedDefault++;
- }
-
- // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
- else if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
- else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
- {
- if (pbs.PathCurve == (byte)Extrusion.Straight)
- {
- iPropertiesNotSupportedDefault++;
- }
- else if (pbs.PathCurve == (byte)Extrusion.Curve1)
- {
- iPropertiesNotSupportedDefault++;
- }
- }
-
- if (iPropertiesNotSupportedDefault == 0)
- {
-#if SPAM
- m_log.Warn("NonMesh");
-#endif
- return false;
- }
-#if SPAM
- m_log.Debug("Mesh");
-#endif
- return true;
- }
///
/// Called to queue a change to a actor
@@ -1766,8 +1631,52 @@ namespace OpenSim.Region.Physics.OdePlugin
///
///
public override void AddPhysicsActorTaint(PhysicsActor prim)
+ {
+ }
+
+ // does all pending changes generated during region load process
+ public override void PrepareSimulation()
+ {
+ lock (OdeLock)
{
+ if (world == IntPtr.Zero)
+ {
+ ChangesQueue.Clear();
+ return;
+ }
+
+ ODEchangeitem item;
+
+ int donechanges = 0;
+ if (ChangesQueue.Count > 0)
+ {
+ m_log.InfoFormat("[ODE] start processing pending actor operations");
+ int tstart = Util.EnvironmentTickCount();
+
+ while (ChangesQueue.Dequeue(out item))
+ {
+ if (item.actor != null)
+ {
+ try
+ {
+ if (item.actor is OdeCharacter)
+ ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
+ else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
+ RemovePrimThreadLocked((OdePrim)item.actor);
+ }
+ catch
+ {
+ m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
+ item.actor.Name, item.what.ToString());
+ }
+ }
+ donechanges++;
+ }
+ int time = Util.EnvironmentTickCountSubtract(tstart);
+ m_log.InfoFormat("[ODE] finished {0} operations in {1}ms", donechanges, time);
+ }
}
+ }
///
/// This is our main simulate loop
@@ -1813,21 +1722,17 @@ namespace OpenSim.Region.Physics.OdePlugin
lock(OdeLock)
{
if (world == IntPtr.Zero)
- return 0;
-
- // adjust number of iterations per step
-
-// try
-// {
- d.WorldSetQuickStepNumIterations(world, curphysiteractions);
-/* }
- catch (StackOverflowException)
{
- m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
-// ode.drelease(world);
- base.TriggerPhysicsBasedRestart();
+ ChangesQueue.Clear();
+ return 0;
}
-*/
+
+ ODEchangeitem item;
+
+
+
+ d.WorldSetQuickStepNumIterations(world, curphysiteractions);
+
while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
{
try
@@ -1835,14 +1740,12 @@ namespace OpenSim.Region.Physics.OdePlugin
// clear pointer/counter to contacts to pass into joints
m_global_contactcount = 0;
- ODEchangeitem item;
-
- if(ChangesQueue.Count >0)
+ if (ChangesQueue.Count > 0)
{
int ttmpstart = Util.EnvironmentTickCount();
int ttmp;
- while(ChangesQueue.Dequeue(out item))
+ while (ChangesQueue.Dequeue(out item))
{
if (item.actor != null)
{
@@ -1851,12 +1754,13 @@ namespace OpenSim.Region.Physics.OdePlugin
if (item.actor is OdeCharacter)
((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
- RemovePrimThreadLocked((OdePrim)item.actor);
+ RemovePrimThreadLocked((OdePrim)item.actor);
}
catch
{
- m_log.Warn("[PHYSICS]: doChange failed for a actor");
- };
+ m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
+ item.actor.Name, item.what.ToString());
+ }
}
ttmp = Util.EnvironmentTickCountSubtract(ttmpstart);
if (ttmp > 20)
@@ -1994,10 +1898,47 @@ namespace OpenSim.Region.Physics.OdePlugin
mesher.ExpireReleaseMeshs();
m_lastMeshExpire = now;
}
+
+// information block running in debug only
/*
- int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
- int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
+ int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
+ int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
+ int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
+
+ int nactivegeoms = 0;
+ int nactivespaces = 0;
+
+ int nstaticgeoms = 0;
+ int nstaticspaces = 0;
+ IntPtr sp;
+
+ for (int i = 0; i < ntopactivegeoms; i++)
+ {
+ sp = d.SpaceGetGeom(ActiveSpace, i);
+ if (d.GeomIsSpace(sp))
+ {
+ nactivespaces++;
+ nactivegeoms += d.SpaceGetNumGeoms(sp);
+ }
+ else
+ nactivegeoms++;
+ }
+
+ for (int i = 0; i < ntopstaticgeoms; i++)
+ {
+ sp = d.SpaceGetGeom(StaticSpace, i);
+ if (d.GeomIsSpace(sp))
+ {
+ nstaticspaces++;
+ nstaticgeoms += d.SpaceGetNumGeoms(sp);
+ }
+ else
+ nstaticgeoms++;
+ }
+
int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
+
+ int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
int nbodies = d.NTotalBodies;
int ngeoms = d.NTotalGeoms;
*/
@@ -2294,7 +2235,9 @@ namespace OpenSim.Region.Physics.OdePlugin
offset, thickness, wrap);
d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
- GroundGeom = d.CreateHeightfield(StaticSpace, HeightmapData, 1);
+
+ GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
+
if (GroundGeom != IntPtr.Zero)
{
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
@@ -2415,12 +2358,13 @@ namespace OpenSim.Region.Physics.OdePlugin
thickness, wrap);
// d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
- GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1);
+ GroundGeom = d.CreateUbitTerrain(GroundSpace, HeightmapData, 1);
if (GroundGeom != IntPtr.Zero)
{
d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
d.GeomSetCollideBits(GroundGeom, 0);
+
PhysicsActor pa = new NullPhysicsActor();
pa.Name = "Terrain";
pa.PhysicsActorType = (int)ActorTypes.Ground;
@@ -2599,6 +2543,9 @@ namespace OpenSim.Region.Physics.OdePlugin
*/
public override void Dispose()
{
+ if (m_meshWorker != null)
+ m_meshWorker.Stop();
+
lock (OdeLock)
{
m_rayCastManager.Dispose();
@@ -2633,6 +2580,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomDestroy(GroundGeom);
}
+
RegionTerrain.Clear();
if (TerrainHeightFieldHeightsHandlers.Count > 0)