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).

afrisby
MW 2007-10-11 10:50:55 +00:00
parent e7869d0666
commit 86e5f82cb1
5 changed files with 356 additions and 268 deletions

View File

@ -189,7 +189,7 @@ namespace OpenSim.Region.Environment.Scenes
m_eventManager.OnPermissionError += SendPermissionAlert; 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();
QuadTree.Subdivide(); QuadTree.Subdivide();

View File

@ -11,6 +11,7 @@ using OpenSim.Framework.Utilities;
using OpenSim.Region.Environment.Interfaces; using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Environment.Scenes.Scripting;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Environment.Types;
namespace OpenSim.Region.Environment.Scenes namespace OpenSim.Region.Environment.Scenes
{ {
@ -681,15 +682,13 @@ namespace OpenSim.Region.Environment.Scenes
List<ScenePresence> avatars = m_parentGroup.GetScenePresences(); List<ScenePresence> avatars = m_parentGroup.GetScenePresences();
for (int i = 0; i < avatars.Count; i++) 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) public void AddFullUpdateToAvatar(ScenePresence presence)
{ {
presence.AddFullPart(this); presence.QueuePartForUpdate(this);
//presence.QueuePartForUpdate(this);
} }
/// <summary> /// <summary>
@ -745,15 +744,13 @@ namespace OpenSim.Region.Environment.Scenes
List<ScenePresence> avatars = m_parentGroup.GetScenePresences(); List<ScenePresence> avatars = m_parentGroup.GetScenePresences();
for (int i = 0; i < avatars.Count; i++) 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) public void AddTerseUpdateToAvatar(ScenePresence presence)
{ {
presence.AddTersePart(this); presence.QueuePartForUpdate(this);
// presence.QueuePartForUpdate(this);
} }
/// <summary> /// <summary>

View File

