From 78ce7a0a04dc5ce3212acfb0e88a3a5a1b876100 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Oct 2012 01:20:52 +0100 Subject: [PATCH] [DANGER UNTESTED] ODE mesh assets. Other plugins will not do meshs/sculpts now --- .../Framework/Scenes/SceneObjectGroup.cs | 4 +- .../Framework/Scenes/SceneObjectPart.cs | 38 +- .../Region/Physics/UbitMeshing/Meshmerizer.cs | 64 +- .../Physics/UbitOdePlugin/ODECharacter.cs | 1 - .../Physics/UbitOdePlugin/ODEMeshWorker.cs | 582 +++++++----- .../Region/Physics/UbitOdePlugin/ODEPrim.cs | 840 ++++-------------- .../Region/Physics/UbitOdePlugin/OdeScene.cs | 191 ++-- 7 files changed, 650 insertions(+), 1070 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 4798481b42..4b22ebe65c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -4299,8 +4299,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 1bddf22a0b..633cd3b25f 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); } } @@ -1654,8 +1654,8 @@ namespace OpenSim.Region.Framework.Scenes else { PhysActor.PhysicsShapeType = m_physicsShapeType; - if (Shape.SculptEntry) - CheckSculptAndLoad(); +// if (Shape.SculptEntry) +// CheckSculptAndLoad(); } if (ParentGroup != null) @@ -2115,12 +2115,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 +2143,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 +2153,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 +2343,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); } } @@ -3125,6 +3127,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) @@ -3152,7 +3155,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Send a full update to the client for the given part /// @@ -4377,7 +4380,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) @@ -4385,7 +4388,7 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived); } } - +*/ if (ParentGroup != null) { ParentGroup.HasGroupChanged = true; @@ -4793,9 +4796,9 @@ namespace OpenSim.Region.Framework.Scenes } } - if (Shape.SculptEntry) - CheckSculptAndLoad(); - else +// if (Shape.SculptEntry) +// CheckSculptAndLoad(); +// else ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); if (!building) @@ -4898,6 +4901,7 @@ 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); @@ -4925,7 +4929,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Update the texture entry for this part. /// diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index 44c8972367..2933d864dd 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs @@ -74,10 +74,6 @@ namespace OpenSim.Region.Physics.Meshing 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 @@ -92,29 +88,9 @@ 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; - if(mesh_config != null) useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); - try - { - if (!Directory.Exists(decodedSculptMapPath)) - Directory.CreateDirectory(decodedSculptMapPath); - } - catch (Exception e) - { - m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); - } } /// @@ -444,7 +420,7 @@ 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) @@ -717,29 +693,7 @@ namespace OpenSim.Region.Physics.Meshing 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 +702,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 +727,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 @@ -1048,7 +991,6 @@ 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); 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 index 702c336713..3fcbb1bb81 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs @@ -18,26 +18,63 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.OdePlugin { + 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 float physCost; + public float streamCost; + public byte shapetype; + public bool hasOBB; + public bool hasMeshVolume; + public AssetState assetState; + 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 IntPtr m_workODEspace = IntPtr.Zero; - public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IntPtr pWorkSpace, IConfig pConfig) + 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; - m_workODEspace = pWorkSpace; if (pConfig != null) { @@ -46,8 +83,177 @@ namespace OpenSim.Region.Physics.OdePlugin 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() + { + 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: + if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor)) + m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep); + break; + case meshWorkerCmnds.addnew: + if (CreateActorPhysRep(nextRep)) + m_scene.AddChange(nextRep.actor, changes.AddPhysRep, nextRep); + break; + case meshWorkerCmnds.getmesh: + DoRepDataGetMesh(nextRep); + break; + } + } + } + } + + public void Stop() + { + m_running = false; + m_thread.Abort(); + } + + 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; + + // if (CheckMeshDone(repData)) + { + CheckMeshDone(repData); + CalcVolumeData(repData); + m_scene.AddChange(actor, changes.PhysRepData, repData); + return; + } + +// repData.comand = meshWorkerCmnds.changefull; +// createqueue.Enqueue(repData); + } + + public void 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; + + // bool done = CheckMeshDone(repData); + + CheckMeshDone(repData); + CalcVolumeData(repData); + m_scene.AddChange(actor, changes.AddPhysRep, repData); +// if (done) + return; + +// repData.comand = meshWorkerCmnds.addnew; +// createqueue.Enqueue(repData); + } + + public void RequestMeshAsset(ODEPhysRepData repData) + { + if (repData.assetState != AssetState.needAsset) + return; + + if (repData.assetID == null || repData.assetID == UUID.Zero) + return; + + repData.mesh = null; + + repData.assetState = AssetState.loadingAsset; + + repData.comand = meshWorkerCmnds.getmesh; + createqueue.Enqueue(repData); + } + + public bool CreateActorPhysRep(ODEPhysRepData repData) + { + getMesh(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.assetState = AssetState.AssetFailed; + repData.hasOBB = false; + repData.mesh = null; + m_scene.mesher.ReleaseMesh(mesh); + } + else + { + repData.OBBOffset = mesh.GetCentroid(); + repData.OBB = mesh.GetOBB(); + repData.hasOBB = true; + repData.physCost = 0.0013f * (float)indexCount; + // todo + repData.streamCost = 1.0f; + 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); + } + } + } + + public void DoRepDataGetMesh(ODEPhysRepData repData) + { + if (!repData.pbs.SculptEntry) + return; + + if (repData.assetState != AssetState.loadingAsset) + return; + + if (repData.assetID == null || repData.assetID == UUID.Zero) + return; + + if (repData.assetID != repData.pbs.SculptTexture) + 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 /// @@ -169,194 +375,151 @@ namespace OpenSim.Region.Physics.OdePlugin return true; } - public IMesh getMesh(PhysicsActor actor, PrimitiveBaseShape ppbs, Vector3 psize, byte pshapetype) + public bool CheckMeshDone(ODEPhysRepData repData) { - if (!(actor is OdePrim)) - return null; + PhysicsActor actor = repData.actor; + PrimitiveBaseShape pbs = repData.pbs; + + repData.mesh = null; + repData.hasOBB = false; + + if (!needsMeshing(pbs)) + { + repData.assetState = AssetState.noNeedAsset; + return true; + } + + if (pbs.SculptEntry) + { + if (repData.assetState == AssetState.AssetFailed) + { + if (pbs.SculptTexture == repData.assetID) + return true; + } + } + else + { + repData.assetState = AssetState.noNeedAsset; + repData.assetID = null; + } IMesh mesh = null; - PrimitiveBaseShape pbs = ppbs; - Vector3 size = psize; - byte shapetype = pshapetype; - if (needsMeshing(pbs)) + Vector3 size = repData.size; + byte shapetype = repData.shapetype; + + bool convex; + + int clod = (int)LevelOfDetail.High; + if (shapetype == 0) + convex = false; + else { - 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) { - 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) - return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex); - - if (pbs.SculptTexture == UUID.Zero) - return null; - - if (pbs.SculptType != (byte)SculptType.Mesh) - { // check for sculpt decoded image on cache) - if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + pbs.SculptTexture.ToString()))) - return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex); + if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero) + { + repData.assetID = pbs.SculptTexture; + repData.assetState = AssetState.needAsset; } - - if (pbs.SculptData != null && pbs.SculptData.Length > 0) - return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex); - - ODEAssetRequest asr; - RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod; - if (assetProvider != null) - asr = new ODEAssetRequest(this, assetProvider, actor, pbs, m_log); - - return null; + else + repData.assetState = AssetState.AssetFailed; } - } - return mesh; - } - - private bool GetTriMeshGeo(ODEPhysRepData repData) - { - IntPtr vertices, indices; - IntPtr triMeshData = IntPtr.Zero; - IntPtr geo = IntPtr.Zero; - int vertexCount, indexCount; - int vertexStride, triStride; - - PhysicsActor actor = repData.actor; - - IMesh mesh = repData.mesh; - - if (mesh == null) - { - mesh = getMesh(repData.actor, repData.pbs, repData.size, repData.shapetype); - } - - if (mesh == null) - 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]: Invalid mesh data on prim {0} mesh UUID {1}", - actor.Name, repData.pbs.SculptTexture.ToString()); - mesh.releaseSourceMeshData(); return false; } - repData.OBBOffset = mesh.GetCentroid(); - repData.OBB = mesh.GetOBB(); - repData.hasOBB = true; - repData.physCost = 0.0013f * (float)indexCount; - - mesh.releaseSourceMeshData(); - - try + repData.mesh = mesh; + if (pbs.SculptEntry) { - triMeshData = d.GeomTriMeshDataCreate(); - - d.GeomTriMeshDataBuildSimple(triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); - d.GeomTriMeshDataPreprocess(triMeshData); - - m_scene.waitForSpaceUnlock(m_workODEspace); - geo = d.CreateTriMesh(m_workODEspace, triMeshData, null, null, null); + repData.assetState = AssetState.AssetOK; + repData.assetID = pbs.SculptTexture; + pbs.SculptData = Utils.EmptyBytes; } - - catch (Exception e) - { - m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", actor.Name, e); - if (triMeshData != IntPtr.Zero) - { - d.GeomTriMeshDataDestroy(triMeshData); - repData.triMeshData = IntPtr.Zero; - } - repData.geo = IntPtr.Zero; - return false; - } - - repData.geo = geo; - repData.triMeshData = triMeshData; - repData.curSpace = m_workODEspace; return true; } - public ODEPhysRepData CreateActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, IMesh pMesh, Vector3 size, byte shapetype) + + public bool getMesh(ODEPhysRepData repData) { - ODEPhysRepData repData = new ODEPhysRepData(); + PhysicsActor actor = repData.actor; - repData.actor = actor; - repData.pbs = pbs; - repData.mesh = pMesh; - repData.size = size; - repData.shapetype = shapetype; + PrimitiveBaseShape pbs = repData.pbs; - IntPtr geo = IntPtr.Zero; - bool hasMesh = false; - if (needsMeshing(pbs)) + repData.mesh = null; + repData.hasOBB = false; + + if (!needsMeshing(pbs)) + return false; + + if (pbs.SculptEntry) { - if (GetTriMeshGeo(repData)) - hasMesh = true; - else - repData.NoColide = true; + if (repData.assetState == AssetState.AssetFailed) + { + if (pbs.SculptTexture == repData.assetID) + return true; + } } - if (!hasMesh) + repData.assetState = AssetState.noNeedAsset; + + IMesh mesh = null; + Vector3 size = repData.size; + byte shapetype = repData.shapetype; + + bool convex; + int clod = (int)LevelOfDetail.High; + if (shapetype == 0) + convex = false; + else { - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 - && size.X == size.Y && size.Y == size.Z) - { // it's a sphere - m_scene.waitForSpaceUnlock(m_workODEspace); - try + 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 == UUID.Zero) + return false; + + repData.assetID = pbs.SculptTexture; + repData.assetState = AssetState.AssetOK; + + if (pbs.SculptData == null || pbs.SculptData.Length == 0) { - geo = d.CreateSphere(m_workODEspace, size.X * 0.5f); - } - catch (Exception e) - { - m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e); - return null; - } - } - else - {// do it as a box - m_scene.waitForSpaceUnlock(m_workODEspace); - try - { - //Console.WriteLine(" CreateGeom 4"); - geo = d.CreateBox(m_workODEspace, size.X, size.Y, size.Z); - } - catch (Exception e) - { - m_log.Warn("[PHYSICS]: Create box failed: {0}", e); - return null; + repData.assetState = AssetState.needAsset; + return false; } } - repData.physCost = 0.1f; - repData.streamCost = 1.0f; - repData.geo = geo; + mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex); + } - - repData.curSpace = m_workODEspace; - CalcVolumeData(repData); + repData.mesh = mesh; + repData.pbs.SculptData = Utils.EmptyBytes; - return repData; - } + if (mesh == null) + { + if (pbs.SculptEntry) + repData.assetState = AssetState.AssetFailed; - public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, - Vector3 size, byte shapetype, MeshWorkerChange what) - { - ODEPhysRepData repData = CreateActorPhysRep(actor, pbs, null, size, shapetype); - repData.changed |= what; - if (repData != null && actor != null) - ((OdePrim)actor).AddChange(changes.PhysRepData, repData); + return false; + } + + if (pbs.SculptEntry) + repData.assetState = AssetState.AssetOK; + + return true; } private void CalculateBasicPrimVolume(ODEPhysRepData repData) @@ -662,46 +825,12 @@ namespace OpenSim.Region.Physics.OdePlugin private void CalcVolumeData(ODEPhysRepData repData) { - float volume; - Vector3 OBB = repData.size; - Vector3 OBBoffset; - IntPtr geo = repData.geo; - - if (geo == IntPtr.Zero || repData.triMeshData == IntPtr.Zero) - { - OBB.X *= 0.5f; - OBB.Y *= 0.5f; - OBB.Z *= 0.5f; - - repData.OBB = OBB; - repData.OBBOffset = Vector3.Zero; - } - else if (!repData.hasOBB) // should this happen? - { - d.AABB AABB; - d.GeomGetAABB(geo, out AABB); // get the AABB from engine geom - - OBB.X = (AABB.MaxX - AABB.MinX) * 0.5f; - OBB.Y = (AABB.MaxY - AABB.MinY) * 0.5f; - OBB.Z = (AABB.MaxZ - AABB.MinZ) * 0.5f; - repData.OBB = OBB; - OBBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f; - OBBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f; - OBBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f; - repData.OBBOffset = Vector3.Zero; - } - - // also its own inertia and mass - // keep using basic shape mass for now - CalculateBasicPrimVolume(repData); - if (repData.hasOBB) { - OBB = repData.OBB; + Vector3 OBB = repData.OBB; float pc = repData.physCost; float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z; psf *= 1.33f * .2f; - pc *= psf; if (pc < 0.1f) pc = 0.1f; @@ -709,54 +838,79 @@ namespace OpenSim.Region.Physics.OdePlugin repData.physCost = pc; } else + { + Vector3 OBB = repData.size; + OBB.X *= 0.5f; + OBB.Y *= 0.5f; + OBB.Z *= 0.5f; + + repData.OBB = OBB; + repData.OBBOffset = Vector3.Zero; + repData.physCost = 0.1f; + repData.streamCost = 1.0f; + } + + CalculateBasicPrimVolume(repData); } } public class ODEAssetRequest { - PhysicsActor m_actor; ODEMeshWorker m_worker; - PrimitiveBaseShape m_pbs; private ILog m_log; + ODEPhysRepData repData; public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider, - PhysicsActor pActor, PrimitiveBaseShape ppbs, ILog plog) + ODEPhysRepData pRepData, ILog plog) { - m_actor = pActor; m_worker = pWorker; - m_pbs = ppbs; m_log = plog; + repData = pRepData; + repData.assetState = AssetState.AssetFailed; if (provider == null) return; - UUID assetID = m_pbs.SculptTexture; + if (repData.assetID == null) + return; + + UUID assetID = (UUID) repData.assetID; if (assetID == UUID.Zero) return; + repData.assetState = AssetState.loadingAsset; provider(assetID, ODEassetReceived); } void ODEassetReceived(AssetBase asset) { - if (m_actor != null && m_pbs != null) + repData.assetState = AssetState.AssetFailed; + if (asset != null) { - if (asset != null) + if (asset.Data != null && asset.Data.Length > 0) { - if (asset.Data != null && asset.Data.Length > 0) - { - m_pbs.SculptData = asset.Data; - m_actor.Shape = m_pbs; - } - else - m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.", - m_actor.Name, asset.ID.ToString()); + if (!repData.pbs.SculptEntry) + return; + if (repData.pbs.SculptTexture != repData.assetID) + return; + + // asset get may return a pointer to the same asset data + // for similar prims and we destroy with it + // so waste a lot of time stressing gc and hoping it clears things + // TODO avoid this + repData.pbs.SculptData = new byte[asset.Data.Length]; + asset.Data.CopyTo(repData.pbs.SculptData,0); + repData.assetState = AssetState.AssetOK; + m_worker.AssetLoaded(repData); } else - m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.", - m_actor.Name); + 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 7650571e25..cbe129a71c 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,14 +91,14 @@ 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; @@ -107,14 +107,14 @@ namespace OpenSim.Region.Physics.OdePlugin 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 @@ -144,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 AssetState m_assetState; + 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; @@ -163,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; @@ -391,9 +400,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (value.IsFinite()) { - AddChange(changes.Size, value); - -// _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype, MeshWorkerChange.size); + _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype); } else { @@ -463,7 +470,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; @@ -503,7 +510,7 @@ namespace OpenSim.Region.Physics.OdePlugin { get { - return primOOBsize; + return m_OBB; } } @@ -511,7 +518,7 @@ namespace OpenSim.Region.Physics.OdePlugin { get { - return primOOBoffset; + return m_OBBOffset; } } @@ -527,8 +534,8 @@ namespace OpenSim.Region.Physics.OdePlugin { set { - AddChange(changes.Shape, value); -// _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype, MeshWorkerChange.shape); +// AddChange(changes.Shape, value); + _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype); } } @@ -541,8 +548,7 @@ namespace OpenSim.Region.Physics.OdePlugin set { m_shapetype = value; - AddChange(changes.Shape, null); -// _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value, MeshWorkerChange.shapetype); + _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value); } } @@ -1012,7 +1018,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 +1069,6 @@ namespace OpenSim.Region.Physics.OdePlugin m_colliderfilter = 0; m_NoColide = false; - hasOOBoffsetFromMesh = false; _triMeshData = IntPtr.Zero; m_shapetype = _shapeType; @@ -1079,29 +1083,9 @@ 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_mesh = _parent_scene.m_meshWorker.getMesh(this, pbs, _size, m_shapetype); - m_building = true; // control must set this to false when done - AddChange(changes.Add, null); + _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype); } private void resetCollisionAccounting() @@ -1325,83 +1309,34 @@ namespace OpenSim.Region.Physics.OdePlugin } } - private bool setMesh(OdeScene parent_scene) + private bool GetMeshGeom() { IntPtr vertices, indices; int vertexCount, indexCount; int vertexStride, triStride; - if (Body != IntPtr.Zero) + 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) { - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this, false); - } - } - else - { - DestroyBody(); - } + m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0} mesh UUID {1}", + Name, _pbs.SculptTexture.ToString()); + 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_assetState = AssetState.AssetFailed; + m_mesh = null; + return false; } - - 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); -*/ - mesh = _parent_scene.m_meshWorker.getMesh(this, _pbs, _size, m_shapetype); - } - 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(); @@ -1409,8 +1344,7 @@ namespace OpenSim.Region.Physics.OdePlugin 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); + prim_geom = d.CreateTriMesh(IntPtr.Zero, _triMeshData, null, null, null); } catch (Exception e) @@ -1418,85 +1352,56 @@ namespace OpenSim.Region.Physics.OdePlugin m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e); if (_triMeshData != IntPtr.Zero) { - d.GeomTriMeshDataDestroy(_triMeshData); - _triMeshData = IntPtr.Zero; + try + { + d.GeomTriMeshDataDestroy(_triMeshData); + } + catch + { + } } + _triMeshData = IntPtr.Zero; + prim_geom = 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_assetState = AssetState.AssetFailed; + m_mesh = null; return false; } - - SetGeom(geo); return true; } - private void SetGeom(IntPtr geom) - { - prim_geom = geom; - //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); - if (prim_geom != IntPtr.Zero) - { - - if (m_NoColide) - { - d.GeomSetCategoryBits(prim_geom, 0); - if (m_isphysical) - { - d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land); - } - else - { - d.GeomSetCollideBits(prim_geom, 0); - d.GeomDisable(prim_geom); - } - } - else - { - d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags); - } - - CalcPrimBodyData(); - - _parent_scene.actor_name_map[prim_geom] = this; - - } - 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() { - if (_triMeshData != IntPtr.Zero) - { - d.GeomTriMeshDataDestroy(_triMeshData); - _triMeshData = IntPtr.Zero; - } + IntPtr geo = IntPtr.Zero; + bool hasMesh = false; - bool haveMesh = false; - hasOOBoffsetFromMesh = false; m_NoColide = false; - if (_parent_scene.m_meshWorker.needsMeshing(_pbs)) + if (m_assetState == AssetState.AssetFailed) + 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) { 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(IntPtr.Zero, _size.X * 0.5f); } catch (Exception e) { @@ -1506,11 +1411,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(IntPtr.Zero, _size.X, _size.Y, _size.Z); } catch (Exception e) { @@ -1518,18 +1421,18 @@ namespace OpenSim.Region.Physics.OdePlugin return; } } + m_physCost = 0.1f; + m_streamCost = 1.0f; + prim_geom = geo; } } - /// - /// Set a new geometry for this prim. - /// - /// private void RemoveGeom() { if (prim_geom != IntPtr.Zero) { _parent_scene.actor_name_map.Remove(prim_geom); + try { d.GeomDestroy(prim_geom); @@ -1546,6 +1449,7 @@ namespace OpenSim.Region.Physics.OdePlugin prim_geom = IntPtr.Zero; collide_geom = IntPtr.Zero; + m_targetSpace = IntPtr.Zero; } else { @@ -1562,7 +1466,7 @@ namespace OpenSim.Region.Physics.OdePlugin } Body = IntPtr.Zero; - hasOOBoffsetFromMesh = false; + m_hasOBB = false; } //sets non physical prim m_targetSpace to right space in spaces grid for static prims @@ -2136,358 +2040,6 @@ namespace OpenSim.Region.Physics.OdePlugin #region Mass Calculation - private float CalculatePrimVolume() - { - 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; - - if (primMass <= 0) - primMass = 0.0001f;//ckrinke: Mass must be greater then zero. - if (primMass > _parent_scene.maximumMassObject) - primMass = _parent_scene.maximumMassObject; - - _mass = primMass; // just in case - - d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z); - - d.MassTranslate(ref primdMass, - primOOBoffset.X, - primOOBoffset.Y, - primOOBoffset.Z); - - primOOBsize *= 0.5f; // let obb size be a corner coords - primOOBradiusSQ = primOOBsize.LengthSquared(); - } - private void UpdatePrimBodyData() { primMass = m_density * primVolume; @@ -2499,14 +2051,14 @@ 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); - primOOBradiusSQ = primOOBsize.LengthSquared(); + primOOBradiusSQ = m_OBBOffset.LengthSquared(); } #endregion @@ -2697,27 +2249,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) @@ -3161,41 +2692,45 @@ namespace OpenSim.Region.Physics.OdePlugin resetCollisionAccounting(); } - private void changeprimsizeshape() + private void changeSize(Vector3 newSize) { - CheckDelaySelect(); + } - OdePrim parent = (OdePrim)_parent; + private void changeShape(PrimitiveBaseShape newShape) + { + } - bool chp = childPrim; + - if (chp) - { - if (parent != null) - { - parent.DestroyBody(); - } - } - else - { - DestroyBody(); - } + private void changeAddPhysRep(ODEPhysRepData repData) + { + _size = repData.size; //?? + _pbs = repData.pbs; + m_shapetype = repData.shapetype; - RemoveGeom(); + m_mesh = repData.mesh; - // 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 + m_assetID = repData.assetID; + m_assetState = repData.assetState; + + m_hasOBB = repData.hasOBB; + m_OBBOffset = repData.OBBOffset; + m_OBB = repData.OBB; + +// m_NoColide = repData.NoColide; + m_physCost = repData.physCost; + m_streamCost = repData.streamCost; + + primVolume = repData.volume; CreateGeom(); if (prim_geom != IntPtr.Zero) { + UpdatePrimBodyData(); + + _parent_scene.actor_name_map[prim_geom] = this; + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); d.Quaternion myrot = new d.Quaternion(); myrot.X = _orientation.X; @@ -3203,44 +2738,26 @@ namespace OpenSim.Region.Physics.OdePlugin myrot.Z = _orientation.Z; myrot.W = _orientation.W; d.GeomSetQuaternion(prim_geom, ref myrot); - } - if (m_isphysical) - { - if (chp) + if (!m_isphysical) { - if (parent != null) - { - parent.MakeBody(); - } + SetInStaticSpace(this); + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); } else - MakeBody(); + MakeBody(); + + if (m_assetState == AssetState.needAsset) + { + repData.size = _size; + repData.pbs = _pbs; + repData.shapetype = m_shapetype; + _parent_scene.m_meshWorker.RequestMeshAsset(repData); + } } - - else - { - UpdateCollisionCatFlags(); - ApplyCollisionCatFlags(); - } - - resetCollisionAccounting(); } - private void changeSize(Vector3 newSize) - { - _size = newSize; - changeprimsizeshape(); - } - - private void changeShape(PrimitiveBaseShape newShape) - { - if(newShape != null) - _pbs = newShape; - changeprimsizeshape(); - } - - private void changePhysRepData(ODEPhysRepData repData) { CheckDelaySelect(); @@ -3261,32 +2778,43 @@ namespace OpenSim.Region.Physics.OdePlugin DestroyBody(); } - RemoveGeom(); + RemoveGeom(); - prim_geom = repData.geo; - _triMeshData = repData.triMeshData; _size = repData.size; _pbs = repData.pbs; - m_mesh = repData.mesh; m_shapetype = repData.shapetype; - hasOOBoffsetFromMesh = repData.hasOBB; - primOOBoffset = repData.OBBOffset; - primOOBsize = repData.OBB; + m_mesh = repData.mesh; - m_NoColide = repData.NoColide; -// m_physCost = repData.physCost; -// m_streamCost = repData.streamCost; + m_assetID = repData.assetID; + m_assetState = repData.assetState; + + m_hasOBB = repData.hasOBB; + m_OBBOffset = repData.OBBOffset; + m_OBB = repData.OBB; + + m_physCost = repData.physCost; + m_streamCost = repData.streamCost; primVolume = repData.volume; - m_targetSpace = repData.curSpace; - UpdatePrimBodyData(); - - _parent_scene.actor_name_map[prim_geom] = this; + CreateGeom(); if (prim_geom != IntPtr.Zero) { + m_targetSpace = IntPtr.Zero; + + UpdatePrimBodyData(); + + try + { + _parent_scene.actor_name_map[prim_geom] = this; + } + catch + { + + } + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); d.Quaternion myrot = new d.Quaternion(); myrot.X = _orientation.X; @@ -3294,32 +2822,39 @@ namespace OpenSim.Region.Physics.OdePlugin myrot.Z = _orientation.Z; myrot.W = _orientation.W; d.GeomSetQuaternion(prim_geom, ref myrot); - } - if (m_isphysical) - { - if (chp) + + if (m_isphysical) { - if (parent != null) + if (chp) { - parent.MakeBody(); + if (parent != null) + { + parent.MakeBody(); + } } + else + MakeBody(); } + else - MakeBody(); - } + { + SetInStaticSpace(this); + UpdateCollisionCatFlags(); + ApplyCollisionCatFlags(); + } - else - { - SetInStaticSpace(this); - UpdateCollisionCatFlags(); - ApplyCollisionCatFlags(); + resetCollisionAccounting(); + if (m_assetState == AssetState.needAsset) + { + repData.size = _size; + repData.pbs = _pbs; + repData.shapetype = m_shapetype; + _parent_scene.m_meshWorker.RequestMeshAsset(repData); + } } - - resetCollisionAccounting(); } - private void changeFloatOnWater(bool newval) { m_collidesWater = newval; @@ -3984,7 +3519,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; } @@ -3995,6 +3530,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 diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index d758c85334..5e4c2a503e 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -60,29 +60,6 @@ namespace OpenSim.Region.Physics.OdePlugin public int lastframe; } - public class ODEPhysRepData - { - public PhysicsActor actor; - public IntPtr geo = IntPtr.Zero; - public IntPtr triMeshData = IntPtr.Zero; - public IMesh mesh; - public IntPtr curSpace = IntPtr.Zero; - public PrimitiveBaseShape pbs; - - public Vector3 size = Vector3.Zero; - public Vector3 OBB = Vector3.Zero; - public Vector3 OBBOffset = Vector3.Zero; - - public float volume; - - public float physCost = 0.0f; - public float streamCost = 0; - public MeshWorkerChange changed; - public byte shapetype = 0; - public bool NoColide = false; - public bool hasOBB = false; - public bool hasMeshVolume = false; - } // colision flags of things others can colide with // rays, sensors, probes removed since can't be colided with @@ -133,13 +110,16 @@ namespace OpenSim.Region.Physics.OdePlugin light = 7 // compatibility with old viewers } - [Flags] - public enum MeshWorkerChange : uint + + public enum AssetState : byte { - none = 0, - size = 1, - shape = 2, - shapetype = 3, + noNeedAsset = 0, + needAsset = 1, + loadingAsset = 2, + procAsset = 3, + AssetOK = 4, + + AssetFailed = 0xff } public enum changes : int @@ -180,6 +160,7 @@ namespace OpenSim.Region.Physics.OdePlugin Size, Shape, PhysRepData, + AddPhysRep, CollidesWater, VolumeDtc, @@ -330,7 +311,6 @@ 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 WorkSpace; // no collisions work space // some speedup variables private int spaceGridMaxX; @@ -342,7 +322,7 @@ namespace OpenSim.Region.Physics.OdePlugin private IntPtr[] staticPrimspaceOffRegion; public Object OdeLock; - private static Object SimulationLock; + public static Object SimulationLock; public IMesher mesher; @@ -403,7 +383,6 @@ namespace OpenSim.Region.Physics.OdePlugin // now the major subspaces ActiveSpace = d.HashSpaceCreate(TopSpace); StaticSpace = d.HashSpaceCreate(TopSpace); - WorkSpace = d.HashSpaceCreate(TopSpace); } catch { @@ -413,12 +392,10 @@ namespace OpenSim.Region.Physics.OdePlugin d.HashSpaceSetLevels(TopSpace, -2, 8); d.HashSpaceSetLevels(ActiveSpace, -2, 8); d.HashSpaceSetLevels(StaticSpace, -2, 8); - d.HashSpaceSetLevels(WorkSpace, -2, 8); // demote to second level d.SpaceSetSublevel(ActiveSpace, 1); d.SpaceSetSublevel(StaticSpace, 1); - d.SpaceSetSublevel(WorkSpace, 1); d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | CollisionCategories.Geom | @@ -436,8 +413,6 @@ namespace OpenSim.Region.Physics.OdePlugin )); d.GeomSetCollideBits(StaticSpace, 0); - d.GeomSetCategoryBits(WorkSpace, 0); - d.GeomSetCollideBits(WorkSpace, 0); contactgroup = d.JointGroupCreate(0); //contactgroup @@ -518,7 +493,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } - m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, WorkSpace, physicsconfig); + m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, physicsconfig); HalfOdeStep = ODE_STEPSIZE * 0.5f; odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); @@ -1316,6 +1291,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 @@ -1371,59 +1355,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) { @@ -1444,44 +1375,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) @@ -1534,6 +1460,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 @@ -1706,20 +1654,9 @@ namespace OpenSim.Region.Physics.OdePlugin { if (world == IntPtr.Zero) return 0; + + d.WorldSetQuickStepNumIterations(world, curphysiteractions); - // 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(); - } -*/ while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever { try @@ -1747,8 +1684,9 @@ namespace OpenSim.Region.Physics.OdePlugin } 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) @@ -2491,6 +2429,9 @@ namespace OpenSim.Region.Physics.OdePlugin */ public override void Dispose() { + if (m_meshWorker != null) + m_meshWorker.Stop(); + lock (OdeLock) { m_rayCastManager.Dispose();