From 7131703244983223451fe6dc2edc80463716fa65 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 13 Jul 2016 14:00:33 +0100 Subject: [PATCH] ugly culling --- .../ClientStack/Linden/UDP/LLClientView.cs | 193 +++++++++++------- 1 file changed, 122 insertions(+), 71 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9136f2d956..5d70dc2c90 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1722,17 +1722,43 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityUpdates.Remove(localIDs); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); - // TODO: don't create new blocks if recycling an old packet - kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; + + int perpacket = localIDs.Count; + if(perpacket > 200) + perpacket = 200; + + int nsent = 0; + + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[perpacket]; for (int i = 0 ; i < localIDs.Count ; i++ ) { - kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock(); - kill.ObjectData[i].ID = localIDs[i]; - } - kill.Header.Reliable = true; - kill.Header.Zerocoded = true; + kill.ObjectData[nsent] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[nsent].ID = localIDs[i]; - OutPacket(kill, ThrottleOutPacketType.Task); + if(++nsent >= 200) + { + kill.Header.Reliable = true; + kill.Header.Zerocoded = true; + OutPacket(kill, ThrottleOutPacketType.Task); + + perpacket = localIDs.Count - i - 1; + if(perpacket == 0) + break; + if(perpacket > 200) + perpacket = 200; + + kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[perpacket]; + nsent = 0; + } + } + + if(nsent != 0) + { + kill.Header.Reliable = true; + kill.Header.Zerocoded = true; + OutPacket(kill, ThrottleOutPacketType.Task); + } } /// @@ -4292,17 +4318,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_killRecord.Clear(); } - lock(GroupsNeedFullUpdate) + if(GroupsNeedFullUpdate.Count > 0) { - if(GroupsNeedFullUpdate.Count > 0) + foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) { - foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) - { - grp.ScheduleGroupForFullUpdate(); - lock(GroupsInView) - GroupsInView.Add(grp); - } - GroupsNeedFullUpdate.Clear(); + grp.ScheduleGroupForFullUpdate(); + lock(GroupsInView) + GroupsInView.Add(grp); } } #endregion @@ -4339,81 +4361,110 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ReprioritizeUpdates() { - CheckGroupsInView(); lock (m_entityUpdates.SyncRoot) m_entityUpdates.Reprioritize(UpdatePriorityHandler); + CheckGroupsInView(); } + private bool CheckGroupsInViewBusy = false; + private bool CheckGroupsInViewOverRun = false; + public void CheckGroupsInView() { bool doCulling = m_scene.ObjectsCullingByDistance; if(!doCulling) return; - float cullingrange = 64.0f; - Vector3 mycamera = Vector3.Zero; - Vector3 mypos = Vector3.Zero; - ScenePresence mysp = (ScenePresence)SceneAgent; - if(mysp != null && !mysp.IsDeleted) - { - cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; - mycamera = mysp.CameraPosition; - mypos = mysp.AbsolutePosition; - } - else - return; - HashSet NewGroupsInView = new HashSet(); - HashSet GroupsNeedFullUpdate = new HashSet(); - List kills = new List(); - // will this take for ever ? - EntityBase[] entities = m_scene.Entities.GetEntities(); - foreach (EntityBase e in entities) + if(CheckGroupsInViewBusy) { - if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) + CheckGroupsInViewOverRun = true; + return; + } + CheckGroupsInViewBusy = true; + do + { + CheckGroupsInViewOverRun = false; + + float cullingrange = 64.0f; + Vector3 mycamera = Vector3.Zero; + Vector3 mypos = Vector3.Zero; + ScenePresence mysp = (ScenePresence)SceneAgent; + if(mysp != null && !mysp.IsDeleted) { - SceneObjectGroup grp = (SceneObjectGroup)e; - Vector3 grppos = grp.AbsolutePosition; - float dcam = (grppos - mycamera).LengthSquared(); - float dpos = (grppos - mypos).LengthSquared(); - if(dcam < dpos) - dpos = dcam; - dpos = (float)Math.Sqrt(dpos) - grp.GetBoundsRadius(); - bool inview; - lock(GroupsInView) - inview = GroupsInView.Contains(grp); - if(dpos > cullingrange) + cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; + mycamera = mysp.CameraPosition; + mypos = mysp.AbsolutePosition; + } + else + { + CheckGroupsInViewBusy= false; + return; + } + + HashSet NewGroupsInView = new HashSet(); + HashSet GroupsNeedFullUpdate = new HashSet(); + List kills = new List(); + + EntityBase[] entities = m_scene.Entities.GetEntities(); + foreach (EntityBase e in entities) + { + if(!IsActive) + return; + if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment) { - if(inview) + SceneObjectGroup grp = (SceneObjectGroup)e; + Vector3 grppos = grp.AbsolutePosition; + + float dcam = (grppos - mycamera).LengthSquared(); + float dpos = (grppos - mypos).LengthSquared(); + if(dcam < dpos) + dpos = dcam; + + dpos = (float)Math.Sqrt(dpos) - grp.GetBoundsRadius(); + + bool inview; + lock(GroupsInView) + inview = GroupsInView.Contains(grp); + + if(dpos > cullingrange) { -// GroupsInView.Remove(grp); - if (!kills.Contains(grp.LocalId)) + if(inview) + { kills.Add(grp.LocalId); + if (kills.Count > 100) + { + SendKillObject(kills); + kills.Clear(); + Thread.Sleep(50); + } + } + } + else + { + if(!inview) + GroupsNeedFullUpdate.Add(grp); + NewGroupsInView.Add(grp); } } - else - { - if(!inview) - GroupsNeedFullUpdate.Add(grp); - NewGroupsInView.Add(grp); - } } - } - lock(GroupsInView) - GroupsInView = NewGroupsInView; + lock(GroupsInView) + GroupsInView = NewGroupsInView; - if (kills.Count > 0) - { - SendKillObject(kills); - kills.Clear(); - } + if (kills.Count > 0) + { + SendKillObject(kills); + kills.Clear(); + } - if(GroupsNeedFullUpdate.Count > 0) - { - foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) - grp.ScheduleGroupForFullUpdate(); - } - GroupsNeedFullUpdate.Clear(); + if(GroupsNeedFullUpdate.Count > 0) + { + foreach(SceneObjectGroup grp in GroupsNeedFullUpdate) + grp.ScheduleGroupForFullUpdate(); + } + } while(CheckGroupsInViewOverRun); + + CheckGroupsInViewBusy = false; } private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)