From 4a73cc81dc4e03b2b7c46829cecfc0627c3fddb4 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 28 Dec 2018 13:52:59 +0000 Subject: now break several things at same time... sog/sop updates, threads options,... --- OpenSim/Region/Framework/Scenes/Scene.cs | 26 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 126 +++--- .../Region/Framework/Scenes/SceneObjectGroup.cs | 27 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 448 ++++++++++++--------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 145 ++----- 5 files changed, 411 insertions(+), 361 deletions(-) (limited to 'OpenSim/Region/Framework') diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 502bbda..e5aa21e 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -62,9 +62,23 @@ namespace OpenSim.Region.Framework.Scenes private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; - public delegate void SynchronizeSceneHandler(Scene scene); + protected static int m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0x5fffafL); + + public int NextObjectAnimationSequenceNumber + { + get + { + int ret = Interlocked.Increment(ref m_animationSequenceNumber); + if (ret <= 0 ) + { + m_animationSequenceNumber = (int)(Util.GetTimeStampTicks() & 0xafff5fL); + ret = Interlocked.Increment(ref m_animationSequenceNumber); + } + return ret; + } + } #region Fields /// @@ -945,6 +959,7 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); + m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); if (RegionInfo.NonphysPrimMin > 0) { @@ -1547,10 +1562,9 @@ namespace OpenSim.Region.Framework.Scenes // tell physics to finish building actor m_sceneGraph.ProcessPhysicsPreSimulation(); - m_heartbeatThread - = WorkManager.StartThread( - Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); - + m_heartbeatThread = WorkManager.StartThread( + Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, + false, null, 20000, false); StartScripts(); } @@ -1943,7 +1957,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!m_backingup) { - WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0}", Name), false); + WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0})", Name), false); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 61a243d..68864cc 100755 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -28,6 +28,7 @@ using System; using System.Threading; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Reflection; using OpenMetaverse; using OpenMetaverse.Packets; @@ -68,8 +69,10 @@ namespace OpenSim.Region.Framework.Scenes #region Fields - protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); - protected Dictionary m_scenePresenceMap = new Dictionary(); + protected System.Threading.ReaderWriterLockSlim m_scenePresencesLock = new System.Threading.ReaderWriterLockSlim(); + + protected ConcurrentDictionary m_scenePresenceMap = new ConcurrentDictionary(); + protected ConcurrentDictionary m_scenePresenceLocalIDMap = new ConcurrentDictionary(); protected List m_scenePresenceArray = new List(); protected internal EntityManager Entities = new EntityManager(); @@ -147,10 +150,9 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - Dictionary newmap = new Dictionary(); - List newlist = new List(); - m_scenePresenceMap = newmap; - m_scenePresenceArray = newlist; + m_scenePresenceMap = new ConcurrentDictionary(); + m_scenePresenceLocalIDMap = new ConcurrentDictionary(); + m_scenePresenceArray = new List(); } finally { @@ -165,22 +167,13 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroupsByLocalPartID.Clear(); Entities.Clear(); + m_scenePresencesLock.Dispose(); } #region Update Methods protected internal void UpdatePreparePhysics() { - // If we are using a threaded physics engine - // grab the latest scene from the engine before - // trying to process it. - - // PhysX does this (runs in the background). - - if (PhysicsScene.IsThreaded) - { - PhysicsScene.GetResults(); - } } /// @@ -197,6 +190,14 @@ namespace OpenSim.Region.Framework.Scenes }); } + protected internal void UpdateScenePresenceMovement() + { + ForEachScenePresence(delegate (ScenePresence presence) + { + presence.UpdateMovement(); + }); + } + /// /// Perform a physics frame update. /// @@ -204,23 +205,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal float UpdatePhysics(double elapsed) { - // Here is where the Scene calls the PhysicsScene. This is a one-way - // interaction; the PhysicsScene cannot access the calling Scene directly. - // But with joints, we want a PhysicsActor to be able to influence a - // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected - // with a joint should be able to move the SceneObjectPart which is the visual - // representation of that joint (for editing and serialization purposes). - // However the PhysicsActor normally cannot directly influence anything outside - // of the PhysicsScene, and the non-physical SceneObjectPart which represents - // the joint in the Scene does not exist in the PhysicsScene. - // - // To solve this, we have an event in the PhysicsScene that is fired when a joint - // has changed position (because one of its associated PhysicsActors has changed - // position). - // - // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). - - return PhysicsScene.Simulate((float)elapsed); + if (PhysicsScene != null) + return PhysicsScene.Simulate((float)elapsed); + return 0; } protected internal void ProcessPhysicsPreSimulation() @@ -229,14 +216,6 @@ namespace OpenSim.Region.Framework.Scenes PhysicsScene.ProcessPreSimulation(); } - protected internal void UpdateScenePresenceMovement() - { - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.UpdateMovement(); - }); - } - public void GetCoarseLocations(out List coarseLocations, out List avatarUUIDs, uint maxLocations) { coarseLocations = new List(); @@ -640,7 +619,7 @@ namespace OpenSim.Region.Framework.Scenes lock (m_updateList) { updates = new List(m_updateList.Values); - m_updateList.Clear(); + m_updateList = new Dictionary(); } // Go through all updates @@ -720,26 +699,32 @@ namespace OpenSim.Region.Framework.Scenes { m_numChildAgents++; - Dictionary newmap = new Dictionary(m_scenePresenceMap); List newlist = new List(m_scenePresenceArray); - if (!newmap.ContainsKey(presence.UUID)) + if (!m_scenePresenceMap.ContainsKey(presence.UUID)) { - newmap.Add(presence.UUID, presence); + m_scenePresenceMap[presence.UUID] = presence; + m_scenePresenceLocalIDMap[presence.LocalId] = presence; newlist.Add(presence); } else { // Remember the old presence reference from the dictionary - ScenePresence oldref = newmap[presence.UUID]; + ScenePresence oldref = m_scenePresenceMap[presence.UUID]; + uint oldLocalID = oldref.LocalId; // Replace the presence reference in the dictionary with the new value - newmap[presence.UUID] = presence; - // Find the index in the list where the old ref was stored and update the reference + m_scenePresenceMap[presence.UUID] = presence; newlist[newlist.IndexOf(oldref)] = presence; + + if(presence.LocalId != oldLocalID) + { + m_scenePresenceLocalIDMap.TryRemove(oldLocalID, out oldref); + m_scenePresenceLocalIDMap[presence.LocalId] = presence; + } + // Find the index in the list where the old ref was stored and update the reference } // Swap out the dictionary and list with new references - m_scenePresenceMap = newmap; m_scenePresenceArray = newlist; } finally @@ -765,20 +750,15 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - Dictionary newmap = new Dictionary(m_scenePresenceMap); - List newlist = new List(m_scenePresenceArray); - // Remove the presence reference from the dictionary - if (newmap.ContainsKey(agentID)) + ScenePresence oldref; + if(m_scenePresenceMap.TryRemove(agentID, out oldref)) { - ScenePresence oldref = newmap[agentID]; - newmap.Remove(agentID); - // Find the index in the list where the old ref was stored and remove the reference - newlist.RemoveAt(newlist.IndexOf(oldref)); - // Swap out the dictionary and list with new references - m_scenePresenceMap = newmap; - m_scenePresenceArray = newlist; + List newsps = new List(m_scenePresenceArray); + newsps.RemoveAt(newsps.IndexOf(oldref)); + m_scenePresenceArray = newsps; + m_scenePresenceLocalIDMap.TryRemove(oldref.LocalId, out oldref); } else { @@ -914,7 +894,16 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal List GetScenePresences() { - return m_scenePresenceArray; + + m_scenePresencesLock.EnterReadLock(); + try + { + return m_scenePresenceArray; + } + finally + { + m_scenePresencesLock.ExitReadLock(); + } } /// @@ -924,9 +913,8 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(UUID agentID) { - Dictionary presences = m_scenePresenceMap; ScenePresence presence; - presences.TryGetValue(agentID, out presence); + m_scenePresenceMap.TryGetValue(agentID, out presence); return presence; } @@ -955,24 +943,28 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(uint localID) { + ScenePresence sp = null; + if(m_scenePresenceLocalIDMap.TryGetValue(localID, out sp)) + return sp; +/* List presences = GetScenePresences(); foreach (ScenePresence presence in presences) if (presence.LocalId == localID) return presence; +*/ return null; } protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) { - Dictionary presences = m_scenePresenceMap; - presences.TryGetValue(agentID, out avatar); - return (avatar != null); + return m_scenePresenceMap.TryGetValue(agentID, out avatar); } protected internal bool TryGetAvatarByName(string name, out ScenePresence avatar) { avatar = null; - foreach (ScenePresence presence in GetScenePresences()) + List presences = GetScenePresences(); + foreach (ScenePresence presence in presences) { if (String.Compare(name, presence.ControllingClient.Name, true) == 0) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 423fbc7..a78ed8b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2584,14 +2584,33 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdateToClient(IClientAPI remoteClient) { - RootPart.SendFullUpdate(remoteClient); + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + + RootPart.SendFullUpdate(remoteClient, update); + + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + if (part != RootPart) + part.SendFullUpdate(remoteClient, update); + } + } + + public void SendFullAnimUpdateToClient(IClientAPI remoteClient) + { + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + if (RootPart.Shape.MeshFlagEntry) + update = PrimUpdateFlags.FullUpdatewithAnim; + + RootPart.SendFullUpdate(remoteClient, update); SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part != RootPart) - part.SendFullUpdate(remoteClient); + part.SendFullUpdate(remoteClient, update); } } @@ -3110,7 +3129,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this,UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); return; } } @@ -3160,7 +3179,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.TerseUpdate); return; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6c035f0..c549f5c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -68,22 +68,6 @@ namespace OpenSim.Region.Framework.Scenes POSITION = 32768 } - // I don't really know where to put this except here. - // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants - [Flags] - public enum ExtraParamType - { - Something1 = 1, - Something2 = 2, - Something3 = 4, - Something4 = 8, - Flexible = 16, - Light = 32, - Sculpt = 48, - Something5 = 64, - Something6 = 128 - } - [Flags] public enum TextureAnimFlags : byte { @@ -109,13 +93,6 @@ namespace OpenSim.Region.Framework.Scenes SCULPT = 7 } - public enum UpdateRequired : byte - { - NONE = 0, - TERSE = 1, - FULL = 2 - } - #endregion Enumerations public class SceneObjectPart : ISceneEntity @@ -182,10 +159,13 @@ namespace OpenSim.Region.Framework.Scenes { get { - return - !(SitTargetPosition == Vector3.Zero - && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion - || (SitTargetOrientation.W == 0f && SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f ))); // Invalid Quaternion + // assume SitTargetOrientation is normalized (as needed elsewhere) + if( SitTargetPosition != Vector3.Zero || + SitTargetOrientation.X != 0f || + SitTargetOrientation.Y != 0f || + SitTargetOrientation.Z != 0f) + return true; + return false; } } @@ -1212,7 +1192,18 @@ namespace OpenSim.Region.Framework.Scenes return a * b; } - public UpdateRequired UpdateFlag { get; set; } + public PrimUpdateFlags UpdateFlag { get; set; } + + public PrimUpdateFlags GetAndClearUpdateFlag() + { + lock(UpdateFlagLock) + { + PrimUpdateFlags ret = UpdateFlag; + UpdateFlag = PrimUpdateFlags.None; + return ret; + } + } + private object UpdateFlagLock = new object(); /// @@ -1503,11 +1494,16 @@ namespace OpenSim.Region.Framework.Scenes } set { + UUID old = m_collisionSound; + m_collisionSoundType = value; if (value == -1) m_collisionSound = invalidCollisionSoundUUID; else if (value == 0) m_collisionSound = UUID.Zero; + + if(m_collisionSound != old && ParentGroup != null) + ParentGroup.HasGroupChanged = true; } } @@ -1516,6 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_collisionSound; } set { + UUID olds = m_collisionSound; m_collisionSound = value; if (value == invalidCollisionSoundUUID) @@ -1525,13 +1522,24 @@ namespace OpenSim.Region.Framework.Scenes else m_collisionSoundType = 1; + if(m_collisionSound != olds && ParentGroup != null) + ParentGroup.HasGroupChanged = true; } } public float CollisionSoundVolume { get { return m_collisionSoundVolume; } - set { m_collisionSoundVolume = value; } + set + { + float oldvalue = m_collisionSoundVolume; + if(value >= 0) + m_collisionSoundVolume = value; + else + m_collisionSoundVolume = 0.0f; + if(m_collisionSoundVolume != oldvalue && ParentGroup != null) + ParentGroup.HasGroupChanged = true; + } } public float Buoyancy @@ -1884,7 +1892,7 @@ namespace OpenSim.Region.Framework.Scenes public void ClearUpdateSchedule() { lock(UpdateFlagLock) - UpdateFlag = UpdateRequired.NONE; + UpdateFlag = PrimUpdateFlags.None; } /// @@ -3276,40 +3284,27 @@ namespace OpenSim.Region.Framework.Scenes { // m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); - if (ParentGroup == null) - return; - if (ParentGroup.Scene == null) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) return; - + if(ParentGroup.Scene.GetNumberOfClients() == 0) return; ParentGroup.QueueForUpdateCheck(); // just in case lock(UpdateFlagLock) - { - if(UpdateFlag != UpdateRequired.FULL) - { - UpdateFlag = UpdateRequired.FULL; + UpdateFlag |= PrimUpdateFlags.FullUpdate; - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", - // UUID, Name, TimeStampFull); - - } - } ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); } /// /// Schedule a terse update for this prim. Terse updates only send position, - /// rotation, velocity and rotational velocity information. WRONG!!!! + /// rotation, velocity and rotational velocity information. /// public void ScheduleTerseUpdate() { - if (ParentGroup == null) - return; - if (ParentGroup.Scene == null) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) return; ParentGroup.HasGroupChanged = true; @@ -3317,28 +3312,47 @@ namespace OpenSim.Region.Framework.Scenes if(ParentGroup.Scene.GetNumberOfClients() == 0) return; - // This was pulled from SceneViewer. Attachments always receive full updates. - // This is needed because otherwise if only the root prim changes position, then - // it looks as if the entire object has moved (including the other prims). - if (ParentGroup.IsAttachment) + ParentGroup.QueueForUpdateCheck(); + + bool isfull = false; + lock (UpdateFlagLock) { - ScheduleFullUpdate(); - return; + if (ParentGroup.IsAttachment) + { + UpdateFlag |= PrimUpdateFlags.FullUpdate; + isfull = true; + } + else + UpdateFlag |= PrimUpdateFlags.TerseUpdate; } + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull); + } + + public void ScheduleUpdate(PrimUpdateFlags update) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.Scene == null) + return; + + ParentGroup.HasGroupChanged = true; + + if (ParentGroup.Scene.GetNumberOfClients() == 0) + return; ParentGroup.QueueForUpdateCheck(); - lock(UpdateFlagLock) + + bool isfull = false; + lock (UpdateFlagLock) { - if (UpdateFlag == UpdateRequired.NONE) + if (ParentGroup.IsAttachment) { - UpdateFlag = UpdateRequired.TERSE; - - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1}", - // UUID, Name); + UpdateFlag |= update | PrimUpdateFlags.FullUpdate; + isfull = true; } + else + UpdateFlag |= update; } - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); + + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, isfull); } public void ScriptSetPhysicsStatus(bool UsePhysics) @@ -3364,7 +3378,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); } } else @@ -3373,6 +3387,29 @@ namespace OpenSim.Region.Framework.Scenes } } + protected internal void SendFullUpdate(IClientAPI remoteClient, PrimUpdateFlags update) + { + if (ParentGroup == null) + return; + + // m_log.DebugFormat( + // "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); + + + if (ParentGroup.IsAttachment) + { + ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); + if (sp != null) + { + sp.SendAttachmentUpdate(this, update); + } + } + else + { + SendUpdateToClient(remoteClient, update); + } + } + /// /// Send a full update for this part to all clients. /// @@ -3419,7 +3456,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.FULL); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.FullUpdate); } } else @@ -3469,136 +3506,109 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendScheduledUpdates(double now) { - bool sendterse = false; - bool sendfull = false; - - lock(UpdateFlagLock) + PrimUpdateFlags current; + lock (UpdateFlagLock) { - switch (UpdateFlag) - { - case UpdateRequired.NONE: - break; + current = UpdateFlag; - case UpdateRequired.TERSE: - sendterse = true; + if (current == PrimUpdateFlags.None) + return; - Vector3 curvel = Velocity; - Vector3 curacc = Acceleration; - Vector3 angvel = AngularVelocity; + if(current == PrimUpdateFlags.TerseUpdate) + { + Vector3 curvel = Velocity; + Vector3 curacc = Acceleration; + Vector3 angvel = AngularVelocity; - while(true) // just to avoid ugly goto - { - double elapsed = now - m_lastUpdateSentTime; - if (elapsed > TIME_MS_TOLERANCE) - break; + while(true) // just to avoid ugly goto + { + double elapsed = now - m_lastUpdateSentTime; + if (elapsed > TIME_MS_TOLERANCE) + break; - if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE || + if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE || Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE || Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE) - break; - - if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || + break; + + if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE) - break; - - float vx = Math.Abs(curvel.X); - if(vx > 128.0) - break; - float vy = Math.Abs(curvel.Y); - if(vy > 128.0) - break; - float vz = Math.Abs(curvel.Z); - if(vz > 128.0) - break; + break; + + float vx = Math.Abs(curvel.X); + if(vx > 128.0) + break; + float vy = Math.Abs(curvel.Y); + if(vy > 128.0) + break; + float vz = Math.Abs(curvel.Z); + if(vz > 128.0) + break; - if ( + if( vx < VELOCITY_TOLERANCE && vy < VELOCITY_TOLERANCE && vz < VELOCITY_TOLERANCE ) - { - if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) - break; - - if (vx < 1e-4 && + { + if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) + break; + if(vx < 1e-4 && vy < 1e-4 && vz < 1e-4 && ( - Math.Abs(m_lastVelocity.X) > 1e-4 || - Math.Abs(m_lastVelocity.Y) > 1e-4 || - Math.Abs(m_lastVelocity.Z) > 1e-4 + Math.Abs(m_lastVelocity.X) > 1e-4 || + Math.Abs(m_lastVelocity.Y) > 1e-4 || + Math.Abs(m_lastVelocity.Z) > 1e-4 )) - break; - } + break; + } - if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE || + if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE || Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > ANGVELOCITY_TOLERANCE || Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > ANGVELOCITY_TOLERANCE) - break; + break; - // viewer interpolators have a limit of 64rad/s - float ax = Math.Abs(angvel.X); - if(ax > 64.0) - break; - float ay = Math.Abs(angvel.Y); - if(ay > 64.0) - break; - float az = Math.Abs(angvel.Z); - if(az > 64.0) - break; + // viewer interpolators have a limit of 64rad/s + float ax = Math.Abs(angvel.X); + if(ax > 64.0) + break; + float ay = Math.Abs(angvel.Y); + if(ay > 64.0) + break; + float az = Math.Abs(angvel.Z); + if(az > 64.0) + break; - if ( + if ( ax < ANGVELOCITY_TOLERANCE && ay < ANGVELOCITY_TOLERANCE && az < ANGVELOCITY_TOLERANCE && !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ) - break; - - sendterse = false; break; - } - - if(sendterse) - { - // Update the "last" values - m_lastPosition = AbsolutePosition; - m_lastRotation = RotationOffset; - m_lastVelocity = curvel; - m_lastAcceleration = curacc; - m_lastAngularVelocity = angvel; - m_lastUpdateSentTime = now; - ClearUpdateSchedule(); - } - break; - - case UpdateRequired.FULL: - m_lastPosition = AbsolutePosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = now; - ClearUpdateSchedule(); - sendfull = true; - break; + return; + } } - } - if(sendterse) - { - ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) + + if((current & PrimUpdateFlags.TerseUpdate) != 0) { - SendTerseUpdateToClient(client); - }); + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = now; + } + + UpdateFlag = PrimUpdateFlags.None; } - else if(sendfull) + + ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { - ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - SendFullUpdate(avatar.ControllingClient); - }); - } + SendUpdateToClient(avatar.ControllingClient, current); + }); } /// @@ -3608,10 +3618,10 @@ namespace OpenSim.Region.Framework.Scenes { if (ParentGroup == null || ParentGroup.Scene == null) return; + lock(UpdateFlagLock) { - if(UpdateFlag != UpdateRequired.NONE) - return; + UpdateFlag &= ~PrimUpdateFlags.TerseUpdate; // Update the "last" values m_lastPosition = AbsolutePosition; @@ -3635,8 +3645,7 @@ namespace OpenSim.Region.Framework.Scenes lock(UpdateFlagLock) { - if(UpdateFlag != UpdateRequired.NONE) - return; + UpdateFlag &= ~PrimUpdateFlags.TerseUpdate; // Update the "last" values m_lastPosition = AbsolutePosition; @@ -3652,7 +3661,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar); if (sp != null) { - sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); + sp.SendAttachmentUpdate(this, PrimUpdateFlags.TerseUpdate); } } else @@ -3682,12 +3691,6 @@ namespace OpenSim.Region.Framework.Scenes public void SetBuoyancy(float fvalue) { Buoyancy = fvalue; -/* - if (PhysActor != null) - { - PhysActor.Buoyancy = fvalue; - } - */ } public void SetDieAtEdge(bool p) @@ -4085,7 +4088,8 @@ namespace OpenSim.Region.Framework.Scenes GroupID = groupID; // if (client != null) // SendPropertiesToClient(client); - UpdateFlag = UpdateRequired.FULL; + lock(UpdateFlagLock) + UpdateFlag |= PrimUpdateFlags.FullUpdate; } /// @@ -4273,8 +4277,6 @@ namespace OpenSim.Region.Framework.Scenes Vector3 pos = GetWorldPosition(); Quaternion rot = GetWorldRotation(); - // Variables prefixed with AX are Axiom.Math copies of the LL variety. - Quaternion AXrot = rot; AXrot.Normalize(); @@ -4645,7 +4647,7 @@ namespace OpenSim.Region.Framework.Scenes { if (ParentGroup.RootPart.GetStatusSandbox()) { - if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) + if (Vector3.DistanceSquared(ParentGroup.RootPart.StatusSandboxPos, newPos) > 100) { ParentGroup.RootPart.ScriptSetPhysicsStatus(false); newPos = OffsetPosition; @@ -5230,7 +5232,7 @@ namespace OpenSim.Region.Framework.Scenes // Materials capable viewers can send a ObjectImage packet // when nothing in TE has changed. MaterialID should be updated // by the RenderMaterials CAP handler, so updating it here may cause a - // race condtion. Therefore, if no non-materials TE fields have changed, + // race condtion. Therefore, if no non-materials TE fields have not changed, // we should ignore any changes and not update Shape.TextureEntry bool otherFieldsChanged = false; @@ -5279,7 +5281,7 @@ namespace OpenSim.Region.Framework.Scenes } if (changeFlags == 0) - return; + return; m_shape.TextureEntry = newTex.GetBytes(); TriggerScriptChangedEvent(changeFlags); ParentGroup.HasGroupChanged = true; @@ -5412,6 +5414,21 @@ namespace OpenSim.Region.Framework.Scenes #endregion Public Methods + public void SendUpdateToClient(IClientAPI remoteClient, PrimUpdateFlags PrimUpdateFlags) + { + if (ParentGroup.IsDeleted) + return; + + if (ParentGroup.IsAttachment && + (ParentGroup.RootPart != this || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) + return; + + remoteClient.SendEntityUpdate(this, PrimUpdateFlags); + + ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); + } + + public void SendTerseUpdateToClient(IClientAPI remoteClient) { if (ParentGroup.IsDeleted) @@ -5424,10 +5441,7 @@ namespace OpenSim.Region.Framework.Scenes // Causes this thread to dig into the Client Thread Data. // Remember your locking here! - remoteClient.SendEntityUpdate( - this, - PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); + remoteClient.SendEntityUpdate(this, PrimUpdateFlags.TerseUpdate); ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); } @@ -5691,5 +5705,75 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.Building = true; UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false); } + + private object animsLock = new object(); + public Dictionary Animations = null; + public Dictionary AnimationsNames = null; + + public bool AddAnimation(UUID animId, string animName) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return false; + + lock (animsLock) + { + if (Animations == null) + Animations = new Dictionary(1); + if (AnimationsNames == null) + AnimationsNames = new Dictionary(1); + + if (Animations.ContainsKey(animId)) + return false; + + Animations[animId] = ParentGroup.Scene.NextObjectAnimationSequenceNumber; + AnimationsNames[animId] = animName; + ScheduleUpdate(PrimUpdateFlags.Animations); + } + return true; + } + + public bool RemoveAnimation(UUID animId) + { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return false; + + lock (animsLock) + { + if (Animations == null) + return false; + + if (Animations.ContainsKey(animId)) + { + Animations.Remove(animId); + if(AnimationsNames!=null) + AnimationsNames.Remove(animId); + ScheduleUpdate(PrimUpdateFlags.Animations); + return true; + } + } + return false; + } + + public int GetAnimations(out UUID[] ids, out int[] seqs) + { + ids = null; + seqs = null; + + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return -1; + + lock (animsLock) + { + if (Animations == null) + return -1; + if(Animations.Count == 0) + return 0; + ids = new UUID[Animations.Count]; + Animations.Keys.CopyTo(ids, 0); + seqs = new int[Animations.Count]; + Animations.Values.CopyTo(seqs, 0); + return Animations.Count; + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 3312ace..a308abb 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2173,7 +2173,7 @@ namespace OpenSim.Region.Framework.Scenes // if(root.LocalId != ParentPart.LocalId) // ControllingClient.SendEntityTerseUpdateImmediate(root); // ControllingClient.SendEntityTerseUpdateImmediate(ParentPart); - ParentPart.ParentGroup.SendFullUpdateToClient(ControllingClient); + ParentPart.ParentGroup.SendFullAnimUpdateToClient(ControllingClient); } // verify baked textures and cache @@ -4036,7 +4036,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (EntityBase e in entities) { if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) - ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); + ((SceneObjectGroup)e).SendFullAnimUpdateToClient(ControllingClient); } m_reprioritizationLastPosition = AbsolutePosition; @@ -4883,18 +4883,31 @@ namespace OpenSim.Region.Framework.Scenes Animator.ResetAnimations(); Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides); - + int nanim = ControllingClient.NextAnimationSequenceNumber; // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? if (cAgent.DefaultAnim != null) + { + if (cAgent.DefaultAnim.SequenceNum > nanim) + nanim = cAgent.DefaultAnim.SequenceNum; Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); + } if (cAgent.AnimState != null) + { + if (cAgent.AnimState.SequenceNum > nanim) + nanim = cAgent.AnimState.SequenceNum; Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); + } if (cAgent.Anims != null) - Animator.Animations.FromArray(cAgent.Anims); + { + int canim = Animator.Animations.FromArray(cAgent.Anims); + if(canim > nanim) + nanim = canim; + } + ControllingClient.NextAnimationSequenceNumber = ++nanim; + if (cAgent.MotionState != 0) Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState; - crossingFlags = cAgent.CrossingFlags; gotCrossUpdate = (crossingFlags != 0); if(gotCrossUpdate) @@ -5401,14 +5414,18 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = sog.Parts; SceneObjectPart rootpart = sog.RootPart; - p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate); + PrimUpdateFlags update = PrimUpdateFlags.FullUpdate; + if (rootpart.Shape.MeshFlagEntry) + update = PrimUpdateFlags.FullUpdatewithAnim; + + p.ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate); + p.ControllingClient.SendEntityUpdate(part, update); } } @@ -5422,51 +5439,30 @@ namespace OpenSim.Region.Framework.Scenes PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length]; SceneObjectPart rootpart = sog.RootPart; - UpdateRequired rootreq = sog.RootPart.UpdateFlag; + PrimUpdateFlags rootreq = sog.RootPart.GetAndClearUpdateFlag(); int j = 0; - bool allterse = true; + + PrimUpdateFlags cur; for (int i = 0; i < origparts.Length; i++) { if (origparts[i] != rootpart) { - switch (origparts[i].UpdateFlag) - { - case UpdateRequired.NONE: - break; - - case UpdateRequired.TERSE: - flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - parts[j] = origparts[i]; - j++; - break; - - case UpdateRequired.FULL: - flags[j] = PrimUpdateFlags.FullUpdate; - allterse = false; - parts[j] = origparts[i]; - j++; - break; - } + cur = origparts[i].GetAndClearUpdateFlag(); + if(cur == PrimUpdateFlags.None) + continue; + flags[j] = cur; + parts[j] = origparts[i]; + j++; } - origparts[i].UpdateFlag = 0; } - if (j == 0 && rootreq == UpdateRequired.NONE) + if (j == 0 && rootreq == PrimUpdateFlags.None) return; - PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate; - - if (rootreq != UpdateRequired.FULL && allterse) - { - rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - } - int nparts = j; - ControllingClient.SendEntityUpdate(rootpart, rootflag); + ControllingClient.SendEntityUpdate(rootpart, rootreq); for (int i = 0; i < nparts; i++) { @@ -5485,7 +5481,7 @@ namespace OpenSim.Region.Framework.Scenes if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) continue; - p.ControllingClient.SendEntityUpdate(rootpart, rootflag); + p.ControllingClient.SendEntityUpdate(rootpart, rootreq); for (int i = 0; i < nparts; i++) { @@ -5494,41 +5490,22 @@ namespace OpenSim.Region.Framework.Scenes } } - public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag) + public void SendAttachmentUpdate(SceneObjectGroup sog, PrimUpdateFlags update) { if (IsChildAgent || IsInTransit) return; - PrimUpdateFlags flag; - switch (UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - SceneObjectPart[] parts = sog.Parts; SceneObjectPart rootpart = sog.RootPart; -// rootpart.UpdateFlag = 0; - - ControllingClient.SendEntityUpdate(rootpart, flag); + ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - ControllingClient.SendEntityUpdate(part, flag); -// part.UpdateFlag = 0; + ControllingClient.SendEntityUpdate(part, update); } if (sog.HasPrivateAttachmentPoint) @@ -5543,14 +5520,14 @@ namespace OpenSim.Region.Framework.Scenes if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) continue; - p.ControllingClient.SendEntityUpdate(rootpart, flag); + p.ControllingClient.SendEntityUpdate(rootpart, update); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part == rootpart) continue; - p.ControllingClient.SendEntityUpdate(part, flag); + p.ControllingClient.SendEntityUpdate(part, update); } } } @@ -5560,24 +5537,7 @@ namespace OpenSim.Region.Framework.Scenes if (IsChildAgent || IsInTransit) return; - - PrimUpdateFlags flag; - switch (part.UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - - part.UpdateFlag = 0; + PrimUpdateFlags flag = part.GetAndClearUpdateFlag(); ControllingClient.SendEntityUpdate(part, flag); @@ -5597,30 +5557,11 @@ namespace OpenSim.Region.Framework.Scenes } } - - public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag) + public void SendAttachmentUpdate(SceneObjectPart part, PrimUpdateFlags flag) { if (IsChildAgent || IsInTransit) return; - PrimUpdateFlags flag; - switch (UpdateFlag) - { - case UpdateRequired.TERSE: - flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity - | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity; - break; - - case UpdateRequired.FULL: - flag = PrimUpdateFlags.FullUpdate; - break; - - default: - return; - } - -// part.UpdateFlag = 0; - ControllingClient.SendEntityUpdate(part, flag); if (part.ParentGroup.HasPrivateAttachmentPoint) -- cgit v1.1