diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Prioritizer.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Prioritizer.cs | 164 |
1 files changed, 132 insertions, 32 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index ae85560..53ca849 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs | |||
@@ -35,7 +35,7 @@ using OpenSim.Region.PhysicsModules.SharedBase; | |||
35 | 35 | ||
36 | /* | 36 | /* |
37 | * Steps to add a new prioritization policy: | 37 | * Steps to add a new prioritization policy: |
38 | * | 38 | * |
39 | * - Add a new value to the UpdatePrioritizationSchemes enum. | 39 | * - Add a new value to the UpdatePrioritizationSchemes enum. |
40 | * - Specify this new value in the [InterestManagement] section of your | 40 | * - Specify this new value in the [InterestManagement] section of your |
41 | * OpenSim.ini. The name in the config file must match the enum value name | 41 | * OpenSim.ini. The name in the config file must match the enum value name |
@@ -59,7 +59,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
59 | public class Prioritizer | 59 | public class Prioritizer |
60 | { | 60 | { |
61 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 61 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
62 | 62 | ||
63 | private Scene m_scene; | 63 | private Scene m_scene; |
64 | 64 | ||
65 | public Prioritizer(Scene scene) | 65 | public Prioritizer(Scene scene) |
@@ -91,9 +91,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
91 | return 0; | 91 | return 0; |
92 | 92 | ||
93 | uint priority; | 93 | uint priority; |
94 | 94 | ||
95 | switch (m_scene.UpdatePrioritizationScheme) | 95 | switch (m_scene.UpdatePrioritizationScheme) |
96 | { | 96 | { |
97 | /* | ||
97 | case UpdatePrioritizationSchemes.Time: | 98 | case UpdatePrioritizationSchemes.Time: |
98 | priority = GetPriorityByTime(client, entity); | 99 | priority = GetPriorityByTime(client, entity); |
99 | break; | 100 | break; |
@@ -106,13 +107,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
106 | case UpdatePrioritizationSchemes.FrontBack: | 107 | case UpdatePrioritizationSchemes.FrontBack: |
107 | priority = GetPriorityByFrontBack(client, entity); | 108 | priority = GetPriorityByFrontBack(client, entity); |
108 | break; | 109 | break; |
110 | */ | ||
111 | case UpdatePrioritizationSchemes.SimpleAngularDistance: | ||
112 | priority = GetPriorityByAngularDistance(client, entity); // TODO: Reimplement SimpleAngularDistance | ||
113 | break; | ||
109 | case UpdatePrioritizationSchemes.BestAvatarResponsiveness: | 114 | case UpdatePrioritizationSchemes.BestAvatarResponsiveness: |
115 | default: | ||
110 | priority = GetPriorityByBestAvatarResponsiveness(client, entity); | 116 | priority = GetPriorityByBestAvatarResponsiveness(client, entity); |
111 | break; | 117 | break; |
112 | default: | ||
113 | throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); | ||
114 | } | 118 | } |
115 | 119 | ||
116 | return priority; | 120 | return priority; |
117 | } | 121 | } |
118 | 122 | ||
@@ -141,7 +145,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
141 | 145 | ||
142 | return ComputeDistancePriority(client,entity,false); | 146 | return ComputeDistancePriority(client,entity,false); |
143 | } | 147 | } |
144 | 148 | ||
145 | private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) | 149 | private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) |
146 | { | 150 | { |
147 | // And anything attached to this avatar gets top priority as well | 151 | // And anything attached to this avatar gets top priority as well |
@@ -157,30 +161,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
157 | 161 | ||
158 | private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) | 162 | private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) |
159 | { | 163 | { |
160 | uint pqueue = ComputeDistancePriority(client,entity,true); | 164 | uint pqueue = 2; // keep compiler happy |
161 | 165 | ||
162 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); | 166 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); |
163 | if (presence != null) | 167 | if (presence != null) |
164 | { | 168 | { |
165 | if (!presence.IsChildAgent) | 169 | // All avatars other than our own go into pqueue 1 |
170 | if (entity is ScenePresence) | ||
171 | return 1; | ||
172 | |||
173 | if (entity is SceneObjectPart) | ||
166 | { | 174 | { |
167 | // All avatars other than our own go into pqueue 1 | 175 | SceneObjectGroup sog = ((SceneObjectPart)entity).ParentGroup; |
168 | if (entity is ScenePresence) | 176 | // Attachments are high priority, |
169 | return 1; | 177 | if (sog.IsAttachment) |
178 | return 2; | ||
170 | 179 | ||
171 | if (entity is SceneObjectPart) | 180 | |
181 | if(presence.ParentPart != null) | ||
172 | { | 182 | { |
173 | // Attachments are high priority, | 183 | if(presence.ParentPart.ParentGroup == sog) |
174 | if (((SceneObjectPart)entity).ParentGroup.IsAttachment) | 184 | return 2; |
175 | return 1; | ||
176 | |||
177 | // Non physical prims are lower priority than physical prims | ||
178 | PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; | ||
179 | if (physActor == null || !physActor.IsPhysical) | ||
180 | pqueue++; | ||
181 | } | 185 | } |
186 | |||
187 | pqueue = ComputeDistancePriority(client, entity, false); | ||
188 | |||
189 | // Non physical prims are lower priority than physical prims | ||
190 | PhysicsActor physActor = sog.RootPart.PhysActor; | ||
191 | if (physActor == null || !physActor.IsPhysical) | ||
192 | pqueue++; | ||
182 | } | 193 | } |
183 | } | 194 | } |
195 | else | ||
196 | pqueue = ComputeDistancePriority(client, entity, false); | ||
184 | 197 | ||
185 | return pqueue; | 198 | return pqueue; |
186 | } | 199 | } |
@@ -191,7 +204,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
191 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); | 204 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); |
192 | if (presence == null) | 205 | if (presence == null) |
193 | { | 206 | { |
194 | // this shouldn't happen, it basically means that we are prioritizing | 207 | // this shouldn't happen, it basically means that we are prioritizing |
195 | // updates to send to a client that doesn't have a presence in the scene | 208 | // updates to send to a client that doesn't have a presence in the scene |
196 | // seems like there's race condition here... | 209 | // seems like there's race condition here... |
197 | 210 | ||
@@ -199,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
199 | // throw new InvalidOperationException("Prioritization agent not defined"); | 212 | // throw new InvalidOperationException("Prioritization agent not defined"); |
200 | return PriorityQueue.NumberOfQueues - 1; | 213 | return PriorityQueue.NumberOfQueues - 1; |
201 | } | 214 | } |
202 | 215 | ||
203 | // Use group position for child prims, since we are putting child prims in | 216 | // Use group position for child prims, since we are putting child prims in |
204 | // the same queue with the root of the group, the root prim (which goes into | 217 | // the same queue with the root of the group, the root prim (which goes into |
205 | // the queue first) should always be sent first, no need to adjust child prim | 218 | // the queue first) should always be sent first, no need to adjust child prim |
@@ -212,25 +225,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
212 | } | 225 | } |
213 | 226 | ||
214 | // Use the camera position for local agents and avatar position for remote agents | 227 | // Use the camera position for local agents and avatar position for remote agents |
215 | Vector3 presencePos = (presence.IsChildAgent) ? | 228 | // Why would I want that? They could be camming but I still see them at the |
216 | presence.AbsolutePosition : | 229 | // avatar position, so why should I update them as if they were at their |
217 | presence.CameraPosition; | 230 | // camera positions? Makes no sense! |
231 | // TODO: Fix this mess | ||
232 | //Vector3 presencePos = (presence.IsChildAgent) ? | ||
233 | // presence.AbsolutePosition : | ||
234 | // presence.CameraPosition; | ||
235 | |||
236 | Vector3 presencePos = presence.AbsolutePosition; | ||
218 | 237 | ||
219 | // Compute the distance... | 238 | // Compute the distance... |
220 | double distance = Vector3.Distance(presencePos, entityPos); | 239 | double distance = Vector3.Distance(presencePos, entityPos); |
221 | 240 | ||
222 | // And convert the distance to a priority queue, this computation gives queues | 241 | // And convert the distance to a priority queue, this computation gives queues |
223 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m | 242 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m |
224 | uint pqueue = PriorityQueue.NumberOfImmediateQueues; | 243 | uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue |
225 | uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; | 244 | uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; |
226 | 245 | /* | |
227 | for (int i = 0; i < queues - 1; i++) | 246 | for (int i = 0; i < queues - 1; i++) |
228 | { | 247 | { |
229 | if (distance < 10 * Math.Pow(2.0,i)) | 248 | if (distance < 30 * Math.Pow(2.0,i)) |
230 | break; | 249 | break; |
231 | pqueue++; | 250 | pqueue++; |
232 | } | 251 | } |
233 | 252 | */ | |
253 | if (distance > 10f) | ||
254 | { | ||
255 | float tmp = (float)Math.Log((double)distance) * 1.442695f - 3.321928f; | ||
256 | // for a map identical to original: | ||
257 | // now | ||
258 | // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) | ||
259 | // 2st constant makes it be log2(distance/10) | ||
260 | pqueue += (uint)tmp; | ||
261 | if (pqueue > queues - 1) | ||
262 | pqueue = queues - 1; | ||
263 | } | ||
264 | |||
234 | // If this is a root agent, then determine front & back | 265 | // If this is a root agent, then determine front & back |
235 | // Bump up the priority queue (drop the priority) for any objects behind the avatar | 266 | // Bump up the priority queue (drop the priority) for any objects behind the avatar |
236 | if (useFrontBack && ! presence.IsChildAgent) | 267 | if (useFrontBack && ! presence.IsChildAgent) |
@@ -242,12 +273,81 @@ namespace OpenSim.Region.Framework.Scenes | |||
242 | // Plane equation | 273 | // Plane equation |
243 | float d = -Vector3.Dot(camPosition, camAtAxis); | 274 | float d = -Vector3.Dot(camPosition, camAtAxis); |
244 | float p = Vector3.Dot(camAtAxis, entityPos) + d; | 275 | float p = Vector3.Dot(camAtAxis, entityPos) + d; |
245 | if (p < 0.0f) | 276 | if (p < 0.0f) |
246 | pqueue++; | 277 | pqueue++; |
247 | } | 278 | } |
248 | 279 | ||
249 | return pqueue; | 280 | return pqueue; |
250 | } | 281 | } |
251 | 282 | ||
283 | private uint GetPriorityByAngularDistance(IClientAPI client, ISceneEntity entity) | ||
284 | { | ||
285 | ScenePresence presence = m_scene.GetScenePresence(client.AgentId); | ||
286 | if (presence == null) | ||
287 | return PriorityQueue.NumberOfQueues - 1; | ||
288 | |||
289 | uint pqueue = ComputeAngleDistancePriority(presence, entity); | ||
290 | return pqueue; | ||
291 | } | ||
292 | |||
293 | private uint ComputeAngleDistancePriority(ScenePresence presence, ISceneEntity entity) | ||
294 | { | ||
295 | // And convert the distance to a priority queue, this computation gives queues | ||
296 | // at 10, 20, 40, 80, 160, 320, 640, and 1280m | ||
297 | // uint minpqueue = PriorityQueue.NumberOfImmediateQueues; | ||
298 | uint maxqueue = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues -1; | ||
299 | // uint pqueue = minpqueue; | ||
300 | uint pqueue = PriorityQueue.NumberOfImmediateQueues; | ||
301 | float distance; | ||
302 | |||
303 | Vector3 presencePos = presence.AbsolutePosition; | ||
304 | if(entity is ScenePresence) | ||
305 | { | ||
306 | ScenePresence sp = entity as ScenePresence; | ||
307 | distance = Vector3.Distance(presencePos, sp.AbsolutePosition); | ||
308 | distance *= 0.5f; | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; | ||
313 | if(presence.ParentPart != null) | ||
314 | { | ||
315 | if(presence.ParentPart.ParentGroup == group) | ||
316 | return pqueue; | ||
317 | } | ||
318 | if(group.IsAttachment) | ||
319 | { | ||
320 | if(group.RootPart.LocalId == presence.LocalId) | ||
321 | return pqueue; | ||
322 | } | ||
323 | |||
324 | float bradius = group.GetBoundsRadius(); | ||
325 | Vector3 grppos = group.AbsolutePosition + group.getBoundsCenter(); | ||
326 | distance = Vector3.Distance(presencePos, grppos); | ||
327 | distance -= bradius; | ||
328 | distance *= group.getAreaFactor(); | ||
329 | if(group.IsAttachment) | ||
330 | distance *= 0.5f; | ||
331 | else if(group.UsesPhysics) | ||
332 | distance *= 0.6f; | ||
333 | else if(group.GetSittingAvatarsCount() > 0) | ||
334 | distance *= 0.5f; | ||
335 | } | ||
336 | |||
337 | if (distance > 10f) | ||
338 | { | ||
339 | float tmp = (float)Math.Log(distance) * 1.442695f - 3.321928f; | ||
340 | // for a map identical to original: | ||
341 | // now | ||
342 | // 1st constant is 1/(log(2)) (natural log) so we get log2(distance) | ||
343 | // 2st constant makes it be log2(distance/10) | ||
344 | |||
345 | pqueue += (uint)tmp; | ||
346 | if (pqueue > maxqueue) | ||
347 | pqueue = maxqueue; | ||
348 | } | ||
349 | |||
350 | return pqueue; | ||
351 | } | ||
252 | } | 352 | } |
253 | } | 353 | } |