diff options
31 files changed, 910 insertions, 247 deletions
diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 82e2d6f..69d03a9 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs | |||
@@ -1402,19 +1402,18 @@ namespace OpenSim.Groups | |||
1402 | if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 1402 | if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
1403 | 1403 | ||
1404 | // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff | 1404 | // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff |
1405 | UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); | 1405 | string firstname = "Unknown", lastname = "Unknown"; |
1406 | string firstname, lastname; | 1406 | string name = m_UserManagement.GetUserName(dataForAgentID); |
1407 | if (account != null) | 1407 | if (!string.IsNullOrEmpty(name)) |
1408 | { | ||
1409 | firstname = account.FirstName; | ||
1410 | lastname = account.LastName; | ||
1411 | } | ||
1412 | else | ||
1413 | { | 1408 | { |
1414 | firstname = "Unknown"; | 1409 | string[] parts = name.Split(new char[] { ' ' }); |
1415 | lastname = "Unknown"; | 1410 | if (parts.Length >= 2) |
1411 | { | ||
1412 | firstname = parts[0]; | ||
1413 | lastname = parts[1]; | ||
1414 | } | ||
1416 | } | 1415 | } |
1417 | 1416 | ||
1418 | remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, | 1417 | remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, |
1419 | lastname, activeGroupPowers, activeGroupName, | 1418 | lastname, activeGroupPowers, activeGroupName, |
1420 | activeGroupTitle); | 1419 | activeGroupTitle); |
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 6c9e7c9..22cc79d 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -834,6 +834,8 @@ namespace OpenSim.Framework | |||
834 | /// </remarks> | 834 | /// </remarks> |
835 | event UpdateAgent OnAgentUpdate; | 835 | event UpdateAgent OnAgentUpdate; |
836 | 836 | ||
837 | event UpdateAgent OnAgentCameraUpdate; | ||
838 | |||
837 | event AgentRequestSit OnAgentRequestSit; | 839 | event AgentRequestSit OnAgentRequestSit; |
838 | event AgentSit OnAgentSit; | 840 | event AgentSit OnAgentSit; |
839 | event AvatarPickerRequest OnAvatarPickerRequest; | 841 | event AvatarPickerRequest OnAvatarPickerRequest; |
@@ -1489,7 +1491,7 @@ namespace OpenSim.Framework | |||
1489 | void SendChangeUserRights(UUID agentID, UUID friendID, int rights); | 1491 | void SendChangeUserRights(UUID agentID, UUID friendID, int rights); |
1490 | void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId); | 1492 | void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId); |
1491 | 1493 | ||
1492 | void StopFlying(ISceneEntity presence); | 1494 | void SendAgentTerseUpdate(ISceneEntity presence); |
1493 | 1495 | ||
1494 | void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data); | 1496 | void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data); |
1495 | } | 1497 | } |
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index 9629b6e..ffd5132 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs | |||
@@ -225,7 +225,13 @@ namespace OpenSim.Framework.Monitoring | |||
225 | public virtual string ToConsoleString() | 225 | public virtual string ToConsoleString() |
226 | { | 226 | { |
227 | StringBuilder sb = new StringBuilder(); | 227 | StringBuilder sb = new StringBuilder(); |
228 | sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName); | 228 | sb.AppendFormat( |
229 | "{0}.{1}.{2} : {3}{4}", | ||
230 | Category, | ||
231 | Container, | ||
232 | ShortName, | ||
233 | Value, | ||
234 | UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName)); | ||
229 | 235 | ||
230 | AppendMeasuresOfInterest(sb); | 236 | AppendMeasuresOfInterest(sb); |
231 | 237 | ||
@@ -253,6 +259,8 @@ namespace OpenSim.Framework.Monitoring | |||
253 | == MeasuresOfInterest.AverageChangeOverTime) | 259 | == MeasuresOfInterest.AverageChangeOverTime) |
254 | { | 260 | { |
255 | double totalChange = 0; | 261 | double totalChange = 0; |
262 | double lastChangeOverTime = 0; | ||
263 | double? penultimateSample = null; | ||
256 | double? lastSample = null; | 264 | double? lastSample = null; |
257 | 265 | ||
258 | lock (m_samples) | 266 | lock (m_samples) |
@@ -266,13 +274,25 @@ namespace OpenSim.Framework.Monitoring | |||
266 | if (lastSample != null) | 274 | if (lastSample != null) |
267 | totalChange += s - (double)lastSample; | 275 | totalChange += s - (double)lastSample; |
268 | 276 | ||
277 | penultimateSample = lastSample; | ||
269 | lastSample = s; | 278 | lastSample = s; |
270 | } | 279 | } |
271 | } | 280 | } |
272 | 281 | ||
282 | if (lastSample != null && penultimateSample != null) | ||
283 | lastChangeOverTime | ||
284 | = ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000); | ||
285 | |||
273 | int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; | 286 | int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; |
274 | 287 | ||
275 | sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); | 288 | double averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000); |
289 | |||
290 | sb.AppendFormat( | ||
291 | ", {0:0.##}{1}/s, {2:0.##}{3}/s", | ||
292 | lastChangeOverTime, | ||
293 | UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName), | ||
294 | averageChangeOverTime, | ||
295 | UnitName == null || UnitName == "" ? "" : string.Format(" {0}", UnitName)); | ||
276 | } | 296 | } |
277 | } | 297 | } |
278 | } | 298 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ac5e77e..0e20e38 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -96,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
96 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; | 96 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; |
97 | public event UpdateAgent OnPreAgentUpdate; | 97 | public event UpdateAgent OnPreAgentUpdate; |
98 | public event UpdateAgent OnAgentUpdate; | 98 | public event UpdateAgent OnAgentUpdate; |
99 | public event UpdateAgent OnAgentCameraUpdate; | ||
99 | public event AgentRequestSit OnAgentRequestSit; | 100 | public event AgentRequestSit OnAgentRequestSit; |
100 | public event AgentSit OnAgentSit; | 101 | public event AgentSit OnAgentSit; |
101 | public event AvatarPickerRequest OnAvatarPickerRequest; | 102 | public event AvatarPickerRequest OnAvatarPickerRequest; |
@@ -368,7 +369,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
368 | /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods | 369 | /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods |
369 | /// cannot retain a reference to it outside of that method. | 370 | /// cannot retain a reference to it outside of that method. |
370 | /// </remarks> | 371 | /// </remarks> |
371 | private AgentUpdateArgs m_lastAgentUpdateArgs; | 372 | private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs(); |
372 | 373 | ||
373 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); | 374 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); |
374 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers | 375 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers |
@@ -505,6 +506,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
505 | m_udpServer = udpServer; | 506 | m_udpServer = udpServer; |
506 | m_udpClient = udpClient; | 507 | m_udpClient = udpClient; |
507 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; | 508 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; |
509 | m_udpClient.HasUpdates += HandleHasUpdates; | ||
508 | m_udpClient.OnPacketStats += PopulateStats; | 510 | m_udpClient.OnPacketStats += PopulateStats; |
509 | 511 | ||
510 | m_prioritizer = new Prioritizer(m_scene); | 512 | m_prioritizer = new Prioritizer(m_scene); |
@@ -4164,8 +4166,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4164 | 4166 | ||
4165 | void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) | 4167 | void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) |
4166 | { | 4168 | { |
4169 | // if (!m_udpServer.IsRunningOutbound) | ||
4170 | // return; | ||
4171 | |||
4167 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) | 4172 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) |
4168 | { | 4173 | { |
4174 | // if (!m_udpServer.IsRunningOutbound) | ||
4175 | // return; | ||
4176 | |||
4169 | if (m_maxUpdates == 0 || m_LastQueueFill == 0) | 4177 | if (m_maxUpdates == 0 || m_LastQueueFill == 0) |
4170 | { | 4178 | { |
4171 | m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; | 4179 | m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; |
@@ -4191,6 +4199,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4191 | ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); | 4199 | ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); |
4192 | } | 4200 | } |
4193 | 4201 | ||
4202 | internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories) | ||
4203 | { | ||
4204 | bool hasUpdates = false; | ||
4205 | |||
4206 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) | ||
4207 | { | ||
4208 | if (m_entityUpdates.Count > 0) | ||
4209 | hasUpdates = true; | ||
4210 | else if (m_entityProps.Count > 0) | ||
4211 | hasUpdates = true; | ||
4212 | } | ||
4213 | |||
4214 | if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) | ||
4215 | { | ||
4216 | if (ImageManager.HasUpdates()) | ||
4217 | hasUpdates = true; | ||
4218 | } | ||
4219 | |||
4220 | return hasUpdates; | ||
4221 | } | ||
4222 | |||
4194 | public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) | 4223 | public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) |
4195 | { | 4224 | { |
4196 | AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); | 4225 | AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); |
@@ -5058,7 +5087,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5058 | SceneObjectPart part = (SceneObjectPart)entity; | 5087 | SceneObjectPart part = (SceneObjectPart)entity; |
5059 | 5088 | ||
5060 | attachPoint = part.ParentGroup.AttachmentPoint; | 5089 | attachPoint = part.ParentGroup.AttachmentPoint; |
5061 | 5090 | attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16)); | |
5062 | // m_log.DebugFormat( | 5091 | // m_log.DebugFormat( |
5063 | // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", | 5092 | // "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", |
5064 | // attachPoint, part.Name, part.LocalId, Name); | 5093 | // attachPoint, part.Name, part.LocalId, Name); |
@@ -5086,7 +5115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5086 | pos += 4; | 5115 | pos += 4; |
5087 | 5116 | ||
5088 | // Avatar/CollisionPlane | 5117 | // Avatar/CollisionPlane |
5089 | data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; | 5118 | data[pos++] = (byte) attachPoint; |
5090 | if (avatar) | 5119 | if (avatar) |
5091 | { | 5120 | { |
5092 | data[pos++] = 1; | 5121 | data[pos++] = 1; |
@@ -5618,83 +5647,137 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5618 | 5647 | ||
5619 | #region Packet Handlers | 5648 | #region Packet Handlers |
5620 | 5649 | ||
5650 | public int TotalAgentUpdates { get; set; } | ||
5651 | |||
5621 | #region Scene/Avatar | 5652 | #region Scene/Avatar |
5622 | 5653 | ||
5623 | private bool HandleAgentUpdate(IClientAPI sener, Packet packet) | 5654 | // Threshold for body rotation to be a significant agent update |
5655 | private const float QDELTA = 0.000001f; | ||
5656 | // Threshold for camera rotation to be a significant agent update | ||
5657 | private const float VDELTA = 0.01f; | ||
5658 | |||
5659 | /// <summary> | ||
5660 | /// This checks the update significance against the last update made. | ||
5661 | /// </summary> | ||
5662 | /// <remarks>Can only be called by one thread at a time</remarks> | ||
5663 | /// <returns></returns> | ||
5664 | /// <param name='x'></param> | ||
5665 | public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) | ||
5624 | { | 5666 | { |
5625 | if (OnAgentUpdate != null) | 5667 | return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x); |
5626 | { | 5668 | } |
5627 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; | ||
5628 | 5669 | ||
5629 | #region Packet Session and User Check | 5670 | /// <summary> |
5630 | if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) | 5671 | /// This checks the movement/state update significance against the last update made. |
5631 | { | 5672 | /// </summary> |
5632 | PacketPool.Instance.ReturnPacket(packet); | 5673 | /// <remarks>Can only be called by one thread at a time</remarks> |
5633 | return false; | 5674 | /// <returns></returns> |
5634 | } | 5675 | /// <param name='x'></param> |
5635 | #endregion | 5676 | private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) |
5677 | { | ||
5678 | float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); | ||
5679 | //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); | ||
5680 | |||
5681 | bool movementSignificant = | ||
5682 | (qdelta1 > QDELTA) // significant if body rotation above threshold | ||
5683 | // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack | ||
5684 | // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold | ||
5685 | || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed | ||
5686 | || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands | ||
5687 | || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed | ||
5688 | || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed | ||
5689 | || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed | ||
5690 | ; | ||
5691 | //if (movementSignificant) | ||
5692 | //{ | ||
5693 | //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}", | ||
5694 | // qdelta1, qdelta2); | ||
5695 | //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}", | ||
5696 | // x.ControlFlags, x.Flags, x.Far, x.State); | ||
5697 | //} | ||
5698 | return movementSignificant; | ||
5699 | } | ||
5636 | 5700 | ||
5637 | bool update = false; | 5701 | /// <summary> |
5638 | AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; | 5702 | /// This checks the camera update significance against the last update made. |
5639 | 5703 | /// </summary> | |
5640 | if (m_lastAgentUpdateArgs != null) | 5704 | /// <remarks>Can only be called by one thread at a time</remarks> |
5641 | { | 5705 | /// <returns></returns> |
5642 | // These should be ordered from most-likely to | 5706 | /// <param name='x'></param> |
5643 | // least likely to change. I've made an initial | 5707 | private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) |
5644 | // guess at that. | 5708 | { |
5645 | update = | 5709 | float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); |
5646 | ( | 5710 | float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); |
5647 | (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || | 5711 | float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); |
5648 | (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || | 5712 | float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); |
5649 | (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || | ||
5650 | (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || | ||
5651 | (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || | ||
5652 | (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || | ||
5653 | (x.ControlFlags != 0) || | ||
5654 | (x.Far != m_lastAgentUpdateArgs.Far) || | ||
5655 | (x.Flags != m_lastAgentUpdateArgs.Flags) || | ||
5656 | (x.State != m_lastAgentUpdateArgs.State) || | ||
5657 | (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || | ||
5658 | (x.SessionID != m_lastAgentUpdateArgs.SessionID) || | ||
5659 | (x.AgentID != m_lastAgentUpdateArgs.AgentID) | ||
5660 | ); | ||
5661 | } | ||
5662 | else | ||
5663 | { | ||
5664 | m_lastAgentUpdateArgs = new AgentUpdateArgs(); | ||
5665 | update = true; | ||
5666 | } | ||
5667 | 5713 | ||
5668 | if (update) | 5714 | bool cameraSignificant = |
5669 | { | 5715 | (vdelta1 > VDELTA) || |
5670 | // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); | 5716 | (vdelta2 > VDELTA) || |
5717 | (vdelta3 > VDELTA) || | ||
5718 | (vdelta4 > VDELTA) | ||
5719 | ; | ||
5671 | 5720 | ||
5672 | m_lastAgentUpdateArgs.AgentID = x.AgentID; | 5721 | //if (cameraSignificant) |
5673 | m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; | 5722 | //{ |
5674 | m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; | 5723 | //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}", |
5675 | m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; | 5724 | // x.CameraAtAxis, x.CameraCenter); |
5676 | m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; | 5725 | //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}", |
5677 | m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; | 5726 | // x.CameraLeftAxis, x.CameraUpAxis); |
5678 | m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; | 5727 | //} |
5679 | m_lastAgentUpdateArgs.Far = x.Far; | ||
5680 | m_lastAgentUpdateArgs.Flags = x.Flags; | ||
5681 | m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; | ||
5682 | m_lastAgentUpdateArgs.SessionID = x.SessionID; | ||
5683 | m_lastAgentUpdateArgs.State = x.State; | ||
5684 | 5728 | ||
5685 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; | 5729 | return cameraSignificant; |
5686 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; | 5730 | } |
5687 | 5731 | ||
5688 | if (handlerPreAgentUpdate != null) | 5732 | private bool HandleAgentUpdate(IClientAPI sener, Packet packet) |
5689 | OnPreAgentUpdate(this, m_lastAgentUpdateArgs); | 5733 | { |
5734 | // We got here, which means that something in agent update was significant | ||
5690 | 5735 | ||
5691 | if (handlerAgentUpdate != null) | 5736 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; |
5692 | OnAgentUpdate(this, m_lastAgentUpdateArgs); | 5737 | AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; |
5693 | 5738 | ||
5694 | handlerAgentUpdate = null; | 5739 | if (x.AgentID != AgentId || x.SessionID != SessionId) |
5695 | handlerPreAgentUpdate = null; | 5740 | return false; |
5696 | } | 5741 | |
5697 | } | 5742 | // Before we update the current m_thisAgentUpdateArgs, let's check this again |
5743 | // to see what exactly changed | ||
5744 | bool movement = CheckAgentMovementUpdateSignificance(x); | ||
5745 | bool camera = CheckAgentCameraUpdateSignificance(x); | ||
5746 | |||
5747 | m_thisAgentUpdateArgs.AgentID = x.AgentID; | ||
5748 | m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; | ||
5749 | m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; | ||
5750 | m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter; | ||
5751 | m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; | ||
5752 | m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; | ||
5753 | m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags; | ||
5754 | m_thisAgentUpdateArgs.Far = x.Far; | ||
5755 | m_thisAgentUpdateArgs.Flags = x.Flags; | ||
5756 | m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation; | ||
5757 | m_thisAgentUpdateArgs.SessionID = x.SessionID; | ||
5758 | m_thisAgentUpdateArgs.State = x.State; | ||
5759 | |||
5760 | UpdateAgent handlerAgentUpdate = OnAgentUpdate; | ||
5761 | UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; | ||
5762 | UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate; | ||
5763 | |||
5764 | // Was there a significant movement/state change? | ||
5765 | if (movement) | ||
5766 | { | ||
5767 | if (handlerPreAgentUpdate != null) | ||
5768 | OnPreAgentUpdate(this, m_thisAgentUpdateArgs); | ||
5769 | |||
5770 | if (handlerAgentUpdate != null) | ||
5771 | OnAgentUpdate(this, m_thisAgentUpdateArgs); | ||
5772 | } | ||
5773 | // Was there a significant camera(s) change? | ||
5774 | if (camera) | ||
5775 | if (handlerAgentCameraUpdate != null) | ||
5776 | handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs); | ||
5777 | |||
5778 | handlerAgentUpdate = null; | ||
5779 | handlerPreAgentUpdate = null; | ||
5780 | handlerAgentCameraUpdate = null; | ||
5698 | 5781 | ||
5699 | PacketPool.Instance.ReturnPacket(packet); | 5782 | PacketPool.Instance.ReturnPacket(packet); |
5700 | 5783 | ||
@@ -12813,7 +12896,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12813 | OutPacket(dialog, ThrottleOutPacketType.Task); | 12896 | OutPacket(dialog, ThrottleOutPacketType.Task); |
12814 | } | 12897 | } |
12815 | 12898 | ||
12816 | public void StopFlying(ISceneEntity p) | 12899 | public void SendAgentTerseUpdate(ISceneEntity p) |
12817 | { | 12900 | { |
12818 | if (p is ScenePresence) | 12901 | if (p is ScenePresence) |
12819 | { | 12902 | { |
@@ -12827,25 +12910,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12827 | 12910 | ||
12828 | Vector3 pos = presence.AbsolutePosition; | 12911 | Vector3 pos = presence.AbsolutePosition; |
12829 | 12912 | ||
12830 | if (presence.Appearance.AvatarHeight != 127.0f) | ||
12831 | pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f)); | ||
12832 | else | ||
12833 | pos += new Vector3(0f, 0f, (1.56f/6f)); | ||
12834 | |||
12835 | presence.AbsolutePosition = pos; | ||
12836 | |||
12837 | // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. | ||
12838 | // Collision plane below the avatar's position a 6th of the avatar's height is suitable. | ||
12839 | // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a | ||
12840 | // certain amount.. because the LLClient wouldn't land in that situation anyway. | ||
12841 | |||
12842 | // why are we still testing for this really old height value default??? | ||
12843 | if (presence.Appearance.AvatarHeight != 127.0f) | ||
12844 | presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f); | ||
12845 | else | ||
12846 | presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f)); | ||
12847 | |||
12848 | |||
12849 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = | 12913 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = |
12850 | CreateImprovedTerseBlock(p, false); | 12914 | CreateImprovedTerseBlock(p, false); |
12851 | 12915 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index 073c357..41dd4d1 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs | |||
@@ -206,6 +206,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | public bool HasUpdates() | ||
210 | { | ||
211 | J2KImage image = GetHighestPriorityImage(); | ||
212 | |||
213 | return image != null && image.IsDecoded; | ||
214 | } | ||
215 | |||
209 | public bool ProcessImageQueue(int packetsToSend) | 216 | public bool ProcessImageQueue(int packetsToSend) |
210 | { | 217 | { |
211 | int packetsSent = 0; | 218 | int packetsSent = 0; |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index f7ed14d..d52ad7e 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -31,6 +31,7 @@ using System.Net; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | using OpenMetaverse; | 35 | using OpenMetaverse; |
35 | using OpenMetaverse.Packets; | 36 | using OpenMetaverse.Packets; |
36 | 37 | ||
@@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
81 | /// hooked to put more data on the empty queue</summary> | 82 | /// hooked to put more data on the empty queue</summary> |
82 | public event QueueEmpty OnQueueEmpty; | 83 | public event QueueEmpty OnQueueEmpty; |
83 | 84 | ||
85 | public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates; | ||
86 | |||
84 | /// <summary>AgentID for this client</summary> | 87 | /// <summary>AgentID for this client</summary> |
85 | public readonly UUID AgentID; | 88 | public readonly UUID AgentID; |
86 | /// <summary>The remote address of the connected client</summary> | 89 | /// <summary>The remote address of the connected client</summary> |
@@ -645,15 +648,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
645 | /// <param name="categories">Throttle categories to fire the callback for</param> | 648 | /// <param name="categories">Throttle categories to fire the callback for</param> |
646 | private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) | 649 | private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) |
647 | { | 650 | { |
648 | if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) | 651 | // if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) |
652 | if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) | ||
649 | { | 653 | { |
654 | m_isQueueEmptyRunning = true; | ||
655 | |||
656 | int start = Environment.TickCount & Int32.MaxValue; | ||
657 | const int MIN_CALLBACK_MS = 30; | ||
658 | |||
659 | m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | ||
660 | if (m_nextOnQueueEmpty == 0) | ||
661 | m_nextOnQueueEmpty = 1; | ||
662 | |||
650 | // Use a value of 0 to signal that FireQueueEmpty is running | 663 | // Use a value of 0 to signal that FireQueueEmpty is running |
651 | m_nextOnQueueEmpty = 0; | 664 | // m_nextOnQueueEmpty = 0; |
652 | // Asynchronously run the callback | 665 | |
653 | Util.FireAndForget(FireQueueEmpty, categories); | 666 | m_categories = categories; |
667 | |||
668 | if (HasUpdates(m_categories)) | ||
669 | { | ||
670 | // Asynchronously run the callback | ||
671 | Util.FireAndForget(FireQueueEmpty, categories); | ||
672 | } | ||
673 | else | ||
674 | { | ||
675 | m_isQueueEmptyRunning = false; | ||
676 | } | ||
654 | } | 677 | } |
655 | } | 678 | } |
656 | 679 | ||
680 | private bool m_isQueueEmptyRunning; | ||
681 | private ThrottleOutPacketTypeFlags m_categories = 0; | ||
682 | |||
657 | /// <summary> | 683 | /// <summary> |
658 | /// Fires the OnQueueEmpty callback and sets the minimum time that it | 684 | /// Fires the OnQueueEmpty callback and sets the minimum time that it |
659 | /// can be called again | 685 | /// can be called again |
@@ -663,22 +689,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
663 | /// signature</param> | 689 | /// signature</param> |
664 | private void FireQueueEmpty(object o) | 690 | private void FireQueueEmpty(object o) |
665 | { | 691 | { |
666 | const int MIN_CALLBACK_MS = 30; | 692 | // int start = Environment.TickCount & Int32.MaxValue; |
693 | // const int MIN_CALLBACK_MS = 30; | ||
667 | 694 | ||
668 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | 695 | // if (m_udpServer.IsRunningOutbound) |
669 | QueueEmpty callback = OnQueueEmpty; | 696 | // { |
670 | 697 | ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; | |
671 | int start = Environment.TickCount & Int32.MaxValue; | 698 | QueueEmpty callback = OnQueueEmpty; |
672 | 699 | ||
673 | if (callback != null) | 700 | if (callback != null) |
674 | { | 701 | { |
675 | try { callback(categories); } | 702 | // if (m_udpServer.IsRunningOutbound) |
676 | catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } | 703 | // { |
677 | } | 704 | try { callback(categories); } |
705 | catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } | ||
706 | // } | ||
707 | } | ||
708 | // } | ||
709 | |||
710 | // m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | ||
711 | // if (m_nextOnQueueEmpty == 0) | ||
712 | // m_nextOnQueueEmpty = 1; | ||
713 | |||
714 | // } | ||
678 | 715 | ||
679 | m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; | 716 | m_isQueueEmptyRunning = false; |
680 | if (m_nextOnQueueEmpty == 0) | ||
681 | m_nextOnQueueEmpty = 1; | ||
682 | } | 717 | } |
683 | internal void ForceThrottleSetting(int throttle, int setting) | 718 | internal void ForceThrottleSetting(int throttle, int setting) |
684 | { | 719 | { |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b4ac021..7a4c6f4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -69,9 +69,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
69 | 69 | ||
70 | StatsManager.RegisterStat( | 70 | StatsManager.RegisterStat( |
71 | new Stat( | 71 | new Stat( |
72 | "IncomingUDPReceivesCount", | ||
73 | "Number of UDP receives performed", | ||
74 | "Number of UDP receives performed", | ||
75 | "", | ||
76 | "clientstack", | ||
77 | scene.Name, | ||
78 | StatType.Pull, | ||
79 | MeasuresOfInterest.AverageChangeOverTime, | ||
80 | stat => stat.Value = m_udpServer.UdpReceives, | ||
81 | StatVerbosity.Debug)); | ||
82 | |||
83 | StatsManager.RegisterStat( | ||
84 | new Stat( | ||
72 | "IncomingPacketsProcessedCount", | 85 | "IncomingPacketsProcessedCount", |
73 | "Number of inbound UDP packets processed", | 86 | "Number of inbound LL protocol packets processed", |
74 | "Number of inbound UDP packets processed", | 87 | "Number of inbound LL protocol packets processed", |
75 | "", | 88 | "", |
76 | "clientstack", | 89 | "clientstack", |
77 | scene.Name, | 90 | scene.Name, |
@@ -79,6 +92,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
79 | MeasuresOfInterest.AverageChangeOverTime, | 92 | MeasuresOfInterest.AverageChangeOverTime, |
80 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, | 93 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, |
81 | StatVerbosity.Debug)); | 94 | StatVerbosity.Debug)); |
95 | |||
96 | StatsManager.RegisterStat( | ||
97 | new Stat( | ||
98 | "OutgoingUDPSendsCount", | ||
99 | "Number of UDP sends performed", | ||
100 | "Number of UDP sends performed", | ||
101 | "", | ||
102 | "clientstack", | ||
103 | scene.Name, | ||
104 | StatType.Pull, | ||
105 | MeasuresOfInterest.AverageChangeOverTime, | ||
106 | stat => stat.Value = m_udpServer.UdpSends, | ||
107 | StatVerbosity.Debug)); | ||
108 | |||
109 | StatsManager.RegisterStat( | ||
110 | new Stat( | ||
111 | "AverageUDPProcessTime", | ||
112 | "Average number of milliseconds taken to process each incoming UDP packet in a sample.", | ||
113 | "This is for initial receive processing which is separate from the later client LL packet processing stage.", | ||
114 | "ms", | ||
115 | "clientstack", | ||
116 | scene.Name, | ||
117 | StatType.Pull, | ||
118 | MeasuresOfInterest.None, | ||
119 | stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, | ||
120 | // stat => | ||
121 | // stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7), | ||
122 | StatVerbosity.Debug)); | ||
82 | } | 123 | } |
83 | 124 | ||
84 | public bool HandlesRegion(Location x) | 125 | public bool HandlesRegion(Location x) |
@@ -185,6 +226,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
185 | protected bool m_sendPing; | 226 | protected bool m_sendPing; |
186 | 227 | ||
187 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); | 228 | private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); |
229 | |||
230 | /// <summary> | ||
231 | /// Event used to signal when queued packets are available for sending. | ||
232 | /// </summary> | ||
233 | /// <remarks> | ||
234 | /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. | ||
235 | /// Some data is sent immediately and not queued. That data would not trigger this event. | ||
236 | /// </remarks> | ||
237 | private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); | ||
238 | |||
188 | private Pool<IncomingPacket> m_incomingPacketPool; | 239 | private Pool<IncomingPacket> m_incomingPacketPool; |
189 | 240 | ||
190 | /// <summary> | 241 | /// <summary> |
@@ -462,6 +513,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
462 | m_scene = (Scene)scene; | 513 | m_scene = (Scene)scene; |
463 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 514 | m_location = new Location(m_scene.RegionInfo.RegionHandle); |
464 | 515 | ||
516 | StatsManager.RegisterStat( | ||
517 | new Stat( | ||
518 | "InboxPacketsCount", | ||
519 | "Number of LL protocol packets waiting for the second stage of processing after initial receive.", | ||
520 | "Number of LL protocol packets waiting for the second stage of processing after initial receive.", | ||
521 | "", | ||
522 | "clientstack", | ||
523 | scene.Name, | ||
524 | StatType.Pull, | ||
525 | MeasuresOfInterest.AverageChangeOverTime, | ||
526 | stat => stat.Value = packetInbox.Count, | ||
527 | StatVerbosity.Debug)); | ||
528 | |||
465 | // XXX: These stats are also pool stats but we register them separately since they are currently not | 529 | // XXX: These stats are also pool stats but we register them separately since they are currently not |
466 | // turned on and off by EnablePools()/DisablePools() | 530 | // turned on and off by EnablePools()/DisablePools() |
467 | StatsManager.RegisterStat( | 531 | StatsManager.RegisterStat( |
@@ -575,6 +639,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
575 | "debug lludp status", | 639 | "debug lludp status", |
576 | "Return status of LLUDP packet processing.", | 640 | "Return status of LLUDP packet processing.", |
577 | HandleStatusCommand); | 641 | HandleStatusCommand); |
642 | |||
643 | MainConsole.Instance.Commands.AddCommand( | ||
644 | "Debug", | ||
645 | false, | ||
646 | "debug lludp toggle agentupdate", | ||
647 | "debug lludp toggle agentupdate", | ||
648 | "Toggle whether agentupdate packets are processed or simply discarded.", | ||
649 | HandleAgentUpdateCommand); | ||
578 | } | 650 | } |
579 | 651 | ||
580 | private void HandlePacketCommand(string module, string[] args) | 652 | private void HandlePacketCommand(string module, string[] args) |
@@ -709,6 +781,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
709 | } | 781 | } |
710 | } | 782 | } |
711 | 783 | ||
784 | bool m_discardAgentUpdates; | ||
785 | |||
786 | private void HandleAgentUpdateCommand(string module, string[] args) | ||
787 | { | ||
788 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | ||
789 | return; | ||
790 | |||
791 | m_discardAgentUpdates = !m_discardAgentUpdates; | ||
792 | |||
793 | MainConsole.Instance.OutputFormat( | ||
794 | "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name); | ||
795 | } | ||
796 | |||
712 | private void HandleStatusCommand(string module, string[] args) | 797 | private void HandleStatusCommand(string module, string[] args) |
713 | { | 798 | { |
714 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 799 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) |
@@ -809,12 +894,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
809 | } | 894 | } |
810 | 895 | ||
811 | PacketPool.Instance.ReturnPacket(packet); | 896 | PacketPool.Instance.ReturnPacket(packet); |
812 | m_dataPresentEvent.Set(); | ||
813 | 897 | ||
898 | m_dataPresentEvent.Set(); | ||
814 | } | 899 | } |
815 | 900 | ||
816 | private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); | ||
817 | |||
818 | /// <summary> | 901 | /// <summary> |
819 | /// Start the process of sending a packet to the client. | 902 | /// Start the process of sending a packet to the client. |
820 | /// </summary> | 903 | /// </summary> |
@@ -1325,6 +1408,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1325 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); | 1408 | LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); |
1326 | #endregion BinaryStats | 1409 | #endregion BinaryStats |
1327 | 1410 | ||
1411 | if (packet.Type == PacketType.AgentUpdate) | ||
1412 | { | ||
1413 | if (m_discardAgentUpdates) | ||
1414 | return; | ||
1415 | |||
1416 | ((LLClientView)client).TotalAgentUpdates++; | ||
1417 | |||
1418 | AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; | ||
1419 | |||
1420 | LLClientView llClient = client as LLClientView; | ||
1421 | if (agentUpdate.AgentData.SessionID != client.SessionId | ||
1422 | || agentUpdate.AgentData.AgentID != client.AgentId | ||
1423 | || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) ) | ||
1424 | { | ||
1425 | PacketPool.Instance.ReturnPacket(packet); | ||
1426 | return; | ||
1427 | } | ||
1428 | } | ||
1429 | |||
1328 | #region Ping Check Handling | 1430 | #region Ping Check Handling |
1329 | 1431 | ||
1330 | if (packet.Type == PacketType.StartPingCheck) | 1432 | if (packet.Type == PacketType.StartPingCheck) |
@@ -1734,7 +1836,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1734 | // Action generic every round | 1836 | // Action generic every round |
1735 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; | 1837 | Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; |
1736 | 1838 | ||
1737 | // while (true) | ||
1738 | while (base.IsRunningOutbound) | 1839 | while (base.IsRunningOutbound) |
1739 | { | 1840 | { |
1740 | m_scene.ThreadAlive(2); | 1841 | m_scene.ThreadAlive(2); |
@@ -1798,6 +1899,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1798 | // token bucket could get more tokens | 1899 | // token bucket could get more tokens |
1799 | //if (!m_packetSent) | 1900 | //if (!m_packetSent) |
1800 | // Thread.Sleep((int)TickCountResolution); | 1901 | // Thread.Sleep((int)TickCountResolution); |
1902 | // | ||
1903 | // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with | ||
1904 | // modern mono it reduces CPU base load since there is no more continuous polling. | ||
1801 | m_dataPresentEvent.WaitOne(100); | 1905 | m_dataPresentEvent.WaitOne(100); |
1802 | 1906 | ||
1803 | Watchdog.UpdateThread(); | 1907 | Watchdog.UpdateThread(); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 7035e38..48c5b37 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs | |||
@@ -78,6 +78,36 @@ namespace OpenMetaverse | |||
78 | public bool IsRunningOutbound { get; private set; } | 78 | public bool IsRunningOutbound { get; private set; } |
79 | 79 | ||
80 | /// <summary> | 80 | /// <summary> |
81 | /// Number of UDP receives. | ||
82 | /// </summary> | ||
83 | public int UdpReceives { get; private set; } | ||
84 | |||
85 | /// <summary> | ||
86 | /// Number of UDP sends | ||
87 | /// </summary> | ||
88 | public int UdpSends { get; private set; } | ||
89 | |||
90 | /// <summary> | ||
91 | /// Number of receives over which to establish a receive time average. | ||
92 | /// </summary> | ||
93 | private readonly static int s_receiveTimeSamples = 500; | ||
94 | |||
95 | /// <summary> | ||
96 | /// Current number of samples taken to establish a receive time average. | ||
97 | /// </summary> | ||
98 | private int m_currentReceiveTimeSamples; | ||
99 | |||
100 | /// <summary> | ||
101 | /// Cumulative receive time for the sample so far. | ||
102 | /// </summary> | ||
103 | private int m_receiveTicksInCurrentSamplePeriod; | ||
104 | |||
105 | /// <summary> | ||
106 | /// The average time taken for each require receive in the last sample. | ||
107 | /// </summary> | ||
108 | public float AverageReceiveTicksForLastSamplePeriod { get; private set; } | ||
109 | |||
110 | /// <summary> | ||
81 | /// Default constructor | 111 | /// Default constructor |
82 | /// </summary> | 112 | /// </summary> |
83 | /// <param name="bindAddress">Local IP address to bind the server to</param> | 113 | /// <param name="bindAddress">Local IP address to bind the server to</param> |
@@ -111,6 +141,8 @@ namespace OpenMetaverse | |||
111 | 141 | ||
112 | if (!IsRunningInbound) | 142 | if (!IsRunningInbound) |
113 | { | 143 | { |
144 | m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop"); | ||
145 | |||
114 | const int SIO_UDP_CONNRESET = -1744830452; | 146 | const int SIO_UDP_CONNRESET = -1744830452; |
115 | 147 | ||
116 | IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); | 148 | IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); |
@@ -151,6 +183,8 @@ namespace OpenMetaverse | |||
151 | /// </summary> | 183 | /// </summary> |
152 | public void StartOutbound() | 184 | public void StartOutbound() |
153 | { | 185 | { |
186 | m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop"); | ||
187 | |||
154 | IsRunningOutbound = true; | 188 | IsRunningOutbound = true; |
155 | } | 189 | } |
156 | 190 | ||
@@ -158,10 +192,8 @@ namespace OpenMetaverse | |||
158 | { | 192 | { |
159 | if (IsRunningInbound) | 193 | if (IsRunningInbound) |
160 | { | 194 | { |
161 | // wait indefinitely for a writer lock. Once this is called, the .NET runtime | 195 | m_log.DebugFormat("[UDPBASE]: Stopping inbound UDP loop"); |
162 | // will deny any more reader locks, in effect blocking all other send/receive | 196 | |
163 | // threads. Once we have the lock, we set IsRunningInbound = false to inform the other | ||
164 | // threads that the socket is closed. | ||
165 | IsRunningInbound = false; | 197 | IsRunningInbound = false; |
166 | m_udpSocket.Close(); | 198 | m_udpSocket.Close(); |
167 | } | 199 | } |
@@ -169,6 +201,8 @@ namespace OpenMetaverse | |||
169 | 201 | ||
170 | public void StopOutbound() | 202 | public void StopOutbound() |
171 | { | 203 | { |
204 | m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop"); | ||
205 | |||
172 | IsRunningOutbound = false; | 206 | IsRunningOutbound = false; |
173 | } | 207 | } |
174 | 208 | ||
@@ -267,6 +301,8 @@ namespace OpenMetaverse | |||
267 | // to AsyncBeginReceive | 301 | // to AsyncBeginReceive |
268 | if (IsRunningInbound) | 302 | if (IsRunningInbound) |
269 | { | 303 | { |
304 | UdpReceives++; | ||
305 | |||
270 | // Asynchronous mode will start another receive before the | 306 | // Asynchronous mode will start another receive before the |
271 | // callback for this packet is even fired. Very parallel :-) | 307 | // callback for this packet is even fired. Very parallel :-) |
272 | if (m_asyncPacketHandling) | 308 | if (m_asyncPacketHandling) |
@@ -278,6 +314,8 @@ namespace OpenMetaverse | |||
278 | 314 | ||
279 | try | 315 | try |
280 | { | 316 | { |
317 | int startTick = Util.EnvironmentTickCount(); | ||
318 | |||
281 | // get the length of data actually read from the socket, store it with the | 319 | // get the length of data actually read from the socket, store it with the |
282 | // buffer | 320 | // buffer |
283 | buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); | 321 | buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); |
@@ -285,6 +323,23 @@ namespace OpenMetaverse | |||
285 | // call the abstract method PacketReceived(), passing the buffer that | 323 | // call the abstract method PacketReceived(), passing the buffer that |
286 | // has just been filled from the socket read. | 324 | // has just been filled from the socket read. |
287 | PacketReceived(buffer); | 325 | PacketReceived(buffer); |
326 | |||
327 | // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler) | ||
328 | // then a particular stat may be inaccurate due to a race condition. We won't worry about this | ||
329 | // since this should be rare and won't cause a runtime problem. | ||
330 | if (m_currentReceiveTimeSamples >= s_receiveTimeSamples) | ||
331 | { | ||
332 | AverageReceiveTicksForLastSamplePeriod | ||
333 | = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples; | ||
334 | |||
335 | m_receiveTicksInCurrentSamplePeriod = 0; | ||
336 | m_currentReceiveTimeSamples = 0; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick); | ||
341 | m_currentReceiveTimeSamples++; | ||
342 | } | ||
288 | } | 343 | } |
289 | catch (SocketException) { } | 344 | catch (SocketException) { } |
290 | catch (ObjectDisposedException) { } | 345 | catch (ObjectDisposedException) { } |
@@ -298,14 +353,13 @@ namespace OpenMetaverse | |||
298 | if (!m_asyncPacketHandling) | 353 | if (!m_asyncPacketHandling) |
299 | AsyncBeginReceive(); | 354 | AsyncBeginReceive(); |
300 | } | 355 | } |
301 | |||
302 | } | 356 | } |
303 | } | 357 | } |
304 | 358 | ||
305 | public void AsyncBeginSend(UDPPacketBuffer buf) | 359 | public void AsyncBeginSend(UDPPacketBuffer buf) |
306 | { | 360 | { |
307 | if (IsRunningOutbound) | 361 | // if (IsRunningOutbound) |
308 | { | 362 | // { |
309 | try | 363 | try |
310 | { | 364 | { |
311 | m_udpSocket.BeginSendTo( | 365 | m_udpSocket.BeginSendTo( |
@@ -319,7 +373,7 @@ namespace OpenMetaverse | |||
319 | } | 373 | } |
320 | catch (SocketException) { } | 374 | catch (SocketException) { } |
321 | catch (ObjectDisposedException) { } | 375 | catch (ObjectDisposedException) { } |
322 | } | 376 | // } |
323 | } | 377 | } |
324 | 378 | ||
325 | void AsyncEndSend(IAsyncResult result) | 379 | void AsyncEndSend(IAsyncResult result) |
@@ -328,6 +382,8 @@ namespace OpenMetaverse | |||
328 | { | 382 | { |
329 | // UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; | 383 | // UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; |
330 | m_udpSocket.EndSendTo(result); | 384 | m_udpSocket.EndSendTo(result); |
385 | |||
386 | UdpSends++; | ||
331 | } | 387 | } |
332 | catch (SocketException) { } | 388 | catch (SocketException) { } |
333 | catch (ObjectDisposedException) { } | 389 | catch (ObjectDisposedException) { } |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index e0c8ea6..8f9800f 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs | |||
@@ -185,8 +185,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) | 188 | public void UploadInventoryItem(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel) |
189 | { | 189 | { |
190 | if (type == AssetType.Link) | ||
191 | return; | ||
192 | |||
190 | string userAssetServer = string.Empty; | 193 | string userAssetServer = string.Empty; |
191 | if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) | 194 | if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) |
192 | { | 195 | { |
@@ -221,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
221 | { | 224 | { |
222 | UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); | 225 | UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); |
223 | 226 | ||
224 | UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0); | 227 | UploadInventoryItem(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0); |
225 | 228 | ||
226 | return newAssetID; | 229 | return newAssetID; |
227 | } | 230 | } |
@@ -232,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
232 | protected override void ExportAsset(UUID agentID, UUID assetID) | 235 | protected override void ExportAsset(UUID agentID, UUID assetID) |
233 | { | 236 | { |
234 | if (!assetID.Equals(UUID.Zero)) | 237 | if (!assetID.Equals(UUID.Zero)) |
235 | UploadInventoryItem(agentID, assetID, "", 0); | 238 | UploadInventoryItem(agentID, AssetType.Unknown, assetID, "", 0); |
236 | else | 239 | else |
237 | m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); | 240 | m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); |
238 | } | 241 | } |
@@ -348,7 +351,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
348 | InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); | 351 | InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); |
349 | InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); | 352 | InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); |
350 | 353 | ||
351 | inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); | 354 | List<InventoryFolderBase> keep = new List<InventoryFolderBase>(); |
355 | |||
356 | foreach (InventoryFolderBase f in content.Folders) | ||
357 | { | ||
358 | if (f.Name != "My Suitcase" && f.Name != "Current Outfit") | ||
359 | keep.Add(f); | ||
360 | } | ||
361 | |||
362 | inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); | ||
352 | } | 363 | } |
353 | } | 364 | } |
354 | } | 365 | } |
@@ -381,7 +392,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
381 | 392 | ||
382 | foreach (InventoryFolderBase f in content.Folders) | 393 | foreach (InventoryFolderBase f in content.Folders) |
383 | { | 394 | { |
384 | if (f.Name != "My Suitcase") | 395 | if (f.Name != "My Suitcase" && f.Name != "Current Outfit") |
385 | { | 396 | { |
386 | f.Name = f.Name + " (Unavailable)"; | 397 | f.Name = f.Name + " (Unavailable)"; |
387 | keep.Add(f); | 398 | keep.Add(f); |
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index a91adfa..53bd2e2 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -389,7 +389,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
389 | } | 389 | } |
390 | 390 | ||
391 | names[0] = "Unknown"; | 391 | names[0] = "Unknown"; |
392 | names[1] = "UserUMMTGUN7"; | 392 | names[1] = "UserUMMTGUN8"; |
393 | 393 | ||
394 | return false; | 394 | return false; |
395 | } | 395 | } |
@@ -601,7 +601,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
601 | // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or | 601 | // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or |
602 | // disappeared. | 602 | // disappeared. |
603 | user.FirstName = "Unknown"; | 603 | user.FirstName = "Unknown"; |
604 | user.LastName = "UserUMMAU3"; | 604 | user.LastName = "UserUMMAU4"; |
605 | } | 605 | } |
606 | 606 | ||
607 | AddUserInternal(user); | 607 | AddUserInternal(user); |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 1018b54..6e8eb91 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
743 | public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; | 743 | public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; |
744 | public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); | 744 | public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); |
745 | 745 | ||
746 | public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); | 746 | public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel); |
747 | 747 | ||
748 | public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; | 748 | public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; |
749 | 749 | ||
@@ -2172,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2172 | } | 2172 | } |
2173 | } | 2173 | } |
2174 | 2174 | ||
2175 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) | 2175 | public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel) |
2176 | { | 2176 | { |
2177 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; | 2177 | NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; |
2178 | if (handlerNewInventoryItemUpdateComplete != null) | 2178 | if (handlerNewInventoryItemUpdateComplete != null) |
@@ -2181,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2181 | { | 2181 | { |
2182 | try | 2182 | try |
2183 | { | 2183 | { |
2184 | d(agentID, AssetID, AssetName, userlevel); | 2184 | d(agentID, type, AssetID, AssetName, userlevel); |
2185 | } | 2185 | } |
2186 | catch (Exception e) | 2186 | catch (Exception e) |
2187 | { | 2187 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 70018c8..8f6073a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -139,7 +139,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
139 | { | 139 | { |
140 | userlevel = 1; | 140 | userlevel = 1; |
141 | } | 141 | } |
142 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); | 142 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); |
143 | 143 | ||
144 | return true; | 144 | return true; |
145 | } | 145 | } |
@@ -178,7 +178,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
178 | { | 178 | { |
179 | userlevel = 1; | 179 | userlevel = 1; |
180 | } | 180 | } |
181 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); | 181 | EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); |
182 | 182 | ||
183 | if (originalFolder != UUID.Zero) | 183 | if (originalFolder != UUID.Zero) |
184 | { | 184 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a..421cb08 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | |||
@@ -416,6 +416,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
416 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) | 416 | void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) |
417 | { | 417 | { |
418 | // TODO: don't create new blocks if recycling an old packet | 418 | // TODO: don't create new blocks if recycling an old packet |
419 | bool discardableEffects = true; | ||
419 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; | 420 | ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; |
420 | for (int i = 0; i < args.Count; i++) | 421 | for (int i = 0; i < args.Count; i++) |
421 | { | 422 | { |
@@ -427,17 +428,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
427 | effect.Type = args[i].Type; | 428 | effect.Type = args[i].Type; |
428 | effect.TypeData = args[i].TypeData; | 429 | effect.TypeData = args[i].TypeData; |
429 | effectBlockArray[i] = effect; | 430 | effectBlockArray[i] = effect; |
431 | |||
432 | if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam) | ||
433 | discardableEffects = false; | ||
434 | |||
435 | //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type); | ||
430 | } | 436 | } |
431 | 437 | ||
432 | ForEachClient( | 438 | ForEachScenePresence(sp => |
433 | delegate(IClientAPI client) | ||
434 | { | 439 | { |
435 | if (client.AgentId != remoteClient.AgentId) | 440 | if (sp.ControllingClient.AgentId != remoteClient.AgentId) |
436 | client.SendViewerEffect(effectBlockArray); | 441 | { |
437 | } | 442 | if (!discardableEffects || |
438 | ); | 443 | (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp))) |
444 | { | ||
445 | //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID); | ||
446 | sp.ControllingClient.SendViewerEffect(effectBlockArray); | ||
447 | } | ||
448 | //else | ||
449 | // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID); | ||
450 | } | ||
451 | }); | ||
439 | } | 452 | } |
440 | 453 | ||
454 | private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) | ||
455 | { | ||
456 | return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; | ||
457 | } | ||
458 | |||
441 | private class DescendentsRequestData | 459 | private class DescendentsRequestData |
442 | { | 460 | { |
443 | public IClientAPI RemoteClient; | 461 | public IClientAPI RemoteClient; |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 6e4ac98..1225c2e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -142,6 +142,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
142 | private Vector3 m_lastVelocity; | 142 | private Vector3 m_lastVelocity; |
143 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); | 143 | private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); |
144 | 144 | ||
145 | private bool m_followCamAuto = false; | ||
146 | |||
145 | 147 | ||
146 | private Vector3? m_forceToApply; | 148 | private Vector3? m_forceToApply; |
147 | private int m_userFlags; | 149 | private int m_userFlags; |
@@ -874,6 +876,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
874 | { | 876 | { |
875 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; | 877 | ControllingClient.OnCompleteMovementToRegion += CompleteMovement; |
876 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; | 878 | ControllingClient.OnAgentUpdate += HandleAgentUpdate; |
879 | ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate; | ||
877 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; | 880 | ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; |
878 | ControllingClient.OnAgentSit += HandleAgentSit; | 881 | ControllingClient.OnAgentSit += HandleAgentSit; |
879 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; | 882 | ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; |
@@ -1306,7 +1309,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
1306 | 1309 | ||
1307 | public void StopFlying() | 1310 | public void StopFlying() |
1308 | { | 1311 | { |
1309 | ControllingClient.StopFlying(this); | 1312 | Vector3 pos = AbsolutePosition; |
1313 | if (Appearance.AvatarHeight != 127.0f) | ||
1314 | pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); | ||
1315 | else | ||
1316 | pos += new Vector3(0f, 0f, (1.56f / 6f)); | ||
1317 | |||
1318 | AbsolutePosition = pos; | ||
1319 | |||
1320 | // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. | ||
1321 | // Collision plane below the avatar's position a 6th of the avatar's height is suitable. | ||
1322 | // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a | ||
1323 | // certain amount.. because the LLClient wouldn't land in that situation anyway. | ||
1324 | |||
1325 | // why are we still testing for this really old height value default??? | ||
1326 | if (Appearance.AvatarHeight != 127.0f) | ||
1327 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f); | ||
1328 | else | ||
1329 | CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); | ||
1330 | |||
1331 | ControllingClient.SendAgentTerseUpdate(this); | ||
1310 | } | 1332 | } |
1311 | 1333 | ||
1312 | /// <summary> | 1334 | /// <summary> |
@@ -1662,9 +1684,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1662 | /// </summary> | 1684 | /// </summary> |
1663 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | 1685 | public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) |
1664 | { | 1686 | { |
1665 | // m_log.DebugFormat( | 1687 | //m_log.DebugFormat( |
1666 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", | 1688 | // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", |
1667 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | 1689 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); |
1668 | 1690 | ||
1669 | if (IsChildAgent) | 1691 | if (IsChildAgent) |
1670 | { | 1692 | { |
@@ -1672,10 +1694,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1672 | return; | 1694 | return; |
1673 | } | 1695 | } |
1674 | 1696 | ||
1675 | ++m_movementUpdateCount; | ||
1676 | if (m_movementUpdateCount < 1) | ||
1677 | m_movementUpdateCount = 1; | ||
1678 | |||
1679 | #region Sanity Checking | 1697 | #region Sanity Checking |
1680 | 1698 | ||
1681 | // This is irritating. Really. | 1699 | // This is irritating. Really. |
@@ -1706,21 +1724,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1706 | 1724 | ||
1707 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | 1725 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; |
1708 | 1726 | ||
1709 | // Camera location in world. We'll need to raytrace | ||
1710 | // from this location from time to time. | ||
1711 | CameraPosition = agentData.CameraCenter; | ||
1712 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
1713 | { | ||
1714 | ReprioritizeUpdates(); | ||
1715 | m_lastCameraPosition = CameraPosition; | ||
1716 | } | ||
1717 | |||
1718 | // Use these three vectors to figure out what the agent is looking at | ||
1719 | // Convert it to a Matrix and/or Quaternion | ||
1720 | CameraAtAxis = agentData.CameraAtAxis; | ||
1721 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
1722 | CameraUpAxis = agentData.CameraUpAxis; | ||
1723 | |||
1724 | // The Agent's Draw distance setting | 1727 | // The Agent's Draw distance setting |
1725 | // When we get to the point of re-computing neighbors everytime this | 1728 | // When we get to the point of re-computing neighbors everytime this |
1726 | // changes, then start using the agent's drawdistance rather than the | 1729 | // changes, then start using the agent's drawdistance rather than the |
@@ -2005,10 +2008,79 @@ namespace OpenSim.Region.Framework.Scenes | |||
2005 | SendControlsToScripts(flagsForScripts); | 2008 | SendControlsToScripts(flagsForScripts); |
2006 | } | 2009 | } |
2007 | 2010 | ||
2011 | // We need to send this back to the client in order to see the edit beams | ||
2012 | if ((State & (uint)AgentState.Editing) != 0) | ||
2013 | ControllingClient.SendAgentTerseUpdate(this); | ||
2014 | |||
2008 | m_scene.EventManager.TriggerOnClientMovement(this); | 2015 | m_scene.EventManager.TriggerOnClientMovement(this); |
2009 | TriggerScenePresenceUpdated(); | ||
2010 | } | 2016 | } |
2011 | 2017 | ||
2018 | |||
2019 | /// <summary> | ||
2020 | /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. | ||
2021 | /// </summary> | ||
2022 | private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) | ||
2023 | { | ||
2024 | //m_log.DebugFormat( | ||
2025 | // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}", | ||
2026 | // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); | ||
2027 | |||
2028 | if (IsChildAgent) | ||
2029 | { | ||
2030 | // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); | ||
2031 | return; | ||
2032 | } | ||
2033 | |||
2034 | ++m_movementUpdateCount; | ||
2035 | if (m_movementUpdateCount < 1) | ||
2036 | m_movementUpdateCount = 1; | ||
2037 | |||
2038 | |||
2039 | AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; | ||
2040 | |||
2041 | // Camera location in world. We'll need to raytrace | ||
2042 | // from this location from time to time. | ||
2043 | CameraPosition = agentData.CameraCenter; | ||
2044 | if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance) | ||
2045 | { | ||
2046 | ReprioritizeUpdates(); | ||
2047 | m_lastCameraPosition = CameraPosition; | ||
2048 | } | ||
2049 | |||
2050 | // Use these three vectors to figure out what the agent is looking at | ||
2051 | // Convert it to a Matrix and/or Quaternion | ||
2052 | CameraAtAxis = agentData.CameraAtAxis; | ||
2053 | CameraLeftAxis = agentData.CameraLeftAxis; | ||
2054 | CameraUpAxis = agentData.CameraUpAxis; | ||
2055 | |||
2056 | // The Agent's Draw distance setting | ||
2057 | // When we get to the point of re-computing neighbors everytime this | ||
2058 | // changes, then start using the agent's drawdistance rather than the | ||
2059 | // region's draw distance. | ||
2060 | // DrawDistance = agentData.Far; | ||
2061 | DrawDistance = Scene.DefaultDrawDistance; | ||
2062 | |||
2063 | // Check if Client has camera in 'follow cam' or 'build' mode. | ||
2064 | Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); | ||
2065 | |||
2066 | m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) | ||
2067 | && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; | ||
2068 | |||
2069 | |||
2070 | //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); | ||
2071 | // Raycast from the avatar's head to the camera to see if there's anything blocking the view | ||
2072 | if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) | ||
2073 | { | ||
2074 | if (m_followCamAuto) | ||
2075 | { | ||
2076 | Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; | ||
2077 | m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); | ||
2078 | } | ||
2079 | } | ||
2080 | |||
2081 | TriggerScenePresenceUpdated(); | ||
2082 | } | ||
2083 | |||
2012 | /// <summary> | 2084 | /// <summary> |
2013 | /// Calculate an update to move the presence to the set target. | 2085 | /// Calculate an update to move the presence to the set target. |
2014 | /// </summary> | 2086 | /// </summary> |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index b28d96b..a96c8b4 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -688,6 +688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
688 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; | 688 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; |
689 | public event UpdateAgent OnPreAgentUpdate; | 689 | public event UpdateAgent OnPreAgentUpdate; |
690 | public event UpdateAgent OnAgentUpdate; | 690 | public event UpdateAgent OnAgentUpdate; |
691 | public event UpdateAgent OnAgentCameraUpdate; | ||
691 | public event AgentRequestSit OnAgentRequestSit; | 692 | public event AgentRequestSit OnAgentRequestSit; |
692 | public event AgentSit OnAgentSit; | 693 | public event AgentSit OnAgentSit; |
693 | public event AvatarPickerRequest OnAvatarPickerRequest; | 694 | public event AvatarPickerRequest OnAvatarPickerRequest; |
@@ -1687,7 +1688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | |||
1687 | { | 1688 | { |
1688 | } | 1689 | } |
1689 | 1690 | ||
1690 | public void StopFlying(ISceneEntity presence) | 1691 | public void SendAgentTerseUpdate(ISceneEntity presence) |
1691 | { | 1692 | { |
1692 | } | 1693 | } |
1693 | 1694 | ||
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 79509ab..15dea17 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs | |||
@@ -611,7 +611,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden | |||
611 | // | 611 | // |
612 | if (showParams.Length <= 4) | 612 | if (showParams.Length <= 4) |
613 | { | 613 | { |
614 | m_log.InfoFormat("[INFO]: {0,-12} {1,20} {2,6} {3,11} {4, 10}", "Region", "Name", "Root", "Time", "Reqs/min"); | 614 | m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates"); |
615 | foreach (Scene scene in m_scenes.Values) | 615 | foreach (Scene scene in m_scenes.Values) |
616 | { | 616 | { |
617 | scene.ForEachClient( | 617 | scene.ForEachClient( |
@@ -624,9 +624,15 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden | |||
624 | int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); | 624 | int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); |
625 | avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); | 625 | avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); |
626 | 626 | ||
627 | m_log.InfoFormat("[INFO]: {0,-12} {1,20} {2,4} {3,9}min {4,10}", | 627 | m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", |
628 | scene.RegionInfo.RegionName, llClient.Name, | 628 | scene.RegionInfo.RegionName, llClient.Name, |
629 | (llClient.SceneAgent.IsChildAgent ? "N" : "Y"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs); | 629 | llClient.SceneAgent.IsChildAgent ? "N" : "Y", |
630 | (DateTime.Now - cinfo.StartedTime).Minutes, | ||
631 | avg_reqs, | ||
632 | string.Format( | ||
633 | "{0} ({1:0.00}%)", | ||
634 | llClient.TotalAgentUpdates, | ||
635 | (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100)); | ||
630 | } | 636 | } |
631 | }); | 637 | }); |
632 | } | 638 | } |
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index c8aab54..f2355e2 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | |||
@@ -259,6 +259,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
259 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; | 259 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; |
260 | public event UpdateAgent OnPreAgentUpdate; | 260 | public event UpdateAgent OnPreAgentUpdate; |
261 | public event UpdateAgent OnAgentUpdate; | 261 | public event UpdateAgent OnAgentUpdate; |
262 | public event UpdateAgent OnAgentCameraUpdate; | ||
262 | public event AgentRequestSit OnAgentRequestSit; | 263 | public event AgentRequestSit OnAgentRequestSit; |
263 | public event AgentSit OnAgentSit; | 264 | public event AgentSit OnAgentSit; |
264 | public event AvatarPickerRequest OnAvatarPickerRequest; | 265 | public event AvatarPickerRequest OnAvatarPickerRequest; |
@@ -1242,7 +1243,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC | |||
1242 | { | 1243 | { |
1243 | } | 1244 | } |
1244 | 1245 | ||
1245 | public void StopFlying(ISceneEntity presence) | 1246 | public void SendAgentTerseUpdate(ISceneEntity presence) |
1246 | { | 1247 | { |
1247 | } | 1248 | } |
1248 | 1249 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs index fff63e4..e0ccc50 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs | |||
@@ -69,7 +69,7 @@ public class BSActorCollection | |||
69 | { | 69 | { |
70 | lock (m_actors) | 70 | lock (m_actors) |
71 | { | 71 | { |
72 | Release(); | 72 | ForEachActor(a => a.Dispose()); |
73 | m_actors.Clear(); | 73 | m_actors.Clear(); |
74 | } | 74 | } |
75 | } | 75 | } |
@@ -98,10 +98,6 @@ public class BSActorCollection | |||
98 | { | 98 | { |
99 | ForEachActor(a => a.SetEnabled(enabl)); | 99 | ForEachActor(a => a.SetEnabled(enabl)); |
100 | } | 100 | } |
101 | public void Release() | ||
102 | { | ||
103 | ForEachActor(a => a.Dispose()); | ||
104 | } | ||
105 | public void Refresh() | 101 | public void Refresh() |
106 | { | 102 | { |
107 | ForEachActor(a => a.Refresh()); | 103 | ForEachActor(a => a.Refresh()); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 0204967..82d7c44 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
45 | private static string LogHeader = "[BULLETSIM VEHICLE]"; | 45 | private static string LogHeader = "[BULLETSIM VEHICLE]"; |
46 | 46 | ||
47 | // the prim this dynamic controller belongs to | 47 | // the prim this dynamic controller belongs to |
48 | private BSPrim ControllingPrim { get; set; } | 48 | private BSPrimLinkable ControllingPrim { get; set; } |
49 | 49 | ||
50 | private bool m_haveRegisteredForSceneEvents; | 50 | private bool m_haveRegisteredForSceneEvents; |
51 | 51 | ||
@@ -128,9 +128,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
128 | public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) | 128 | public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) |
129 | : base(myScene, myPrim, actorName) | 129 | : base(myScene, myPrim, actorName) |
130 | { | 130 | { |
131 | ControllingPrim = myPrim; | ||
132 | Type = Vehicle.TYPE_NONE; | 131 | Type = Vehicle.TYPE_NONE; |
133 | m_haveRegisteredForSceneEvents = false; | 132 | m_haveRegisteredForSceneEvents = false; |
133 | |||
134 | ControllingPrim = myPrim as BSPrimLinkable; | ||
135 | if (ControllingPrim == null) | ||
136 | { | ||
137 | // THIS CANNOT HAPPEN!! | ||
138 | } | ||
139 | VDetailLog("{0},Creation", ControllingPrim.LocalID); | ||
134 | } | 140 | } |
135 | 141 | ||
136 | // Return 'true' if this vehicle is doing vehicle things | 142 | // Return 'true' if this vehicle is doing vehicle things |
@@ -585,6 +591,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
585 | // Friction affects are handled by this vehicle code | 591 | // Friction affects are handled by this vehicle code |
586 | m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); | 592 | m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); |
587 | m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); | 593 | m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); |
594 | // ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction); | ||
595 | // ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution); | ||
588 | 596 | ||
589 | // Moderate angular movement introduced by Bullet. | 597 | // Moderate angular movement introduced by Bullet. |
590 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. | 598 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. |
@@ -595,17 +603,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
595 | 603 | ||
596 | // Vehicles report collision events so we know when it's on the ground | 604 | // Vehicles report collision events so we know when it's on the ground |
597 | m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 605 | m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
606 | // ControllingPrim.Linkset.SetPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
598 | 607 | ||
599 | Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); | 608 | Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); |
600 | ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor; | 609 | ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor; |
601 | m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); | 610 | m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); |
602 | m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); | 611 | m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); |
612 | // ControllingPrim.Linkset.ComputeLocalInertia(BSParam.VehicleInertiaFactor); | ||
603 | 613 | ||
604 | // Set the gravity for the vehicle depending on the buoyancy | 614 | // Set the gravity for the vehicle depending on the buoyancy |
605 | // TODO: what should be done if prim and vehicle buoyancy differ? | 615 | // TODO: what should be done if prim and vehicle buoyancy differ? |
606 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); | 616 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); |
607 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. | 617 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. |
608 | m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); | 618 | m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); |
619 | // ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero); | ||
609 | 620 | ||
610 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", | 621 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", |
611 | ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, | 622 | ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, |
@@ -617,6 +628,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
617 | { | 628 | { |
618 | if (ControllingPrim.PhysBody.HasPhysicalBody) | 629 | if (ControllingPrim.PhysBody.HasPhysicalBody) |
619 | m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 630 | m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
631 | // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
620 | } | 632 | } |
621 | } | 633 | } |
622 | 634 | ||
@@ -629,6 +641,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
629 | // BSActor.Release() | 641 | // BSActor.Release() |
630 | public override void Dispose() | 642 | public override void Dispose() |
631 | { | 643 | { |
644 | VDetailLog("{0},Dispose", ControllingPrim.LocalID); | ||
632 | UnregisterForSceneEvents(); | 645 | UnregisterForSceneEvents(); |
633 | Type = Vehicle.TYPE_NONE; | 646 | Type = Vehicle.TYPE_NONE; |
634 | Enabled = false; | 647 | Enabled = false; |
@@ -1001,7 +1014,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1001 | else if (newVelocityLengthSq < 0.001f) | 1014 | else if (newVelocityLengthSq < 0.001f) |
1002 | VehicleVelocity = Vector3.Zero; | 1015 | VehicleVelocity = Vector3.Zero; |
1003 | 1016 | ||
1004 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.IsColliding, VehicleVelocity ); | 1017 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity ); |
1005 | 1018 | ||
1006 | } // end MoveLinear() | 1019 | } // end MoveLinear() |
1007 | 1020 | ||
@@ -1029,8 +1042,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1029 | // Add this correction to the velocity to make it faster/slower. | 1042 | // Add this correction to the velocity to make it faster/slower. |
1030 | VehicleVelocity += linearMotorVelocityW; | 1043 | VehicleVelocity += linearMotorVelocityW; |
1031 | 1044 | ||
1032 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", | 1045 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}", |
1033 | ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, | 1046 | ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV, |
1034 | linearMotorVelocityW, VehicleVelocity, frictionFactorV); | 1047 | linearMotorVelocityW, VehicleVelocity, frictionFactorV); |
1035 | } | 1048 | } |
1036 | 1049 | ||
@@ -1062,7 +1075,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1062 | Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation; | 1075 | Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation; |
1063 | 1076 | ||
1064 | // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall. | 1077 | // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall. |
1065 | if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.IsColliding) | 1078 | if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision) |
1066 | { | 1079 | { |
1067 | linearDeflectionW.Z = 0f; | 1080 | linearDeflectionW.Z = 0f; |
1068 | } | 1081 | } |
@@ -1222,7 +1235,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1222 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); | 1235 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); |
1223 | distanceAboveGround = VehiclePosition.Z - targetHeight; | 1236 | distanceAboveGround = VehiclePosition.Z - targetHeight; |
1224 | // Not colliding if the vehicle is off the ground | 1237 | // Not colliding if the vehicle is off the ground |
1225 | if (!Prim.IsColliding) | 1238 | if (!Prim.HasSomeCollision) |
1226 | { | 1239 | { |
1227 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 1240 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
1228 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); | 1241 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); |
@@ -1233,12 +1246,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1233 | // be computed with a motor. | 1246 | // be computed with a motor. |
1234 | // TODO: add interaction with banking. | 1247 | // TODO: add interaction with banking. |
1235 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", | 1248 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", |
1236 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); | 1249 | Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret); |
1237 | */ | 1250 | */ |
1238 | 1251 | ||
1239 | // Another approach is to measure if we're going up. If going up and not colliding, | 1252 | // Another approach is to measure if we're going up. If going up and not colliding, |
1240 | // the vehicle is in the air. Fix that by pushing down. | 1253 | // the vehicle is in the air. Fix that by pushing down. |
1241 | if (!ControllingPrim.IsColliding && VehicleVelocity.Z > 0.1) | 1254 | if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1) |
1242 | { | 1255 | { |
1243 | // Get rid of any of the velocity vector that is pushing us up. | 1256 | // Get rid of any of the velocity vector that is pushing us up. |
1244 | float upVelocity = VehicleVelocity.Z; | 1257 | float upVelocity = VehicleVelocity.Z; |
@@ -1260,7 +1273,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1260 | } | 1273 | } |
1261 | */ | 1274 | */ |
1262 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", | 1275 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", |
1263 | ControllingPrim.LocalID, ControllingPrim.IsColliding, upVelocity, VehicleVelocity); | 1276 | ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity); |
1264 | } | 1277 | } |
1265 | } | 1278 | } |
1266 | } | 1279 | } |
@@ -1270,14 +1283,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1270 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; | 1283 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; |
1271 | 1284 | ||
1272 | // Hack to reduce downward force if the vehicle is probably sitting on the ground | 1285 | // Hack to reduce downward force if the vehicle is probably sitting on the ground |
1273 | if (ControllingPrim.IsColliding && IsGroundVehicle) | 1286 | if (ControllingPrim.HasSomeCollision && IsGroundVehicle) |
1274 | appliedGravity *= BSParam.VehicleGroundGravityFudge; | 1287 | appliedGravity *= BSParam.VehicleGroundGravityFudge; |
1275 | 1288 | ||
1276 | VehicleAddForce(appliedGravity); | 1289 | VehicleAddForce(appliedGravity); |
1277 | 1290 | ||
1278 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}", | 1291 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}", |
1279 | ControllingPrim.LocalID, m_VehicleGravity, | 1292 | ControllingPrim.LocalID, m_VehicleGravity, |
1280 | ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); | 1293 | ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); |
1281 | } | 1294 | } |
1282 | 1295 | ||
1283 | // ======================================================================= | 1296 | // ======================================================================= |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index ad8e10f..960c0b4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -203,6 +203,33 @@ public abstract class BSLinkset | |||
203 | return ret; | 203 | return ret; |
204 | } | 204 | } |
205 | 205 | ||
206 | // Called after a simulation step to post a collision with this object. | ||
207 | // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have | ||
208 | // anything to add for the collision and it should be passed through normal processing. | ||
209 | // Default processing for a linkset. | ||
210 | public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee, | ||
211 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
212 | { | ||
213 | bool ret = false; | ||
214 | |||
215 | // prims in the same linkset cannot collide with each other | ||
216 | BSPrimLinkable convCollidee = collidee as BSPrimLinkable; | ||
217 | if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID)) | ||
218 | { | ||
219 | // By returning 'true', we tell the caller the collision has been 'handled' so it won't | ||
220 | // do anything about this collision and thus, effectivily, ignoring the collision. | ||
221 | ret = true; | ||
222 | } | ||
223 | else | ||
224 | { | ||
225 | // Not a collision between members of the linkset. Must be a real collision. | ||
226 | // So the linkset root can know if there is a collision anywhere in the linkset. | ||
227 | LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep; | ||
228 | } | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | |||
206 | // I am the root of a linkset and a new child is being added | 233 | // I am the root of a linkset and a new child is being added |
207 | // Called while LinkActivity is locked. | 234 | // Called while LinkActivity is locked. |
208 | protected abstract void AddChildToLinkset(BSPrimLinkable child); | 235 | protected abstract void AddChildToLinkset(BSPrimLinkable child); |
@@ -251,6 +278,73 @@ public abstract class BSLinkset | |||
251 | public abstract bool RemoveDependencies(BSPrimLinkable child); | 278 | public abstract bool RemoveDependencies(BSPrimLinkable child); |
252 | 279 | ||
253 | // ================================================================ | 280 | // ================================================================ |
281 | // Some physical setting happen to all members of the linkset | ||
282 | public virtual void SetPhysicalFriction(float friction) | ||
283 | { | ||
284 | ForEachMember((member) => | ||
285 | { | ||
286 | if (member.PhysBody.HasPhysicalBody) | ||
287 | m_physicsScene.PE.SetFriction(member.PhysBody, friction); | ||
288 | return false; // 'false' says to continue looping | ||
289 | } | ||
290 | ); | ||
291 | } | ||
292 | public virtual void SetPhysicalRestitution(float restitution) | ||
293 | { | ||
294 | ForEachMember((member) => | ||
295 | { | ||
296 | if (member.PhysBody.HasPhysicalBody) | ||
297 | m_physicsScene.PE.SetRestitution(member.PhysBody, restitution); | ||
298 | return false; // 'false' says to continue looping | ||
299 | } | ||
300 | ); | ||
301 | } | ||
302 | public virtual void SetPhysicalGravity(OMV.Vector3 gravity) | ||
303 | { | ||
304 | ForEachMember((member) => | ||
305 | { | ||
306 | if (member.PhysBody.HasPhysicalBody) | ||
307 | m_physicsScene.PE.SetGravity(member.PhysBody, gravity); | ||
308 | return false; // 'false' says to continue looping | ||
309 | } | ||
310 | ); | ||
311 | } | ||
312 | public virtual void ComputeLocalInertia(OMV.Vector3 inertiaFactor) | ||
313 | { | ||
314 | ForEachMember((member) => | ||
315 | { | ||
316 | if (member.PhysBody.HasPhysicalBody) | ||
317 | { | ||
318 | OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, member.Mass); | ||
319 | member.Inertia = inertia * inertiaFactor; | ||
320 | m_physicsScene.PE.SetMassProps(member.PhysBody, member.Mass, member.Inertia); | ||
321 | m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody); | ||
322 | } | ||
323 | return false; // 'false' says to continue looping | ||
324 | } | ||
325 | ); | ||
326 | } | ||
327 | public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags) | ||
328 | { | ||
329 | ForEachMember((member) => | ||
330 | { | ||
331 | if (member.PhysBody.HasPhysicalBody) | ||
332 | m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags); | ||
333 | return false; // 'false' says to continue looping | ||
334 | } | ||
335 | ); | ||
336 | } | ||
337 | public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags) | ||
338 | { | ||
339 | ForEachMember((member) => | ||
340 | { | ||
341 | if (member.PhysBody.HasPhysicalBody) | ||
342 | m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags); | ||
343 | return false; // 'false' says to continue looping | ||
344 | } | ||
345 | ); | ||
346 | } | ||
347 | // ================================================================ | ||
254 | protected virtual float ComputeLinksetMass() | 348 | protected virtual float ComputeLinksetMass() |
255 | { | 349 | { |
256 | float mass = LinksetRoot.RawMass; | 350 | float mass = LinksetRoot.RawMass; |
@@ -311,6 +405,5 @@ public abstract class BSLinkset | |||
311 | if (m_physicsScene.PhysicsLogging.Enabled) | 405 | if (m_physicsScene.PhysicsLogging.Enabled) |
312 | m_physicsScene.DetailLog(msg, args); | 406 | m_physicsScene.DetailLog(msg, args); |
313 | } | 407 | } |
314 | |||
315 | } | 408 | } |
316 | } | 409 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 1d94142..33ae5a5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -44,6 +44,42 @@ public sealed class BSLinksetCompound : BSLinkset | |||
44 | { | 44 | { |
45 | } | 45 | } |
46 | 46 | ||
47 | // ================================================================ | ||
48 | // Changing the physical property of the linkset only needs to change the root | ||
49 | public override void SetPhysicalFriction(float friction) | ||
50 | { | ||
51 | if (LinksetRoot.PhysBody.HasPhysicalBody) | ||
52 | m_physicsScene.PE.SetFriction(LinksetRoot.PhysBody, friction); | ||
53 | } | ||
54 | public override void SetPhysicalRestitution(float restitution) | ||
55 | { | ||
56 | if (LinksetRoot.PhysBody.HasPhysicalBody) | ||
57 | m_physicsScene.PE.SetRestitution(LinksetRoot.PhysBody, restitution); | ||
58 | } | ||
59 | public override void SetPhysicalGravity(OMV.Vector3 gravity) | ||
60 | { | ||
61 | if (LinksetRoot.PhysBody.HasPhysicalBody) | ||
62 | m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity); | ||
63 | } | ||
64 | public override void ComputeLocalInertia(OMV.Vector3 inertiaFactor) | ||
65 | { | ||
66 | OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, LinksetRoot.Mass); | ||
67 | LinksetRoot.Inertia = inertia * inertiaFactor; | ||
68 | m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, LinksetRoot.Mass, LinksetRoot.Inertia); | ||
69 | m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody); | ||
70 | } | ||
71 | public override void SetPhysicalCollisionFlags(CollisionFlags collFlags) | ||
72 | { | ||
73 | if (LinksetRoot.PhysBody.HasPhysicalBody) | ||
74 | m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags); | ||
75 | } | ||
76 | public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags) | ||
77 | { | ||
78 | if (LinksetRoot.PhysBody.HasPhysicalBody) | ||
79 | m_physicsScene.PE.RemoveFromCollisionFlags(LinksetRoot.PhysBody, collFlags); | ||
80 | } | ||
81 | // ================================================================ | ||
82 | |||
47 | // When physical properties are changed the linkset needs to recalculate | 83 | // When physical properties are changed the linkset needs to recalculate |
48 | // its internal properties. | 84 | // its internal properties. |
49 | public override void Refresh(BSPrimLinkable requestor) | 85 | public override void Refresh(BSPrimLinkable requestor) |
@@ -59,6 +95,7 @@ public sealed class BSLinksetCompound : BSLinkset | |||
59 | { | 95 | { |
60 | DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", | 96 | DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", |
61 | requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); | 97 | requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); |
98 | |||
62 | // When rebuilding, it is possible to set properties that would normally require a rebuild. | 99 | // When rebuilding, it is possible to set properties that would normally require a rebuild. |
63 | // If already rebuilding, don't request another rebuild. | 100 | // If already rebuilding, don't request another rebuild. |
64 | // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. | 101 | // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index a06a44d..f17d698 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -48,12 +48,22 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
48 | { | 48 | { |
49 | base.Refresh(requestor); | 49 | base.Refresh(requestor); |
50 | 50 | ||
51 | if (HasAnyChildren && IsRoot(requestor)) | 51 | } |
52 | |||
53 | private void ScheduleRebuild(BSPrimLinkable requestor) | ||
54 | { | ||
55 | DetailLog("{0},BSLinksetConstraint.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", | ||
56 | requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); | ||
57 | |||
58 | // When rebuilding, it is possible to set properties that would normally require a rebuild. | ||
59 | // If already rebuilding, don't request another rebuild. | ||
60 | // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. | ||
61 | if (!Rebuilding && HasAnyChildren) | ||
52 | { | 62 | { |
53 | // Queue to happen after all the other taint processing | 63 | // Queue to happen after all the other taint processing |
54 | m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() | 64 | m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() |
55 | { | 65 | { |
56 | if (HasAnyChildren && IsRoot(requestor)) | 66 | if (HasAnyChildren) |
57 | RecomputeLinksetConstraints(); | 67 | RecomputeLinksetConstraints(); |
58 | }); | 68 | }); |
59 | } | 69 | } |
@@ -67,8 +77,14 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
67 | // Called at taint-time! | 77 | // Called at taint-time! |
68 | public override bool MakeDynamic(BSPrimLinkable child) | 78 | public override bool MakeDynamic(BSPrimLinkable child) |
69 | { | 79 | { |
70 | // What is done for each object in BSPrim is what we want. | 80 | bool ret = false; |
71 | return false; | 81 | DetailLog("{0},BSLinksetConstraints.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); |
82 | if (IsRoot(child)) | ||
83 | { | ||
84 | // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. | ||
85 | ScheduleRebuild(LinksetRoot); | ||
86 | } | ||
87 | return ret; | ||
72 | } | 88 | } |
73 | 89 | ||
74 | // The object is going static (non-physical). Do any setup necessary for a static linkset. | 90 | // The object is going static (non-physical). Do any setup necessary for a static linkset. |
@@ -78,8 +94,16 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
78 | // Called at taint-time! | 94 | // Called at taint-time! |
79 | public override bool MakeStatic(BSPrimLinkable child) | 95 | public override bool MakeStatic(BSPrimLinkable child) |
80 | { | 96 | { |
81 | // What is done for each object in BSPrim is what we want. | 97 | bool ret = false; |
82 | return false; | 98 | |
99 | DetailLog("{0},BSLinksetConstraint.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); | ||
100 | child.ClearDisplacement(); | ||
101 | if (IsRoot(child)) | ||
102 | { | ||
103 | // Schedule a rebuild to verify that the root shape is set to the real shape. | ||
104 | ScheduleRebuild(LinksetRoot); | ||
105 | } | ||
106 | return ret; | ||
83 | } | 107 | } |
84 | 108 | ||
85 | // Called at taint-time!! | 109 | // Called at taint-time!! |
@@ -105,7 +129,7 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
105 | // Just undo all the constraints for this linkset. Rebuild at the end of the step. | 129 | // Just undo all the constraints for this linkset. Rebuild at the end of the step. |
106 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); | 130 | ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); |
107 | // Cause the constraints, et al to be rebuilt before the next simulation step. | 131 | // Cause the constraints, et al to be rebuilt before the next simulation step. |
108 | Refresh(LinksetRoot); | 132 | ScheduleRebuild(LinksetRoot); |
109 | } | 133 | } |
110 | return ret; | 134 | return ret; |
111 | } | 135 | } |
@@ -123,7 +147,7 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
123 | DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); | 147 | DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); |
124 | 148 | ||
125 | // Cause constraints and assorted properties to be recomputed before the next simulation step. | 149 | // Cause constraints and assorted properties to be recomputed before the next simulation step. |
126 | Refresh(LinksetRoot); | 150 | ScheduleRebuild(LinksetRoot); |
127 | } | 151 | } |
128 | return; | 152 | return; |
129 | } | 153 | } |
@@ -147,7 +171,7 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
147 | PhysicallyUnlinkAChildFromRoot(rootx, childx); | 171 | PhysicallyUnlinkAChildFromRoot(rootx, childx); |
148 | }); | 172 | }); |
149 | // See that the linkset parameters are recomputed at the end of the taint time. | 173 | // See that the linkset parameters are recomputed at the end of the taint time. |
150 | Refresh(LinksetRoot); | 174 | ScheduleRebuild(LinksetRoot); |
151 | } | 175 | } |
152 | else | 176 | else |
153 | { | 177 | { |
@@ -165,6 +189,7 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
165 | Refresh(rootPrim); | 189 | Refresh(rootPrim); |
166 | } | 190 | } |
167 | 191 | ||
192 | // Create a static constraint between the two passed objects | ||
168 | private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) | 193 | private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) |
169 | { | 194 | { |
170 | // Zero motion for children so they don't interpolate | 195 | // Zero motion for children so they don't interpolate |
@@ -281,24 +306,39 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
281 | DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", | 306 | DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", |
282 | LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass); | 307 | LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass); |
283 | 308 | ||
284 | foreach (BSPrimLinkable child in m_children) | 309 | try |
285 | { | 310 | { |
286 | // A child in the linkset physically shows the mass of the whole linkset. | 311 | Rebuilding = true; |
287 | // This allows Bullet to apply enough force on the child to move the whole linkset. | ||
288 | // (Also do the mass stuff before recomputing the constraint so mass is not zero.) | ||
289 | child.UpdatePhysicalMassProperties(linksetMass, true); | ||
290 | 312 | ||
291 | BSConstraint constrain; | 313 | // There is no reason to build all this physical stuff for a non-physical linkset. |
292 | if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) | 314 | if (!LinksetRoot.IsPhysicallyActive) |
293 | { | 315 | { |
294 | // If constraint doesn't exist yet, create it. | 316 | DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); |
295 | constrain = BuildConstraint(LinksetRoot, child); | 317 | return; // Note the 'finally' clause at the botton which will get executed. |
296 | } | 318 | } |
297 | constrain.RecomputeConstraintVariables(linksetMass); | ||
298 | 319 | ||
299 | // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG | 320 | foreach (BSPrimLinkable child in m_children) |
300 | } | 321 | { |
322 | // A child in the linkset physically shows the mass of the whole linkset. | ||
323 | // This allows Bullet to apply enough force on the child to move the whole linkset. | ||
324 | // (Also do the mass stuff before recomputing the constraint so mass is not zero.) | ||
325 | child.UpdatePhysicalMassProperties(linksetMass, true); | ||
326 | |||
327 | BSConstraint constrain; | ||
328 | if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) | ||
329 | { | ||
330 | // If constraint doesn't exist yet, create it. | ||
331 | constrain = BuildConstraint(LinksetRoot, child); | ||
332 | } | ||
333 | constrain.RecomputeConstraintVariables(linksetMass); | ||
301 | 334 | ||
335 | // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG | ||
336 | } | ||
337 | } | ||
338 | finally | ||
339 | { | ||
340 | Rebuilding = false; | ||
341 | } | ||
302 | } | 342 | } |
303 | } | 343 | } |
304 | } | 344 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index dcf1e83..0bdb5f1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | |||
@@ -461,8 +461,9 @@ public static class BSParam | |||
461 | (s) => { return MaxAddForceMagnitude; }, | 461 | (s) => { return MaxAddForceMagnitude; }, |
462 | (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ), | 462 | (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ), |
463 | // Density is passed around as 100kg/m3. This scales that to 1kg/m3. | 463 | // Density is passed around as 100kg/m3. This scales that to 1kg/m3. |
464 | // Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well | ||
464 | new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", | 465 | new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", |
465 | 0.01f ), | 466 | 0.0001f ), |
466 | 467 | ||
467 | new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing", | 468 | new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing", |
468 | 2200f ), | 469 | 2200f ), |
@@ -607,8 +608,9 @@ public static class BSParam | |||
607 | 0.0f ), | 608 | 0.0f ), |
608 | new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", | 609 | new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", |
609 | 0.0f ), | 610 | 0.0f ), |
611 | // Turn off fudge with DensityScaleFactor = 0.0001. Value used to be 0.2f; | ||
610 | new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", | 612 | new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", |
611 | 0.2f ), | 613 | 1.0f ), |
612 | new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", | 614 | new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", |
613 | 60.0f ), | 615 | 60.0f ), |
614 | new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect", | 616 | new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect", |
@@ -701,7 +703,7 @@ public static class BSParam | |||
701 | new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", | 703 | new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", |
702 | (float)BSLinkset.LinksetImplementation.Compound ), | 704 | (float)BSLinkset.LinksetImplementation.Compound ), |
703 | new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same", | 705 | new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same", |
704 | false ), | 706 | true ), |
705 | new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | 707 | new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", |
706 | false ), | 708 | false ), |
707 | new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", | 709 | new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index fc4545f..d34b797 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -353,6 +353,16 @@ public abstract class BSPhysObject : PhysicsActor | |||
353 | CollidingStep = BSScene.NotASimulationStep; | 353 | CollidingStep = BSScene.NotASimulationStep; |
354 | } | 354 | } |
355 | } | 355 | } |
356 | // Complex objects (like linksets) need to know if there is a collision on any part of | ||
357 | // their shape. 'IsColliding' has an existing definition of reporting a collision on | ||
358 | // only this specific prim or component of linksets. | ||
359 | // 'HasSomeCollision' is defined as reporting if there is a collision on any part of | ||
360 | // the complex body that this prim is the root of. | ||
361 | public virtual bool HasSomeCollision | ||
362 | { | ||
363 | get { return IsColliding; } | ||
364 | set { IsColliding = value; } | ||
365 | } | ||
356 | public override bool CollidingGround { | 366 | public override bool CollidingGround { |
357 | get { return (CollidingGroundStep == PhysScene.SimulationStep); } | 367 | get { return (CollidingGroundStep == PhysScene.SimulationStep); } |
358 | set | 368 | set |
@@ -386,6 +396,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
386 | // Return 'true' if a collision was processed and should be sent up. | 396 | // Return 'true' if a collision was processed and should be sent up. |
387 | // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision. | 397 | // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision. |
388 | // Called at taint time from within the Step() function | 398 | // Called at taint time from within the Step() function |
399 | public delegate bool CollideCall(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth); | ||
389 | public virtual bool Collide(uint collidingWith, BSPhysObject collidee, | 400 | public virtual bool Collide(uint collidingWith, BSPhysObject collidee, |
390 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 401 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
391 | { | 402 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d43448e..e92a1d2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -96,7 +96,7 @@ public class BSPrim : BSPhysObject | |||
96 | _isVolumeDetect = false; | 96 | _isVolumeDetect = false; |
97 | 97 | ||
98 | // Add a dynamic vehicle to our set of actors that can move this prim. | 98 | // Add a dynamic vehicle to our set of actors that can move this prim. |
99 | PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName)); | 99 | // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName)); |
100 | 100 | ||
101 | _mass = CalculateMass(); | 101 | _mass = CalculateMass(); |
102 | 102 | ||
@@ -440,8 +440,8 @@ public class BSPrim : BSPhysObject | |||
440 | Gravity = ComputeGravity(Buoyancy); | 440 | Gravity = ComputeGravity(Buoyancy); |
441 | PhysScene.PE.SetGravity(PhysBody, Gravity); | 441 | PhysScene.PE.SetGravity(PhysBody, Gravity); |
442 | 442 | ||
443 | OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG | 443 | // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG |
444 | DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG | 444 | // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG |
445 | 445 | ||
446 | Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); | 446 | Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass); |
447 | PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia); | 447 | PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia); |
@@ -495,9 +495,9 @@ public class BSPrim : BSPhysObject | |||
495 | } | 495 | } |
496 | } | 496 | } |
497 | 497 | ||
498 | // Find and return a handle to the current vehicle actor. | 498 | // Find and return a handle to the current vehicle actor. |
499 | // Return 'null' if there is no vehicle actor. | 499 | // Return 'null' if there is no vehicle actor. |
500 | public BSDynamics GetVehicleActor() | 500 | public BSDynamics GetVehicleActor(bool createIfNone) |
501 | { | 501 | { |
502 | BSDynamics ret = null; | 502 | BSDynamics ret = null; |
503 | BSActor actor; | 503 | BSActor actor; |
@@ -505,12 +505,21 @@ public class BSPrim : BSPhysObject | |||
505 | { | 505 | { |
506 | ret = actor as BSDynamics; | 506 | ret = actor as BSDynamics; |
507 | } | 507 | } |
508 | else | ||
509 | { | ||
510 | if (createIfNone) | ||
511 | { | ||
512 | ret = new BSDynamics(PhysScene, this, VehicleActorName); | ||
513 | PhysicalActors.Add(ret.ActorName, ret); | ||
514 | } | ||
515 | } | ||
508 | return ret; | 516 | return ret; |
509 | } | 517 | } |
518 | |||
510 | public override int VehicleType { | 519 | public override int VehicleType { |
511 | get { | 520 | get { |
512 | int ret = (int)Vehicle.TYPE_NONE; | 521 | int ret = (int)Vehicle.TYPE_NONE; |
513 | BSDynamics vehicleActor = GetVehicleActor(); | 522 | BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */); |
514 | if (vehicleActor != null) | 523 | if (vehicleActor != null) |
515 | ret = (int)vehicleActor.Type; | 524 | ret = (int)vehicleActor.Type; |
516 | return ret; | 525 | return ret; |
@@ -524,11 +533,24 @@ public class BSPrim : BSPhysObject | |||
524 | // change all the parameters. Like a plane changing to CAR when on the | 533 | // change all the parameters. Like a plane changing to CAR when on the |
525 | // ground. In this case, don't want to zero motion. | 534 | // ground. In this case, don't want to zero motion. |
526 | // ZeroMotion(true /* inTaintTime */); | 535 | // ZeroMotion(true /* inTaintTime */); |
527 | BSDynamics vehicleActor = GetVehicleActor(); | 536 | if (type == Vehicle.TYPE_NONE) |
528 | if (vehicleActor != null) | ||
529 | { | 537 | { |
530 | vehicleActor.ProcessTypeChange(type); | 538 | // Vehicle type is 'none' so get rid of any actor that may have been allocated. |
531 | ActivateIfPhysical(false); | 539 | BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */); |
540 | if (vehicleActor != null) | ||
541 | { | ||
542 | PhysicalActors.RemoveAndRelease(vehicleActor.ActorName); | ||
543 | } | ||
544 | } | ||
545 | else | ||
546 | { | ||
547 | // Vehicle type is not 'none' so create an actor and set it running. | ||
548 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); | ||
549 | if (vehicleActor != null) | ||
550 | { | ||
551 | vehicleActor.ProcessTypeChange(type); | ||
552 | ActivateIfPhysical(false); | ||
553 | } | ||
532 | } | 554 | } |
533 | }); | 555 | }); |
534 | } | 556 | } |
@@ -537,7 +559,7 @@ public class BSPrim : BSPhysObject | |||
537 | { | 559 | { |
538 | PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() | 560 | PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() |
539 | { | 561 | { |
540 | BSDynamics vehicleActor = GetVehicleActor(); | 562 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
541 | if (vehicleActor != null) | 563 | if (vehicleActor != null) |
542 | { | 564 | { |
543 | vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); | 565 | vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); |
@@ -549,7 +571,7 @@ public class BSPrim : BSPhysObject | |||
549 | { | 571 | { |
550 | PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() | 572 | PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() |
551 | { | 573 | { |
552 | BSDynamics vehicleActor = GetVehicleActor(); | 574 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
553 | if (vehicleActor != null) | 575 | if (vehicleActor != null) |
554 | { | 576 | { |
555 | vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); | 577 | vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); |
@@ -561,7 +583,7 @@ public class BSPrim : BSPhysObject | |||
561 | { | 583 | { |
562 | PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() | 584 | PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() |
563 | { | 585 | { |
564 | BSDynamics vehicleActor = GetVehicleActor(); | 586 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
565 | if (vehicleActor != null) | 587 | if (vehicleActor != null) |
566 | { | 588 | { |
567 | vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); | 589 | vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); |
@@ -573,7 +595,7 @@ public class BSPrim : BSPhysObject | |||
573 | { | 595 | { |
574 | PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate() | 596 | PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate() |
575 | { | 597 | { |
576 | BSDynamics vehicleActor = GetVehicleActor(); | 598 | BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); |
577 | if (vehicleActor != null) | 599 | if (vehicleActor != null) |
578 | { | 600 | { |
579 | vehicleActor.ProcessVehicleFlags(param, remove); | 601 | vehicleActor.ProcessVehicleFlags(param, remove); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 1fbcfcc..2f392da 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs | |||
@@ -200,20 +200,38 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
200 | } | 200 | } |
201 | 201 | ||
202 | // Called after a simulation step to post a collision with this object. | 202 | // Called after a simulation step to post a collision with this object. |
203 | // This returns 'true' if the collision has been queued and the SendCollisions call must | ||
204 | // be made at the end of the simulation step. | ||
203 | public override bool Collide(uint collidingWith, BSPhysObject collidee, | 205 | public override bool Collide(uint collidingWith, BSPhysObject collidee, |
204 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 206 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
205 | { | 207 | { |
206 | // prims in the same linkset cannot collide with each other | 208 | bool ret = false; |
207 | BSPrimLinkable convCollidee = collidee as BSPrimLinkable; | 209 | // Ask the linkset if it wants to handle the collision |
208 | if (convCollidee != null && (this.Linkset.LinksetID == convCollidee.Linkset.LinksetID)) | 210 | if (!Linkset.HandleCollide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth)) |
209 | { | 211 | { |
210 | return false; | 212 | // The linkset didn't handle it so pass the collision through normal processing |
213 | ret = base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); | ||
211 | } | 214 | } |
215 | return ret; | ||
216 | } | ||
212 | 217 | ||
213 | // TODO: handle collisions of other objects with with children of linkset. | 218 | // A linkset reports any collision on any part of the linkset. |
214 | // This is a problem for LinksetCompound since the children are packed into the root. | 219 | public long SomeCollisionSimulationStep = 0; |
220 | public override bool HasSomeCollision | ||
221 | { | ||
222 | get | ||
223 | { | ||
224 | return (SomeCollisionSimulationStep == PhysScene.SimulationStep) || base.IsColliding; | ||
225 | } | ||
226 | set | ||
227 | { | ||
228 | if (value) | ||
229 | SomeCollisionSimulationStep = PhysScene.SimulationStep; | ||
230 | else | ||
231 | SomeCollisionSimulationStep = 0; | ||
215 | 232 | ||
216 | return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); | 233 | base.HasSomeCollision = value; |
234 | } | ||
217 | } | 235 | } |
218 | } | 236 | } |
219 | } | 237 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs index 48d3742..48e74eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs | |||
@@ -116,7 +116,7 @@ public class BasicVehicles : OpenSimTestCase | |||
116 | // Instead the appropriate values are set and calls are made just the parts of the | 116 | // Instead the appropriate values are set and calls are made just the parts of the |
117 | // controller we want to exercise. Stepping the physics engine then applies | 117 | // controller we want to exercise. Stepping the physics engine then applies |
118 | // the actions of that one feature. | 118 | // the actions of that one feature. |
119 | BSDynamics vehicleActor = TestVehicle.GetVehicleActor(); | 119 | BSDynamics vehicleActor = TestVehicle.GetVehicleActor(true /* createIfNone */); |
120 | if (vehicleActor != null) | 120 | if (vehicleActor != null) |
121 | { | 121 | { |
122 | vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); | 122 | vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 7cd364b..739e984 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs | |||
@@ -415,6 +415,11 @@ namespace OpenSim.Region.Physics.Manager | |||
415 | public virtual PhysicsActor ParentActor { get { return this; } } | 415 | public virtual PhysicsActor ParentActor { get { return this; } } |
416 | 416 | ||
417 | 417 | ||
418 | // Extendable interface for new, physics engine specific operations | ||
419 | public virtual object Extension(string pFunct, params object[] pParams) | ||
420 | { | ||
421 | throw new NotImplementedException(); | ||
422 | } | ||
418 | } | 423 | } |
419 | 424 | ||
420 | public class NullPhysicsActor : PhysicsActor | 425 | public class NullPhysicsActor : PhysicsActor |
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index 20a70b4..52f2809 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs | |||
@@ -25,10 +25,13 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
28 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
29 | using System.Reflection; | 30 | using System.Reflection; |
31 | |||
30 | using log4net; | 32 | using log4net; |
31 | using Nini.Config; | 33 | using Nini.Config; |
34 | |||
32 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
33 | using OpenMetaverse; | 36 | using OpenMetaverse; |
34 | 37 | ||
@@ -386,5 +389,11 @@ namespace OpenSim.Region.Physics.Manager | |||
386 | { | 389 | { |
387 | return 0; | 390 | return 0; |
388 | } | 391 | } |
392 | |||
393 | // Extendable interface for new, physics engine specific operations | ||
394 | public virtual object Extension(string pFunct, params object[] pParams) | ||
395 | { | ||
396 | throw new NotImplementedException(); | ||
397 | } | ||
389 | } | 398 | } |
390 | } | 399 | } |
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index 2567c8f..0601ece 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs | |||
@@ -493,6 +493,22 @@ namespace OpenSim.Services.HypergridService | |||
493 | return null; | 493 | return null; |
494 | } | 494 | } |
495 | 495 | ||
496 | private XInventoryFolder GetCurrentOutfitXFolder(UUID userID) | ||
497 | { | ||
498 | XInventoryFolder root = GetRootXFolder(userID); | ||
499 | if (root == null) | ||
500 | return null; | ||
501 | |||
502 | XInventoryFolder[] folders = m_Database.GetFolders( | ||
503 | new string[] { "agentID", "type", "parentFolderID" }, | ||
504 | new string[] { userID.ToString(), ((int)AssetType.CurrentOutfitFolder).ToString(), root.folderID.ToString() }); | ||
505 | |||
506 | if (folders.Length == 0) | ||
507 | return null; | ||
508 | |||
509 | return folders[0]; | ||
510 | } | ||
511 | |||
496 | private XInventoryFolder GetSuitcaseXFolder(UUID principalID) | 512 | private XInventoryFolder GetSuitcaseXFolder(UUID principalID) |
497 | { | 513 | { |
498 | // Warp! Root folder for travelers | 514 | // Warp! Root folder for travelers |
@@ -531,6 +547,7 @@ namespace OpenSim.Services.HypergridService | |||
531 | if (m_SuitcaseTrees.TryGetValue(principalID, out t)) | 547 | if (m_SuitcaseTrees.TryGetValue(principalID, out t)) |
532 | return t; | 548 | return t; |
533 | 549 | ||
550 | // Get the tree of the suitcase folder | ||
534 | t = GetFolderTreeRecursive(folder); | 551 | t = GetFolderTreeRecursive(folder); |
535 | m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes | 552 | m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes |
536 | return t; | 553 | return t; |
@@ -577,6 +594,9 @@ namespace OpenSim.Services.HypergridService | |||
577 | List<XInventoryFolder> tree = new List<XInventoryFolder>(); | 594 | List<XInventoryFolder> tree = new List<XInventoryFolder>(); |
578 | tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder | 595 | tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder |
579 | tree.AddRange(GetFolderTree(principalID, suitcase.folderID)); | 596 | tree.AddRange(GetFolderTree(principalID, suitcase.folderID)); |
597 | // Also add the Current Outfit folder to the list of available folders | ||
598 | tree.Add(GetCurrentOutfitXFolder(principalID)); | ||
599 | |||
580 | XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) | 600 | XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) |
581 | { | 601 | { |
582 | if (fl.folderID == folderID) return true; | 602 | if (fl.folderID == folderID) return true; |
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 6528d9a..df8cf27 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs | |||
@@ -107,6 +107,7 @@ namespace OpenSim.Tests.Common.Mock | |||
107 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; | 107 | public event Action<IClientAPI, bool> OnCompleteMovementToRegion; |
108 | public event UpdateAgent OnPreAgentUpdate; | 108 | public event UpdateAgent OnPreAgentUpdate; |
109 | public event UpdateAgent OnAgentUpdate; | 109 | public event UpdateAgent OnAgentUpdate; |
110 | public event UpdateAgent OnAgentCameraUpdate; | ||
110 | public event AgentRequestSit OnAgentRequestSit; | 111 | public event AgentRequestSit OnAgentRequestSit; |
111 | public event AgentSit OnAgentSit; | 112 | public event AgentSit OnAgentSit; |
112 | public event AvatarPickerRequest OnAvatarPickerRequest; | 113 | public event AvatarPickerRequest OnAvatarPickerRequest; |
@@ -1266,7 +1267,7 @@ namespace OpenSim.Tests.Common.Mock | |||
1266 | { | 1267 | { |
1267 | } | 1268 | } |
1268 | 1269 | ||
1269 | public void StopFlying(ISceneEntity presence) | 1270 | public void SendAgentTerseUpdate(ISceneEntity presence) |
1270 | { | 1271 | { |
1271 | } | 1272 | } |
1272 | 1273 | ||