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