From 86e5f82cb12dc5e854fe33526aee0ce899715410 Mon Sep 17 00:00:00 2001 From: MW Date: Thu, 11 Oct 2007 10:50:55 +0000 Subject: Some changes to the sending of updates of SceneObjects to clients, that I did a few weeks ago but never committed (and never completely finished what I had planned). --- OpenSim/Region/Environment/Scenes/Scene.cs | 2 +- .../Region/Environment/Scenes/SceneObjectPart.cs | 13 +- OpenSim/Region/Environment/Scenes/ScenePresence.cs | 105 ++++-- .../Region/Environment/Types/BasicQuadTreeNode.cs | 402 ++++++++++++--------- OpenSim/Region/Environment/Types/UpdateQueue.cs | 100 ++--- 5 files changed, 355 insertions(+), 267 deletions(-) (limited to 'OpenSim/Region/Environment') diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 384ec10..b0f0b9a 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -189,7 +189,7 @@ namespace OpenSim.Region.Environment.Scenes m_eventManager.OnPermissionError += SendPermissionAlert; - QuadTree = new BasicQuadTreeNode(null, 0, 0, 256, 256); + QuadTree = new BasicQuadTreeNode(null, "/0/", 0, 0, 256, 256); QuadTree.Subdivide(); QuadTree.Subdivide(); diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 406db9b..22408d3 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -11,6 +11,7 @@ using OpenSim.Framework.Utilities; using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Environment.Types; namespace OpenSim.Region.Environment.Scenes { @@ -681,15 +682,13 @@ namespace OpenSim.Region.Environment.Scenes List avatars = m_parentGroup.GetScenePresences(); for (int i = 0; i < avatars.Count; i++) { - avatars[i].AddFullPart(this); - // avatars[i].QueuePartForUpdate(this); + avatars[i].QueuePartForUpdate(this); } } public void AddFullUpdateToAvatar(ScenePresence presence) { - presence.AddFullPart(this); - //presence.QueuePartForUpdate(this); + presence.QueuePartForUpdate(this); } /// @@ -745,15 +744,13 @@ namespace OpenSim.Region.Environment.Scenes List avatars = m_parentGroup.GetScenePresences(); for (int i = 0; i < avatars.Count; i++) { - avatars[i].AddTersePart(this); - // avatars[i].QueuePartForUpdate(this); + avatars[i].QueuePartForUpdate(this); } } public void AddTerseUpdateToAvatar(ScenePresence presence) { - presence.AddTersePart(this); - // presence.QueuePartForUpdate(this); + presence.QueuePartForUpdate(this); } /// diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 428b771..22a0754 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -35,6 +35,7 @@ using OpenSim.Framework.Interfaces; using OpenSim.Framework.Types; using OpenSim.Framework.Utilities; using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Environment.Types; namespace OpenSim.Region.Environment.Scenes { @@ -89,11 +90,13 @@ namespace OpenSim.Region.Environment.Scenes //public List InterestList = new List(); - // private Queue m_fullGroupUpdates = new Queue(); - // private Queue m_terseGroupUpdates = new Queue(); + // private string m_currentQuadNode = " "; - private readonly Queue m_fullPartUpdates = new Queue(); - private readonly Queue m_tersePartUpdates = new Queue(); + // private Queue m_fullPartUpdates = new Queue(); + //private Queue m_tersePartUpdates = new Queue(); + + private UpdateQueue m_partsUpdateQueue = new UpdateQueue(); + private Dictionary m_updateTimes = new Dictionary(); #region Properties @@ -277,53 +280,69 @@ namespace OpenSim.Region.Environment.Scenes #endregion - public void AddTersePart(SceneObjectPart part) - { - m_tersePartUpdates.Enqueue(part); - } - - public void AddFullPart(SceneObjectPart part) + public void QueuePartForUpdate(SceneObjectPart part) { - m_fullPartUpdates.Enqueue(part); + //if (InterestList.Contains(part.ParentGroup)) + //{ + lock (m_partsUpdateQueue) + { + m_partsUpdateQueue.Enqueue(part); + } + // } } public void SendPrimUpdates() { - if (m_tersePartUpdates.Count > 0) - { - bool terse = true; - int terseCount = 0; + // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode) + //{ + // this.UpdateQuadTreeNode(); + //this.RefreshQuadObject(); + //} - while (terse) + if (m_partsUpdateQueue.Count > 0) + { + bool runUpdate = true; + int updateCount = 0; + while (runUpdate) { - SceneObjectPart part = m_tersePartUpdates.Dequeue(); - part.SendTerseUpdate(m_controllingClient); - terseCount++; - - if ((m_tersePartUpdates.Count < 1) | (terseCount > 30)) + SceneObjectPart part = m_partsUpdateQueue.Dequeue(); + if (m_updateTimes.ContainsKey(part.UUID)) + { + ScenePartUpdate update = m_updateTimes[part.UUID]; + if (update.LastFullUpdateTime < part.TimeStampFull) + { + //need to do a full update + part.SendFullUpdate(this.ControllingClient); + update.LastFullUpdateTime = (uint)Util.UnixTimeSinceEpoch(); + updateCount++; + } + else if (update.LastTerseUpdateTime < part.TimeStampTerse) + { + part.SendTerseUpdate(this.ControllingClient); + update.LastTerseUpdateTime = (uint)Util.UnixTimeSinceEpoch(); + updateCount++; + } + } + else { - terse = false; + //never been sent to client before so do full update + part.SendFullUpdate(this.ControllingClient); + ScenePartUpdate update = new ScenePartUpdate(); + update.FullID = part.UUID; + update.LastFullUpdateTime = (uint)Util.UnixTimeSinceEpoch(); + m_updateTimes.Add(part.UUID, update); + updateCount++; } - } - } - if (m_fullPartUpdates.Count > 0) - { - bool full = true; - int fullCount = 0; - while (full) - { - SceneObjectPart part = m_fullPartUpdates.Dequeue(); - part.SendFullUpdate(m_controllingClient); - fullCount++; - if ((m_fullPartUpdates.Count < 1) | (fullCount > 40)) + if (m_partsUpdateQueue.Count < 1 | updateCount > 60) { - full = false; + runUpdate = false; } } } } + #region Status Methods public void MakeAvatarPhysical(LLVector3 pos, bool isFlying) @@ -901,6 +920,22 @@ namespace OpenSim.Region.Environment.Scenes } } + public class ScenePartUpdate + { + public LLUUID FullID; + public uint LastFullUpdateTime; + public uint LastTerseUpdateTime; + + public ScenePartUpdate() + { + FullID = LLUUID.Zero; + LastFullUpdateTime = 0; + LastTerseUpdateTime = 0; + } + + } + + public override void SetText(string text, Vector3 color, double alpha) { throw new Exception("Can't set Text on avatar."); diff --git a/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs b/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs index 2b8d92e..fd1307a 100644 --- a/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs +++ b/OpenSim/Region/Environment/Types/BasicQuadTreeNode.cs @@ -1,174 +1,230 @@ -using System.Collections.Generic; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Types -{ - public class BasicQuadTreeNode - { - private List m_objects = new List(); - private BasicQuadTreeNode[] m_childNodes = null; - private BasicQuadTreeNode m_parent = null; - - private short m_leftX; - private short m_leftY; - private short m_width; - private short m_height; - - public BasicQuadTreeNode(BasicQuadTreeNode parent, short leftX, short leftY, short width, short height) - { - m_parent = parent; - m_leftX = leftX; - m_leftY = leftY; - m_width = width; - m_height = height; - } - - public void AddObject(SceneObjectGroup obj) - { - if (m_childNodes == null) - { - if (!m_objects.Contains(obj)) - { - m_objects.Add(obj); - } - } - else - { - if (obj.AbsolutePosition.X < (m_leftX + (m_width/2))) - { - if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) - { - m_childNodes[0].AddObject(obj); - } - else - { - m_childNodes[2].AddObject(obj); - } - } - else - { - if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) - { - m_childNodes[1].AddObject(obj); - } - else - { - m_childNodes[3].AddObject(obj); - } - } - } - } - - public void Subdivide() - { - if (m_childNodes == null) - { - m_childNodes = new BasicQuadTreeNode[4]; - m_childNodes[0] = - new BasicQuadTreeNode(this, m_leftX, m_leftY, (short) (m_width/2), (short) (m_height/2)); - m_childNodes[1] = - new BasicQuadTreeNode(this, (short) (m_leftX + (m_width/2)), m_leftY, (short) (m_width/2), - (short) (m_height/2)); - m_childNodes[2] = - new BasicQuadTreeNode(this, m_leftX, (short) (m_leftY + (m_height/2)), (short) (m_width/2), - (short) (m_height/2)); - m_childNodes[3] = - new BasicQuadTreeNode(this, (short) (m_leftX + (m_width/2)), (short) (m_height + (m_height/2)), - (short) (m_width/2), (short) (m_height/2)); - } - else - { - for (int i = 0; i < m_childNodes.Length; i++) - { - m_childNodes[i].Subdivide(); - } - } - } - - public List GetObjectsFrom(int x, int y) - { - if (m_childNodes == null) - { - return m_objects; - } - else - { - if (x < (m_leftX + (m_width/2))) - { - if (y < (m_leftY + (m_height/2))) - { - return m_childNodes[0].GetObjectsFrom(x, y); - } - else - { - return m_childNodes[2].GetObjectsFrom(x, y); - } - } - else - { - if (y < (m_leftY + (m_height/2))) - { - return m_childNodes[1].GetObjectsFrom(x, y); - } - else - { - return m_childNodes[3].GetObjectsFrom(x, y); - } - } - } - } - - public void Update() - { - if (m_childNodes != null) - { - for (int i = 0; i < 4; i++) - { - m_childNodes[i].Update(); - } - } - else - { - List outBounds = new List(); - foreach (SceneObjectGroup group in m_objects) - { - if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && - ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) - { - //still in bounds - } - else - { - outBounds.Add(group); - } - } - - foreach (SceneObjectGroup removee in outBounds) - { - m_objects.Remove(removee); - if (m_parent != null) - { - m_parent.PassUp(removee); - } - } - outBounds.Clear(); - } - } - - public void PassUp(SceneObjectGroup group) - { - if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && - ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) - { - AddObject(group); - } - else - { - if (m_parent != null) - { - m_parent.PassUp(group); - } - } - } - } +using System.Collections.Generic; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Types +{ + public class BasicQuadTreeNode + { + private List m_objects = new List(); + private BasicQuadTreeNode[] m_childNodes = null; + private BasicQuadTreeNode m_parent = null; + + private short m_leftX; + private short m_leftY; + private short m_width; + private short m_height; + //private int m_quadNumber; + private string m_quadID; + + public BasicQuadTreeNode(BasicQuadTreeNode parent, string quadID, short leftX, short leftY, short width, short height) + { + m_parent = parent; + m_quadID = quadID; + m_leftX = leftX; + m_leftY = leftY; + m_width = width; + m_height = height; + // Console.WriteLine("creating quadtree node " + m_quadID); + } + + public void AddObject(SceneObjectGroup obj) + { + if (m_childNodes == null) + { + if (!m_objects.Contains(obj)) + { + m_objects.Add(obj); + } + } + else + { + if (obj.AbsolutePosition.X < (m_leftX + (m_width / 2))) + { + if (obj.AbsolutePosition.Y < (m_leftY + (m_height / 2))) + { + m_childNodes[0].AddObject(obj); + } + else + { + m_childNodes[2].AddObject(obj); + } + } + else + { + if (obj.AbsolutePosition.Y < (m_leftY + (m_height / 2))) + { + m_childNodes[1].AddObject(obj); + } + else + { + m_childNodes[3].AddObject(obj); + } + } + } + } + + public void Subdivide() + { + if (m_childNodes == null) + { + m_childNodes = new BasicQuadTreeNode[4]; + m_childNodes[0] = new BasicQuadTreeNode(this, m_quadID + "1/", m_leftX, m_leftY, (short)(m_width / 2), (short)(m_height / 2)); + m_childNodes[1] = new BasicQuadTreeNode(this, m_quadID + "2/", (short)(m_leftX + (m_width / 2)), m_leftY, (short)(m_width / 2), (short)(m_height / 2)); + m_childNodes[2] = new BasicQuadTreeNode(this, m_quadID + "3/", m_leftX, (short)(m_leftY + (m_height / 2)), (short)(m_width / 2), (short)(m_height / 2)); + m_childNodes[3] = new BasicQuadTreeNode(this, m_quadID + "4/", (short)(m_leftX + (m_width / 2)), (short)(m_height + (m_height / 2)), (short)(m_width / 2), (short)(m_height / 2)); + } + else + { + for (int i = 0; i < m_childNodes.Length; i++) + { + m_childNodes[i].Subdivide(); + } + } + } + + public List GetObjectsFrom(float x, float y) + { + if (m_childNodes == null) + { + return new List(m_objects); + } + else + { + if (x < m_leftX + (m_width / 2)) + { + if (y < m_leftY + (m_height / 2)) + { + return m_childNodes[0].GetObjectsFrom(x, y); + } + else + { + return m_childNodes[2].GetObjectsFrom(x, y); + } + } + else + { + if (y < m_leftY + (m_height / 2)) + { + return m_childNodes[1].GetObjectsFrom(x, y); + } + else + { + return m_childNodes[3].GetObjectsFrom(x, y); + } + } + } + } + + public List GetObjectsFrom(string nodeName) + { + if (nodeName == m_quadID) + { + return new List(m_objects); + } + else if (m_childNodes != null) + { + for (int i = 0; i < 4; i++) + { + List retVal; + retVal = m_childNodes[i].GetObjectsFrom(nodeName); + if (retVal != null) + { + return retVal; + } + } + } + return null; + } + + public string GetNodeID(float x, float y) + { + if (m_childNodes == null) + { + return m_quadID; + } + else + { + if (x < m_leftX + (m_width / 2)) + { + if (y < m_leftY + (m_height / 2)) + { + return m_childNodes[0].GetNodeID(x, y); + } + else + { + return m_childNodes[2].GetNodeID(x, y); + } + } + else + { + if (y < m_leftY + (m_height / 2)) + { + return m_childNodes[1].GetNodeID(x, y); + } + else + { + return m_childNodes[3].GetNodeID(x, y); + } + } + } + } + + public void Update() + { + if (m_childNodes != null) + { + for (int i = 0; i < 4; i++) + { + m_childNodes[i].Update(); + } + } + else + { + List outBounds = new List(); + foreach (SceneObjectGroup group in m_objects) + { + if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) + { + //still in bounds + } + else + { + outBounds.Add(group); + } + } + + foreach (SceneObjectGroup removee in outBounds) + { + m_objects.Remove(removee); + if (m_parent != null) + { + m_parent.PassUp(removee); + } + } + outBounds.Clear(); + } + } + + public void PassUp(SceneObjectGroup group) + { + if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && ((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) + { + AddObject(group); + } + else + { + if (m_parent != null) + { + m_parent.PassUp(group); + } + } + } + + public string[] GetNeighbours(string nodeName) + { + string[] retVal = new string[1]; + retVal[0] = ""; + return retVal; + } + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Types/UpdateQueue.cs b/OpenSim/Region/Environment/Types/UpdateQueue.cs index c1fb161..0d341ae 100644 --- a/OpenSim/Region/Environment/Types/UpdateQueue.cs +++ b/OpenSim/Region/Environment/Types/UpdateQueue.cs @@ -1,51 +1,51 @@ -using System.Collections.Generic; -using libsecondlife; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Types -{ - public class UpdateQueue - { - private Queue m_queue; - - private List m_ids; - - public int Count - { - get { return m_queue.Count; } - } - - public UpdateQueue() - { - m_queue = new Queue(); - m_ids = new List(); - } - - public void Enqueue(SceneObjectPart part) - { - lock (m_ids) - { - if (!m_ids.Contains(part.UUID)) - { - m_ids.Add(part.UUID); - m_queue.Enqueue(part); - } - } - } - - public SceneObjectPart Dequeue() - { - SceneObjectPart part = null; - if (m_queue.Count > 0) - { - part = m_queue.Dequeue(); - lock (m_ids) - { - m_ids.Remove(part.UUID); - } - } - - return part; - } - } +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Types +{ + public class UpdateQueue + { + private Queue m_queue; + + private List m_ids; + + public int Count + { + get { return m_queue.Count; } + } + + public UpdateQueue() + { + m_queue = new Queue(); + m_ids = new List(); + } + + public void Enqueue(SceneObjectPart part) + { + lock (m_ids) + { + if (!m_ids.Contains(part.UUID)) + { + m_ids.Add(part.UUID); + m_queue.Enqueue(part); + } + } + } + + public SceneObjectPart Dequeue() + { + SceneObjectPart part = null; + if (m_queue.Count > 0) + { + part = m_queue.Dequeue(); + lock (m_ids) + { + m_ids.Remove(part.UUID); + } + } + + return part; + } + } } \ No newline at end of file -- cgit v1.1