From a3c0e3ed260a8a76e3009e99162cdcb8142ea1b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Oct 2012 22:19:47 +0100 Subject: minor: elaborate method doc on Scene.NewUserConnection() --- OpenSim/Region/Framework/Scenes/Scene.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 671feda..ed88571 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3461,11 +3461,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// At the moment, this consists of setting up the caps infrastructure - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it let, we allowed banned users in still. /// /// CircuitData of the agent who is connecting + /// /// Outputs the reason for the false response on this string /// True if the region accepts this agent. False if it does not. False will /// also return a reason. @@ -3476,10 +3474,20 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// At the moment, this consists of setting up the caps infrastructure + /// + /// + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it yet, we still allowed banned users in. + /// + /// At the moment this method consists of setting up the caps infrastructure /// The return bool should allow for connections to be refused, but as not all calling paths /// take proper notice of it let, we allowed banned users in still. - /// + /// + /// This method is called by the login service (in the case of login) or another simulator (in the case of region + /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection + /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of + /// the LLUDP stack). + /// /// CircuitData of the agent who is connecting /// Outputs the reason for the false response on this string /// True for normal presence. False for NPC @@ -3566,7 +3574,6 @@ namespace OpenSim.Region.Framework.Scenes return false; } - ScenePresence sp = GetScenePresence(agent.AgentID); if (sp != null && !sp.IsChildAgent) -- cgit v1.1 From e76b01a201a9b2d45b56cd5dc2a207b08b4529e5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 00:26:43 +0100 Subject: Lock on AgentCircuitData during Scene.AddClient() and RemoveClient() to prevent an inactive connection being left behind if the user closes the viewer whilst the connection is being established. This should remove the need to run the console command "kick user --force" when these connections are left around. --- .../Linden/Caps/EventQueue/EventQueueGetModule.cs | 13 +- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 14 +- OpenSim/Region/Framework/Scenes/Scene.cs | 457 ++++++++++++--------- 3 files changed, 265 insertions(+), 219 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 594b229..0dd0904 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); - scene.EventManager.OnNewClient += OnNewClient; +// scene.EventManager.OnNewClient += OnNewClient; // TODO: Leaving these open, or closing them when we // become a child is incorrect. It messes up TP in a big @@ -102,6 +102,7 @@ namespace OpenSim.Region.ClientStack.Linden // circuit is there. scene.EventManager.OnClientClosed += ClientClosed; + scene.EventManager.OnMakeChildAgent += MakeChildAgent; scene.EventManager.OnRegisterCaps += OnRegisterCaps; @@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden #endregion - private void OnNewClient(IClientAPI client) - { - //client.OnLogout += ClientClosed; - } - -// private void ClientClosed(IClientAPI client) -// { -// ClientClosed(client.AgentId); -// } - private void ClientClosed(UUID agentID, Scene scene) { // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index d11fcbf..ab670a7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -1103,20 +1103,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP { IClientAPI client = null; - // In priciple there shouldn't be more than one thread here, ever. - // But in case that happens, we need to synchronize this piece of code - // because it's too important - lock (this) + // We currently synchronize this code across the whole scene to avoid issues such as + // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done + // consistently, this lock could probably be removed. + lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); - + client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; - + ((LLClientView)client).DisableFacelights = m_disableFacelights; - + client.Start(); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ed88571..fb2decc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes public SynchronizeSceneHandler SynchronizeScene; /// + /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. + /// + private object m_removeClientLock = new object(); + + /// /// Statistical information for this scene. /// public SimStatsReporter StatsReporter { get; private set; } @@ -2709,69 +2714,89 @@ namespace OpenSim.Region.Framework.Scenes public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) { + ScenePresence sp; + bool vialogin; + // Validation occurs in LLUDPServer + // + // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with + // each other. In practice, this does not currently occur in the code. AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - bool vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - -// CheckHeartbeat(); - - ScenePresence sp = GetScenePresence(client.AgentId); - - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possible the code calling AddNewClient() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - - m_clientManager.Add(client); - SubscribeToClientEvents(client); - - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); - m_eventManager.TriggerOnNewPresence(sp); - - sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection + // and a simultaneous one that removes it (as can happen if the client is closed at a particular point + // whilst connecting). + // + // It would be easier to lock across all NewUserConnection(), AddNewClient() and + // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service + // response in some module listening to AddNewClient()) from holding up unrelated agent calls. + // + // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all + // AddNewClient() operations (though not other ops). + // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. + lock (aCircuit) + { + vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + + // CheckHeartbeat(); + + sp = GetScenePresence(client.AgentId); - // The first agent upon login is a root agent by design. - // For this agent we will have to rez the attachments. - // All other AddNewClient calls find aCircuit.child to be true. - if (aCircuit.child == false) + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possible the code calling AddNewClient() should ensure that no client is already + // connected. + if (sp == null) { - // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to - // start the scripts again (since this is done in RezAttachments()). - // XXX: This is convoluted. - sp.IsChildAgent = false; - - if (AttachmentsModule != null) - Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); + + m_clientManager.Add(client); + SubscribeToClientEvents(client); + + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + m_eventManager.TriggerOnNewPresence(sp); + + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; + + // The first agent upon login is a root agent by design. + // For this agent we will have to rez the attachments. + // All other AddNewClient calls find aCircuit.child to be true. + if (aCircuit.child == false) + { + // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to + // start the scripts again (since this is done in RezAttachments()). + // XXX: This is convoluted. + sp.IsChildAgent = false; + + if (AttachmentsModule != null) + Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + } } - } - else - { - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - } + else + { + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); + } + + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - client.SceneAgent = sp; + // Cache the user's name + CacheUserName(sp, aCircuit); + + EventManager.TriggerOnNewClient(client); + if (vialogin) + EventManager.TriggerOnClientLogin(client); + } m_LastLogin = Util.EnvironmentTickCount(); - // Cache the user's name - CacheUserName(sp, aCircuit); - - EventManager.TriggerOnNewClient(client); - if (vialogin) - EventManager.TriggerOnClientLogin(client); - return sp; } @@ -3300,109 +3325,129 @@ namespace OpenSim.Region.Framework.Scenes { // CheckHeartbeat(); bool isChildAgent = false; - ScenePresence avatar = GetScenePresence(agentID); - - if (avatar == null) - { - m_log.WarnFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - - return; - } + AgentCircuitData acd; - try + lock (m_removeClientLock) { - isChildAgent = avatar.IsChildAgent; - - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + acd = m_authenticateHandler.GetAgentCircuitData(agentID); - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) + if (acd == null) { - // Tell a single agent to disconnect from the region. - IEventQueue eq = RequestModuleInterface(); - if (eq != null) - { - eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); - } - else - { - avatar.ControllingClient.SendShutdownConnectionNotice(); - } + m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); + return; } - - // Only applies to root agents. - if (avatar.ParentID != 0) + else { - avatar.StandUp(); + // We remove the acd up here to avoid later raec conditions if two RemoveClient() calls occurred + // simultaneously. + m_authenticateHandler.RemoveCircuit(acd.circuitcode); } + } - m_sceneGraph.removeUserCount(!isChildAgent); - - // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop - // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - - // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever - // this method is doing is HORRIBLE!!! - avatar.Scene.NeedSceneCacheClear(avatar.UUID); - - if (closeChildAgents && !isChildAgent) + lock (acd) + { + ScenePresence avatar = GetScenePresence(agentID); + + if (avatar == null) { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + m_log.WarnFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); + + return; } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) + + try { - if (AttachmentsModule != null) + isChildAgent = avatar.IsChildAgent; + + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) { - AttachmentsModule.DeRezAttachments(avatar); + // Tell a single agent to disconnect from the region. + IEventQueue eq = RequestModuleInterface(); + if (eq != null) + { + eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); + } + else + { + avatar.ControllingClient.SendShutdownConnectionNotice(); + } } - - ForEachClient( - delegate(IClientAPI client) + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + m_sceneGraph.removeUserCount(!isChildAgent); + + // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop + // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever + // this method is doing is HORRIBLE!!! + avatar.Scene.NeedSceneCacheClear(avatar.UUID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } - - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + AttachmentsModule.DeRezAttachments(avatar); + } - m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } - avatar.Close(); + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); } catch (Exception e) { m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { + try + { + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); + + avatar.Close(); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); + } } } @@ -3572,87 +3617,97 @@ namespace OpenSim.Region.Framework.Scenes agent.firstname, agent.lastname, agent.Viewer); reason = "Access denied, your viewer is banned by the region owner"; return false; - } - - ScenePresence sp = GetScenePresence(agent.AgentID); - - if (sp != null && !sp.IsChildAgent) - { - // We have a zombie from a crashed session. - // Or the same user is trying to be root twice here, won't work. - // Kill it. - m_log.WarnFormat( - "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", - sp.Name, sp.UUID, RegionInfo.RegionName); - - sp.ControllingClient.Close(true); - sp = null; } - ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + ILandObject land; - //On login test land permisions - if (vialogin) + lock (agent) { - if (land != null && !TestLandRestrictions(agent, land, out reason)) + ScenePresence sp = GetScenePresence(agent.AgentID); + + if (sp != null && !sp.IsChildAgent) { - return false; + // We have a zombie from a crashed session. + // Or the same user is trying to be root twice here, won't work. + // Kill it. + m_log.WarnFormat( + "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", + sp.Name, sp.UUID, RegionInfo.RegionName); + + sp.ControllingClient.Close(true); + sp = null; } - } - - if (sp == null) // We don't have an [child] agent here already - { - if (requirePresenceLookup) + + land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + + //On login test land permisions + if (vialogin) { - try - { - if (!VerifyUserPresence(agent, out reason)) - return false; - } catch (Exception e) + if (land != null && !TestLandRestrictions(agent, land, out reason)) { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); return false; } } - - try - { - if (!AuthorizeUser(agent, out reason)) - return false; - } catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - return false; - } - - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode); - - if (CapsModule != null) + + if (sp == null) // We don't have an [child] agent here already { - CapsModule.SetAgentCapsSeeds(agent); - CapsModule.CreateCaps(agent.AgentID); - } - } else - { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; + if (requirePresenceLookup) + { + try + { + if (!VerifyUserPresence(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - agent.AgentID, RegionInfo.RegionName); + return false; + } + } + + try + { + if (!AuthorizeUser(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); - sp.AdjustKnownSeeds(); - + return false; + } + + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, + agent.AgentID, agent.circuitcode); + if (CapsModule != null) + { CapsModule.SetAgentCapsSeeds(agent); + CapsModule.CreateCaps(agent.AgentID); + } + } + else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; + + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + agent.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + CapsModule.SetAgentCapsSeeds(agent); + } } } -- cgit v1.1 From 528085adefdd105aca2621c747fefe728ea8c218 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 00:48:20 +0100 Subject: minor: Add method doc to EventManager.OnNewClient, OnClientLogin, ClientClosed, OnRemovePresence that any long-running operations should be launched on a thread separate to the event thread. --- OpenSim/Region/Framework/Scenes/EventManager.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index a8ff218..4c49b71 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -121,13 +121,21 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// This is triggered for both child and root agent client connections. + /// /// Triggered before OnClientLogin. + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event OnNewClientDelegate OnNewClient; /// /// Fired if the client entering this sim is doing so as a new login /// + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. + /// public event Action OnClientLogin; public delegate void OnNewPresenceDelegate(ScenePresence presence); @@ -149,6 +157,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// Triggered in which is used by both /// users and NPCs + /// + /// Triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event OnRemovePresenceDelegate OnRemovePresence; @@ -425,6 +436,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// At the point of firing, the scene still contains the client's scene presence. + /// + /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please + /// do this on a separate thread. /// public event ClientClosed OnClientClosed; -- cgit v1.1 From 11d8119a21c645d6a0d71edc7444f058ba89414b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 01:37:57 +0100 Subject: Remove osDropAttachment threat level check wrongly placed in OSSL_Api.ShoutErrorOnLackingOwnerPerms. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 31be450..279ad59 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3555,7 +3555,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// boolean indicating whether an error was shouted. protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); m_host.AddScriptLPS(1); bool fail = false; if (m_item.PermsGranter != m_host.OwnerID) -- cgit v1.1 From 756ac4f32104db9dcdfb1c1da81075299e2cbfb4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 01:39:47 +0100 Subject: Correct osSetContentType() threat check to query osSetContentType rather than osSetResponseType --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 279ad59..29bc163 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3545,10 +3545,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public void osSetContentType(LSL_Key id, string type) { - CheckThreatLevel(ThreatLevel.High,"osSetResponseType"); + CheckThreatLevel(ThreatLevel.High, "osSetContentType"); + if (m_UrlModule != null) m_UrlModule.HttpContentType(new UUID(id),type); } + /// Shout an error if the object owner did not grant the script the specified permissions. /// /// -- cgit v1.1 From efd9791506b00e424bb5f1846b37d79e7638bda2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 10 Oct 2012 23:30:48 +0100 Subject: Add "delete object pos to " console command. This allows one to delete objects within a certain volume. See help on console for more details. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 109 ++++++++++++++++----- 1 file changed, 85 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6e39e9a..85779ec 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; @@ -83,29 +84,56 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, "delete object owner", "delete object owner ", - "Delete a scene object by owner", HandleDeleteObject); + "Delete scene objects by owner", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object creator", "delete object creator ", - "Delete a scene object by creator", HandleDeleteObject); + "Delete scene objects by creator", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object uuid", "delete object uuid ", - "Delete a scene object by uuid", HandleDeleteObject); + "Delete a scene object by uuid", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object name", "delete object name [--regex] ", "Delete a scene object by name.", - "If --regex is specified then the name is treatead as a regular expression", + "Command will ask for confirmation before proceeding.\n" + + "If --regex is specified then the name is treatead as a regular expression", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object outside", "delete object outside", - "Delete all scene objects outside region boundaries", HandleDeleteObject); + "Delete all scene objects outside region boundaries", + "Command will ask for confirmation before proceeding.", + HandleDeleteObject); + + m_console.Commands.AddCommand( + "Objects", + false, + "delete object pos", + "delete object pos to ", + "Delete scene objects within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "delete object pos 20,20,20 to 40,40,40\n" + + "delete object pos 20,20 to 40,40\n" + + "delete object pos ,20,20 to ,40,40\n" + + "delete object pos ,,30 to ,,~\n" + + "delete object pos ,,-~ to ,,30", + HandleDeleteObject); m_console.Commands.AddCommand( "Objects", @@ -301,23 +329,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - string rawConsoleStartVector = cmdparams[3]; - Vector3 startVector; + Vector3 startVector, endVector; - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) return; - } - - string rawConsoleEndVector = cmdparams[5]; - Vector3 endVector; - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return; - } Predicate searchPredicate = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); @@ -557,6 +572,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; + case "pos": + deletes = GetDeleteCandidatesByPos(module, cmd); + break; + default: m_console.OutputFormat("Unrecognized mode {0}", mode); return; @@ -571,7 +590,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string.Format( "Are you sure that you want to delete {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName), - "n"); + "y/N"); if (response.ToLower() != "y") { @@ -593,9 +612,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private List GetDeleteCandidatesByName(string module, string[] cmdparams) { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return null; - bool useRegex = false; OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); @@ -629,5 +645,50 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sceneObjects; } + + /// + /// Get scene object delete candidates by position + /// + /// + /// + /// null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there + /// are no objects to delete then the list will be empty./returns> + private List GetDeleteCandidatesByPos(string module, string[] cmdparams) + { + if (cmdparams.Length < 5) + { + m_console.OutputFormat("Usage: delete object pos to "); + return null; + } + + Vector3 startVector, endVector; + + if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) + return null; + + return m_scene.GetSceneObjectGroups().FindAll( + so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); + } + + private bool TryParseVectorRange(IEnumerable rawComponents, out Vector3 startVector, out Vector3 endVector) + { + string rawConsoleStartVector = rawComponents.Take(1).Single(); + + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) + { + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return false; + } + + string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return false; + } + + return true; + } } } \ No newline at end of file -- cgit v1.1 From b768c35f6f69606d17fdd76d94b95428ac9d0029 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 00:05:34 +0100 Subject: Assign endVector before control leaves ObjectCommandsModule.TryParseVectorRange() in order to fix mono 2.4.3 compile failure. This doesn't fail the compile on mono 2.10.8. --- .../Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 85779ec..7a35182 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -677,6 +677,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) { m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + endVector = Vector3.Zero; + return false; } -- cgit v1.1 From 87825b0abee76c28dcffdaa2c532779b813b6d14 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 5 Oct 2012 15:33:17 -0700 Subject: BulletSim: Fix crash when linking large physical linksets. Properly remove and restore linkage constraints when upgrading a prim's mesh to a hull. Lots more debug logging. Definitions and use of Bullet structure dumping. Centralize detail logging so a Flush() can be added for debugging. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 13 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 137 ++++++++++----------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 3 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 9 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 11 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 45 ++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 14 ++- 8 files changed, 132 insertions(+), 102 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 63a4127..a20be3a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -49,9 +49,16 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { m_enabled = false; - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); - m_constraint.ptr = System.IntPtr.Zero; + if (m_constraint.ptr != IntPtr.Zero) + { + bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); + m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", + BSScene.DetailLogZero, + m_body1.ID, m_body1.ptr.ToString("X"), + m_body2.ID, m_body2.ptr.ToString("X"), + success); + m_constraint.ptr = System.IntPtr.Zero; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4ba2f62..3fb2253 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -862,7 +862,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin private void VDetailLog(string msg, params Object[] args) { if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.PhysicsLogging.Write(msg, args); + Prim.PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3e82642..20db4de 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -52,8 +52,8 @@ public class BSLinkset // the physical 'taint' children separately. // After taint processing and before the simulation step, these // two lists must be the same. - private List m_children; - private List m_taintChildren; + private HashSet m_children; + private HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -90,8 +90,8 @@ public class BSLinkset m_nextLinksetID = 1; PhysicsScene = scene; LinksetRoot = parent; - m_children = new List(); - m_taintChildren = new List(); + m_children = new HashSet(); + m_taintChildren = new HashSet(); m_mass = parent.MassRaw; } @@ -197,6 +197,8 @@ public class BSLinkset PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() { RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); }); } } @@ -215,13 +217,10 @@ public class BSLinkset if (IsRoot(child)) { // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); - ret = true; - } + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); } else { @@ -229,12 +228,9 @@ public class BSLinkset child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); - // Remove the dependency on the body of this one - if (m_taintChildren.Contains(child)) - { - PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); - ret = true; - } + // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); + // Despite the function name, this removes any link to the specified object. + ret = PhysicallyUnlinkAllChildrenFromRoot(child); } } return ret; @@ -254,7 +250,7 @@ public class BSLinkset child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { - PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + PhysicallyLinkAChildToRoot(LinksetRoot, bpo); } } else @@ -263,7 +259,7 @@ public class BSLinkset LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + PhysicallyLinkAChildToRoot(LinksetRoot, child); } } } @@ -330,22 +326,22 @@ public class BSLinkset { m_children.Add(child); - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); + DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { - DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - // build the physical binding between me and the child - m_taintChildren.Add(childx); - + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); // Since this is taint-time, the body and shape could have changed for the child - PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody); + rootx.ForcePosition = rootx.Position; // DEBUG + childx.ForcePosition = childx.Position; // DEBUG + PhysicallyLinkAChildToRoot(rootx, childx); + m_taintChildren.Add(child); }); } return; @@ -378,10 +374,8 @@ public class BSLinkset PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - if (m_taintChildren.Contains(childx)) - m_taintChildren.Remove(childx); - - PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody); + m_taintChildren.Remove(child); + PhysicallyUnlinkAChildFromRoot(rootx, childx); RecomputeLinksetConstraintVariables(); }); @@ -396,8 +390,7 @@ public class BSLinkset // Create a constraint between me (root of linkset) and the passed prim (the child). // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody, - BSPhysObject childPrim, BulletBody childBody) + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -409,33 +402,17 @@ public class BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, - rootPrim.LocalID, rootBody.ptr.ToString("X"), - childPrim.LocalID, childBody.ptr.ToString("X"), + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // There is great subtlty in these paramters. Notice the check for a ptr of zero. - // We pass the BulletBody structure into the taint in order to capture the pointer - // of the body at the time of constraint creation. This doesn't work for the very first - // construction because there is no body yet. The body - // is constructed later at taint time. Thus we use the body address at time of the - // taint creation but, if it is zero, use what's in the prim at the moment. - // There is a possible race condition since shape can change without a taint call - // (like changing to a mesh that is already constructed). The fix for that would be - // to only change BSShape at taint time thus syncronizing these operations at - // the cost of efficiency and lag. BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, - rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody, - childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody, - midPoint, - true, - true - ); + PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms @@ -452,7 +429,7 @@ public class BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, OMV.Vector3.Zero, @@ -486,39 +463,44 @@ public class BSLinkset { constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); } - - RecomputeLinksetConstraintVariables(); } // Remove linkage between myself and a particular child // The root and child bodies are passed in because we need to remove the constraint between // the bodies that were at unlink time. // Called at taint time! - private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BulletBody rootBody, - BSPhysObject childPrim, BulletBody childBody) + private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { - DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + bool ret = false; + DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, - rootPrim.LocalID, rootBody.ptr.ToString("X"), - childPrim.LocalID, childBody.ptr.ToString("X")); + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list - PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootBody, childBody); + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + { + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + ret = true; + } - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + return ret; } - /* // Remove linkage between myself and any possible children I might have. // Called at taint time! - private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) + private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { - DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + bool ret = false; - PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) + { + ret = true; + } + return ret; } - */ // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Used when objects are added or removed @@ -550,11 +532,17 @@ public class BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); } + + // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG } return; } @@ -563,7 +551,8 @@ public class BSLinkset // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 1ac8c59..0665292 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -207,7 +207,8 @@ public abstract class BSPhysObject : PhysicsActor // High performance detailed logging routine used by the physical objects. protected void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index f7b68ba..98a18a1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -196,7 +196,7 @@ public sealed class BSPrim : BSPhysObject _isSelected = value; PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() { - // DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); + DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); SetObjectDynamic(false); }); } @@ -620,8 +620,10 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); // There can be special things needed for implementing linksets Linkset.MakeStatic(this); - // The activation state is 'disabled' so Bullet will not try to act on it - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + // The activation state is 'disabled' so Bullet will not try to act on it. + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + // Start it out sleeping and physical actions could wake it up. + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -1204,6 +1206,7 @@ public sealed class BSPrim : BSPhysObject { // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. + // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); }); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index aaed7de..eed915d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -254,7 +254,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The bounding box for the simulated world. The origin is 0,0,0 unless we're // a child in a mega-region. - // Turns out that Bullet really doesn't care about the extents of the simulated + // Bullet actually doesn't care about the extents of the simulated // area. It tracks active objects no matter where they are. Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); @@ -331,7 +331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { - PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); + DetailLog("[BULLETS UNMANAGED]:" + msg); } public override void Dispose() @@ -494,8 +494,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_simulationStep++; int numSubSteps = 0; - // Sometimes needed for debugging to find out what happened before the step - // PhysicsLogging.Flush(); + // DEBUG + DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); try { @@ -715,6 +715,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG tcbe.callback(); } catch (Exception e) @@ -1270,6 +1271,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); + // Add the Flush() if debugging crashes to get all the messages written out. + PhysicsLogging.Flush(); // DEBUG DEBUG DEBUG } // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 399a133..283b601 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -136,7 +136,21 @@ public class BSShapeCollection : IDisposable // New entry bodyDesc.ptr = body.ptr; bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", body.ID, body, bodyDesc.referenceCount); + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", + body.ID, body, bodyDesc.referenceCount); + BSScene.TaintCallback createOperation = delegate() + { + if (!BulletSimAPI.IsInWorld2(body.ptr)) + { + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", + body.ID, body); + } + }; + if (atTaintTime) + createOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); } bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; @@ -160,21 +174,22 @@ public class BSShapeCollection : IDisposable Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); - // If body is no longer being used, free it -- bodies are never shared. + // If body is no longer being used, free it -- bodies can never be shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", - body.ID, body.ptr.ToString("X")); + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", + body.ID, body.ptr.ToString("X"), inTaintTime); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + + // Zero any reference to the shape so it is not freed when the body is deleted. + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }; // If already in taint-time, do the operations now. Otherwise queue for later. @@ -208,7 +223,7 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this mesh. meshDesc.referenceCount++; - DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); } else @@ -217,7 +232,7 @@ public class BSShapeCollection : IDisposable meshDesc.ptr = shape.ptr; // We keep a reference to the underlying IMesh data so a hull can be built meshDesc.referenceCount = 1; - DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); ret = true; } @@ -230,7 +245,7 @@ public class BSShapeCollection : IDisposable { // There is an existing instance of this hull. hullDesc.referenceCount++; - DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); } else @@ -238,7 +253,7 @@ public class BSShapeCollection : IDisposable // This is a new reference to a hull hullDesc.ptr = shape.ptr; hullDesc.referenceCount = 1; - DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", + DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); ret = true; @@ -525,7 +540,7 @@ public class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. + // Remove usage of the previous shape. DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); @@ -659,6 +674,7 @@ public class BSShapeCollection : IDisposable if (pbs.SculptEntry) lod = PhysicsScene.SculptLOD; + // Mega prims usually get more detail because one can interact with shape approximations at this size. float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; @@ -709,13 +725,13 @@ public class BSShapeCollection : IDisposable { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); - // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); + DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); @@ -731,7 +747,8 @@ public class BSShapeCollection : IDisposable private void DetailLog(string msg, params Object[] args) { - PhysicsScene.PhysicsLogging.Write(msg, args); + if (PhysicsScene.PhysicsLogging.Enabled) + PhysicsScene.DetailLog(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a43880d..bb4d399 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -192,8 +192,9 @@ public struct ShapeData SHAPE_SPHERE = 5, SHAPE_MESH = 6, SHAPE_HULL = 7, - SHAPE_GROUNDPLANE = 8, - SHAPE_TERRAIN = 9, + // following defined by BulletSim + SHAPE_GROUNDPLANE = 20, + SHAPE_TERRAIN = 21, }; public uint ID; public PhysicsShapeType Type; @@ -1108,6 +1109,15 @@ public static extern float GetMargin2(IntPtr shape); public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpAllInfo2(IntPtr sim); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 68698975f1537725a1f53bc4b2db2cfc798ac7f3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 9 Oct 2012 12:58:06 -0700 Subject: BulletSim: Add Force* operations to objects to allow direct push to engine. Update BSDynamics to use same (don't want to delay updates til next taint-time. Suppress queuing a taint update for position and orientation calls if value does not change. Move Bullet timing statistics call from C# back to C++ code. Throttle taints per simulation step and add parameter to set. By default, don't create hulls for physical objects. Add a parameter to turn on and off. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 11 ++++ OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 12 ++-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 33 +++++++++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 65 ++++++++++++++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 + 7 files changed, 100 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a52e01..c23ccd5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -332,6 +332,13 @@ public class BSCharacter : BSPhysObject }); } } + public override OMV.Vector3 ForceVelocity { + get { return _velocity; } + set { + _velocity = value; + BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + } + } public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; @@ -432,6 +439,10 @@ public class BSCharacter : BSPhysObject get { return _rotationalVelocity; } set { _rotationalVelocity = value; } } + public override OMV.Vector3 ForceRotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } + } public override bool Kinematic { get { return _kinematic; } set { _kinematic = value; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 3fb2253..76230a1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -481,7 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastPositionVector = Prim.ForcePosition; VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity); + Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); }// end Step // Apply the effect of the linear motor. @@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Mass * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.MassRaw * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -678,10 +678,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_newVelocity.Z = 0; // Apply velocity - Prim.Velocity = m_newVelocity; + Prim.ForceVelocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. - // m_prim.AddForce(grav, false); + Prim.AddForce(grav, false); // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); @@ -704,7 +704,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_lastAngularVelocity // what was last applied to body // Get what the body is doing, this includes 'external' influences - Vector3 angularVelocity = Prim.RotationalVelocity; + Vector3 angularVelocity = Prim.ForceRotationalVelocity; if (m_angularMotorApply > 0) { @@ -810,7 +810,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - Prim.RotationalVelocity = m_lastAngularVelocity; + Prim.ForceRotationalVelocity = m_lastAngularVelocity; VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 0665292..cae599c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -85,6 +85,10 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Quaternion ForceOrientation { get; set; } + public abstract OMV.Vector3 ForceVelocity { get; set; } + + public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 98a18a1..d408be0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -265,6 +265,11 @@ public sealed class BSPrim : BSPhysObject return _position; } set { + // If you must push the position into the physics engine, use ForcePosition. + if (_position == value) + { + return; + } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? PositionSanityCheck(); @@ -453,7 +458,6 @@ public sealed class BSPrim : BSPhysObject } return; } - public override OMV.Vector3 Velocity { get { return _velocity; } set { @@ -465,6 +469,13 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForceVelocity { + get { return _velocity; } + set { + _velocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + } + } public override OMV.Vector3 Torque { get { return _torque; } set { _torque = value; @@ -490,6 +501,8 @@ public sealed class BSPrim : BSPhysObject return _orientation; } set { + if (_orientation == value) + return; _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() @@ -621,9 +634,9 @@ public sealed class BSPrim : BSPhysObject // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); // Start it out sleeping and physical actions could wake it up. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; @@ -640,6 +653,9 @@ public sealed class BSPrim : BSPhysObject // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 BulletSimAPI.ClearAllForces2(BSBody.ptr); + // For good measure, make sure the transform is set through to the motion state + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + // A dynamic object has mass IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); @@ -776,6 +792,15 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForceRotationalVelocity { + get { + return _rotationalVelocity; + } + set { + _rotationalVelocity = value; + BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + } + } public override bool Kinematic { get { return _kinematic; } set { _kinematic = value; @@ -1307,7 +1332,7 @@ public sealed class BSPrim : BSPhysObject /* else { - // For debugging, we can also report the movement of children + // For debugging, report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index eed915d..33ac116 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -90,10 +90,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters // let my minuions use my logger public ILog Logger { get { return m_log; } } - // If non-zero, the number of simulation steps between calls to the physics - // engine to output detailed physics stats. Debug logging level must be on also. - private int m_detailedStatsStep = 0; - public IMesher mesher; // Level of Detail values kept as float because that's what the Meshmerizer wants public float MeshLOD { get; private set; } @@ -112,6 +108,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters private float m_fixedTimeStep; private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } + private int m_taintsToProcessPerStep; // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates @@ -131,6 +128,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes + public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects public float PID_D { get; private set; } // derivative public float PID_P { get; private set; } // proportional @@ -582,15 +580,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // If enabled, call into the physics engine to dump statistics - if (m_detailedStatsStep > 0) - { - if ((m_simulationStep % m_detailedStatsStep) == 0) - { - BulletSimAPI.DumpBulletStatistics(); - } - } - // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. @@ -617,7 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BSPhysObject collidee = null; PhysObjects.TryGetValue(collidingWith, out collidee); - DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) { @@ -704,6 +693,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { // swizzle a new list into the list location so we can process what's there + int taintCount = m_taintsToProcessPerStep; + TaintCallbackEntry oneCallback = new TaintCallbackEntry(); + while (_taintedObjects.Count > 0 && taintCount-- > 0) + { + bool gotOne = false; + lock (_taintLock) + { + if (_taintedObjects.Count > 0) + { + oneCallback = _taintedObjects[0]; + _taintedObjects.RemoveAt(0); + gotOne = true; + } + } + if (gotOne) + { + try + { + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG + oneCallback.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); + } + } + } + /* + // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) { @@ -724,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } oldList.Clear(); + */ } } @@ -835,6 +854,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), + new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, + (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, @@ -877,6 +901,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_maxUpdatesPerFrame; }, (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), + new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", + 100f, + (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_taintsToProcessPerStep; }, + (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 10000.01f, (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, @@ -1086,11 +1115,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintSolverIterations; }, (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), - new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", + new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", 0f, - (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_detailedStatsStep; }, - (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), + (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, + (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), }; // Convert a boolean to our numeric true and false values diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 283b601..e619b48 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -407,7 +407,7 @@ public class BSShapeCollection : IDisposable // made. Native shapes are best used in either case. if (!haveShape) { - if (prim.IsPhysical) + if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bb4d399..7a60afb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -306,6 +306,8 @@ public struct ConfigurationParameters public float linkConstraintCFM; public float linkConstraintSolverIterations; + public float physicsLoggingFrames; + public const float numericTrue = 1f; public const float numericFalse = 0f; } -- cgit v1.1 From a791620622dc0a67a6af2c4a9c011d9057360411 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 08:02:37 -0700 Subject: BulletSim: cosmetic changes (comments and renaming). Give mass to terrain to improve interactions. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 55 +++++++++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 ++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 9 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 31 ++++++------ .../Physics/BulletSPlugin/BSTerrainManager.cs | 14 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 +- 7 files changed, 74 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index c23ccd5..2e6b2da 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -263,7 +263,7 @@ public class BSCharacter : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool atTaintTime) + private bool PositionSanityCheck2(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -275,7 +275,7 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }; - if (atTaintTime) + if (inTaintTime) sanityOperation(); else PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 20db4de..b84ccdc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -160,6 +160,31 @@ public class BSLinkset return ret; } + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // May be called at runtime or taint-time (just pass the appropriate flag). + public void Refresh(BSPhysObject requestor, bool inTaintTime) + { + // If there are no children, there can't be any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + BSScene.TaintCallback refreshOperation = delegate() + { + RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + }; + if (inTaintTime) + refreshOperation(); + else + PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + } + } + // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. // Only the state of the passed object can be modified. The rest of the linkset @@ -182,24 +207,19 @@ public class BSLinkset return false; } - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // Called at runtime. - public void Refresh(BSPhysObject requestor) + // If the software is handling the movement of all the objects in a linkset + // (like if one doesn't use constraints for static linksets), this is called + // when an update for the root of the linkset is received. + // Called at taint-time!! + public void UpdateProperties(BSPhysObject physObject) { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) - return; - - // Only the root does the recomputation - if (IsRoot(requestor)) + // The root local properties have been updated. Apply to the children if appropriate. + if (IsRoot(physObject) && HasAnyChildren) { - PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + if (!physObject.IsPhysical) { - RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }); + // TODO: implement software linkset update for static object linksets + } } } @@ -236,9 +256,8 @@ public class BSLinkset return ret; } - // Routine used when rebuilding the body of the root of the linkset - // This is called after RemoveAllLinksToRoot() to restore all the constraints. - // This is called when the root body has been changed. + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. // Called at taint-time!! public void RestoreBodyDependencies(BSPrim child) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d408be0..b26f049 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -327,7 +327,7 @@ public sealed class BSPrim : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool atTaintTime) + private bool PositionSanityCheck2(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -339,7 +339,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); }; - if (atTaintTime) + if (inTaintTime) sanityOperation(); else PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); @@ -583,7 +583,7 @@ public sealed class BSPrim : BSPhysObject // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); - // Update vehicle specific parameters + // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) _vehicle.Refresh(); // Arrange for collision events if the simulator wants them @@ -606,7 +606,7 @@ public sealed class BSPrim : BSPhysObject // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this); + Linkset.Refresh(this, true); DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); @@ -1322,6 +1322,8 @@ public sealed class BSPrim : BSPhysObject PositionSanityCheck2(true); + Linkset.UpdateProperties(this); + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 33ac116..50091cc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,7 +39,6 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Move all logic out of the C++ code and into the C# code for easier future modifications. // Test sculpties (verified that they don't work) // Compute physics FPS reasonably // Based on material, set density and friction @@ -493,7 +492,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters int numSubSteps = 0; // DEBUG - DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); + // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); try { @@ -503,8 +502,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, nTaints={1}, simTime={2}, substeps={3}, updates={4}, colliders={5}", - DetailLogZero, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", + DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { @@ -855,7 +854,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericFalse, + ConfigurationParameters.numericTrue, (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e619b48..d5e2172 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -67,8 +67,8 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); + private Dictionary Meshes = new Dictionary(); + private Dictionary Hulls = new Dictionary(); private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) @@ -121,7 +121,7 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. // Bodies only have one user so the reference count is either 1 or 0. - public void ReferenceBody(BulletBody body, bool atTaintTime) + public void ReferenceBody(BulletBody body, bool inTaintTime) { lock (m_collectionActivityLock) { @@ -147,7 +147,7 @@ public class BSShapeCollection : IDisposable body.ID, body); } }; - if (atTaintTime) + if (inTaintTime) createOperation(); else PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); @@ -272,7 +272,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. - public void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) + public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) return; @@ -294,14 +294,14 @@ public class BSShapeCollection : IDisposable if (shape.ptr != IntPtr.Zero & shape.isNativeShape) { DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); + BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); if (shapeCallback != null) shapeCallback(shape); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; } }; - if (atTaintTime) + if (inTaintTime) { lock (m_collectionActivityLock) { @@ -441,7 +441,7 @@ public class BSShapeCollection : IDisposable // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (ulong)shapeKey; + newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. @@ -461,7 +461,7 @@ public class BSShapeCollection : IDisposable BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; - ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) @@ -484,7 +484,7 @@ public class BSShapeCollection : IDisposable return true; // 'true' means a new shape has been added to this prim } - private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IMesh meshData = null; IntPtr meshPtr; @@ -531,7 +531,7 @@ public class BSShapeCollection : IDisposable BulletShape newShape; float lod; - ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) @@ -554,7 +554,7 @@ public class BSShapeCollection : IDisposable } List m_hulls; - private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) + private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IntPtr hullPtr; @@ -667,7 +667,7 @@ public class BSShapeCollection : IDisposable // Create a hash of all the shape parameters to be used as a key // for this particular shape. - private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) + private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; @@ -680,10 +680,10 @@ public class BSShapeCollection : IDisposable lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; - return (ulong)pbs.GetMeshKey(shapeData.Size, lod); + return pbs.GetMeshKey(shapeData.Size, lod); } // For those who don't want the LOD - private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) + private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) { float lod; return ComputeShapeKey(shapeData, pbs, out lod); @@ -717,6 +717,7 @@ public class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { + // Free any old body DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 70aa429..2808603 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -201,10 +201,10 @@ public class BSTerrainManager // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when // calling this routine from initialization or taint-time routines) or whether to delay // all the unmanaged activities to taint-time. - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool atTaintTime) + private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},atTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, atTaintTime); + DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", + BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); float minZ = float.MaxValue; float maxZ = float.MinValue; @@ -320,7 +320,9 @@ public class BSTerrainManager BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, 0f, Vector3.Zero); + float terrainMass = 1000; + Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(mapInfo.terrainBody.ptr, terrainMass); + BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, terrainMass, localInertia); BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); // Return the new terrain to the world of physical objects @@ -342,7 +344,7 @@ public class BSTerrainManager // There is the option to do the changes now (we're already in 'taint time'), or // to do the Bullet operations later. - if (atTaintTime) + if (inTaintTime) rebuildOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); @@ -381,7 +383,7 @@ public class BSTerrainManager }; // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. - if (atTaintTime) + if (inTaintTime) createOperation(); else PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 7a60afb..e23fe5a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -101,9 +101,8 @@ public struct BulletShape } public IntPtr ptr; public ShapeData.PhysicsShapeType type; - public ulong shapeKey; + public System.UInt64 shapeKey; public bool isNativeShape; - // Hulls have an underlying mesh. A pointer to it is hidden here. public override string ToString() { StringBuilder buff = new StringBuilder(); -- cgit v1.1 From 919569f6ecd5fe84d0f5b0981a48b4808a44f7ad Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 09:43:46 -0700 Subject: BulletSim: Change defaults for constraint CFM and ERP to make large linksets more rigid. Remove mass calculation for terrain (it should stay a static object). --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | 15 ++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 50091cc..617bdb4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1099,12 +1099,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, + 0.001f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.2f, + 0.8f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 2808603..caf411e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -114,6 +114,8 @@ public class BSTerrainManager BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + // Ground plane does not move + BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); // Everything collides with the ground plane. BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); @@ -296,16 +298,16 @@ public class BSTerrainManager mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); + // Create the terrain shape from the mapInfo + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), + ShapeData.PhysicsShapeType.SHAPE_TERRAIN); + // The terrain object initial position is at the center of the object Vector3 centerPos; centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); centerPos.Z = minZ + ((maxZ - minZ) / 2f); - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); - mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, id, centerPos, Quaternion.Identity)); @@ -320,11 +322,6 @@ public class BSTerrainManager BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - float terrainMass = 1000; - Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(mapInfo.terrainBody.ptr, terrainMass); - BulletSimAPI.SetMassProps2(mapInfo.terrainBody.ptr, terrainMass, localInertia); - BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.ptr); - // Return the new terrain to the world of physical objects BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); -- cgit v1.1 From 3a458e2a36253f6514720213deaa19372b06cc52 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 13:56:16 -0700 Subject: BulletSim: Use full linkset mass when computing vehicle gravity force. Add taint-time specification to new AddForce(). --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 9 +++------ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 12 ++++++++++-- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 76230a1..56342b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -462,7 +462,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin return; // Set the prim's inertia to zero. The vehicle code handles that and this - // removes the torque action introduced by Bullet. + // removes the motion and torque actions introduced by Bullet. Vector3 inertia = Vector3.Zero; BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); @@ -540,7 +540,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.MassRaw * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); /* * RA: Not sure why one would do this @@ -681,7 +681,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceVelocity = m_newVelocity; // apply gravity force // Why is this set here? The physics engine already does gravity. - Prim.AddForce(grav, false); + Prim.AddForce(grav, false, true); // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index b84ccdc..43b1262 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -165,13 +165,11 @@ public class BSLinkset // May be called at runtime or taint-time (just pass the appropriate flag). public void Refresh(BSPhysObject requestor, bool inTaintTime) { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) + // If there are no children, not physical or not root, I am not the one that recomputes the constraints + // (For the moment, static linksets do create constraints so remove the test for physical.) + if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) return; - // Only the root does the recomputation - if (IsRoot(requestor)) - { BSScene.TaintCallback refreshOperation = delegate() { RecomputeLinksetConstraintVariables(); @@ -182,7 +180,6 @@ public class BSLinkset refreshOperation(); else PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); - } } // The object is going dynamic (physical). Do any setup necessary diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b26f049..692713d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -855,6 +855,9 @@ public sealed class BSPrim : BSPhysObject private List m_accumulatedForces = new List(); public override void AddForce(OMV.Vector3 force, bool pushforce) { + AddForce(force, pushforce, false); + } + public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) { @@ -867,11 +870,12 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - PhysicsScene.TaintedObject("BSPrim.AddForce", delegate() + BSScene.TaintCallback addForceOperation = delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) { + // Sum the accumulated additional forces for one big force to apply once. foreach (OMV.Vector3 v in m_accumulatedForces) { fSum += v; @@ -881,7 +885,11 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); - }); + }; + if (inTaintTime) + addForceOperation(); + else + PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); } public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { -- cgit v1.1 From a86fedd25ffb02c328b0591d16eda1dab797d8f9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 16:51:50 -0700 Subject: BulletSim: normalize physics FPS to 45. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 617bdb4..25f8f5f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -581,8 +581,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // Since Bullet normally does 5 or 6 substeps, this will normally sum to about 60 FPS. - return numSubSteps * m_fixedTimeStep * 1000; + // We multiply by 45 to give a recognizable running rate (45 or less). + return numSubSteps * m_fixedTimeStep * 1000 * 45; + // return timeStep * 1000 * 45; } // Something has collided @@ -1300,7 +1301,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { PhysicsLogging.Write(msg, args); // Add the Flush() if debugging crashes to get all the messages written out. - PhysicsLogging.Flush(); // DEBUG DEBUG DEBUG + // PhysicsLogging.Flush(); } // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; -- cgit v1.1 From 5b82f18d6422d89da53d382eb1ae89e47b4465b7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 10 Oct 2012 16:53:58 -0700 Subject: BulletSim: normalize physics FPS to 45 (for real this time). --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 25f8f5f..2c3c481 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -582,8 +582,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 45 to give a recognizable running rate (45 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 45; - // return timeStep * 1000 * 45; + return numSubSteps * m_fixedTimeStep * 1000 * 45; + // return timeStep * 1000 * 45; } // Something has collided -- cgit v1.1 From b24190ec98f31f1e4672d1174163426b9b44e25d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 11 Oct 2012 12:54:27 -0700 Subject: BulletSim: remove some unused API2 calls because they were removed from Bullet 2.81 --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 ++-- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 692713d..6a4365c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -673,8 +673,8 @@ public sealed class BSPrim : BSPhysObject // Force activation of the object so Bullet will act on it. // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.Activate2(BSBody.ptr, true); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + // BulletSimAPI.Activate2(BSBody.ptr, true); BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; BSBody.collisionMask = CollisionFilterGroups.ObjectMask; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e23fe5a..276111c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -1039,18 +1039,6 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); public static extern int GetNumConstraintRefs2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetDeltaLinearVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetDeltaAngularVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetPushVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTurnVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); // ===================================================================================== -- cgit v1.1 From 1f2472d0fcd86a7ae09c01ecb3508eab001ce033 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 23:28:53 +0100 Subject: Extend "show stats" command to "show stats [list|all|]" This allows different categories of stats to be shown, with options to list categories or show all stats. Currently categories are scene and simulator and only a very few stats are currently registered via this mechanism. This commit also adds percentage stats for packets and blocks reused from the packet pool. --- OpenSim/Region/Application/OpenSimBase.cs | 72 +++++++++++----------- .../Region/ClientStack/Linden/UDP/PacketPool.cs | 43 ++++++++++--- 2 files changed, 70 insertions(+), 45 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f784398..4f1b439 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -223,8 +223,6 @@ namespace OpenSim base.StartupSpecific(); - m_stats = StatsManager.SimExtraStats; - // Create a ModuleLoader instance m_moduleLoader = new ModuleLoader(m_config.Source); @@ -234,51 +232,51 @@ namespace OpenSim plugin.PostInitialise(); } - AddPluginCommands(); + if (m_console != null) + { + StatsManager.RegisterConsoleCommands(m_console); + AddPluginCommands(m_console); + } } - protected virtual void AddPluginCommands() + protected virtual void AddPluginCommands(CommandConsole console) { - // If console exists add plugin commands. - if (m_console != null) - { - List topics = GetHelpTopics(); + List topics = GetHelpTopics(); - foreach (string topic in topics) - { - string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); + foreach (string topic in topics) + { + string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); - // This is a hack to allow the user to enter the help command in upper or lowercase. This will go - // away at some point. - m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); - m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); + // This is a hack to allow the user to enter the help command in upper or lowercase. This will go + // away at some point. + console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); + console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); - ICommander commander = null; + ICommander commander = null; - Scene s = SceneManager.CurrentOrFirstScene; + Scene s = SceneManager.CurrentOrFirstScene; - if (s != null && s.GetCommanders() != null) - { - if (s.GetCommanders().ContainsKey(topic)) - commander = s.GetCommanders()[topic]; - } + if (s != null && s.GetCommanders() != null) + { + if (s.GetCommanders().ContainsKey(topic)) + commander = s.GetCommanders()[topic]; + } - if (commander == null) - continue; + if (commander == null) + continue; - foreach (string command in commander.Commands.Keys) - { - m_console.Commands.AddCommand(capitalizedTopic, false, - topic + " " + command, - topic + " " + commander.Commands[command].ShortHelp(), - String.Empty, HandleCommanderCommand); - } + foreach (string command in commander.Commands.Keys) + { + console.Commands.AddCommand(capitalizedTopic, false, + topic + " " + command, + topic + " " + commander.Commands[command].ShortHelp(), + String.Empty, HandleCommanderCommand); } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fc9406b..3d9f94f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -31,6 +31,7 @@ using System.Reflection; using OpenMetaverse; using OpenMetaverse.Packets; using log4net; +using OpenSim.Framework.Monitoring; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -43,17 +44,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool packetPoolEnabled = true; private bool dataBlockPoolEnabled = true; + private PercentageStat m_packetsReusedStat = new PercentageStat( + "PacketsReused", + "Packets reused", + "simulator", + "simulator", + StatVerbosity.Debug, + "Number of packets reused out of all requests to the packet pool"); + + private PercentageStat m_blocksReusedStat = new PercentageStat( + "BlocksReused", + "Blocks reused", + "simulator", + "simulator", + StatVerbosity.Debug, + "Number of data blocks reused out of all requests to the packet pool"); + /// /// Pool of packets available for reuse. /// private readonly Dictionary> pool = new Dictionary>(); - private static Dictionary> DataBlocks = - new Dictionary>(); - - static PacketPool() - { - } + private static Dictionary> DataBlocks = new Dictionary>(); public static PacketPool Instance { @@ -72,8 +84,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return dataBlockPoolEnabled; } } + private PacketPool() + { + StatsManager.RegisterStat(m_packetsReusedStat); + StatsManager.RegisterStat(m_blocksReusedStat); + } + public Packet GetPacket(PacketType type) { + m_packetsReusedStat.Consequent++; + Packet packet; if (!packetPoolEnabled) @@ -89,6 +109,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP else { // Recycle old packages + m_packetsReusedStat.Antecedent++; + packet = (pool[type]).Pop(); } } @@ -211,16 +233,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public static T GetDataBlock() where T: new() + public T GetDataBlock() where T: new() { lock (DataBlocks) { + m_blocksReusedStat.Consequent++; + Stack s; if (DataBlocks.TryGetValue(typeof(T), out s)) { if (s.Count > 0) + { + m_blocksReusedStat.Antecedent++; return (T)s.Pop(); + } } else { @@ -231,7 +258,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public static void ReturnDataBlock(T block) where T: new() + public void ReturnDataBlock(T block) where T: new() { if (block == null) return; -- cgit v1.1 From 2e9ef015f7b73a3942011a36a9f94ce59d848dc0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Oct 2012 23:58:37 +0100 Subject: Fix packetpool for ImprovedTerseObjectUpdate packets. These were neither being returned or in many places reused. Getting packets from a pool rather than deallocating and reallocating reduces memory churn which in turn reduces garbage collection time and frequency. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 14 +++++++++++--- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 2 ++ OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 62f51d9..dc88686 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3922,7 +3922,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseAgentUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -3967,7 +3969,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -12286,7 +12291,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + ImprovedTerseObjectUpdatePacket packet + = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( + PacketType.ImprovedTerseObjectUpdate); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index ab670a7..6d2cda5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -420,6 +420,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category, method); } + + PacketPool.Instance.ReturnPacket(packet); } /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 3d9f94f..fd6b0ed 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_packetsReusedStat = new PercentageStat( "PacketsReused", "Packets reused", - "simulator", + "clientstack", "simulator", StatVerbosity.Debug, "Number of packets reused out of all requests to the packet pool"); @@ -55,7 +55,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", - "simulator", + "clientstack", "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From 8a402850ddbdd9497998774b646c8e0ae6ef1eb8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 00:21:45 +0100 Subject: Enable reuse of data blocks for ImprovedTerseObjectUpdate using existing Packetpool code. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index dc88686..5f9face 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4964,7 +4964,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block + = PacketPool.Instance.GetDataBlock(); + block.Data = data; if (textureEntry != null && textureEntry.Length > 0) -- cgit v1.1 From 59a17ad676326d5affc2e221ef9c02166a85c6fd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 00:26:15 +0100 Subject: Fix percentage stats to multiply by 100. Adjust container name for packetpool stats. --- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fd6b0ed..a8a1bfe 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -48,14 +48,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP "PacketsReused", "Packets reused", "clientstack", - "simulator", + "packetpool", StatVerbosity.Debug, "Number of packets reused out of all requests to the packet pool"); private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", - "clientstack", + "packetpool", "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From 87a87ebb9a68f9bb4cd44f3b00954ed7fca7da3a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 11 Oct 2012 17:06:58 -0700 Subject: BulletSim: fix problem with some shapes (like cylinders) being implemented as cubes. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d5e2172..a0d111a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -387,7 +387,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, forceRebuild, prim.BSShape); } } - else + if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) { haveShape = true; if (forceRebuild -- cgit v1.1 From 21d0cbf7038cfb1b1010310a0f4b455cf9ab700d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 01:39:37 +0100 Subject: Add AgentUpdate to PacketPool. This is the most common inbound packet from viewers. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 21 +++++++++++++++++++-- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 8 +++++++- .../Linden/UDP/Tests/BasicCircuitTests.cs | 4 ++-- 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 6d2cda5..e3f4679 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -100,9 +100,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The measured resolution of Environment.TickCount public readonly float TickCountResolution; + /// Number of prim updates to put on the queue each time the /// OnQueueEmpty event is triggered for updates public readonly int PrimUpdatesPerCallback; + /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for textures public readonly int TextureSendLimit; @@ -111,6 +113,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //PacketEventDictionary packetEvents = new PacketEventDictionary(); /// Incoming packets that are awaiting handling private OpenMetaverse.BlockingQueue packetInbox = new OpenMetaverse.BlockingQueue(); + /// //private UDPClientCollection m_clients = new UDPClientCollection(); /// Bandwidth throttle for this UDP server @@ -121,28 +124,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Manages authentication for agent circuits private AgentCircuitManager m_circuitManager; + /// Reference to the scene this UDP server is attached to protected Scene m_scene; + /// The X/Y coordinates of the scene this UDP server is attached to private Location m_location; + /// The size of the receive buffer for the UDP socket. This value /// is passed up to the operating system and used in the system networking /// stack. Use zero to leave this value as the default private int m_recvBufferSize; + /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// Tracks whether or not a packet was sent each round so we know /// whether or not to sleep private bool m_packetSent; /// Environment.TickCount of the last time that packet stats were reported to the scene private int m_elapsedMSSinceLastStatReport = 0; + /// Environment.TickCount of the last time the outgoing packet handler executed private int m_tickLastOutgoingPacketHandler; + /// Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped private int m_elapsedMSOutgoingPacketHandler; + /// Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed100MSOutgoingPacketHandler; + /// Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed500MSOutgoingPacketHandler; @@ -739,7 +751,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - packet = Packet.BuildPacket(buffer.Data, ref packetEnd, +// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, +// // Only allocate a buffer for zerodecoding if the packet is zerocoded +// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } @@ -754,11 +769,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; // Drop short packet } - catch(Exception e) + catch (Exception e) { if (m_malformedCount < 100) m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); + m_malformedCount++; + if ((m_malformedCount % 100000) == 0) m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index a8a1bfe..052d334 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -90,6 +90,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP StatsManager.RegisterStat(m_blocksReusedStat); } + /// + /// Gets a packet of the given type. + /// + /// + /// Guaranteed to always return a packet, whether from the pool or newly constructed. public Packet GetPacket(PacketType type) { m_packetsReusedStat.Consequent++; @@ -160,7 +165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketType type = GetType(bytes); - Array.Clear(zeroBuffer, 0, zeroBuffer.Length); +// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); int i = 0; Packet packet = GetPacket(type); @@ -207,6 +212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP switch (packet.Type) { // List pooling packets here + case PacketType.AgentUpdate: case PacketType.PacketAck: case PacketType.ObjectUpdate: case PacketType.ImprovedTerseObjectUpdate: diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 109a8e1..fa9378c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// This will contain basic tests for the LindenUDP client stack /// [TestFixture] - public class BasicCircuitTests + public class BasicCircuitTests : OpenSimTestCase { private Scene m_scene; private TestLLUDPServer m_udpServer; @@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests public void TestAddClient() { TestHelpers.InMethod(); -// XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); AddUdpServer(); -- cgit v1.1 From 8873a4a8fcaa3372713463094f2cfebeaaf45834 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 01:59:47 +0100 Subject: minor: Fix bug in categorization of blocks reused stat from packetpool --- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 052d334..71f6fe1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -55,8 +55,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private PercentageStat m_blocksReusedStat = new PercentageStat( "BlocksReused", "Blocks reused", + "clientstack", "packetpool", - "simulator", StatVerbosity.Debug, "Number of data blocks reused out of all requests to the packet pool"); -- cgit v1.1 From b7e75d467c2edf052b0cf5216043937ebf583ef4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 02:10:30 +0100 Subject: minor: Use && instead of & when deciding whether to print Improve/ObjectUpdate packet out messages when debug is turned on. Practical effect is probably none. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 5f9face..2db8df2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -11765,7 +11765,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (DebugPacketLevel <= 50 - & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) + && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) -- cgit v1.1 From b5a3c74a5cbd1634d021923124a997fc4945e5ef Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 02:52:08 +0100 Subject: Add "active true|false" to "debug scene" console command. This allows the scene update and maintenance loops to be started and stopped for debug purposes. --- OpenSim/Region/Application/OpenSim.cs | 13 ++++++++--- OpenSim/Region/Framework/Scenes/Scene.cs | 40 +++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index c3c612f..b24641a 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -254,8 +254,14 @@ namespace OpenSim m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); m_console.Commands.AddCommand("Debug", false, "debug scene", - "debug scene ", - "Turn on scene debugging", Debug); + "debug scene active|collisions|physics|scripting|teleport true|false", + "Turn on scene debugging.", + "If active is false then main scene update and maintenance loops are suspended.\n" + + "If collisions is false then collisions with other objects are turned off.\n" + + "If physics is false then all physics objects are non-physical.\n" + + "If scripting is false then no scripting operations happen.\n" + + "If teleport is true then some extra teleport debug information is logged.", + Debug); m_console.Commands.AddCommand("General", false, "change region", "change region ", @@ -930,7 +936,8 @@ namespace OpenSim } else { - MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); + MainConsole.Instance.Output( + "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); } break; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fb2decc..7f4f7e5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -306,6 +306,30 @@ namespace OpenSim.Region.Framework.Scenes } private volatile bool m_shuttingDown; + /// + /// Is the scene active? + /// + /// + /// If false, maintenance and update loops are not run. + /// + public bool Active + { + get { return m_active; } + set + { + if (value) + { + if (!m_active) + Start(); + } + else + { + m_active = false; + } + } + } + private volatile bool m_active; + // private int m_lastUpdate; // private bool m_firstHeartbeat = true; @@ -1159,6 +1183,14 @@ namespace OpenSim.Region.Framework.Scenes public void SetSceneCoreDebug(Dictionary options) { + if (options.ContainsKey("active")) + { + bool active; + + if (bool.TryParse(options["active"], out active)) + Active = active; + } + if (options.ContainsKey("scripting")) { bool enableScripts = true; @@ -1298,6 +1330,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void Start() { + m_active = true; + // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); //m_heartbeatTimer.Enabled = true; @@ -1339,7 +1373,7 @@ namespace OpenSim.Region.Framework.Scenes #region Update Methods /// - /// Performs per-frame updates regularly + /// Activate the various loops necessary to continually update the scene. /// private void Heartbeat() { @@ -1396,7 +1430,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) + while (Active && !m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1455,7 +1489,7 @@ namespace OpenSim.Region.Framework.Scenes int previousFrameTick, tmpMS; int maintc = Util.EnvironmentTickCount(); - while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) + while (Active && !m_shuttingDown && (endFrame == null || Frame < endFrame)) { ++Frame; -- cgit v1.1 From b9c2a1508e68b5580328097a5d5e0b5bfbc16a7d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 03:19:12 +0100 Subject: Fix problems with regression tests by allowing invoke of Update() with a finite number of frames even if the scene isn't active. --- OpenSim/Region/Framework/Scenes/Scene.cs | 7 ++++--- .../Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7f4f7e5..fe549bc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -310,7 +310,8 @@ namespace OpenSim.Region.Framework.Scenes /// Is the scene active? /// /// - /// If false, maintenance and update loops are not run. + /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if + /// the scene is not active. /// public bool Active { @@ -1430,7 +1431,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (Active && !m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) + while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1489,7 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes int previousFrameTick, tmpMS; int maintc = Util.EnvironmentTickCount(); - while (Active && !m_shuttingDown && (endFrame == null || Frame < endFrame)) + while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) { ++Frame; diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs index 1d1ff88..9a871f0 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void Init() { m_scene = new SceneHelpers().SetupScene(); + m_scene.Start(); } [Test] -- cgit v1.1 From fba59d905c9f165e0fd8365e045f69df7b1383e3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 12 Oct 2012 03:20:27 +0100 Subject: Get rid of accidental scene start left in ScenePresenceAutopilotTests --- OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs index 9a871f0..1d1ff88 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs @@ -65,7 +65,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests public void Init() { m_scene = new SceneHelpers().SetupScene(); - m_scene.Start(); } [Test] -- cgit v1.1 From 8c40215834bc1286a6bd2902e1c8b0f2ef793fd7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 12 Oct 2012 07:37:52 -0700 Subject: BulletSim: only use native sphere shape if it is a sphere. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a0d111a..d189f1d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -373,7 +373,8 @@ public class BSShapeCollection : IDisposable && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) { - if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) + if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) { haveShape = true; if (forceRebuild -- cgit v1.1 From f6e166cd0bfc868fe17fb003390872ae70190177 Mon Sep 17 00:00:00 2001 From: TBG Renfold Date: Tue, 9 Oct 2012 14:56:25 +0100 Subject: Now using region flags for llRequestSimulatorData DATA_SIM_POS. If the region is not classed a hypergrid region, then the region secret is checked to make sure that it is a valid UUID. Just a temporary fix at this time. --- .../Shared/Api/Implementation/LSL_Api.cs | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7620df3..6b08b00 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -56,6 +56,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PrimType = OpenSim.Region.Framework.Scenes.PrimType; using AssetLandmark = OpenSim.Framework.AssetLandmark; +using RegionFlags = OpenSim.Framework.RegionFlags; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -9327,12 +9328,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(1000); return UUID.Zero.ToString(); } - if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) + + RegionFlags regionFlags = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(info.ScopeID, info.RegionID); + if ((regionFlags & RegionFlags.Hyperlink) != 0) { - //Hypergrid Region co-ordinates uint rx = 0, ry = 0; + //Hypergrid Region co-ordinates Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); - reply = new LSL_Vector( rx, ry, @@ -9340,11 +9342,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - //Local-cooridnates - reply = new LSL_Vector( - info.RegionLocX, - info.RegionLocY, - 0).ToString(); + UUID regionSecret = UUID.Zero; + if (UUID.TryParse(info.RegionSecret, out regionSecret)) + { + if (regionSecret != UUID.Zero) + { + //Local co-oridnates + reply = new LSL_Vector( + info.RegionLocX, + info.RegionLocY, + 0).ToString(); + } + } } break; case ScriptBaseClass.DATA_SIM_STATUS: -- cgit v1.1 From 330b976a62b3153dadfb1acdaa99b60a9084453d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 13 Oct 2012 01:03:09 +0100 Subject: Improve on TBG Renfold's fix to llRequestSimulatorData DATA_SIM_POS by only performing HG regionflags service check if the region secret is not empty. An empty RegionSecret is never HG, whilst a non-empty one may be HG or being genuinely used as a RegionSecret. --- .../Shared/Api/Implementation/LSL_Api.cs | 44 ++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6b08b00..1e8dec8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9314,11 +9314,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridRegion info; - if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? - - info = new GridRegion(m_ScriptEngine.World.RegionInfo); + if (World.RegionInfo.RegionName == simulator) + info = new GridRegion(World.RegionInfo); else - info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); + info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); switch (data) { @@ -9329,12 +9328,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } - RegionFlags regionFlags = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(info.ScopeID, info.RegionID); - if ((regionFlags & RegionFlags.Hyperlink) != 0) + bool isHypergridRegion = false; + + if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") + { + // Hypergrid is currently placing real destination region co-ords into RegionSecret. + // But other code can also use this field for a genuine RegionSecret! Therefore, if + // anything is present we need to disambiguate. + // + // FIXME: Hypergrid should be storing this data in a different field. + RegionFlags regionFlags + = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( + info.ScopeID, info.RegionID); + isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; + } + + if (isHypergridRegion) { uint rx = 0, ry = 0; - //Hypergrid Region co-ordinates Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); + reply = new LSL_Vector( rx, ry, @@ -9342,18 +9355,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - UUID regionSecret = UUID.Zero; - if (UUID.TryParse(info.RegionSecret, out regionSecret)) - { - if (regionSecret != UUID.Zero) - { - //Local co-oridnates - reply = new LSL_Vector( - info.RegionLocX, - info.RegionLocY, - 0).ToString(); - } - } + // Local grid co-oridnates + reply = new LSL_Vector( + info.RegionLocX, + info.RegionLocY, + 0).ToString(); } break; case ScriptBaseClass.DATA_SIM_STATUS: -- cgit v1.1 From dc460579fd94b2017e334e71ffd20d94a3dec425 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 13 Oct 2012 01:47:10 +0100 Subject: minor: Fix and elaborate on log information printed when an unrecognized estate method is received from the client. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 2db8df2..0d4f09d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -9063,7 +9063,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - switch (Utils.BytesToString(messagePacket.MethodData.Method)) + string method = Utils.BytesToString(messagePacket.MethodData.Method); + + switch (method) { case "getinfo": if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) @@ -9379,7 +9381,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; default: - m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); + m_log.WarnFormat( + "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", + method, Name, Scene.Name); + + for (int i = 0; i < messagePacket.ParamList.Length; i++) + { + EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; + string data = (string)Utils.BytesToString(block.Parameter); + m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); + } + return true; } -- cgit v1.1 From 8c2564c05cbf277bef85bba62313f5d5493a4a81 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 00:40:28 +0100 Subject: minor: Comment out the region console caps message for now. --- OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index 36af55f..17c7270 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -107,7 +107,7 @@ namespace OpenSim.Region.ClientStack.Linden UUID capID = UUID.Random(); - m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); +// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler( "SimConsoleAsync", new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); -- cgit v1.1 From 3ac6a423f7748bf9d5da0d1bd8fc62652ed8e151 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 00:54:25 +0100 Subject: minor: comment out "Registered seed capability" message for "Received SEED caps request" message for now. I think this is more useful right now since it tells us if the viewer requested a seed caps at all in various scenarios (such as when teleporting to a new region). --- .../Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 185f9ce..cc69645 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -163,8 +163,8 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler( "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); - m_log.DebugFormat( - "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); +// m_log.DebugFormat( +// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); //m_capsHandlers["MapLayer"] = // new LLSDStreamhandler("POST", @@ -254,11 +254,12 @@ namespace OpenSim.Region.ClientStack.Linden public string SeedCapRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { -// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); + m_log.DebugFormat( + "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) { - m_log.DebugFormat( + m_log.WarnFormat( "[CAPS]: Unauthorized CAPS client {0} from {1}", m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); -- cgit v1.1 From d469bde849f53a4c80b301051599390e916ce08a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:20:41 +0100 Subject: minor: Add/correct some doc messages associated with entity teleport. I believe UseCircuitCode is sent on EnableSimulator EQ message, rather than EstablishAgentCommunication At least with LL 3.3.4, EstablishAgentCommunication appears unnecessary in the teleport context - viewer still requests it though possibly only after TeleportFinish(). However, we will continue to send it. --- .../CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 7 ++++++- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 617a350..90fe430 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -486,6 +486,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (sp.ParentID != (uint)0) sp.StandUp(); + // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to + // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). sp.ControllingClient.SendTeleportStart(teleportFlags); // the avatar.Close below will clear the child region list. We need this below for (possibly) @@ -561,8 +563,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // So let's wait Thread.Sleep(200); + // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears + // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly + // only on TeleportFinish). This is untested for region teleport between different simulators + // though this probably also works. m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); - } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fe549bc..5f45529 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4144,8 +4144,9 @@ namespace OpenSim.Region.Framework.Scenes return false; } - // We have to wait until the viewer contacts this region after receiving EAC. - // That calls AddNewClient, which finally creates the ScenePresence + // We have to wait until the viewer contacts this region + // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send + // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) -- cgit v1.1 From 0eb457442d87315810fd8280458ca8c0c3e97d23 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:31:38 +0100 Subject: minor: Add missing newlines and spacing to help for "debug eq" console command --- .../ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 0dd0904..47cb049 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -111,10 +111,10 @@ namespace OpenSim.Region.ClientStack.Linden false, "debug eq", "debug eq [0|1|2]", - "Turn on event queue debugging" - + "<= 0 - turns off all event queue logging" - + ">= 1 - turns on outgoing event logging" - + ">= 2 - turns on poll notification", + "Turn on event queue debugging\n" + + " <= 0 - turns off all event queue logging\n" + + " >= 1 - turns on outgoing event logging\n" + + " >= 2 - turns on poll notification", HandleDebugEq); } else -- cgit v1.1 From ab0294f0109416da0546e25797e7747b23071d33 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 01:33:35 +0100 Subject: Add missing category paremeter to llGiveInventoryList grid IM construction. This was a regression from 16c9c1df Sat Oct 6 02:34:49 2012 +0100. Should resolve http://opensimulator.org/mantis/view.php?id=6360 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1e8dec8..ac74bf8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6459,7 +6459,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridInstantMessage msg = new GridInstantMessage(World, m_host.OwnerID, m_host.Name, destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, string.Format("'{0}'"), + false, string.Format("'{0}'", category), // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), folderID, false, pos, -- cgit v1.1 From db4ca57590db44aba7d19530285091c7ea4c082c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 21:55:00 +0100 Subject: Make it possible to separate start and stop lludp packet processing from the console for debug processes. This is controlled via the "debug lludp start " and "debug lludp stop " region console commands. The command "debug lludp status" will show current status. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 116 ++++++++++++++++++--- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 44 +++++--- 2 files changed, 129 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index e3f4679..fc6dd4d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -37,6 +37,7 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; @@ -274,16 +275,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void Start() { - if (m_scene == null) - throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); + StartInbound(); + StartOutbound(); + m_elapsedMSSinceLastStatReport = Environment.TickCount; + } + + private void StartInbound() + { m_log.InfoFormat( - "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", + "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode", m_asyncPacketHandling ? "asynchronous" : "synchronous"); - base.Start(m_recvBufferSize, m_asyncPacketHandling); + base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); - // Start the packet processing threads + // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( IncomingPacketHandler, string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), @@ -292,7 +298,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogIncomingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); + } + private void StartOutbound() + { + m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); + + base.StartOutbound(); + + // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( OutgoingPacketHandler, string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), @@ -301,8 +315,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogOutgoingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); + } - m_elapsedMSSinceLastStatReport = Environment.TickCount; + public new void Stop() + { + m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); + base.StopOutbound(); + base.StopInbound(); } /// @@ -327,12 +346,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); } - public new void Stop() - { - m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); - base.Stop(); - } - public void AddScene(IScene scene) { if (m_scene != null) @@ -349,6 +362,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_scene = (Scene)scene; m_location = new Location(m_scene.RegionInfo.RegionHandle); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp start", + "debug lludp start ", + "Control LLUDP packet processing.", + "No effect if packet processing has already started.\n" + + "in - start inbound processing.\n" + + "out - start outbound processing.\n" + + "all - start in and outbound processing.\n", + HandleStartCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp stop", + "debug lludp stop ", + "Stop LLUDP packet processing.", + "No effect if packet processing has already stopped.\n" + + "in - stop inbound processing.\n" + + "out - stop outbound processing.\n" + + "all - stop in and outbound processing.\n", + HandleStopCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp status", + "debug lludp status", + "Return status of LLUDP packet processing.", + HandleStatusCommand); + } + + private void HandleStartCommand(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Usage: debug lludp start "); + return; + } + + string subCommand = args[3]; + + if (subCommand == "in" || subCommand == "all") + StartInbound(); + + if (subCommand == "out" || subCommand == "all") + StartOutbound(); + } + + private void HandleStopCommand(string module, string[] args) + { + if (args.Length != 4) + { + MainConsole.Instance.Output("Usage: debug lludp stop "); + return; + } + + string subCommand = args[3]; + + if (subCommand == "in" || subCommand == "all") + StopInbound(); + + if (subCommand == "out" || subCommand == "all") + StopOutbound(); + } + + private void HandleStatusCommand(string module, string[] args) + { + MainConsole.Instance.OutputFormat( + "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); + + MainConsole.Instance.OutputFormat( + "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); } public bool HandlesRegion(Location x) @@ -1174,7 +1262,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (base.IsRunning) + while (base.IsRunningInbound) { try { @@ -1216,7 +1304,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (base.IsRunning) + while (base.IsRunningOutbound) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 039379d..828c23c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -58,11 +58,12 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// The all important shutdown flag - private volatile bool m_shutdownFlag = true; + /// Returns true if the server is currently listening for inbound packets, otherwise false + public bool IsRunningInbound { get; private set; } - /// Returns true if the server is currently listening, otherwise false - public bool IsRunning { get { return !m_shutdownFlag; } } + /// Returns true if the server is currently sending outbound packets, otherwise false + /// If IsRunningOut = false, then any request to send a packet is simply dropped. + public bool IsRunningOutbound { get; private set; } /// /// Default constructor @@ -76,7 +77,7 @@ namespace OpenMetaverse } /// - /// Start the UDP server + /// Start inbound UDP packet handling. /// /// The size of the receive buffer for /// the UDP socket. This value is passed up to the operating system @@ -91,11 +92,11 @@ namespace OpenMetaverse /// manner (not throwing an exception when the remote side resets the /// connection). This call is ignored on Mono where the flag is not /// necessary - public void Start(int recvBufferSize, bool asyncPacketHandling) + public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { m_asyncPacketHandling = asyncPacketHandling; - if (m_shutdownFlag) + if (!IsRunningInbound) { const int SIO_UDP_CONNRESET = -1744830452; @@ -127,8 +128,7 @@ namespace OpenMetaverse m_udpSocket.Bind(ipep); - // we're not shutting down, we're starting up - m_shutdownFlag = false; + IsRunningInbound = true; // kick off an async receive. The Start() method will return, the // actual receives will occur asynchronously and will be caught in @@ -138,28 +138,38 @@ namespace OpenMetaverse } /// - /// Stops the UDP server + /// Start outbound UDP packet handling. /// - public void Stop() + public void StartOutbound() { - if (!m_shutdownFlag) + IsRunningOutbound = true; + } + + public void StopInbound() + { + if (IsRunningInbound) { // wait indefinitely for a writer lock. Once this is called, the .NET runtime // will deny any more reader locks, in effect blocking all other send/receive - // threads. Once we have the lock, we set shutdownFlag to inform the other + // threads. Once we have the lock, we set IsRunningInbound = false to inform the other // threads that the socket is closed. - m_shutdownFlag = true; + IsRunningInbound = false; m_udpSocket.Close(); } } + public void StopOutbound() + { + IsRunningOutbound = false; + } + private void AsyncBeginReceive() { // allocate a packet buffer //WrappedObject wrappedBuffer = Pool.CheckOut(); UDPPacketBuffer buf = new UDPPacketBuffer(); - if (!m_shutdownFlag) + if (IsRunningInbound) { try { @@ -212,7 +222,7 @@ namespace OpenMetaverse { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive - if (!m_shutdownFlag) + if (IsRunningInbound) { // Asynchronous mode will start another receive before the // callback for this packet is even fired. Very parallel :-) @@ -252,7 +262,7 @@ namespace OpenMetaverse public void AsyncBeginSend(UDPPacketBuffer buf) { - if (!m_shutdownFlag) + if (IsRunningOutbound) { try { -- cgit v1.1 From fc861c7904840b2b0b9de0621e9b5d976c8071b1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 23:35:05 +0100 Subject: Add optional pool for the UDPPacketBuffer objects that handle all incoming UDP data. Even when an avatar is standing still, it's sending in a constant stream of AgentUpdate packets that the client creates new UDPPacketBuffer objects to handle. This option pools those objects. This reduces memory churn. Currently off by default. Works but the scope can be expanded. --- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 42 ++++++++++++---------- .../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 31 ++++++++++++---- 2 files changed, 49 insertions(+), 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index fc6dd4d..42247ca 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -188,7 +188,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private IClientAPI m_currentIncomingClient; - public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) + public LLUDPServer( + IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, + IConfigSource configSource, AgentCircuitManager circuitManager) : base(listenIP, (int)port) { #region Environment.TickCount Measurement @@ -242,6 +244,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); } #region BinaryStats @@ -284,8 +287,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void StartInbound() { m_log.InfoFormat( - "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode", - m_asyncPacketHandling ? "asynchronous" : "synchronous"); + "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", + m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); @@ -300,7 +303,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); } - private void StartOutbound() + private new void StartOutbound() { m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); @@ -317,7 +320,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); } - public new void Stop() + public void Stop() { m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); base.StopOutbound(); @@ -806,7 +809,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient udpClient = null; Packet packet = null; int packetEnd = buffer.DataLength - 1; - IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; + IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; #region Decoding @@ -816,7 +819,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); - return; // Drop undersizd packet + return; // Drop undersized packet } int headerLen = 7; @@ -842,6 +845,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // // Only allocate a buffer for zerodecoding if the packet is zerocoded // ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); + // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we + // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all + // bytes are copied out). packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); @@ -884,7 +890,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) { - object[] array = new object[] { buffer, packet }; + // We need to copy the endpoint so that it doesn't get changed when another thread reuses the + // buffer. + object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; Util.FireAndForget(HandleUseCircuitCode, array); @@ -893,7 +901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Determine which agent this packet came from IClientAPI client; - if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) + if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) { //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); return; @@ -1091,21 +1099,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void HandleUseCircuitCode(object o) { - IPEndPoint remoteEndPoint = null; + IPEndPoint endPoint = null; IClientAPI client = null; try { // DateTime startTime = DateTime.Now; object[] array = (object[])o; - UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; + endPoint = (IPEndPoint)array[0]; UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; m_log.DebugFormat( "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", - uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); - - remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; + uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); AuthenticateResponse sessionInfo; if (IsClientAuthorized(uccp, out sessionInfo)) @@ -1116,13 +1122,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP uccp.CircuitCode.Code, uccp.CircuitCode.ID, uccp.CircuitCode.SessionID, - remoteEndPoint, + endPoint, sessionInfo); // Send ack straight away to let the viewer know that the connection is active. // The client will be null if it already exists (e.g. if on a region crossing the client sends a use // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); + SendAckImmediate(endPoint, uccp.Header.Sequence); // We only want to send initial data to new clients, not ones which are being converted from child to root. if (client != null) @@ -1133,7 +1139,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Don't create clients for unauthorized requesters. m_log.WarnFormat( "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", - uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); + uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); } // m_log.DebugFormat( @@ -1145,7 +1151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.ErrorFormat( "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", - remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", + endPoint != null ? endPoint.ToString() : "n/a", client != null ? client.Name : "unknown", client != null ? client.AgentId.ToString() : "unknown", e.Message, diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 828c23c..6e6b3ef 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -30,6 +30,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; using log4net; +using OpenSim.Framework; namespace OpenMetaverse { @@ -58,6 +59,16 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// + /// Pool to use for handling data. May be null if UsePools = false; + /// + protected OpenSim.Framework.Pool m_pool; + + /// + /// Are we to use object pool(s) to reduce memory churn when receiving data? + /// + public bool UsePools { get; protected set; } + /// Returns true if the server is currently listening for inbound packets, otherwise false public bool IsRunningInbound { get; private set; } @@ -70,6 +81,7 @@ namespace OpenMetaverse /// /// Local IP address to bind the server to /// Port to listening for incoming UDP packets on + /// /// Are we to use an object pool to get objects for handing inbound data? public OpenSimUDPBase(IPAddress bindAddress, int port) { m_localBindAddress = bindAddress; @@ -94,6 +106,11 @@ namespace OpenMetaverse /// necessary public void StartInbound(int recvBufferSize, bool asyncPacketHandling) { + if (UsePools) + m_pool = new Pool(() => new UDPPacketBuffer(), 500); + else + m_pool = null; + m_asyncPacketHandling = asyncPacketHandling; if (!IsRunningInbound) @@ -165,9 +182,12 @@ namespace OpenMetaverse private void AsyncBeginReceive() { - // allocate a packet buffer - //WrappedObject wrappedBuffer = Pool.CheckOut(); - UDPPacketBuffer buf = new UDPPacketBuffer(); + UDPPacketBuffer buf; + + if (UsePools) + buf = m_pool.GetObject(); + else + buf = new UDPPacketBuffer(); if (IsRunningInbound) { @@ -231,8 +251,6 @@ namespace OpenMetaverse // get the buffer that was created in AsyncBeginReceive // this is the received data - //WrappedObject wrappedBuffer = (WrappedObject)iar.AsyncState; - //UDPPacketBuffer buffer = wrappedBuffer.Instance; UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try @@ -249,7 +267,8 @@ namespace OpenMetaverse catch (ObjectDisposedException) { } finally { - //wrappedBuffer.Dispose(); + if (UsePools) + m_pool.ReturnObject(buffer); // Synchronous mode waits until the packet callback completes // before starting the receive to fetch another packet -- cgit v1.1 From f35826eb31e2f286e3ae5bdbcf8c3beb4723d5d9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 16 Oct 2012 23:50:45 +0100 Subject: minor: Make BasicCircuitTests.SetUp() call overriden base method instead of ignoring it. --- OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index fa9378c..556df30 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } [SetUp] - public void SetUp() + public override void SetUp() { + base.SetUp(); m_scene = new SceneHelpers().SetupScene(); } -- cgit v1.1 From 2ed59ad8ac3ec836517b60580f13ab37102a0c67 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 21:08:15 +0100 Subject: If RecycleBaseUDPPackets = true, also pool IncomingPackets to reduce memory churn --- .../ClientStack/Linden/UDP/IncomingPacket.cs | 7 +++++- .../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 25 +++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index 1b8535c..e22670b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs @@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP public Packet Packet; /// - /// Default constructor + /// No arg constructor. + /// + public IncomingPacket() {} + + /// + /// Constructor /// /// Reference to the client this packet came from /// Packet data diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 42247ca..286d931 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -168,6 +168,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Flag to signal when clients should send pings protected bool m_sendPing; + private Pool m_incomingPacketPool; + private int m_defaultRTO = 0; private int m_maxRTO = 0; private int m_ackTimeout = 0; @@ -274,6 +276,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttle = new TokenBucket(null, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); + + if (UsePools) + m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); } public void Start() @@ -1012,8 +1017,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Ping Check Handling + IncomingPacket incomingPacket; + // Inbox insertion - packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); + if (UsePools) + { + incomingPacket = m_incomingPacketPool.GetObject(); + incomingPacket.Client = (LLClientView)client; + incomingPacket.Packet = packet; + } + else + { + incomingPacket = new IncomingPacket((LLClientView)client, packet); + } + + packetInbox.Enqueue(incomingPacket); } #region BinaryStats @@ -1283,7 +1301,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) + { ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); + + if (UsePools) + m_incomingPacketPool.ReturnObject(incomingPacket); + } } catch (Exception ex) { -- cgit v1.1 From faf6b568393d8edfed103e0a656c98322c195e95 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:08:14 +0100 Subject: Explicitly return only the incoming AgentUpdate packet as this is the only one we pool atm, rather than attempting to return all incoming packets. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 11 +++++++---- OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 17 +++++++++++++++-- OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 10 ++++++++-- 3 files changed, 30 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 0d4f09d..1e93b84 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5425,16 +5425,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) + private bool HandleAgentUpdate(IClientAPI sener, Packet packet) { if (OnAgentUpdate != null) { bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + { + PacketPool.Instance.ReturnPacket(packet); return false; + } #endregion AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; @@ -5499,6 +5502,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + PacketPool.Instance.ReturnPacket(packet); + return true; } @@ -11851,8 +11856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!ProcessPacketMethod(packet)) m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); - - PacketPool.Instance.ReturnPacket(packet); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 286d931..419de66 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -314,7 +314,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP base.StartOutbound(); - // This thread will process the packets received that are placed on the packetInbox Watchdog.StartThread( OutgoingPacketHandler, string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), @@ -930,6 +929,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { +// m_log.DebugFormat( +// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", +// packet.Header.AckList.Length, client.Name, m_scene.Name); + for (int i = 0; i < packet.Header.AckList.Length; i++) udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); } @@ -939,6 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketAckPacket ackPacket = (PacketAckPacket)packet; +// m_log.DebugFormat( +// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", +// ackPacket.Packets.Length, client.Name, m_scene.Name); + for (int i = 0; i < ackPacket.Packets.Length; i++) udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); @@ -952,6 +959,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Header.Reliable) { +// m_log.DebugFormat( +// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", +// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); + udpClient.PendingAcks.Enqueue(packet.Header.Sequence); // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, @@ -998,6 +1009,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Type == PacketType.StartPingCheck) { +// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); + // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(udpClient, startPing.PingID.PingID); @@ -1286,7 +1299,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (base.IsRunningInbound) + while (IsRunningInbound) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 71f6fe1..2a3d14f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -108,15 +108,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) { +// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); + // Creating a new packet if we cannot reuse an old package packet = Packet.BuildPacket(type); } else { +// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); + // Recycle old packages m_packetsReusedStat.Antecedent++; - packet = (pool[type]).Pop(); + packet = pool[type].Pop(); } } @@ -227,7 +231,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((pool[type]).Count < 50) { - (pool[type]).Push(packet); +// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); + + pool[type].Push(packet); } } break; -- cgit v1.1 From 3ec2923022dbc3e0b5411b17c6495dab6d641f0b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 17 Oct 2012 23:54:05 +0100 Subject: Reuse the same AgentUpdateArgs object for each AgentUpdate UDP packet (of which there are 10 a second) rather than constructing a new one every time. We can do this because AgentUpdate packets are handled synchronously. --- .../Region/ClientStack/Linden/UDP/LLClientView.cs | 109 +++++++++++++-------- 1 file changed, 68 insertions(+), 41 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 1e93b84..65daca0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,8 +92,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; + + /// + /// Called when an AgentUpdate message is received and before OnAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnPreAgentUpdate; + + /// + /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. + /// + /// + /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. + /// public event UpdateAgent OnAgentUpdate; + public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; @@ -347,7 +362,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - private AgentUpdateArgs lastarg; + + /// + /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for + /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it + /// is doing absolutely nothing. + /// + /// + /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods + /// cannot retain a reference to it outside of that method. + /// + private AgentUpdateArgs m_lastAgentUpdateArgs; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5198,7 +5223,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected virtual void RegisterLocalPacketHandlers() { AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); + + // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs + // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); + AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); @@ -5429,73 +5458,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (OnAgentUpdate != null) { - bool update = false; - AgentUpdatePacket agenUpdate = (AgentUpdatePacket)packet; + AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; #region Packet Session and User Check - if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) + if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) { PacketPool.Instance.ReturnPacket(packet); return false; } #endregion - AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - - // We can only check when we have something to check - // against. + bool update = false; + AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; - if (lastarg != null) + if (m_lastAgentUpdateArgs != null) { + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. update = ( - (x.BodyRotation != lastarg.BodyRotation) || - (x.CameraAtAxis != lastarg.CameraAtAxis) || - (x.CameraCenter != lastarg.CameraCenter) || - (x.CameraLeftAxis != lastarg.CameraLeftAxis) || - (x.CameraUpAxis != lastarg.CameraUpAxis) || - (x.ControlFlags != lastarg.ControlFlags) || - (x.Far != lastarg.Far) || - (x.Flags != lastarg.Flags) || - (x.State != lastarg.State) || - (x.HeadRotation != lastarg.HeadRotation) || - (x.SessionID != lastarg.SessionID) || - (x.AgentID != lastarg.AgentID) + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) ); } else { + m_lastAgentUpdateArgs = new AgentUpdateArgs(); update = true; } - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - AgentUpdateArgs arg = new AgentUpdateArgs(); - arg.AgentID = x.AgentID; - arg.BodyRotation = x.BodyRotation; - arg.CameraAtAxis = x.CameraAtAxis; - arg.CameraCenter = x.CameraCenter; - arg.CameraLeftAxis = x.CameraLeftAxis; - arg.CameraUpAxis = x.CameraUpAxis; - arg.ControlFlags = x.ControlFlags; - arg.Far = x.Far; - arg.Flags = x.Flags; - arg.HeadRotation = x.HeadRotation; - arg.SessionID = x.SessionID; - arg.State = x.State; + m_lastAgentUpdateArgs.AgentID = x.AgentID; + m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_lastAgentUpdateArgs.Far = x.Far; + m_lastAgentUpdateArgs.Flags = x.Flags; + m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_lastAgentUpdateArgs.SessionID = x.SessionID; + m_lastAgentUpdateArgs.State = x.State; + UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - lastarg = arg; // save this set of arguments for nexttime + if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, arg); + OnPreAgentUpdate(this, m_lastAgentUpdateArgs); + if (handlerAgentUpdate != null) - OnAgentUpdate(this, arg); + OnAgentUpdate(this, m_lastAgentUpdateArgs); handlerAgentUpdate = null; handlerPreAgentUpdate = null; -- cgit v1.1 From 0811f3d28d70432e4657df735b5337726eb2f53f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 00:34:10 +0100 Subject: minor: Remove event method doc from LLClientView that I forgot in the last commit (1de80c) --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 65daca0..7427c59 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -92,23 +92,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event Action OnCompleteMovementToRegion; - - /// - /// Called when an AgentUpdate message is received and before OnAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnPreAgentUpdate; - - /// - /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object is reused for subsequent AgentUpdates. - /// public event UpdateAgent OnAgentUpdate; - public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; public event AvatarPickerRequest OnAvatarPickerRequest; -- cgit v1.1 From 1e7fb2dc364bd8fcbe92fc3cca45c3eea85e5558 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Oct 2012 05:53:52 +0100 Subject: i update core ode plugin and make it load is meshs (i hope) Signed-off-by: Melanie --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 51 +++++++++++++++++++++++++++- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 2 +- 2 files changed, 51 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index e7b3b2b..c86084c 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); } @@ -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/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index cbe21e2..d53bd90 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 +} -- cgit v1.1 From de44e93aa27f55d939fd27493d195ee498270381 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 3 Oct 2012 23:18:35 +0100 Subject: missing changed file Signed-off-by: Melanie --- OpenSim/Region/Physics/Manager/PhysicsScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 6a0558a..488900e 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -76,7 +76,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() { -- cgit v1.1 From 7ab83f9eb22c5aaef3118ef45e4681503d6b93fc Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 7 Oct 2012 01:20:52 +0100 Subject: [DANGER UNTESTED] ODE mesh assets. Other plugins will not do meshs/sculpts now Signed-off-by: Melanie --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 4 ++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 28 ++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 45bbbda..0729dc9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3444,8 +3444,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 199526e..58ef9f7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1014,9 +1014,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); } } @@ -1620,12 +1620,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); } @@ -1643,6 +1644,7 @@ namespace OpenSim.Region.Framework.Scenes /// ID of asset received /// Register /// +/* protected void AssetReceived(string id, Object sender, AssetBase asset) { if (asset != null) @@ -1652,7 +1654,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. /// @@ -1833,9 +1835,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); } } @@ -2511,6 +2513,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) @@ -2538,7 +2541,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Send a full update to the client for the given part /// @@ -3783,7 +3786,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) @@ -3791,7 +3794,7 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived); } } - +*/ if (ParentGroup != null) { ParentGroup.HasGroupChanged = true; @@ -4341,6 +4344,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); @@ -4366,7 +4370,7 @@ namespace OpenSim.Region.Framework.Scenes } } } - +*/ /// /// Update the texture entry for this part. /// -- cgit v1.1 From afab5f5cd1f0d39b62a664753897e5d871e6307d Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 18 Oct 2012 15:30:42 +0100 Subject: extend coment to include all unused SOG CheckSculptAndLoad() --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0729dc9..1fa6a75 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3432,6 +3432,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() { if (IsDeleted) @@ -3444,10 +3445,10 @@ 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(); } - +*/ /// /// Set the user group to which this scene object belongs. /// -- cgit v1.1 From a2c93133be90822076e4e8d0b4096a83a30d80bd Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 18 Oct 2012 21:23:57 +0100 Subject: Remove extraneous calls to the now commented CheckSculptAndLoad --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 24 ---------------------- 1 file changed, 24 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 58ef9f7..da2c069 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4028,14 +4028,6 @@ namespace OpenSim.Region.Framework.Scenes if (!wasUsingPhysics) { DoPhysicsPropertyUpdate(UsePhysics, false); - - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } } } else @@ -4075,14 +4067,6 @@ namespace OpenSim.Region.Framework.Scenes pa.SetMaterial(Material); DoPhysicsPropertyUpdate(UsePhysics, true); - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } - if ( ((AggregateScriptEvents & scriptEvents.collision) != 0) || ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || @@ -4107,14 +4091,6 @@ namespace OpenSim.Region.Framework.Scenes else // it already has a physical representation { DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim - - if (!ParentGroup.IsDeleted) - { - if (LocalId == ParentGroup.RootPart.LocalId) - { - ParentGroup.CheckSculptAndLoad(); - } - } } } -- cgit v1.1 From a960273e91e43eedbab923539d817b81c0e50dbd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:02:57 +0100 Subject: Add number of inventory items to information displayed via "show part" console command --- .../World/Objects/Commands/ObjectCommandsModule.cs | 1 + OpenSim/Region/Framework/Interfaces/IEntityInventory.cs | 14 +++++++++++--- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 7a35182..5d0163a 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -456,6 +456,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sb.AppendFormat("Parent: {0}", sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); sb.AppendFormat("Link number: {0}\n", sop.LinkNum); + sb.AppendFormat("Items: {0}\n", sop.Inventory.Count); sb.AppendFormat("Flags: {0}\n", sop.Flags); return sb; diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 8d62847..c457b2f 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -268,17 +268,25 @@ namespace OpenSim.Region.Framework.Interfaces void ApplyGodPermissions(uint perms); /// + /// Number of items in this inventory. + /// + int Count { get; } + + /// /// Returns true if this inventory contains any scripts /// bool ContainsScripts(); /// - /// Returns the count of scripts contained - /// + /// Number of scripts in this inventory. + /// + /// + /// Includes both running and non running scripts. + /// int ScriptCount(); /// - /// Returns the count of running scripts contained + /// Number of running scripts in this inventory. /// int RunningScriptCount(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 821fd81..bdb0446 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -92,6 +92,15 @@ namespace OpenSim.Region.Framework.Scenes QueryScriptStates(); } } + + public int Count + { + get + { + lock (m_items) + return m_items.Count; + } + } /// /// Constructor -- cgit v1.1 From 1f3c9db2b9ba71a84438b53b2a8a6f398137deb0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:41:18 +0100 Subject: Add --full option to "show object name/uuid/pos" to show info on all parts of an object, not just whole object summary information. --- .../World/Objects/Commands/ObjectCommandsModule.cs | 80 ++++++++++++++++------ 1 file changed, 60 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 5d0163a..7ceac7e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -139,25 +139,29 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show object uuid", - "show object uuid ", - "Show details of a scene object with the given UUID", HandleShowObjectByUuid); + "show object uuid [--full] ", + "Show details of a scene object with the given UUID", + "The --full option will print out information on all the parts of the object.", + HandleShowObjectByUuid); m_console.Commands.AddCommand( "Objects", false, "show object name", - "show object name [--regex] ", + "show object name [--full] [--regex] ", "Show details of scene objects with the given name.", - "If --regex is specified then the name is treatead as a regular expression", + "The --full option will print out information on all the parts of the object.\n" + + "If --regex is specified then the name is treatead as a regular expression.", HandleShowObjectByName); m_console.Commands.AddCommand( "Objects", false, "show object pos", - "show object pos to ", + "show object pos [--full] to ", "Show details of scene objects within the given area.", - "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "The --full option will print out information on all the parts of the object.\n" + + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "If you don't care about the z component you can simply omit it.\n" + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" @@ -216,7 +220,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } - private void OutputSogsToConsole(Predicate searchPredicate) + /// + /// Outputs the sogs to console. + /// + /// + /// If true then output all part details. If false then output summary. + private void OutputSogsToConsole(Predicate searchPredicate, bool showFull) { List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); @@ -224,7 +233,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands foreach (SceneObjectGroup so in sceneObjects) { - AddSceneObjectReport(sb, so); + AddSceneObjectReport(sb, so, showFull); sb.Append("\n"); } @@ -253,21 +262,26 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void HandleShowObjectByUuid(string module, string[] cmd) + private void HandleShowObjectByUuid(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) + bool showFull = false; + OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { m_console.OutputFormat("Usage: show object uuid "); return; } UUID objectUuid; - if (!UUID.TryParse(cmd[3], out objectUuid)) + if (!UUID.TryParse(mainParams[3], out objectUuid)) { - m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); return; } @@ -280,7 +294,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddSceneObjectReport(sb, so); + AddSceneObjectReport(sb, so, showFull); m_console.OutputFormat(sb.ToString()); } @@ -290,14 +304,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; + bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + OptionSet options = new OptionSet(); + options.Add("full", v => showFull = v != null ); + options.Add("regex", v => useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show object name [--regex] "); + m_console.OutputFormat("Usage: show object name [--full] [--regex] "); return; } @@ -315,7 +332,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands searchPredicate = so => so.Name == name; } - OutputSogsToConsole(searchPredicate); + OutputSogsToConsole(searchPredicate, showFull); } private void HandleShowObjectByPos(string module, string[] cmdparams) @@ -323,9 +340,14 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmdparams.Length < 5) + bool showFull = false; + OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 5) { - m_console.OutputFormat("Usage: show object pos to "); + m_console.OutputFormat("Usage: show object pos [--full] to "); return; } @@ -337,7 +359,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands Predicate searchPredicate = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); - OutputSogsToConsole(searchPredicate); + OutputSogsToConsole(searchPredicate, showFull); } private void HandleShowPartByUuid(string module, string[] cmd) @@ -437,7 +459,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSopsToConsole(searchPredicate); } - private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) + private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) + { + if (showFull) + { + foreach (SceneObjectPart sop in so.Parts) + { + AddScenePartReport(sb, sop); + sb.Append("\n"); + } + } + else + { + AddSummarySceneObjectReport(sb, so); + } + + return sb; + } + + private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) { sb.AppendFormat("Name: {0}\n", so.Name); sb.AppendFormat("Description: {0}\n", so.Description); -- cgit v1.1 From 75f5e66d1c17ad6507a13c89345f3e4d351c44d2 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:45:07 +0100 Subject: Add local and UUID to information output of "show object" and "show part" region console commands --- .../Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 7ceac7e..b90b71e 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -481,6 +481,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands { sb.AppendFormat("Name: {0}\n", so.Name); sb.AppendFormat("Description: {0}\n", so.Description); + sb.AppendFormat("Local ID {0}\n", so.LocalId); + sb.AppendFormat("UUID {0}\n", so.UUID); sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); sb.AppendFormat("Parts: {0}\n", so.PrimCount); sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); @@ -492,6 +494,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands { sb.AppendFormat("Name: {0}\n", sop.Name); sb.AppendFormat("Description: {0}\n", sop.Description); + sb.AppendFormat("Local ID {0}\n", sop.LocalId); + sb.AppendFormat("UUID {0}\n", sop.UUID); sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); sb.AppendFormat("Parent: {0}", sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); -- cgit v1.1 From 845228b35e75dea4ec597ca394dd43196ff8bb48 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 18 Oct 2012 23:58:29 +0100 Subject: minor: Convert ad-hoc list building in ObjectCommandsModule to use ConsoleDisplayList --- .../World/Objects/Commands/ObjectCommandsModule.cs | 45 ++++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index b90b71e..6feba21 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -479,31 +479,34 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) { - sb.AppendFormat("Name: {0}\n", so.Name); - sb.AppendFormat("Description: {0}\n", so.Description); - sb.AppendFormat("Local ID {0}\n", so.LocalId); - sb.AppendFormat("UUID {0}\n", so.UUID); - sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); - sb.AppendFormat("Parts: {0}\n", so.PrimCount); - sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); - - return sb; + ConsoleDisplayList cdl = new ConsoleDisplayList(); + cdl.AddRow("Name", so.Name); + cdl.AddRow("Descrition", so.Description); + cdl.AddRow("Local ID", so.LocalId); + cdl.AddRow("UUID", so.UUID); + cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); + cdl.AddRow("Parts", so.PrimCount); + cdl.AddRow("Flags", so.RootPart.Flags); + + return sb.Append(cdl.ToString()); } private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) { - sb.AppendFormat("Name: {0}\n", sop.Name); - sb.AppendFormat("Description: {0}\n", sop.Description); - sb.AppendFormat("Local ID {0}\n", sop.LocalId); - sb.AppendFormat("UUID {0}\n", sop.UUID); - sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); - sb.AppendFormat("Parent: {0}", - sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); - sb.AppendFormat("Link number: {0}\n", sop.LinkNum); - sb.AppendFormat("Items: {0}\n", sop.Inventory.Count); - sb.AppendFormat("Flags: {0}\n", sop.Flags); - - return sb; + ConsoleDisplayList cdl = new ConsoleDisplayList(); + cdl.AddRow("Name", sop.Name); + cdl.AddRow("Description", sop.Description); + cdl.AddRow("Local ID", sop.LocalId); + cdl.AddRow("UUID", sop.UUID); + cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); + cdl.AddRow( + "Parent", + sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); + cdl.AddRow("Link number", sop.LinkNum); + cdl.AddRow("Flags", sop.Flags); + cdl.AddRow("Items", sop.Inventory.Count); + + return sb.Append(cdl.ToString()); } private void HandleDeleteObject(string module, string[] cmd) -- cgit v1.1 From b058ba5859b1012a23e58c9b9e0d91f77ac19ba3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Oct 2012 00:36:32 +0100 Subject: [UNTESTED] core Ode: stop trying to load a broken asset. Make broken assets behave like phantom by Nebadon request --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 118 +++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index c86084c..a6c657f 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -341,8 +341,17 @@ namespace OpenSim.Region.Physics.OdePlugin prim_geom = geom; //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } _parent_scene.geom_name_map[prim_geom] = Name; _parent_scene.actor_name_map[prim_geom] = this; @@ -405,8 +414,17 @@ namespace OpenSim.Region.Physics.OdePlugin myrot.W = _orientation.W; d.BodySetQuaternion(Body, ref myrot); d.GeomSetBody(prim_geom, Body); - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + } d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); @@ -778,8 +796,16 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionCategories &= ~CollisionCategories.Body; m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } d.BodyDestroy(Body); lock (childrenPrim) @@ -803,8 +829,17 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionCategories &= ~CollisionCategories.Body; m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } Body = IntPtr.Zero; } @@ -1094,8 +1129,16 @@ Console.WriteLine("ZProcessTaints for " + Name); prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); //Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name); - d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); - d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); + if (prm.m_assetFailed) + { + d.GeomSetCategoryBits(prm.prim_geom, 0); + d.GeomSetCollideBits(prm.prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); + } d.Quaternion quat = new d.Quaternion(); quat.W = prm._orientation.W; @@ -1140,10 +1183,18 @@ Console.WriteLine("ZProcessTaints for " + Name); m_collisionCategories |= CollisionCategories.Body; m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); -//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); -//Console.WriteLine(" Post GeomSetCategoryBits 2"); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name); + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + //Console.WriteLine(" Post GeomSetCategoryBits 2"); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } d.Quaternion quat2 = new d.Quaternion(); quat2.W = _orientation.W; @@ -1304,8 +1355,16 @@ Console.WriteLine("ZProcessTaints for " + Name); disableBodySoft(); } - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } if (IsPhysical) { @@ -1326,8 +1385,16 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_collidesWater) m_collisionFlags |= CollisionCategories.Water; - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + if (m_assetFailed) + { + d.GeomSetCategoryBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, 0); + } + else + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } if (IsPhysical) { @@ -1504,6 +1571,8 @@ Console.WriteLine("CreateGeom:"); // m_log.Debug(m_localID); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } #if SPAM @@ -2007,6 +2076,8 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } } @@ -2060,9 +2131,12 @@ Console.WriteLine(" JointCreateFixed"); m_collisionFlags &= ~CollisionCategories.Water; } - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } + if (m_assetFailed) + d.GeomSetCollideBits(prim_geom, 0); + else + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } /// /// Change prim in response to a shape taint. /// @@ -2110,6 +2184,8 @@ Console.WriteLine(" JointCreateFixed"); mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical); if (mesh == null) CheckMeshAsset(); + else + m_assetFailed = false; } CreateGeom(m_targetSpace, mesh); @@ -3278,7 +3354,7 @@ Console.WriteLine(" JointCreateFixed"); _pbs.SculptData = new byte[asset.Data.Length]; asset.Data.CopyTo(_pbs.SculptData, 0); - m_assetFailed = false; +// m_assetFailed = false; m_taintshape = true; _parent_scene.AddPhysicsActorTaint(this); } -- cgit v1.1 From 941717638991f093ae600cd0f1b1d646f0cd3c21 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 00:37:25 +0100 Subject: Make "show part" console commands print out information about each item the part contains --- .../World/Objects/Commands/ObjectCommandsModule.cs | 113 +++++++++++++++++---- 1 file changed, 93 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 6feba21..87241e1 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -141,7 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object uuid", "show object uuid [--full] ", "Show details of a scene object with the given UUID", - "The --full option will print out information on all the parts of the object.", + "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.", HandleShowObjectByUuid); m_console.Commands.AddCommand( @@ -151,6 +152,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object name [--full] [--regex] ", "Show details of scene objects with the given name.", "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.\n" + "If --regex is specified then the name is treatead as a regular expression.", HandleShowObjectByName); @@ -161,6 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show object pos [--full] to ", "Show details of scene objects within the given area.", "The --full option will print out information on all the parts of the object.\n" + + "For yet more detailed part information, use the \"show part\" commands.\n" + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + "If you don't care about the z component you can simply omit it.\n" + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" @@ -242,7 +245,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } - private void OutputSopsToConsole(Predicate searchPredicate) + private void OutputSopsToConsole(Predicate searchPredicate, bool showFull) { List sceneObjects = m_scene.GetSceneObjectGroups(); List parts = new List(); @@ -253,7 +256,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands foreach (SceneObjectPart part in parts) { - AddScenePartReport(sb, part); + AddScenePartReport(sb, part, showFull); sb.Append("\n"); } @@ -362,21 +365,27 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands OutputSogsToConsole(searchPredicate, showFull); } - private void HandleShowPartByUuid(string module, string[] cmd) + private void HandleShowPartByUuid(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmd.Length < 4) +// bool showFull = false; + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part uuid "); + m_console.OutputFormat("Usage: show part uuid [--full] "); return; } UUID objectUuid; - if (!UUID.TryParse(cmd[3], out objectUuid)) + if (!UUID.TryParse(mainParams[3], out objectUuid)) { - m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + m_console.OutputFormat("{0} is not a valid uuid", mainParams[3]); return; } @@ -389,7 +398,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddScenePartReport(sb, sop); + AddScenePartReport(sb, sop, true); m_console.OutputFormat(sb.ToString()); } @@ -399,13 +408,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - if (cmdparams.Length < 5) +// bool showFull = false; + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 5) { - m_console.OutputFormat("Usage: show part pos to "); + m_console.OutputFormat("Usage: show part pos [--full] to "); return; } - string rawConsoleStartVector = cmdparams[3]; + string rawConsoleStartVector = mainParams[3]; Vector3 startVector; if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) @@ -414,7 +429,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - string rawConsoleEndVector = cmdparams[5]; + string rawConsoleEndVector = mainParams[5]; Vector3 endVector; if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) @@ -423,7 +438,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return; } - OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector)); + OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); } private void HandleShowPartByName(string module, string[] cmdparams) @@ -431,14 +446,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; +// bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); + OptionSet options = new OptionSet(); +// options.Add("full", v => showFull = v != null ); + options.Add("regex", v => useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part name [--regex] "); + m_console.OutputFormat("Usage: show part name [--full] [--regex] "); return; } @@ -456,16 +474,26 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands searchPredicate = sop => sop.Name == name; } - OutputSopsToConsole(searchPredicate); + OutputSopsToConsole(searchPredicate, true); } + /// + /// Append a scene object report to an input StringBuilder + /// + /// + /// + /// + /// + /// If true then information on all parts of an object is appended. + /// If false then only summary information about an object is appended. + /// private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) { if (showFull) { foreach (SceneObjectPart sop in so.Parts) { - AddScenePartReport(sb, sop); + AddScenePartReport(sb, sop, false); sb.Append("\n"); } } @@ -491,7 +519,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sb.Append(cdl.ToString()); } - private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) + /// + /// Append a scene object part report to an input StringBuilder + /// + /// + /// + /// + /// + /// If true then information on each inventory item will be shown. + /// If false then only summary inventory information is shown. + /// + private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) { ConsoleDisplayList cdl = new ConsoleDisplayList(); cdl.AddRow("Name", sop.Name); @@ -504,11 +542,46 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); cdl.AddRow("Link number", sop.LinkNum); cdl.AddRow("Flags", sop.Flags); - cdl.AddRow("Items", sop.Inventory.Count); + + object itemsOutput; + if (showFull) + { + StringBuilder itemsSb = new StringBuilder("\n"); + itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); + } + else + { + itemsOutput = sop.Inventory.Count; + } + + + cdl.AddRow("Items", itemsOutput); return sb.Append(cdl.ToString()); } + private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) + { + ConsoleDisplayTable cdt = new ConsoleDisplayTable(); + cdt.Indent = 2; + + cdt.AddColumn("Name", 50); + cdt.AddColumn("Type", 12); + cdt.AddColumn("Running", 7); + cdt.AddColumn("Item UUID", 36); + cdt.AddColumn("Asset UUID", 36); + + foreach (TaskInventoryItem item in inv.GetInventoryItems()) + cdt.AddRow( + item.Name, + ((InventoryType)item.InvType).ToString(), + (InventoryType)item.InvType == InventoryType.LSL ? item.ScriptRunning.ToString() : "n/a", + item.ItemID.ToString(), + item.AssetID.ToString()); + + return sb.Append(cdt.ToString()); + } + private void HandleDeleteObject(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) -- cgit v1.1 From 0f70460a320da5606f3bdf316d5d25611fb0b3fb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 00:39:18 +0100 Subject: minor: comment out currently unused logger in DynamicTextureModule --- .../Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 1f340df..93a045e 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; -- cgit v1.1 From 28483150e2dcc123b632c89d0a08595b567af669 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 19 Oct 2012 01:25:30 +0100 Subject: [UNTESTED] core Ode: let broken mesh physical prims collide with land as the defaul basic box so they don't go off world. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a6c657f..5a1fdf9 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -344,7 +344,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -418,7 +418,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -851,6 +851,11 @@ namespace OpenSim.Region.Physics.OdePlugin private static Dictionary m_MeshToTriMeshMap = new Dictionary(); + public int BadAssetColideBits() + { + return (m_isphysical ? (int)CollisionCategories.Land : 0); + } + private void setMesh(OdeScene parent_scene, IMesh mesh) { // m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); @@ -1132,7 +1137,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (prm.m_assetFailed) { d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, 0); + d.GeomSetCollideBits(prm.prim_geom, prm.BadAssetColideBits()); } else { @@ -1186,7 +1191,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -1388,7 +1393,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); } else { @@ -2132,7 +2137,7 @@ Console.WriteLine(" JointCreateFixed"); } if (m_assetFailed) - d.GeomSetCollideBits(prim_geom, 0); + d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); else d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); -- cgit v1.1 From 32171708c3a29d2bb989b5638dc7536c6e4ecf3c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 10 Oct 2012 01:37:59 +0100 Subject: normalize quaternion.Slerp outputs Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index da2c069..27ef4c9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4584,6 +4584,7 @@ namespace OpenSim.Region.Framework.Scenes } Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations); + rot.Normalize(); UpdateRotation(rot); m_APIDIterations--; -- cgit v1.1 From ec044537d50b425178c4e081abcf325d28028480 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:15:34 +0100 Subject: ensuring that operand order in llGetLinkName is internally consistent --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ac74bf8..42ab39a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3828,7 +3828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // simplest case, this prims link number - if (m_host.LinkNum == linknum) + if (linknum == m_host.LinkNum) return m_host.Name; // Single prim -- cgit v1.1 From 597df51f918327f2ac46bc452a3288ec624e029f Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:16:42 +0100 Subject: the simplest case for llGetLinkName also applies to the LINK_THIS constant --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 42ab39a..e8d0bea 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3828,7 +3828,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // simplest case, this prims link number - if (linknum == m_host.LinkNum) + if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) return m_host.Name; // Single prim -- cgit v1.1 From 645e3171b41be4c5611bb43a9c14ec1d501ff8b9 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:18:46 +0100 Subject: since llGetLinkName has a "simplest case", it should be the first check made. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e8d0bea..e8bf5cf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3804,6 +3804,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); + // simplest case, this prims link number + if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) + return m_host.Name; + // parse for sitting avatare-names List nametable = new List(); World.ForEachRootScenePresence(delegate(ScenePresence presence) @@ -3827,10 +3831,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return nametable[totalprims - linknum]; } - // simplest case, this prims link number - if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) - return m_host.Name; - // Single prim if (m_host.LinkNum == 0) { -- cgit v1.1 From af5383e479e264f2c257ff802f258bd03550e4b4 Mon Sep 17 00:00:00 2001 From: SignpostMarv Date: Thu, 18 Oct 2012 10:22:41 +0100 Subject: altering documentation for llGetLinkName, as the current documentation is rather lengthy for a "summary". --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e8bf5cf..cf801ba 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3773,6 +3773,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// + /// Returns the name of the child prim or seated avatar matching the + /// specified link number. + /// + /// + /// The number of a link in the linkset or a link-related constant. + /// + /// + /// The name determined to match the specified link number. + /// + /// /// The rules governing the returned name are not simple. The only /// time a blank name is returned is if the target prim has a blank /// name. If no prim with the given link number can be found then @@ -3800,7 +3810,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Mentions NULL_KEY being returned /// http://wiki.secondlife.com/wiki/LlGetLinkName /// Mentions using the LINK_* constants, some of which are negative - /// + /// public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); -- cgit v1.1 From 6ba42e9e751477d5da3abf79eb1aaffc787dee30 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 02:54:13 +0100 Subject: Fix a few minor issues in ArchiveReadRequest logging. --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index a6923ef..ea806ec 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -290,7 +290,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (DearchiveContext sceneContext in sceneContexts.Values) { - m_log.InfoFormat("[ARCHIVER:] Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); + m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); if (!m_merge) { @@ -324,7 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver Util.FireAndForget(delegate(object o) { Thread.Sleep(15000); - m_log.Info("Starting scripts in scene objects"); + m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); foreach (DearchiveContext sceneContext in sceneContexts.Values) { -- cgit v1.1 From f7dcd3300837f3be42031448198f70cbbb29e467 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 03:12:58 +0100 Subject: minor: Increase attachment name field from 36 to 50 chars in "attachments show" report --- .../OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index d68aabc..68bcb4a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments sb.AppendFormat("Attachments for {0}\n", sp.Name); ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); -- cgit v1.1 From fd7a097849b8a405bdd62cfe6d4ee2bbf0a3961c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 12 Oct 2012 16:03:03 -0700 Subject: BulletSim: Update BSCharacter to use API2 interface. Add capsule shape to BSShapeCollection(). Remember last updated values so inter frame diffs can be computed. Parameterize avatarStandingFriction and reduce to 10 from 999. The latter high value made avatars very hard to push. Set CCD parameters for prims and characters of specified. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 182 +++++++++++++++------ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 12 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 66 +++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 21 ++- .../Physics/BulletSPlugin/BSShapeCollection.cs | 51 ++++-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 11 +- 6 files changed, 250 insertions(+), 93 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2e6b2da..7c2f856 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -41,8 +41,6 @@ public class BSCharacter : BSPhysObject // private bool _stopped; private OMV.Vector3 _size; - private OMV.Vector3 _scale; - private PrimitiveBaseShape _pbs; private bool _grabbed; private bool _selected; private OMV.Vector3 _position; @@ -67,6 +65,10 @@ public class BSCharacter : BSPhysObject private bool _kinematic; private float _buoyancy; + // The friction and velocity of the avatar is modified depending on whether walking or not. + private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar + private float _currentFriction; // the friction currently being used (changed by setVelocity). + private OMV.Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; @@ -84,13 +86,15 @@ public class BSCharacter : BSPhysObject _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; + _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); + _currentFriction = PhysicsScene.Params.avatarStandingFriction; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); _avatarDensity = PhysicsScene.Params.avatarDensity; - // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); ShapeData shapeData = new ShapeData(); @@ -99,24 +103,24 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Scale = _scale; + shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = PhysicsScene.Params.avatarFriction; + shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; shapeData.Restitution = PhysicsScene.Params.avatarRestitution; // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + + SetPhysicalProperties(); // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. // If not set at creation, the avatar will stop flying when created after crossing a region boundry. - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); - - BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); + ForceBuoyancy = _buoyancy; // This works here because CreateObject has already put the character into the physical world. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, @@ -131,10 +135,40 @@ public class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID); + PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); + PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); }); } + private void SetPhysicalProperties() + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + ZeroMotion(); + + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + + // Set the velocity and compute the proper friction + ForceVelocity = _velocity; + + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); + BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + + BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); + + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + } + public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); @@ -147,7 +181,7 @@ public class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - return new OMV.Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); + return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); } set { @@ -162,22 +196,25 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetObjectScaleMass(PhysicsScene.WorldID, LocalID, _scale, _mass, true); + BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); } } - public override PrimitiveBaseShape Shape { - set { _pbs = value; - } + public override OMV.Vector3 Scale { get; set; } + private PrimitiveBaseShape _pbs; + public override PrimitiveBaseShape Shape + { + set { _pbs = value;} } + public override bool Grabbed { - set { _grabbed = value; - } + set { _grabbed = value; } } public override bool Selected { - set { _selected = value; - } + set { _selected = value; } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } @@ -204,7 +241,7 @@ public class BSCharacter : BSPhysObject public override OMV.Vector3 Position { get { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); + // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); return _position; } set { @@ -214,7 +251,7 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -273,7 +310,7 @@ public class BSCharacter : BSPhysObject BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }; if (inTaintTime) sanityOperation(); @@ -284,11 +321,7 @@ public class BSCharacter : BSPhysObject return ret; } - public override float Mass { - get { - return _mass; - } - } + public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing public override float MassRaw { get {return _mass; } } @@ -301,15 +334,13 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce(PhysicsScene.WorldID, LocalID, _force); + BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); }); } } - public override int VehicleType { - get { return 0; } - set { return; } - } + // Avatars don't do vehicles + public override int VehicleType { get { return 0; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -328,15 +359,35 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + ForceVelocity = _velocity; }); } } public override OMV.Vector3 ForceVelocity { get { return _velocity; } set { + // Depending on whether the avatar is moving or not, change the friction + // to keep the avatar from slipping around + if (_velocity.Length() == 0) + { + if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) + { + _currentFriction = PhysicsScene.Params.avatarStandingFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } + else + { + if (_currentFriction == 999f) + { + _currentFriction = PhysicsScene.Params.avatarFriction; + BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + } + } _velocity = value; - BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity); + _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.Activate2(BSBody.ptr, true); } } public override OMV.Vector3 Torque { @@ -360,8 +411,8 @@ public class BSCharacter : BSPhysObject // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + // _position = BulletSimAPI.GetPosition2(BSBody.ptr); + BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); }); } } @@ -389,12 +440,18 @@ public class BSCharacter : BSPhysObject set { _isPhysical = value; } } + public override bool IsSolid { + get { return true; } + } + public override bool IsStatic { + get { return false; } + } public override bool Flying { get { return _flying; } set { _flying = value; // simulate flying by changing the effect of gravity - this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + Buoyancy = ComputeBuoyancyFromFlying(_flying); } } // Flying is implimented by changing the avatar's buoyancy. @@ -454,10 +511,19 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -518,27 +584,29 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { - _scale.X = PhysicsScene.Params.avatarCapsuleRadius; - _scale.Y = PhysicsScene.Params.avatarCapsuleRadius; + OMV.Vector3 newScale = OMV.Vector3.Zero; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // The 1.15 came from ODE but it seems to cause the avatar to float off the ground - // _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); - _scale.Z = (_size.Z) - (_scale.X + _scale.Y); + // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); + newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + Scale = newScale; } - // set _avatarVolume and _mass based on capsule size, _density and _scale + // set _avatarVolume and _mass based on capsule size, _density and Scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * _scale.X - * _scale.Y // the area of capsule cylinder - * _scale.Z // times height of capsule cylinder + * Scale.X + * Scale.Y // the area of capsule cylinder + * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * _scale.X - * Math.Min(_scale.X, _scale.Y) - * _scale.Y // plus the volume of the capsule end caps + * Scale.X + * Math.Min(Scale.X, Scale.Y) + * Scale.Y // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } @@ -555,6 +623,22 @@ public class BSCharacter : BSPhysObject // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. PositionSanityCheck2(true); + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; + + if (entprop.Velocity != LastEntityProperties.Velocity) + { + // Changes in the velocity are suppressed in avatars. + // That's just the way they are defined. + OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); + _velocity = avVel; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); + } + + // Tell the linkset about this + Linkset.UpdateProperties(this); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index cae599c..34dec26 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -69,6 +69,16 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // When the physical properties are updated, an EntityProperty holds the update values. + // Keep the current and last EntityProperties to enable computation of differences + // between the current update and the previous values. + public EntityProperties CurrentEntityProperties { get; set; } + public EntityProperties LastEntityProperties { get; set; } + + public abstract OMV.Vector3 Scale { get; set; } + public abstract bool IsSolid { get; } + public abstract bool IsStatic { get; } + // Stop all physical motion. public abstract void ZeroMotion(); @@ -89,6 +99,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } + public abstract float ForceBuoyancy { get; set; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 6a4365c..3421e30 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -172,11 +172,8 @@ public sealed class BSPrim : BSPhysObject } // Scale is what we set in the physics engine. It is different than 'size' in that // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. - public OMV.Vector3 Scale - { - get { return _scale; } - set { _scale = value; } - } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { _pbs = value; @@ -325,9 +322,9 @@ public sealed class BSPrim : BSPhysObject } // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone + // pushed to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -336,8 +333,8 @@ public sealed class BSPrim : BSPhysObject // just assign to "Position" because of potential call loops. BSScene.TaintCallback sanityOperation = delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + ForcePosition = _position; }; if (inTaintTime) sanityOperation(); @@ -547,13 +544,13 @@ public sealed class BSPrim : BSPhysObject } // An object is static (does not move) if selected or not physical - private bool IsStatic + public override bool IsStatic { get { return _isSelected || !IsPhysical; } } // An object is solid if it's not phantom and if it's not doing VolumeDetect - public bool IsSolid + public override bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } @@ -631,6 +628,12 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); // There is no inertia in a static object BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. @@ -662,6 +665,13 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // Set collision detection parameters + if (PhysicsScene.Params.ccdMotionThreshold > 0f) + { + BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + } + // Various values for simulation limits BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); @@ -812,14 +822,21 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { - // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + { + ForceBuoyancy = _buoyancy; }); } } + public override float ForceBuoyancy { + get { return _buoyancy; } + set { + _buoyancy = value; + // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + // Buoyancy is faked by changing the gravity applied to the object + float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); + BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + } + } // Used for MoveTo public override OMV.Vector3 PIDTarget { @@ -1269,8 +1286,8 @@ public sealed class BSPrim : BSPhysObject const float VELOCITY_TOLERANCE = 0.001f; const float POSITION_TOLERANCE = 0.05f; const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - + const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; + public override void UpdateProperties(EntityProperties entprop) { /* @@ -1326,11 +1343,13 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; + CurrentEntityProperties = entprop; - PositionSanityCheck2(true); - - Linkset.UpdateProperties(this); + PositionSanityCheck(true); DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); @@ -1348,6 +1367,9 @@ public sealed class BSPrim : BSPhysObject entprop.Acceleration, entprop.RotationalVelocity); } */ + // The linkset implimentation might want to know about this. + + Linkset.UpdateProperties(this); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2c3c481..5158011 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -256,10 +256,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle); + m_DebugLogCallbackHandle)); // Initialization to support the transition to a new API which puts most of the logic // into the C# code so it is easier to modify and add to. @@ -360,7 +360,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown(WorldID); + BulletSimAPI.Shutdown2(World.ptr); // Not logging any more PhysicsLogging.Close(); @@ -498,7 +498,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); @@ -1011,6 +1011,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), + new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", + 10f, + (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarStandingFriction; }, + (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, @@ -1246,7 +1251,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: + m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); + /* defaultLoc = val; // setting ALL also sets the default value List objectIDs = lIDs; string xparm = parm.ToLower(); @@ -1257,6 +1264,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); } }); + */ break; default: // setting only one localID @@ -1268,12 +1276,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, uint localID, float val) { + m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); + /* uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); + */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d189f1d..7d0f84a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -93,7 +93,7 @@ public class BSShapeCollection : IDisposable // sure the body is of the right type. // Return 'true' if either the body or the shape changed. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { @@ -351,19 +351,30 @@ public class BSShapeCollection : IDisposable // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. - // No locking here because this is done when we know physics is not simulating. - // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. + // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, + // shared geometries will be used. If the parameters of the existing shape are the same + // as this request, the shape is not rebuilt. + // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; + if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + // an avatar capsule is close to a native shape (it is not shared) + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + haveShape = true; + } // If the prim attributes are simple, this could be a simple Bullet native shape - if (nativeShapePossible + if (!haveShape + && pbs != null + && nativeShapePossible && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 && pbs.ProfileHollow == 0 @@ -406,7 +417,7 @@ public class BSShapeCollection : IDisposable // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes are best used in either case. - if (!haveShape) + if (!haveShape && pbs != null) { if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { @@ -425,8 +436,9 @@ public class BSShapeCollection : IDisposable return ret; } - // Creates a native shape and assignes it to prim.BSShape - private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, + // Creates a native shape and assignes it to prim.BSShape. + // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). + private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { @@ -440,10 +452,19 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); - // Native shapes are always built independently. - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } + else + { + // Native shapes are always built independently. + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; + } // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); @@ -456,7 +477,7 @@ public class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); @@ -526,7 +547,7 @@ public class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -694,7 +715,7 @@ public class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 276111c..30754a7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -223,6 +223,7 @@ public struct ShapeData KEY_SPHERE = 2, KEY_CONE = 3, KEY_CYLINDER = 4, + KEY_CAPSULE = 5, } } [StructLayout(LayoutKind.Sequential)] @@ -282,6 +283,7 @@ public struct ConfigurationParameters public float terrainHitFraction; public float terrainRestitution; public float avatarFriction; + public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; public float avatarCapsuleRadius; @@ -428,6 +430,7 @@ public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); +/* Remove the linkage to the old api methods [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, @@ -531,7 +534,7 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpBulletStatistics(); - +*/ // Log a debug message [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -562,7 +565,8 @@ public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray); + int maxUpdates, IntPtr updateArray, + DebugLogCallback logRoutine); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); @@ -604,6 +608,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) public static extern bool IsNativeShape2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From eaccfa6d99ac51b4963ae0fa457ff0d2b9ce65e7 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 14 Oct 2012 19:23:35 -0700 Subject: BulletSim: Fix small problems with last patch: BSScene.World properly initialized and setting of C++ parameters commented out. Comments and logging added. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 13 ++++--------- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7c2f856..7bc6b69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -146,7 +146,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); // Set the velocity and compute the proper friction diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 5158011..7998b08 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -261,10 +261,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), m_DebugLogCallbackHandle)); - // Initialization to support the transition to a new API which puts most of the logic - // into the C# code so it is easier to modify and add to. - World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID)); - Constraints = new BSConstraintCollection(World); TerrainManager = new BSTerrainManager(this); @@ -1251,10 +1247,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value break; - case PhysParameterEntry.APPLY_TO_ALL: - m_log.ErrorFormat("{0} Cannot change parameters of multiple objects. Someday it will be added.", LogHeader); - /* + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value + /* List objectIDs = lIDs; string xparm = parm.ToLower(); float xval = val; @@ -1276,15 +1271,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, uint localID, float val) { + /* Settings in the C++ code are not working at the moment. TODO: fix the settings. m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); - /* uint xlocalID = localID; string xparm = parm.ToLower(); float xval = val; TaintedObject("BSScene.TaintedUpdateParameter", delegate() { BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); }); - */ + */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7d0f84a..5a77e52 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -369,6 +369,7 @@ public class BSShapeCollection : IDisposable // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -460,7 +461,6 @@ public class BSShapeCollection : IDisposable } else { - // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; -- cgit v1.1 From fc33afddd360843d05f030750b7075315a526ae1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 15 Oct 2012 12:11:00 -0700 Subject: BulletSim: remove code in ShapeCollection that hinted at shape sharing. Add new function to ParameterDefn for calling BulletSimAPI to set values. Tweaking to BSCharacter parameter setting to try and have avatars stand. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 56 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 16 +-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 114 ++++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 110 +++++++------------- .../Physics/BulletSPlugin/BSTerrainManager.cs | 3 +- 5 files changed, 138 insertions(+), 161 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 7bc6b69..8e1171a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -114,17 +114,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); - + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + SetPhysicalProperties(); - - // Set the buoyancy for flying. This will be refactored when all the settings happen in C#. - // If not set at creation, the avatar will stop flying when created after crossing a region boundry. - ForceBuoyancy = _buoyancy; - - // This works here because CreateObject has already put the character into the physical world. - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); }); return; } @@ -146,27 +138,32 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; - - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION); + } + + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + + // Do this after the object has been added to the world + BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + (uint)CollisionFilterGroups.AvatarFilter, + (uint)CollisionFilterGroups.AvatarMask); } public override void RequestPhysicsterseUpdate() @@ -174,9 +171,7 @@ public class BSCharacter : BSPhysObject base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { - get { return false; } - } + public override bool Stopped { get { return false; } } public override OMV.Vector3 Size { get { @@ -185,18 +180,14 @@ public class BSCharacter : BSPhysObject } set { - // When an avatar's size is set, only the height is changed - // and that really only depends on the radius. + // When an avatar's size is set, only the height is changed. _size = value; ComputeAvatarScale(_size); - - // TODO: something has to be done with the avatar's vertical position - ComputeAvatarVolumeAndMass(); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale); + BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); @@ -300,7 +291,7 @@ public class BSCharacter : BSPhysObject // A version of the sanity check that also makes sure a new position value is // pushed back to the physics engine. This routine would be used by anyone // who is not already pushing the value. - private bool PositionSanityCheck2(bool inTaintTime) + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; if (PositionSanityCheck()) @@ -378,14 +369,16 @@ public class BSCharacter : BSPhysObject } else { - if (_currentFriction == 999f) + if (_currentFriction != PhysicsScene.Params.avatarFriction) { _currentFriction = PhysicsScene.Params.avatarFriction; BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); } } _velocity = value; + // Remember the set velocity so we can suppress the reduction by friction, ... _appliedVelocity = value; + BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); BulletSimAPI.Activate2(BSBody.ptr, true); } @@ -590,7 +583,8 @@ public class BSCharacter : BSPhysObject // The 1.15 came from ODE but it seems to cause the avatar to float off the ground // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); - newScale.Z = (_size.Z) - (Scale.X + Scale.Y); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); Scale = newScale; } @@ -621,7 +615,7 @@ public class BSCharacter : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck2(true); + PositionSanityCheck(true); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3421e30..b9e1908 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -333,7 +333,7 @@ public sealed class BSPrim : BSPhysObject // just assign to "Position" because of potential call loops. BSScene.TaintCallback sanityOperation = delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); ForcePosition = _position; }; if (inTaintTime) @@ -822,7 +822,7 @@ public sealed class BSPrim : BSPhysObject set { _buoyancy = value; PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() - { + { ForceBuoyancy = _buoyancy; }); } @@ -1286,8 +1286,8 @@ public sealed class BSPrim : BSPhysObject const float VELOCITY_TOLERANCE = 0.001f; const float POSITION_TOLERANCE = 0.05f; const float ACCELERATION_TOLERANCE = 0.01f; - const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - + const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; + public override void UpdateProperties(EntityProperties entprop) { /* @@ -1343,10 +1343,10 @@ public sealed class BSPrim : BSPhysObject _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; - _rotationalVelocity = entprop.RotationalVelocity; - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; + _rotationalVelocity = entprop.RotationalVelocity; + + // remember the current and last set values + LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; PositionSanityCheck(true); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7998b08..c6e8bc4 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -795,7 +795,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn { @@ -804,7 +805,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter + public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { name = n; @@ -812,7 +814,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; + onObject = null; + } + public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) + { + name = n; + desc = d; + defaultValue = v; + userParam = u; + getter = g; + setter = s; + onObject = o; } } @@ -834,6 +847,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // // The single letter parameters for the delegates are: // s = BSScene + // o = BSPhysObject // p = string parameter name // l = localID of referenced object // v = float value @@ -943,65 +957,74 @@ public class BSScene : PhysicsScene, IPhysicsParameters -9.80665f, (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].gravity; }, - (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, + (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, + (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainFriction; }, - (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 0.8f, (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainHitFraction; }, - (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), new ParameterDefn("TerrainRestitution", "Bouncyness" , 0f, (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainRestitution; }, - (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 0.2f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, @@ -1228,58 +1251,55 @@ public class BSScene : PhysicsScene, IPhysicsParameters return ret; } - // check to see if we are updating a parameter for a particular or all of the prims - protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val) - { - List operateOn; - lock (PhysObjects) operateOn = new List(PhysObjects.Keys); - UpdateParameterSet(operateOn, ref loc, parm, localID, val); - } - // update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) { + List objectIDs = new List(); switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value + // This will cause a call into the physical world if some operation is specified (SetOnObject). + objectIDs.Add(TERRAIN_ID); + TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - /* - List objectIDs = lIDs; - string xparm = parm.ToLower(); - float xval = val; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - foreach (uint lID in objectIDs) - { - BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval); - } - }); - */ + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID - TaintedUpdateParameter(parm, localID, val); + // setting only one localID + objectIDs.Add(localID); + TaintedUpdateParameter(parm, objectIDs, val); break; } } // schedule the actual updating of the paramter to when the phys engine is not busy - protected void TaintedUpdateParameter(string parm, uint localID, float val) + protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - /* Settings in the C++ code are not working at the moment. TODO: fix the settings. - m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader); - uint xlocalID = localID; - string xparm = parm.ToLower(); - float xval = val; - TaintedObject("BSScene.TaintedUpdateParameter", delegate() { - BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval); + float xval = val; + List xlIDs = lIDs; + string xparm = parm; + TaintedObject("BSScene.UpdateParameterSet", delegate() { + ParameterDefn thisParam; + if (TryGetParameter(xparm, out thisParam)) + { + if (thisParam.onObject != null) + { + foreach (uint lID in xlIDs) + { + BSPhysObject theObject = null; + PhysObjects.TryGetValue(lID, out theObject); + thisParam.onObject(this, theObject, xval); + } + } + } }); - */ } // Get parameter. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 5a77e52..bbfdac6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -51,7 +51,7 @@ public class BSShapeCollection : IDisposable } // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects + // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. private struct HullDesc { public IntPtr ptr; @@ -59,17 +59,9 @@ public class BSShapeCollection : IDisposable public DateTime lastReferenced; } - private struct BodyDesc - { - public IntPtr ptr; - // Bodies are only used once so reference count is always either one or zero - public int referenceCount; - public DateTime lastReferenced; - } - + // The sharable set of meshes and hulls. Indexed by their shape hash. private Dictionary Meshes = new Dictionary(); private Dictionary Hulls = new Dictionary(); - private Dictionary Bodies = new Dictionary(); public BSShapeCollection(BSScene physScene) { @@ -92,6 +84,10 @@ public class BSShapeCollection : IDisposable // First checks the shape and updates that if necessary then makes // sure the body is of the right type. // Return 'true' if either the body or the shape changed. + // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before + // the current shape or body is destroyed. This allows the caller to remove any + // higher level dependencies on the shape or body. Mostly used for LinkSets to + // remove the physical constraints before the body is destroyed. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, @@ -103,7 +99,8 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to requested shape + // Updates prim.BSShape with information/pointers to shape. + // CreateGeom returns 'true' of BSShape as changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. @@ -125,35 +122,19 @@ public class BSShapeCollection : IDisposable { lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); + BSScene.TaintCallback createOperation = delegate() { - bodyDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,body={1},ref={2}", body.ID, body, bodyDesc.referenceCount); - } - else - { - // New entry - bodyDesc.ptr = body.ptr; - bodyDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}", - body.ID, body, bodyDesc.referenceCount); - BSScene.TaintCallback createOperation = delegate() + if (!BulletSimAPI.IsInWorld2(body.ptr)) { - if (!BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", - body.ID, body); - } - }; - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); - } - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); + DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); + } + }; + if (inTaintTime) + createOperation(); + else + PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); } } @@ -166,43 +147,25 @@ public class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { - BodyDesc bodyDesc; - if (Bodies.TryGetValue(body.ID, out bodyDesc)) + BSScene.TaintCallback removeOperation = delegate() { - bodyDesc.referenceCount--; - bodyDesc.lastReferenced = System.DateTime.Now; - Bodies[body.ID] = bodyDesc; - DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); - - // If body is no longer being used, free it -- bodies can never be shared. - if (bodyDesc.referenceCount == 0) - { - Bodies.Remove(body.ID); - BSScene.TaintCallback removeOperation = delegate() - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", - body.ID, body.ptr.ToString("X"), inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }; - // If already in taint-time, do the operations now. Otherwise queue for later. - if (inTaintTime) - removeOperation(); - else - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); - } - } + DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", + body.ID, body.ptr.ToString("X"), inTaintTime); + // If the caller needs to know the old body is going away, pass the event up. + if (bodyCallback != null) bodyCallback(body); + + // It may have already been removed from the world in which case the next is a NOOP. + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + + // Zero any reference to the shape so it is not freed when the body is deleted. + BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); + }; + // If already in taint-time, do the operations now. Otherwise queue for later. + if (inTaintTime) + removeOperation(); else - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); - } + PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); } } @@ -271,7 +234,6 @@ public class BSShapeCollection : IDisposable } // Release the usage of a shape. - // The collisionObject is released since it is a copy of the real collision shape. public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index caf411e..9743d94 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -334,7 +334,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); + // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; }; -- cgit v1.1 From e87a179c893ef246dae8338e0f56c3fe20458fbc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 17 Oct 2012 08:30:10 -0700 Subject: BulletSim: change nonimal physics frame rate to 55 to give same numbers as ODE. Change character scaling to represent size of capsule (diameter rather than radius) Modify create capsule call to pass radius and height. Eliminate errors when calculating shape inertia (should have some type checking). --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 46 ++++++++++++---------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 26 ++++++------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 7 +++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 57 insertions(+), 52 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8e1171a..e7bff6e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -89,13 +89,15 @@ public class BSCharacter : BSPhysObject _appliedVelocity = OMV.Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); _currentFriction = PhysicsScene.Params.avatarStandingFriction; + _avatarDensity = PhysicsScene.Params.avatarDensity; // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. ComputeAvatarScale(_size); - _avatarDensity = PhysicsScene.Params.avatarDensity; // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); + DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", + LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); ShapeData shapeData = new ShapeData(); shapeData.ID = LocalID; @@ -103,6 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; + shapeData.Size = Scale; shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -114,8 +117,9 @@ public class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); - + // New body and shape into BSBody and BSShape + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + SetPhysicalProperties(); }); return; @@ -138,7 +142,7 @@ public class BSCharacter : BSPhysObject ZeroMotion(); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); ForcePosition = _position; @@ -151,13 +155,13 @@ public class BSCharacter : BSPhysObject { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - + } + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); // Do this after the object has been added to the world @@ -176,7 +180,7 @@ public class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - return new OMV.Vector3(Scale.X * 2, Scale.Y * 2, Scale.Z); + return _size; } set { @@ -184,11 +188,13 @@ public class BSCharacter : BSPhysObject _size = value; ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); + DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", + LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); }); @@ -578,13 +584,13 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + // Scale wants the diameter so mult radius by two + newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f; - // The 1.15 came from ODE but it seems to cause the avatar to float off the ground - // Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y); - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f); + // From the total height, add the capsule half spheres that are at each end + // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); + newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -593,14 +599,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder + * (Scale.X / 2f) + * (Scale.Y / 2f) // the area of capsule cylinder * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps + * (Scale.X / 2f) + * (Math.Min(Scale.X, Scale.Y) / 2f) + * (Scale.Y / 2f) // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 34dec26..b8ef338 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -141,18 +141,15 @@ public abstract class BSPhysObject : PhysicsActor // if someone has subscribed for collision events.... if (SubscribedEvents()) { CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - // DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - // LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); + DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", + LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); ret = true; } return ret; } - // Routine to send the collected collisions into the simulator. - // Also handles removal of this from the collection of objects with collisions if - // there are no collisions from this object. Mechanism is create one last - // collision event to make collision_end work. + // Send the collected collisions into the simulator. // Called at taint time from within the Step() function thus no locking problems // with CollisionCollection and ObjectsWithNoMoreCollisions. // Return 'true' if there were some actual collisions passed up @@ -161,10 +158,9 @@ public abstract class BSPhysObject : PhysicsActor bool ret = true; // throttle the collisions to the number of milliseconds specified in the subscription - int nowTime = PhysicsScene.SimulationNowTime; - if (nowTime >= NextCollisionOkTime) + if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) { - NextCollisionOkTime = nowTime + SubscribedEventsMs; + NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; // We are called if we previously had collisions. If there are no collisions // this time, send up one last empty event so OpenSim can sense collision end. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b9e1908..8013e68 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -48,10 +48,10 @@ public sealed class BSPrim : BSPhysObject private PrimitiveBaseShape _pbs; - // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. - // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. + // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. + // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer private bool _grabbed; private bool _isSelected; @@ -98,7 +98,7 @@ public sealed class BSPrim : BSPhysObject _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; - _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; @@ -166,7 +166,7 @@ public sealed class BSPrim : BSPhysObject // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct // scale and margins are set. CreateGeomAndObject(true); - // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, _scale, _mass, IsPhysical); + // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical); }); } } @@ -1224,7 +1224,8 @@ public sealed class BSPrim : BSPhysObject shape.Position = _position; shape.Rotation = _orientation; shape.Velocity = _velocity; - shape.Scale = _scale; + shape.Size = _size; + shape.Scale = Scale; shape.Mass = _isPhysical ? _mass : 0f; shape.Buoyancy = _buoyancy; shape.HullKey = 0; @@ -1234,7 +1235,6 @@ public sealed class BSPrim : BSPhysObject shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; - shape.Size = _size; } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c6e8bc4..ab2835c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -533,7 +533,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a kludge to get avatar movement updates. - // the simulator expects collisions for avatars even if there are have been no collisions. This updates + // The simulator expects collisions for avatars even if there are have been no collisions. This updates // avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) @@ -577,9 +577,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // We multiply by 45 to give a recognizable running rate (45 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 45; - // return timeStep * 1000 * 45; + // We multiply by 55 to give a recognizable running rate (55 or less). + return numSubSteps * m_fixedTimeStep * 1000 * 55; + // return timeStep * 1000 * 55; } // Something has collided @@ -795,7 +795,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); - delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); + delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn @@ -805,7 +805,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters public float defaultValue; // default value if not specified anywhere else public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter - public ParamSet setter; // set the current value for this parameter + public ParamSet setter; // set the current value for this parameter public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { @@ -814,7 +814,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; onObject = null; } public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) @@ -824,7 +824,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters defaultValue = v; userParam = u; getter = g; - setter = s; + setter = s; onObject = o; } } @@ -1266,13 +1266,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters objectIDs.Add(TERRAIN_ID); TaintedUpdateParameter(parm, objectIDs, val); break; - case PhysParameterEntry.APPLY_TO_ALL: + case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); + lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); TaintedUpdateParameter(parm, objectIDs, val); break; default: - // setting only one localID + // setting only one localID objectIDs.Add(localID); TaintedUpdateParameter(parm, objectIDs, val); break; @@ -1282,8 +1282,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters // schedule the actual updating of the paramter to when the phys engine is not busy protected void TaintedUpdateParameter(string parm, List lIDs, float val) { - float xval = val; - List xlIDs = lIDs; + float xval = val; + List xlIDs = lIDs; string xparm = parm; TaintedObject("BSScene.UpdateParameterSet", delegate() { ParameterDefn thisParam; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index bbfdac6..3d15eaa 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,7 +417,10 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { - newShape = new BulletShape(BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, shapeData), shapeType); + // The radius is scaled by 1/2 because we scale by the diameter. + newShape = new BulletShape( + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 0.5f, 1.0f, shapeData.Scale), + shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; } @@ -428,7 +431,7 @@ public class BSShapeCollection : IDisposable newShape.isNativeShape = true; } - // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked. + // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); prim.BSShape = newShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 30754a7..24d8db6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -608,7 +608,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData) public static extern bool IsNativeShape2(IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildCapsuleShape2(IntPtr world, ShapeData shapeData); +public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateCompoundShape2(IntPtr sim); -- cgit v1.1 From f422b9b388fe67c61e610c79efabd5e07512884b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 10:48:45 -0700 Subject: BulletSim: reorder avatar collision checking to eliminate double collision_end. Various tweekings to avatar shape/mass/inertia/etc. Remove change from avatar radius to diameter. But still the avatar sinks. Collision_end now happens immediately rather than at the next subscription time. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 33 +++++++++++----------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 ++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 30 +++++++++++--------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 8 +++--- .../Physics/BulletSPlugin/BSTerrainManager.cs | 1 + .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e7bff6e..fc4526b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -141,10 +141,6 @@ public class BSCharacter : BSPhysObject BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); ZeroMotion(); - - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); - ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; @@ -157,6 +153,9 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); + BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); @@ -583,14 +582,16 @@ public class BSCharacter : BSPhysObject private void ComputeAvatarScale(OMV.Vector3 size) { + // The 'size' given by the simulator is the mid-point of the avatar + // and X and Y are unspecified. + OMV.Vector3 newScale = OMV.Vector3.Zero; - // Scale wants the diameter so mult radius by two - newScale.X = PhysicsScene.Params.avatarCapsuleRadius * 2f; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius * 2f; + newScale.X = PhysicsScene.Params.avatarCapsuleRadius; + newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, add the capsule half spheres that are at each end - // newScale.Z = (size.Z) - Math.Min(newScale.X, newScale.Y); - newScale.Z = (size.Z * 2f); + // From the total height, remote the capsule half spheres that are at each end + newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); + // newScale.Z = (size.Z * 2f); Scale = newScale; } @@ -599,14 +600,14 @@ public class BSCharacter : BSPhysObject { _avatarVolume = (float)( Math.PI - * (Scale.X / 2f) - * (Scale.Y / 2f) // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder + * Scale.X + * Scale.Y // the area of capsule cylinder + * Scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * (Scale.X / 2f) - * (Math.Min(Scale.X, Scale.Y) / 2f) - * (Scale.Y / 2f) // plus the volume of the capsule end caps + * Scale.X + * Math.Min(Scale.X, Scale.Y) + * Scale.Y // plus the volume of the capsule end caps ); _mass = _avatarDensity * _avatarVolume; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index b8ef338..202052d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -156,9 +156,11 @@ public abstract class BSPhysObject : PhysicsActor public virtual bool SendCollisions() { bool ret = true; + // If the 'no collision' call, force it to happen right now so quick collision_end + bool force = CollisionCollection.Count == 0; // throttle the collisions to the number of milliseconds specified in the subscription - if (PhysicsScene.SimulationNowTime >= NextCollisionOkTime) + if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) { NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index ab2835c..6621d39 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -532,26 +532,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. This updates - // avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - bsp.SendCollisions(); - // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. if (ObjectsWithCollisions.Count > 0) { foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!m_avatars.Contains(bsp)) // don't call avatars twice - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } + if (!bsp.SendCollisions()) + { + // If the object is done colliding, see that it's removed from the colliding list + ObjectsWithNoMoreCollisions.Add(bsp); + } } + // This is a kludge to get avatar movement updates. + // The simulator expects collisions for avatars even if there are have been no collisions. + // The event updates avatar animations and stuff. + // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. + foreach (BSPhysObject bsp in m_avatars) + if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice + bsp.SendCollisions(); + // Objects that are done colliding are removed from the ObjectsWithCollisions list. // Not done above because it is inside an iteration of ObjectWithCollisions. if (ObjectsWithNoMoreCollisions.Count > 0) @@ -575,6 +575,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. + // Only enable this in a limited test world with few objects. + // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 3d15eaa..861ffe7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -417,10 +417,9 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { - // The radius is scaled by 1/2 because we scale by the diameter. newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 0.5f, 1.0f, shapeData.Scale), - shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), + shapeType); newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; } @@ -432,7 +431,8 @@ public class BSShapeCollection : IDisposable } // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - // DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape); + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 9743d94..4106534 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -114,6 +114,7 @@ public class BSTerrainManager BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); // Ground plane does not move BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); // Everything collides with the ground plane. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 24d8db6..5ffd591 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -390,7 +390,7 @@ public enum CollisionFilterGroups : uint VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, TerrainMask = BAllFilter & ~BStaticFilter, - GroundPlaneFilter = BAllFilter, + GroundPlaneFilter = BGroundPlaneFilter, GroundPlaneMask = BAllFilter }; -- cgit v1.1 From d94c4646ccf0703019dd5a7915afb43706a4de35 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 19 Oct 2012 15:43:31 -0700 Subject: BulletSim: add asset fetching so BulletSim works with new physics asset handling. Refactor some names to make them available for the asset tracking and fetching. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 3 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 10 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 96 +++---- .../Physics/BulletSPlugin/BSShapeCollection.cs | 296 +++++++++++++-------- 4 files changed, 240 insertions(+), 165 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fc4526b..623ac8f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -200,10 +200,9 @@ public class BSCharacter : BSPhysObject } } public override OMV.Vector3 Scale { get; set; } - private PrimitiveBaseShape _pbs; public override PrimitiveBaseShape Shape { - set { _pbs = value;} + set { BaseShape = value; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 202052d..ead6a08 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -47,6 +47,7 @@ public abstract class BSPhysObject : PhysicsActor TypeName = typeName; Linkset = new BSLinkset(PhysicsScene, this); + LastAssetBuildFailed = false; CollisionCollection = new CollisionEventUpdate(); SubscribedEventsMs = 0; @@ -69,6 +70,13 @@ public abstract class BSPhysObject : PhysicsActor // Reference to the physical shape (btCollisionShape) of this object public BulletShape BSShape; + // 'true' if the mesh's underlying asset failed to build. + // This will keep us from looping after the first time the build failed. + public bool LastAssetBuildFailed { get; set; } + + // The objects base shape information. Null if not a prim type shape. + public PrimitiveBaseShape BaseShape { get; protected set; } + // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences // between the current update and the previous values. @@ -101,6 +109,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract float ForceBuoyancy { get; set; } + public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } + #region Collisions // Requested number of milliseconds between collision events. Zero means disabled. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8013e68..aeeb4dd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -46,8 +46,6 @@ public sealed class BSPrim : BSPhysObject private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private PrimitiveBaseShape _pbs; - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user @@ -103,7 +101,7 @@ public sealed class BSPrim : BSPhysObject _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - _pbs = pbs; + BaseShape = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material @@ -160,14 +158,7 @@ public sealed class BSPrim : BSPhysObject get { return _size; } set { _size = value; - PhysicsScene.TaintedObject("BSPrim.setSize", delegate() - { - _mass = CalculateMass(); // changing size changes the mass - // Since _size changed, the mesh needs to be rebuilt. If rebuilt, all the correct - // scale and margins are set. - CreateGeomAndObject(true); - // DetailLog("{0},BSPrim.setSize,size={1},scale={2},mass={3},physical={4}", LocalID, _size, Scale, _mass, IsPhysical); - }); + ForceBodyShapeRebuild(false); } } // Scale is what we set in the physics engine. It is different than 'size' in that @@ -176,14 +167,23 @@ public sealed class BSPrim : BSPhysObject public override PrimitiveBaseShape Shape { set { - _pbs = value; - PhysicsScene.TaintedObject("BSPrim.setShape", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); + BaseShape = value; + ForceBodyShapeRebuild(false); } } + public override bool ForceBodyShapeRebuild(bool inTaintTime) + { + BSScene.TaintCallback rebuildOperation = delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + CreateGeomAndObject(true); + }; + if (inTaintTime) + rebuildOperation(); + else + PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); + return true; + } public override bool Grabbed { set { _grabbed = value; } @@ -924,19 +924,19 @@ public sealed class BSPrim : BSPhysObject float tmp; float returnMass = 0; - float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; float hollowVolume = hollowAmount * hollowAmount; - switch (_pbs.ProfileShape) + switch (BaseShape.ProfileShape) { case ProfileShape.Square: // default box - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -960,19 +960,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.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 *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); volume -= volume*tmp*tmp; if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -997,13 +997,13 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.78539816339f; // elipse base if (hollowAmount > 0.0) { - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1025,10 +1025,10 @@ public sealed class BSPrim : BSPhysObject } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1037,7 +1037,7 @@ public sealed class BSPrim : BSPhysObject // calculate the hollow volume by it's shape compared to the prim shape hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1061,7 +1061,7 @@ public sealed class BSPrim : BSPhysObject break; case ProfileShape.HalfCircle: - if (_pbs.PathCurve == (byte)Extrusion.Curve1) + if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.52359877559829887307710723054658f; } @@ -1069,7 +1069,7 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.EquilateralTriangle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) + if (BaseShape.PathCurve == (byte)Extrusion.Straight) { volume *= 0.32475953f; @@ -1077,7 +1077,7 @@ public sealed class BSPrim : BSPhysObject { // calculate the hollow volume by it's shape compared to the prim shape - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1102,11 +1102,11 @@ public sealed class BSPrim : BSPhysObject volume *= (1.0f - hollowVolume); } } - else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - _pbs.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1114,7 +1114,7 @@ public sealed class BSPrim : BSPhysObject hollowVolume *= hollowAmount; - switch (_pbs.HollowShape) + switch (BaseShape.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1154,26 +1154,26 @@ public sealed class BSPrim : BSPhysObject float profileBegin; float profileEnd; - if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) + if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) { - taperX1 = _pbs.PathScaleX * 0.01f; + taperX1 = BaseShape.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; taperX = 1.0f - taperX1; - taperY1 = _pbs.PathScaleY * 0.01f; + taperY1 = BaseShape.PathScaleY * 0.01f; if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; } else { - taperX = _pbs.PathTaperX * 0.01f; + taperX = BaseShape.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; taperX1 = 1.0f - taperX; - taperY = _pbs.PathTaperY * 0.01f; + taperY = BaseShape.PathTaperY * 0.01f; if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; @@ -1183,13 +1183,13 @@ public sealed class BSPrim : BSPhysObject 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; + pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)BaseShape.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; + profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; volume *= (profileEnd - profileBegin); returnMass = _density * volume; @@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs, + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 861ffe7..d3ba273 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable // Track another user of a body // We presume the caller has allocated the body. - // Bodies only have one user so the reference count is either 1 or 0. + // Bodies only have one user so the body is just put into the world if not already there. public void ReferenceBody(BulletBody body, bool inTaintTime) { lock (m_collectionActivityLock) @@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable BSScene.TaintCallback dereferenceOperation = delegate() { - switch (shape.type) + if (shape.ptr != IntPtr.Zero) { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: + if (shape.isNativeShape) + { // Native shapes are not tracked and are released immediately - if (shape.ptr != IntPtr.Zero & shape.isNativeShape) + DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", + BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); + if (shapeCallback != null) shapeCallback(shape); + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + else + { + switch (shape.type) { - DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + case ShapeData.PhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape, shapeCallback); + break; + case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + break; + default: + break; } - break; + } } }; if (inTaintTime) @@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { - BulletShape newShape; shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in @@ -415,27 +420,35 @@ public class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.BSShape, true, shapeCallback); + BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); + + // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + shapeData.ID, newShape, shapeData.Scale); + + prim.BSShape = newShape; + return true; + } + + private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, + ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) + { + BulletShape newShape; + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } else { newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; } + newShape.shapeKey = (System.UInt64)shapeKey; + newShape.isNativeShape = true; - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - shapeData.ID, newShape, shapeData.Scale); - - prim.BSShape = newShape; - return true; + return newShape; } // Builds a mesh shape in the physical world and updates prim.BSShape. @@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + // Take evasive action if the mesh was not constructed. + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { IMesh meshData = null; - IntPtr meshPtr; + IntPtr meshPtr = IntPtr.Zero; MeshDesc meshDesc; if (Meshes.TryGetValue(newMeshKey, out meshDesc)) { @@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable // Pass false for physicalness as this creates some sort of bounding box which we don't need meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indices.GetLength(0), indices, vertices.Count, verticesAsFloats); + } } BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; @@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); + newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); ReferenceShape(newShape); @@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) { - IntPtr hullPtr; + IntPtr hullPtr = IntPtr.Zero; HullDesc hullDesc; if (Hulls.TryGetValue(newHullKey, out hullDesc)) { @@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable // Build a new hull in the physical world // Pass false for physicalness as this creates some sort of bounding box which we don't need IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) + if (meshData != null) { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) { - verts[kk++] = ff; + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); } - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) + // setup and do convex hull conversion + m_hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = m_hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in m_hulls) { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in m_hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } } + // create the hull data structure in Bullet + hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); } BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); @@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable return ComputeShapeKey(shapeData, pbs, out lod); } + private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) + { + // If the shape was successfully created, nothing more to do + if (newShape.ptr != IntPtr.Zero) + return newShape; + + // The most common reason for failure is that an underlying asset is not available + + // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset + if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) + { + prim.LastAssetBuildFailed = true; + BSPhysObject xprim = prim; + Util.FireAndForget(delegate + { + RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; + if (assetProvider != null) + { + BSPhysObject yprim = xprim; // probably not necessary, but, just in case. + assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) + { + if (!yprim.BaseShape.SculptEntry) + return; + if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) + return; + + yprim.BaseShape.SculptData = new byte[asset.Data.Length]; + asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); + // This will cause the prim to see that the filler shape is not the right + // one and try again to build the object. + yprim.ForceBodyShapeRebuild(false); + + }); + } + }); + } + + // While we figure out the real problem, stick a simple native shape on the object. + BulletShape fillinShape = + BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); + + return fillinShape; + } + // Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. -- cgit v1.1 From e46987972525f7727eb4bd9d6eafa522937558cb Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 19 Oct 2012 23:45:55 +0100 Subject: Add "debug groups verbose " region console command This allows one to turn on super-verbose groups debug logging on and off whilst the region is in operation. --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index e669f4c..6b69de2 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -123,7 +123,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { if (m_groupsEnabled) + { scene.RegisterModuleInterface(this); + scene.AddCommand( + "debug", + this, + "debug groups verbose", + "debug groups verbose ", + "This setting turns on very verbose groups debugging", + HandleDebugGroupsVerbose); + } + } + + private void HandleDebugGroupsVerbose(object modules, string[] args) + { + if (args.Length < 4) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + bool verbose = false; + if (!bool.TryParse(args[3], out verbose)) + { + MainConsole.Instance.Output("Usage: debug groups verbose "); + return; + } + + m_debugEnabled = verbose; + + MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) -- cgit v1.1 From 6cca7136799c2f89c0511eb1831102e4b7a87fed Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 01:08:52 +0100 Subject: Fix build break from commit e469879 --- OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 6b69de2..b9b4413 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -152,7 +152,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_debugEnabled = verbose; - MainConsole.Instance.Output("{0} verbose logging set to {1}", Name, m_debugEnabled); + MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) -- cgit v1.1 From cd3762ca9f97052a6fe91a3eca491407cc6f039e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 01:26:04 +0100 Subject: Add experimental [Groups] MessageOnlineUsersOnly option for Flotsam XmlRpc groups. This retrieves and caches information from the PresenceService to only send messages to online users. This is reported to much improve performance for large groups where most users are offline. Cache is 20 seconds to balance requests against users not receiving messages until cache updates. This is an alternative to an approach where login/logout notification is sent directly from simulator to groups service. However, I'm not convinced that this PresenceService approach is actually better. Needs more thought. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 76 ++++++++++++++++++++-- 1 file changed, 69 insertions(+), 7 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 10b83e6..55bb7dc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using log4net; using Mono.Addins; @@ -36,6 +37,8 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -45,6 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); + private IPresenceService m_presenceService; private IMessageTransferModule m_msgTransferModule = null; @@ -54,6 +58,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_groupMessagingEnabled = false; private bool m_debugEnabled = true; + /// + /// If enabled, module only tries to send group IMs to online users by querying cached presence information. + /// + private bool m_messageOnlineAgentsOnly; + + /// + /// Cache for online users. + /// + /// + /// Group ID is key, presence information for online members is value. + /// Will only be non-null if m_messageOnlineAgentsOnly = true + /// We cache here so that group messages don't constantly have to re-request the online user list to avoid + /// attempted expensive sending of messages to offline users. + /// The tradeoff is that a user that comes online will not receive messages consistently from all other users + /// until caches have updated. + /// Therefore, we set the cache expiry to just 20 seconds. + /// + private ExpiringCache m_usersOnlineCache; + + private int m_usersOnlineCacheExpirySeconds = 20; + #region IRegionModuleBase Members public void Initialise(IConfigSource config) @@ -83,10 +108,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } + m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); + + if (m_messageOnlineAgentsOnly) + m_usersOnlineCache = new ExpiringCache(); + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); } - m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); + m_log.InfoFormat( + "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", + m_messageOnlineAgentsOnly, m_debugEnabled); } public void AddRegion(Scene scene) @@ -126,6 +158,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } + if (m_presenceService == null) + m_presenceService = scene.PresenceService; m_sceneList.Add(scene); @@ -207,12 +241,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); - - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", - groupID, groupMembers.Count); - + + if (m_messageOnlineAgentsOnly) + { + string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); + + // We cache in order not to overwhlem the presence service on large grids with many groups. This does + // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. + // (assuming this is the same across all grid simulators). + PresenceInfo[] onlineAgents; + if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) + { + onlineAgents = m_presenceService.GetAgents(t1); + m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); + } + + HashSet onlineAgentsUuidSet = new HashSet(); + Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); + + int allMembersCount = groupMembers.Count; + groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); + + // if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", + groupID, allMembersCount, groupMembers.Count()); + } + else + { + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", + groupID, groupMembers.Count); + } + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) -- cgit v1.1 From da2b23f18d232230ac4d967f8d3b256aebd4741e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:02:13 +0100 Subject: Improve efficiency of friends notification by only make one PresenceService call for all friends rather than one for each friend. However, large groups could still take a very long time since we still need to message each avatar on different simulators. --- .../CoreModules/Avatar/Friends/FriendsModule.cs | 53 ++++++++++------------ 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 11db18a..f1903c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Threading; using log4net; @@ -495,42 +496,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - foreach (FriendInfo friend in friendList) + List friendStringIds = friendList.ConvertAll(friend => friend.Friend); + List remoteFriendStringIds = new List(); + foreach (string friendStringId in friendStringIds) { - UUID friendID; - if (UUID.TryParse(friend.Friend, out friendID)) + UUID friendUuid; + if (UUID.TryParse(friendStringId, out friendUuid)) { - // Try local - if (LocalStatusNotification(userID, friendID, online)) + if (LocalStatusNotification(userID, friendUuid, online)) continue; - // The friend is not here [as root]. Let's forward. - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - if (friendSessions != null && friendSessions.Length > 0) - { - PresenceInfo friendSession = null; - foreach (PresenceInfo pinfo in friendSessions) - { - if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - { - friendSession = pinfo; - break; - } - } - - if (friendSession != null) - { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - } - } - - // Friend is not online. Ignore. + remoteFriendStringIds.Add(friendStringId); } else { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); + } + } + + // We do this regrouping so that we can efficiently send a single request rather than one for each + // friend in what may be a very large friends list. + PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); + + foreach (PresenceInfo friendSession in friendSessions) + { + // let's guard against sessions-gone-bad + if (friendSession.RegionID != UUID.Zero) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); } } } -- cgit v1.1 From 1937e5f1ec73dcfb9663ad4fe4b59f33a2210d64 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:13:00 +0100 Subject: Relocate temporary debug message for sending group IMs to online members only so that we can add ms it takes to send. This is chiefly to assess how long it may still take to send messages to such filtered groups. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 55bb7dc..1528330 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -241,6 +241,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); + int groupMembersCount = groupMembers.Count; if (m_messageOnlineAgentsOnly) { @@ -259,13 +260,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups HashSet onlineAgentsUuidSet = new HashSet(); Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); - int allMembersCount = groupMembers.Count; groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", - groupID, allMembersCount, groupMembers.Count()); +// m_log.DebugFormat( +// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", +// groupID, groupMembersCount, groupMembers.Count()); } else { @@ -275,6 +275,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups groupID, groupMembers.Count); } + int requestStartTick = Environment.TickCount; + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) @@ -316,6 +318,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ProcessMessageFromGroupSession(msg); } } + + // Temporary for assessing how long it still takes to send messages to large online groups. + if (m_messageOnlineAgentsOnly) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", + groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } #region SimGridEventHandlers -- cgit v1.1 From d55f72f3df9dad8cd9c96ec7abc2e71de486fe56 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:35:39 +0100 Subject: minor: Rename assetCache constructor param in UUIDGatherer to assetService which is what it is. --- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 28cd09f..e238d01 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -66,9 +66,9 @@ namespace OpenSim.Region.Framework.Scenes // /// // private bool m_waitingForObjectAsset; - public UuidGatherer(IAssetService assetCache) + public UuidGatherer(IAssetService assetService) { - m_assetService = assetCache; + m_assetService = assetService; } /// -- cgit v1.1 From d2b19f00dafe2c7c89c07b6a713fdd359cf9dcab Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:49:16 +0100 Subject: Fix minor issues from commit 28483150 Fix spelling of collide, change to more self-documenting property BadMeshAssetCollideBits, add method doc, change to private to reduce code analysis complexity --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 5a1fdf9..d11dff1 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -67,6 +67,17 @@ namespace OpenSim.Region.Physics.OdePlugin private int m_expectedCollisionContacts = 0; /// + /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. + /// + /// + /// The bad asset collide bits. + /// + private int BadMeshAssetCollideBits + { + get { return m_isphysical ? (int)CollisionCategories.Land : 0; } + } + + /// /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. /// public override bool IsPhysical @@ -344,11 +355,10 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); } @@ -418,7 +428,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -851,11 +861,6 @@ namespace OpenSim.Region.Physics.OdePlugin private static Dictionary m_MeshToTriMeshMap = new Dictionary(); - public int BadAssetColideBits() - { - return (m_isphysical ? (int)CollisionCategories.Land : 0); - } - private void setMesh(OdeScene parent_scene, IMesh mesh) { // m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh); @@ -1137,7 +1142,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (prm.m_assetFailed) { d.GeomSetCategoryBits(prm.prim_geom, 0); - d.GeomSetCollideBits(prm.prim_geom, prm.BadAssetColideBits()); + d.GeomSetCollideBits(prm.prim_geom, prm.BadMeshAssetCollideBits); } else { @@ -1191,7 +1196,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -1393,7 +1398,7 @@ Console.WriteLine("ZProcessTaints for " + Name); if (m_assetFailed) { d.GeomSetCategoryBits(prim_geom, 0); - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); } else { @@ -2137,7 +2142,7 @@ Console.WriteLine(" JointCreateFixed"); } if (m_assetFailed) - d.GeomSetCollideBits(prim_geom, BadAssetColideBits()); + d.GeomSetCollideBits(prim_geom, BadMeshAssetCollideBits); else d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); -- cgit v1.1 From 5bc07a15f508f4860de4defd328f23c4300b33c0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 20 Oct 2012 02:52:38 +0100 Subject: minor: remove unnecessary bit of method doc from OdePrim.BadMeshAssetCollideBits that monodevelop inserted automatically --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index d11dff1..2548648 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -69,9 +69,6 @@ namespace OpenSim.Region.Physics.OdePlugin /// /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. /// - /// - /// The bad asset collide bits. - /// private int BadMeshAssetCollideBits { get { return m_isphysical ? (int)CollisionCategories.Land : 0; } -- cgit v1.1 From 2aac113ac14f22509343ae82eb2eb4c3d7ad85b1 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Sat, 20 Oct 2012 04:28:58 -0400 Subject: Add CLICK_ACTION_ZOOM Add support for V2/3 CLICK_ACTION_ZOOM to llSetClickAction --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 60a7e14..62bd6b8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -612,6 +612,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CLICK_ACTION_OPEN = 4; public const int CLICK_ACTION_PLAY = 5; public const int CLICK_ACTION_OPEN_MEDIA = 6; + public const int CLICK_ACTION_ZOOM = 7; // constants for the llDetectedTouch* functions public const int TOUCH_INVALID_FACE = -1; -- cgit v1.1 From d7fa4cacb3227cb432a13d4f27076e408e8c114f Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Fri, 19 Oct 2012 21:02:54 +0200 Subject: Fix: invinite loading for Viewer3 : parcelinfo request of traffic-value (implementation of dwell-value in LandData + eventhandler, return always 0); source-formatting of LandData Signed-off-by: BlueWall --- .../Region/CoreModules/World/Land/LandManagementModule.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 8b7406d..95edf62 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -207,6 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; client.OnPreAgentUpdate += ClientOnPreAgentUpdate; + client.OnParcelDwellRequest += ClientOnParcelDwellRequest; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -798,6 +799,17 @@ namespace OpenSim.Region.CoreModules.World.Land } } + private void ClientOnParcelDwellRequest(int localID, IClientAPI client) + { + ILandObject parcel = null; + lock (m_landList) + { + if (!m_landList.TryGetValue(localID, out parcel)) + return; + } + client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); + } + #endregion #region Parcel Modification -- cgit v1.1