aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/Prioritizer.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs122
1 files changed, 122 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
new file mode 100644
index 0000000..af25014
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -0,0 +1,122 @@
1using System;
2using System.Collections.Generic;
3using log4net;
4using Nini.Config;
5using OpenSim.Framework;
6using OpenMetaverse;
7
8namespace OpenSim.Region.Framework.Scenes
9{
10 public enum UpdatePrioritizationSchemes
11 {
12 Time = 0,
13 Distance = 1,
14 SimpleAngularDistance = 2,
15 FrontBack = 3,
16 }
17
18 public class Prioritizer
19 {
20 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
21
22 private Scene m_scene;
23
24 public Prioritizer(Scene scene)
25 {
26 m_scene = scene;
27 }
28
29 public double GetUpdatePriority(IClientAPI client, ISceneEntity entity)
30 {
31 switch (m_scene.UpdatePrioritizationScheme)
32 {
33 case UpdatePrioritizationSchemes.Time:
34 return GetPriorityByTime();
35 case UpdatePrioritizationSchemes.Distance:
36 return GetPriorityByDistance(client, entity);
37 case UpdatePrioritizationSchemes.SimpleAngularDistance:
38 return GetPriorityByDistance(client, entity);
39 case UpdatePrioritizationSchemes.FrontBack:
40 return GetPriorityByFrontBack(client, entity);
41 default:
42 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
43 }
44 }
45
46 private double GetPriorityByTime()
47 {
48 return DateTime.UtcNow.ToOADate();
49 }
50
51 private double GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
52 {
53 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
54 if (presence != null)
55 {
56 // If this is an update for our own avatar give it the highest priority
57 if (presence == entity)
58 return 0.0;
59
60 // Use the camera position for local agents and avatar position for remote agents
61 Vector3 presencePos = (presence.IsChildAgent) ?
62 presence.AbsolutePosition :
63 presence.CameraPosition;
64
65 // Use group position for child prims
66 Vector3 entityPos;
67 if (entity is SceneObjectPart)
68 entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
69 else
70 entityPos = entity.AbsolutePosition;
71
72 return Vector3.DistanceSquared(presencePos, entityPos);
73 }
74
75 return double.NaN;
76 }
77
78 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
79 {
80 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
81 if (presence != null)
82 {
83 // If this is an update for our own avatar give it the highest priority
84 if (presence == entity)
85 return 0.0;
86
87 // Use group position for child prims
88 Vector3 entityPos = entity.AbsolutePosition;
89 if (entity is SceneObjectPart)
90 entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
91 else
92 entityPos = entity.AbsolutePosition;
93
94 if (!presence.IsChildAgent)
95 {
96 // Root agent. Use distance from camera and a priority decrease for objects behind us
97 Vector3 camPosition = presence.CameraPosition;
98 Vector3 camAtAxis = presence.CameraAtAxis;
99
100 // Distance
101 double priority = Vector3.DistanceSquared(camPosition, entityPos);
102
103 // Plane equation
104 float d = -Vector3.Dot(camPosition, camAtAxis);
105 float p = Vector3.Dot(camAtAxis, entityPos) + d;
106 if (p < 0.0f) priority *= 2.0;
107
108 return priority;
109 }
110 else
111 {
112 // Child agent. Use the normal distance method
113 Vector3 presencePos = presence.AbsolutePosition;
114
115 return Vector3.DistanceSquared(presencePos, entityPos);
116 }
117 }
118
119 return double.NaN;
120 }
121 }
122}