diff options
Speed improvement mostly when sensing objects especially noticeable in a sim with many objects.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | 91 |
1 files changed, 69 insertions, 22 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 946765a..808d880 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | |||
@@ -73,6 +73,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
73 | public SceneObjectPart host; | 73 | public SceneObjectPart host; |
74 | } | 74 | } |
75 | 75 | ||
76 | // | ||
77 | // Sensed entity | ||
78 | // | ||
79 | private class SensedEntity : IComparable | ||
80 | { | ||
81 | public SensedEntity(double detectedDistance, UUID detectedID) | ||
82 | { | ||
83 | distance = detectedDistance; | ||
84 | itemID = detectedID; | ||
85 | } | ||
86 | public int CompareTo(object obj) | ||
87 | { | ||
88 | if (!(obj is SensedEntity)) throw new InvalidOperationException(); | ||
89 | SensedEntity ent = (SensedEntity)obj; | ||
90 | if (ent == null || ent.distance < distance) return 1; | ||
91 | if (ent.distance > distance) return -1; | ||
92 | return 0; | ||
93 | } | ||
94 | public UUID itemID; | ||
95 | public double distance; | ||
96 | } | ||
97 | |||
76 | private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); | 98 | private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); |
77 | private object SenseRepeatListLock = new object(); | 99 | private object SenseRepeatListLock = new object(); |
78 | 100 | ||
@@ -175,23 +197,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
175 | return; | 197 | return; |
176 | } | 198 | } |
177 | 199 | ||
178 | LSL_Types.list SensedObjects = new LSL_Types.list(); | 200 | List<SensedEntity> sensedEntities = new List<SensedEntity>(); |
179 | 201 | ||
180 | // Is the sensor type is AGENT and not SCRIPTED then include agents | 202 | // Is the sensor type is AGENT and not SCRIPTED then include agents |
181 | if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0) | 203 | if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0) |
182 | { | 204 | { |
183 | doAgentSensor(ts, SensedObjects); | 205 | sensedEntities.AddRange(doAgentSensor(ts)); |
184 | } | 206 | } |
185 | 207 | ||
186 | // If SCRIPTED or PASSIVE or ACTIVE check objects | 208 | // If SCRIPTED or PASSIVE or ACTIVE check objects |
187 | if ((ts.type & SCRIPTED) != 0 || (ts.type & PASSIVE) != 0 || (ts.type & ACTIVE) != 0) | 209 | if ((ts.type & SCRIPTED) != 0 || (ts.type & PASSIVE) != 0 || (ts.type & ACTIVE) != 0) |
188 | { | 210 | { |
189 | doObjectSensor(ts, SensedObjects); | 211 | sensedEntities.AddRange(doObjectSensor(ts)); |
190 | } | 212 | } |
191 | 213 | ||
192 | lock (SenseLock) | 214 | lock (SenseLock) |
193 | { | 215 | { |
194 | if (SensedObjects.Length == 0) | 216 | if (sensedEntities.Count == 0) |
195 | { | 217 | { |
196 | // send a "no_sensor" | 218 | // send a "no_sensor" |
197 | // Add it to queue | 219 | // Add it to queue |
@@ -201,9 +223,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
201 | } | 223 | } |
202 | else | 224 | else |
203 | { | 225 | { |
204 | // the sort is stride = 2 and ascending to get everything ordered by distance | 226 | // Sort the list to get everything ordered by distance |
205 | SensedObjects = SensedObjects.Sort(2, 1); | 227 | sensedEntities.Sort(); |
206 | int count = SensedObjects.Length; | 228 | int count = sensedEntities.Count; |
207 | int idx; | 229 | int idx; |
208 | List<DetectParams> detected = new List<DetectParams>(); | 230 | List<DetectParams> detected = new List<DetectParams>(); |
209 | for (idx = 0; idx < count; idx++) | 231 | for (idx = 0; idx < count; idx++) |
@@ -211,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
211 | try | 233 | try |
212 | { | 234 | { |
213 | DetectParams detect = new DetectParams(); | 235 | DetectParams detect = new DetectParams(); |
214 | detect.Key = (UUID)(SensedObjects.Data[(idx * 2) + 1]); | 236 | detect.Key = sensedEntities[idx].itemID; |
215 | detect.Populate(m_CmdManager.m_ScriptEngine.World); | 237 | detect.Populate(m_CmdManager.m_ScriptEngine.World); |
216 | detected.Add(detect); | 238 | detected.Add(detect); |
217 | } | 239 | } |
@@ -244,9 +266,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
244 | } | 266 | } |
245 | } | 267 | } |
246 | 268 | ||
247 | private void doObjectSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects) | 269 | private List<SensedEntity> doObjectSensor(SenseRepeatClass ts) |
248 | { | 270 | { |
249 | List<EntityBase> Entities; | 271 | List<EntityBase> Entities; |
272 | List<SensedEntity> sensedEntities = new List<SensedEntity>(); | ||
250 | 273 | ||
251 | // If this is an object sense by key try to get it directly | 274 | // If this is an object sense by key try to get it directly |
252 | // rather than getting a list to scan through | 275 | // rather than getting a list to scan through |
@@ -255,7 +278,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
255 | EntityBase e = null; | 278 | EntityBase e = null; |
256 | m_CmdManager.m_ScriptEngine.World.Entities.TryGetValue(ts.keyID, out e); | 279 | m_CmdManager.m_ScriptEngine.World.Entities.TryGetValue(ts.keyID, out e); |
257 | if (e == null) | 280 | if (e == null) |
258 | return; | 281 | return sensedEntities; |
259 | Entities = new List<EntityBase>(); | 282 | Entities = new List<EntityBase>(); |
260 | Entities.Add(e); | 283 | Entities.Add(e); |
261 | } | 284 | } |
@@ -266,7 +289,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
266 | SceneObjectPart SensePoint = ts.host; | 289 | SceneObjectPart SensePoint = ts.host; |
267 | 290 | ||
268 | Vector3 fromRegionPos = SensePoint.AbsolutePosition; | 291 | Vector3 fromRegionPos = SensePoint.AbsolutePosition; |
292 | |||
293 | // pre define some things to avoid repeated definitions in the loop body | ||
269 | Vector3 toRegionPos; | 294 | Vector3 toRegionPos; |
295 | double dis; | ||
296 | int objtype; | ||
297 | SceneObjectPart part; | ||
298 | float dx; | ||
299 | float dy; | ||
300 | float dz; | ||
301 | |||
270 | Quaternion q = SensePoint.RotationOffset; | 302 | Quaternion q = SensePoint.RotationOffset; |
271 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); | 303 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); |
272 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); | 304 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); |
@@ -289,13 +321,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
289 | if (!(ent is SceneObjectGroup)) // dont bother if it is a pesky avatar | 321 | if (!(ent is SceneObjectGroup)) // dont bother if it is a pesky avatar |
290 | continue; | 322 | continue; |
291 | toRegionPos = ent.AbsolutePosition; | 323 | toRegionPos = ent.AbsolutePosition; |
292 | double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos)); | 324 | |
325 | // Calculation is in line for speed | ||
326 | dx = toRegionPos.X - fromRegionPos.X; | ||
327 | dy = toRegionPos.Y - fromRegionPos.Y; | ||
328 | dz = toRegionPos.Z - fromRegionPos.Z; | ||
329 | |||
330 | // Weed out those that will not fit in a cube the size of the range | ||
331 | // no point calculating if they are within a sphere the size of the range | ||
332 | // if they arent even in the cube | ||
333 | if (Math.Abs(dx) > ts.range || Math.Abs(dy) > ts.range || Math.Abs(dz) > ts.range) | ||
334 | dis = ts.range + 1.0; | ||
335 | else | ||
336 | dis = Math.Sqrt(dx * dx + dy * dy + dz * dz); | ||
337 | |||
293 | if (keep && dis <= ts.range && ts.host.UUID != ent.UUID) | 338 | if (keep && dis <= ts.range && ts.host.UUID != ent.UUID) |
294 | { | 339 | { |
295 | // In Range and not the object containing the script, is it the right Type ? | 340 | // In Range and not the object containing the script, is it the right Type ? |
296 | int objtype = 0; | 341 | objtype = 0; |
297 | 342 | ||
298 | SceneObjectPart part = ((SceneObjectGroup)ent).RootPart; | 343 | part = ((SceneObjectGroup)ent).RootPart; |
299 | if (part.AttachmentPoint != 0) // Attached so ignore | 344 | if (part.AttachmentPoint != 0) // Attached so ignore |
300 | continue; | 345 | continue; |
301 | 346 | ||
@@ -347,17 +392,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
347 | if (keep == true) | 392 | if (keep == true) |
348 | { | 393 | { |
349 | // add distance for sorting purposes later | 394 | // add distance for sorting purposes later |
350 | SensedObjects.Add(new LSL_Types.LSLFloat(dis)); | 395 | sensedEntities.Add(new SensedEntity(dis, ent.UUID)); |
351 | SensedObjects.Add(ent.UUID); | ||
352 | } | 396 | } |
353 | } | 397 | } |
354 | } | 398 | } |
355 | } | 399 | } |
400 | return sensedEntities; | ||
356 | } | 401 | } |
357 | 402 | ||
358 | private void doAgentSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects) | 403 | private List<SensedEntity> doAgentSensor(SenseRepeatClass ts) |
359 | { | 404 | { |
360 | List<ScenePresence> Presences; | 405 | List<ScenePresence> Presences; |
406 | List<SensedEntity> sensedEntities = new List<SensedEntity>(); | ||
361 | 407 | ||
362 | // If this is an avatar sense by key try to get them directly | 408 | // If this is an avatar sense by key try to get them directly |
363 | // rather than getting a list to scan through | 409 | // rather than getting a list to scan through |
@@ -365,7 +411,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
365 | { | 411 | { |
366 | ScenePresence p = m_CmdManager.m_ScriptEngine.World.GetScenePresence(ts.keyID); | 412 | ScenePresence p = m_CmdManager.m_ScriptEngine.World.GetScenePresence(ts.keyID); |
367 | if (p == null) | 413 | if (p == null) |
368 | return; | 414 | return sensedEntities; |
369 | Presences = new List<ScenePresence>(); | 415 | Presences = new List<ScenePresence>(); |
370 | Presences.Add(p); | 416 | Presences.Add(p); |
371 | } | 417 | } |
@@ -376,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
376 | 422 | ||
377 | // If nobody about quit fast | 423 | // If nobody about quit fast |
378 | if (Presences.Count == 0) | 424 | if (Presences.Count == 0) |
379 | return; | 425 | return sensedEntities; |
380 | 426 | ||
381 | SceneObjectPart SensePoint = ts.host; | 427 | SceneObjectPart SensePoint = ts.host; |
382 | 428 | ||
@@ -390,6 +436,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
390 | bool attached = (SensePoint.AttachmentPoint != 0); | 436 | bool attached = (SensePoint.AttachmentPoint != 0); |
391 | bool nameSearch = (ts.name != null && ts.name != ""); | 437 | bool nameSearch = (ts.name != null && ts.name != ""); |
392 | Vector3 toRegionPos; | 438 | Vector3 toRegionPos; |
439 | double dis; | ||
393 | 440 | ||
394 | foreach (ScenePresence presence in Presences) | 441 | foreach (ScenePresence presence in Presences) |
395 | { | 442 | { |
@@ -402,7 +449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
402 | keep = false; | 449 | keep = false; |
403 | toRegionPos = presence.AbsolutePosition; | 450 | toRegionPos = presence.AbsolutePosition; |
404 | 451 | ||
405 | double dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos)); | 452 | dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos)); |
406 | 453 | ||
407 | // are they in range | 454 | // are they in range |
408 | if (keep && dis <= ts.range) | 455 | if (keep && dis <= ts.range) |
@@ -452,14 +499,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins | |||
452 | 499 | ||
453 | if (keep) // add to list with distance | 500 | if (keep) // add to list with distance |
454 | { | 501 | { |
455 | SensedObjects.Add(new LSL_Types.LSLFloat(dis)); | 502 | sensedEntities.Add(new SensedEntity(dis, presence.UUID)); |
456 | SensedObjects.Add(presence.UUID); | ||
457 | } | 503 | } |
458 | 504 | ||
459 | // If this is a search by name and we have just found it then no more to do | 505 | // If this is a search by name and we have just found it then no more to do |
460 | if (nameSearch && ts.name == presence.Name) | 506 | if (nameSearch && ts.name == presence.Name) |
461 | return; | 507 | return sensedEntities; |
462 | } | 508 | } |
509 | return sensedEntities; | ||
463 | } | 510 | } |
464 | 511 | ||
465 | public Object[] GetSerializationData(UUID itemID) | 512 | public Object[] GetSerializationData(UUID itemID) |