@ -35,6 +35,7 @@ using OpenSim.Framework.Interfaces;
using OpenSim.Framework.Types; using OpenSim.Framework.Types;
using OpenSim.Framework.Utilities; using OpenSim.Framework.Utilities;
using OpenSim.Region.Physics.Manager; using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Environment.Types;
namespace OpenSim.Region.Environment.Scenes namespace OpenSim.Region.Environment.Scenes
{ {
@ -89,11 +90,13 @@ namespace OpenSim.Region.Environment.Scenes
//public List<SceneObjectGroup> InterestList = new List<SceneObjectGroup>(); //public List<SceneObjectGroup> InterestList = new List<SceneObjectGroup>();
// private Queue<SceneObjectGroup> m_fullGroupUpdates = new Queue<SceneObjectGroup>(); // private string m_currentQuadNode = " ";
// private Queue<SceneObjectGroup> m_terseGroupUpdates = new Queue<SceneObjectGroup>();
private readonly Queue<SceneObjectPart> m_fullPartUpdates = new Queue<SceneObjectPart>(); // private Queue<SceneObjectPart> m_fullPartUpdates = new Queue<SceneObjectPart>();
private readonly Queue<SceneObjectPart> m_tersePartUpdates = new Queue<SceneObjectPart>(); //private Queue<SceneObjectPart> m_tersePartUpdates = new Queue<SceneObjectPart>();
private UpdateQueue m_partsUpdateQueue = new UpdateQueue();
private Dictionary<LLUUID, ScenePartUpdate> m_updateTimes = new Dictionary<LLUUID, ScenePartUpdate>();
#region Properties #region Properties
@ -277,53 +280,69 @@ namespace OpenSim.Region.Environment.Scenes
#endregion #endregion
public void AddTersePart(SceneObjectPart part) public void QueuePartForUpdate(SceneObjectPart part)
{ {
m_tersePartUpdates.Enqueue(part); //if (InterestList.Contains(part.ParentGroup))
} //{
lock (m_partsUpdateQueue)
public void AddFullPart(SceneObjectPart part) {
{ m_partsUpdateQueue.Enqueue(part);
m_fullPartUpdates.Enqueue(part); }
// }
} }
public void SendPrimUpdates() public void SendPrimUpdates()
{ {
if (m_tersePartUpdates.Count > 0) // if (m_scene.QuadTree.GetNodeID(this.AbsolutePosition.X, this.AbsolutePosition.Y) != m_currentQuadNode)
//{
// this.UpdateQuadTreeNode();
//this.RefreshQuadObject();
//}
if (m_partsUpdateQueue.Count > 0)
{ {
bool terse = true; bool runUpdate = true;
int terseCount = 0; int updateCount = 0;
while (runUpdate)
while (terse)
{ {
SceneObjectPart part = m_tersePartUpdates.Dequeue(); SceneObjectPart part = m_partsUpdateQueue.Dequeue();
part.SendTerseUpdate(m_controllingClient); if (m_updateTimes.ContainsKey(part.UUID))
terseCount++;
if ((m_tersePartUpdates.Count < 1) | (terseCount > 30))
{ {
terse = false; 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
}
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))
{ {
full = 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_partsUpdateQueue.Count < 1 | updateCount > 60)
{
runUpdate = false;
} }
} }
} }
} }
#region Status Methods #region Status Methods
public void MakeAvatarPhysical(LLVector3 pos, bool isFlying) 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) public override void SetText(string text, Vector3 color, double alpha)
{ {
throw new Exception("Can't set Text on avatar."); throw new Exception("Can't set Text on avatar.");

View File

@ -1,174 +1,230 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Types namespace OpenSim.Region.Environment.Types
{ {
public class BasicQuadTreeNode public class BasicQuadTreeNode
{ {
private List<SceneObjectGroup> m_objects = new List<SceneObjectGroup>(); private List<SceneObjectGroup> m_objects = new List<SceneObjectGroup>();
private BasicQuadTreeNode[] m_childNodes = null; private BasicQuadTreeNode[] m_childNodes = null;
private BasicQuadTreeNode m_parent = null; private BasicQuadTreeNode m_parent = null;
private short m_leftX; private short m_leftX;
private short m_leftY; private short m_leftY;
private short m_width; private short m_width;
private short m_height; private short m_height;
//private int m_quadNumber;
public BasicQuadTreeNode(BasicQuadTreeNode parent, short leftX, short leftY, short width, short height) private string m_quadID;
{
m_parent = parent; public BasicQuadTreeNode(BasicQuadTreeNode parent, string quadID, short leftX, short leftY, short width, short height)
m_leftX = leftX; {
m_leftY = leftY; m_parent = parent;
m_width = width; m_quadID = quadID;
m_height = height; m_leftX = leftX;
} m_leftY = leftY;
m_width = width;
public void AddObject(SceneObjectGroup obj) m_height = height;
{ // Console.WriteLine("creating quadtree node " + m_quadID);
if (m_childNodes == null) }
{
if (!m_objects.Contains(obj)) public void AddObject(SceneObjectGroup obj)
{ {
m_objects.Add(obj); if (m_childNodes == null)
} {
} if (!m_objects.Contains(obj))
else {
{ m_objects.Add(obj);
if (obj.AbsolutePosition.X < (m_leftX + (m_width/2))) }
{ }
if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) else
{ {
m_childNodes[0].AddObject(obj); if (obj.AbsolutePosition.X < (m_leftX + (m_width / 2)))
} {
else if (obj.AbsolutePosition.Y < (m_leftY + (m_height / 2)))
{ {
m_childNodes[2].AddObject(obj); m_childNodes[0].AddObject(obj);
} }
} else
else {
{ m_childNodes[2].AddObject(obj);
if (obj.AbsolutePosition.Y < (m_leftY + (m_height/2))) }
{ }
m_childNodes[1].AddObject(obj); else
} {
else if (obj.AbsolutePosition.Y < (m_leftY + (m_height / 2)))
{ {
m_childNodes[3].AddObject(obj); m_childNodes[1].AddObject(obj);
} }
} else
} {
} m_childNodes[3].AddObject(obj);
}
public void Subdivide() }
{ }
if (m_childNodes == null) }
{
m_childNodes = new BasicQuadTreeNode[4]; public void Subdivide()
m_childNodes[0] = {
new BasicQuadTreeNode(this, m_leftX, m_leftY, (short) (m_width/2), (short) (m_height/2)); if (m_childNodes == null)
m_childNodes[1] = {
new BasicQuadTreeNode(this, (short) (m_leftX + (m_width/2)), m_leftY, (short) (m_width/2), m_childNodes = new BasicQuadTreeNode[4];
(short) (m_height/2)); m_childNodes[0] = new BasicQuadTreeNode(this, m_quadID + "1/", m_leftX, m_leftY, (short)(m_width / 2), (short)(m_height / 2));
m_childNodes[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));
new BasicQuadTreeNode(this, m_leftX, (short) (m_leftY + (m_height/2)), (short) (m_width/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));
(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));
m_childNodes[3] = }
new BasicQuadTreeNode(this, (short) (m_leftX + (m_width/2)), (short) (m_height + (m_height/2)), else
(short) (m_width/2), (short) (m_height/2)); {
} for (int i = 0; i < m_childNodes.Length; i++)
else {
{ m_childNodes[i].Subdivide();
for (int i = 0; i < m_childNodes.Length; i++) }
{ }
m_childNodes[i].Subdivide(); }
}
} public List<SceneObjectGroup> GetObjectsFrom(float x, float y)
} {
if (m_childNodes == null)
public List<SceneObjectGroup> GetObjectsFrom(int x, int y) {
{ return new List<SceneObjectGroup>(m_objects);
if (m_childNodes == null) }
{ else
return m_objects; {
} if (x < m_leftX + (m_width / 2))
else {
{ if (y < m_leftY + (m_height / 2))
if (x < (m_leftX + (m_width/2))) {
{ return m_childNodes[0].GetObjectsFrom(x, y);
if (y < (m_leftY + (m_height/2))) }
{ else
return m_childNodes[0].GetObjectsFrom(x, y); {
} return m_childNodes[2].GetObjectsFrom(x, y);
else }
{ }
return m_childNodes[2].GetObjectsFrom(x, y); else
} {
} if (y < m_leftY + (m_height / 2))
else {
{ return m_childNodes[1].GetObjectsFrom(x, y);
if (y < (m_leftY + (m_height/2))) }
{ else
return m_childNodes[1].GetObjectsFrom(x, y); {
} return m_childNodes[3].GetObjectsFrom(x, y);
else }
{ }
return m_childNodes[3].GetObjectsFrom(x, y); }
} }
}
} public List<SceneObjectGroup> GetObjectsFrom(string nodeName)
} {
if (nodeName == m_quadID)
public void Update() {
{ return new List<SceneObjectGroup>(m_objects);
if (m_childNodes != null) }
{ else if (m_childNodes != null)
for (int i = 0; i < 4; i++) {
{ for (int i = 0; i < 4; i++)
m_childNodes[i].Update(); {
} List<SceneObjectGroup> retVal;
} retVal = m_childNodes[i].GetObjectsFrom(nodeName);
else if (retVal != null)
{ {
List<SceneObjectGroup> outBounds = new List<SceneObjectGroup>(); return retVal;
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)))) return null;
{ }
//still in bounds
} public string GetNodeID(float x, float y)
else {
{ if (m_childNodes == null)
outBounds.Add(group); {
} return m_quadID;
} }
else
foreach (SceneObjectGroup removee in outBounds) {
{ if (x < m_leftX + (m_width / 2))
m_objects.Remove(removee); {
if (m_parent != null) if (y < m_leftY + (m_height / 2))
{ {
m_parent.PassUp(removee); return m_childNodes[0].GetNodeID(x, y);
} }
} else
outBounds.Clear(); {
} return m_childNodes[2].GetNodeID(x, y);
} }
}
public void PassUp(SceneObjectGroup group) else
{ {
if (((group.AbsolutePosition.X > m_leftX) && (group.AbsolutePosition.X < (m_leftX + m_width))) && if (y < m_leftY + (m_height / 2))
((group.AbsolutePosition.Y > m_leftY) && (group.AbsolutePosition.Y < (m_leftY + m_height)))) {
{ return m_childNodes[1].GetNodeID(x, y);
AddObject(group); }
} else
else {
{ return m_childNodes[3].GetNodeID(x, y);
if (m_parent != null) }
{ }
m_parent.PassUp(group); }
} }
}
} public void Update()
} {
if (m_childNodes != null)
{
for (int i = 0; i < 4; i++)
{
m_childNodes[i].Update();
}
}
else
{
List<SceneObjectGroup> outBounds = new List<SceneObjectGroup>();
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;
}
}
} }

