Speed improvement mostly when sensing objects especially noticeable in a sim with many objects.

0.6.3-post-fixes
idb 2009-01-31 19:02:09 +00:00
parent 4a120e9dd5
commit 1a14066aa6
1 changed files with 69 additions and 22 deletions

View File

@ -73,6 +73,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
public SceneObjectPart host;
}
//
// Sensed entity
//
private class SensedEntity : IComparable
{
public SensedEntity(double detectedDistance, UUID detectedID)
{
distance = detectedDistance;
itemID = detectedID;
}
public int CompareTo(object obj)
{
if (!(obj is SensedEntity)) throw new InvalidOperationException();
SensedEntity ent = (SensedEntity)obj;
if (ent == null || ent.distance < distance) return 1;
if (ent.distance > distance) return -1;
return 0;
}
public UUID itemID;
public double distance;
}
private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
private object SenseRepeatListLock = new object();
@ -175,23 +197,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
return;
}
LSL_Types.list SensedObjects = new LSL_Types.list();
List<SensedEntity> sensedEntities = new List<SensedEntity>();
// Is the sensor type is AGENT and not SCRIPTED then include agents
if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0)
{
doAgentSensor(ts, SensedObjects);
sensedEntities.AddRange(doAgentSensor(ts));
}
// If SCRIPTED or PASSIVE or ACTIVE check objects
if ((ts.type & SCRIPTED) != 0 || (ts.type & PASSIVE) != 0 || (ts.type & ACTIVE) != 0)
{
doObjectSensor(ts, SensedObjects);
sensedEntities.AddRange(doObjectSensor(ts));
}
lock (SenseLock)
{
if (SensedObjects.Length == 0)
if (sensedEntities.Count == 0)
{
// send a "no_sensor"
// Add it to queue
@ -201,9 +223,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
}
else
{
// the sort is stride = 2 and ascending to get everything ordered by distance
SensedObjects = SensedObjects.Sort(2, 1);
int count = SensedObjects.Length;
// Sort the list to get everything ordered by distance
sensedEntities.Sort();
int count = sensedEntities.Count;
int idx;
List<DetectParams> detected = new List<DetectParams>();
for (idx = 0; idx < count; idx++)
@ -211,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
try
{
DetectParams detect = new DetectParams();
detect.Key = (UUID)(SensedObjects.Data[(idx * 2) + 1]);
detect.Key = sensedEntities[idx].itemID;
detect.Populate(m_CmdManager.m_ScriptEngine.World);
detected.Add(detect);
}
@ -244,9 +266,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
}
}
private void doObjectSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects)
private List<SensedEntity> doObjectSensor(SenseRepeatClass ts)
{
List<EntityBase> Entities;
List<SensedEntity> sensedEntities = new List<SensedEntity>();
// If this is an object sense by key try to get it directly
// rather than getting a list to scan through
@ -255,7 +278,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
EntityBase e = null;
m_CmdManager.m_ScriptEngine.World.Entities.TryGetValue(ts.keyID, out e);
if (e == null)
return;
return sensedEntities;
Entities = new List<EntityBase>();
Entities.Add(e);
}
@ -266,7 +289,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
SceneObjectPart SensePoint = ts.host;
Vector3 fromRegionPos = SensePoint.AbsolutePosition;
// pre define some things to avoid repeated definitions in the loop body
Vector3 toRegionPos;
double dis;
int objtype;
SceneObjectPart part;
float dx;
float dy;
float dz;
Quaternion q = SensePoint.RotationOffset;
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
@ -289,13 +321,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
if (!(ent is SceneObjectGroup)) // dont bother if it is a pesky avatar
continue;
toRegionPos = ent.AbsolutePosition;
double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos));
// Calculation is in line for speed
dx = toRegionPos.X - fromRegionPos.X;
dy = toRegionPos.Y - fromRegionPos.Y;
dz = toRegionPos.Z - fromRegionPos.Z;
// Weed out those that will not fit in a cube the size of the range
// no point calculating if they are within a sphere the size of the range
// if they arent even in the cube
if (Math.Abs(dx) > ts.range || Math.Abs(dy) > ts.range || Math.Abs(dz) > ts.range)
dis = ts.range + 1.0;
else
dis = Math.Sqrt(dx * dx + dy * dy + dz * dz);
if (keep && dis <= ts.range && ts.host.UUID != ent.UUID)
{
// In Range and not the object containing the script, is it the right Type ?
int objtype = 0;
objtype = 0;
SceneObjectPart part = ((SceneObjectGroup)ent).RootPart;
part = ((SceneObjectGroup)ent).RootPart;
if (part.AttachmentPoint != 0) // Attached so ignore
continue;
@ -347,17 +392,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
if (keep == true)
{
// add distance for sorting purposes later
SensedObjects.Add(new LSL_Types.LSLFloat(dis));
SensedObjects.Add(ent.UUID);
sensedEntities.Add(new SensedEntity(dis, ent.UUID));
}
}
}
}
return sensedEntities;
}
private void doAgentSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects)
private List<SensedEntity> doAgentSensor(SenseRepeatClass ts)
{
List<ScenePresence> Presences;
List<SensedEntity> sensedEntities = new List<SensedEntity>();
// If this is an avatar sense by key try to get them directly
// rather than getting a list to scan through
@ -365,7 +411,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
ScenePresence p = m_CmdManager.m_ScriptEngine.World.GetScenePresence(ts.keyID);
if (p == null)
return;
return sensedEntities;
Presences = new List<ScenePresence>();
Presences.Add(p);
}
@ -376,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
// If nobody about quit fast
if (Presences.Count == 0)
return;
return sensedEntities;
SceneObjectPart SensePoint = ts.host;
@ -390,6 +436,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
bool attached = (SensePoint.AttachmentPoint != 0);
bool nameSearch = (ts.name != null && ts.name != "");
Vector3 toRegionPos;
double dis;
foreach (ScenePresence presence in Presences)
{
@ -402,7 +449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
keep = false;
toRegionPos = presence.AbsolutePosition;
double dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos));
dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos));
// are they in range
if (keep && dis <= ts.range)
@ -452,14 +499,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
if (keep) // add to list with distance
{
SensedObjects.Add(new LSL_Types.LSLFloat(dis));
SensedObjects.Add(presence.UUID);
sensedEntities.Add(new SensedEntity(dis, presence.UUID));
}
// If this is a search by name and we have just found it then no more to do
if (nameSearch && ts.name == presence.Name)
return;
return sensedEntities;
}
return sensedEntities;
}
public Object[] GetSerializationData(UUID itemID)