View File

@ -1,51 +1,51 @@
using System.Collections.Generic; using System.Collections.Generic;
using libsecondlife; using libsecondlife;
using OpenSim.Region.Environment.Scenes; using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Types namespace OpenSim.Region.Environment.Types
{ {
public class UpdateQueue public class UpdateQueue
{ {
private Queue<SceneObjectPart> m_queue; private Queue<SceneObjectPart> m_queue;
private List<LLUUID> m_ids; private List<LLUUID> m_ids;
public int Count public int Count
{ {
get { return m_queue.Count; } get { return m_queue.Count; }
} }
public UpdateQueue() public UpdateQueue()
{ {
m_queue = new Queue<SceneObjectPart>(); m_queue = new Queue<SceneObjectPart>();
m_ids = new List<LLUUID>(); m_ids = new List<LLUUID>();
} }
public void Enqueue(SceneObjectPart part) public void Enqueue(SceneObjectPart part)
{ {
lock (m_ids) lock (m_ids)
{ {
if (!m_ids.Contains(part.UUID)) if (!m_ids.Contains(part.UUID))
{ {
m_ids.Add(part.UUID); m_ids.Add(part.UUID);
m_queue.Enqueue(part); m_queue.Enqueue(part);
} }
} }
} }
public SceneObjectPart Dequeue() public SceneObjectPart Dequeue()
{ {
SceneObjectPart part = null; SceneObjectPart part = null;
if (m_queue.Count > 0) if (m_queue.Count > 0)
{ {
part = m_queue.Dequeue(); part = m_queue.Dequeue();
lock (m_ids) lock (m_ids)
{ {
m_ids.Remove(part.UUID); m_ids.Remove(part.UUID);
} }
} }
return part; return part;
} }
} }
} }