Fix hit testing link sets properly. Fix raycasting for LSL.
parent
69f29cb53e
commit
8a9a8ed5c9
|
@ -789,6 +789,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
EntityIntersection result = new EntityIntersection();
|
EntityIntersection result = new EntityIntersection();
|
||||||
|
|
||||||
SceneObjectPart[] parts = m_parts.GetArray();
|
SceneObjectPart[] parts = m_parts.GetArray();
|
||||||
|
|
||||||
|
// Find closest hit here
|
||||||
|
float idist = float.MaxValue;
|
||||||
|
|
||||||
for (int i = 0; i < parts.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
{
|
{
|
||||||
SceneObjectPart part = parts[i];
|
SceneObjectPart part = parts[i];
|
||||||
|
@ -803,11 +807,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
|
EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
|
||||||
|
|
||||||
// This may need to be updated to the maximum draw distance possible..
|
|
||||||
// We might (and probably will) be checking for prim creation from other sims
|
|
||||||
// when the camera crosses the border.
|
|
||||||
float idist = Constants.RegionSize;
|
|
||||||
|
|
||||||
if (inter.HitTF)
|
if (inter.HitTF)
|
||||||
{
|
{
|
||||||
// We need to find the closest prim to return to the testcaller along the ray
|
// We need to find the closest prim to return to the testcaller along the ray
|
||||||
|
@ -818,8 +817,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
result.obj = part;
|
result.obj = part;
|
||||||
result.normal = inter.normal;
|
result.normal = inter.normal;
|
||||||
result.distance = inter.distance;
|
result.distance = inter.distance;
|
||||||
|
|
||||||
|
idist = inter.distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
|
public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
|
||||||
{
|
{
|
||||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
protected IScriptEngine m_ScriptEngine;
|
protected IScriptEngine m_ScriptEngine;
|
||||||
protected SceneObjectPart m_host;
|
protected SceneObjectPart m_host;
|
||||||
protected uint m_localID;
|
protected uint m_localID;
|
||||||
|
@ -11124,153 +11124,382 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
m_SayShoutCount = 0;
|
m_SayShoutCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct Tri
|
||||||
|
{
|
||||||
|
public Vector3 p1;
|
||||||
|
public Vector3 p2;
|
||||||
|
public Vector3 p3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool InBoundingBox(ScenePresence avatar, Vector3 point)
|
||||||
|
{
|
||||||
|
float height = avatar.Appearance.AvatarHeight;
|
||||||
|
Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
|
||||||
|
Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
|
||||||
|
|
||||||
|
if (point.X > b1.X && point.X < b2.X &&
|
||||||
|
point.Y > b1.Y && point.Y < b2.Y &&
|
||||||
|
point.Z > b1.Z && point.Z < b2.Z)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
|
||||||
|
{
|
||||||
|
List<ContactResult> contacts = new List<ContactResult>();
|
||||||
|
|
||||||
|
Vector3 ab = rayEnd - rayStart;
|
||||||
|
|
||||||
|
World.ForEachScenePresence(delegate(ScenePresence sp)
|
||||||
|
{
|
||||||
|
Vector3 ac = sp.AbsolutePosition - rayStart;
|
||||||
|
Vector3 bc = sp.AbsolutePosition - rayEnd;
|
||||||
|
|
||||||
|
double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
|
||||||
|
|
||||||
|
if (d > 1.5)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
|
||||||
|
|
||||||
|
if (d2 > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
|
||||||
|
Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
|
||||||
|
|
||||||
|
if (!InBoundingBox(sp, p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ContactResult result = new ContactResult ();
|
||||||
|
result.ConsumerID = sp.LocalId;
|
||||||
|
result.Depth = Vector3.Distance(rayStart, p);
|
||||||
|
result.Normal = Vector3.Zero;
|
||||||
|
result.Pos = p;
|
||||||
|
|
||||||
|
contacts.Add(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
return contacts.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd)
|
||||||
|
{
|
||||||
|
Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
|
||||||
|
List<ContactResult> contacts = new List<ContactResult>();
|
||||||
|
|
||||||
|
Vector3 ab = rayEnd - rayStart;
|
||||||
|
|
||||||
|
World.ForEachSOG(delegate(SceneObjectGroup group)
|
||||||
|
{
|
||||||
|
if (m_host.ParentGroup == group)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (group.IsAttachment)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find the radius ouside of which we don't even need to hit test
|
||||||
|
float minX;
|
||||||
|
float maxX;
|
||||||
|
float minY;
|
||||||
|
float maxY;
|
||||||
|
float minZ;
|
||||||
|
float maxZ;
|
||||||
|
|
||||||
|
float radius = 0.0f;
|
||||||
|
|
||||||
|
group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
|
||||||
|
|
||||||
|
if (Math.Abs(minX) > radius)
|
||||||
|
radius = Math.Abs(minX);
|
||||||
|
if (Math.Abs(minY) > radius)
|
||||||
|
radius = Math.Abs(minY);
|
||||||
|
if (Math.Abs(minZ) > radius)
|
||||||
|
radius = Math.Abs(minZ);
|
||||||
|
if (Math.Abs(maxX) > radius)
|
||||||
|
radius = Math.Abs(maxX);
|
||||||
|
if (Math.Abs(maxY) > radius)
|
||||||
|
radius = Math.Abs(maxY);
|
||||||
|
if (Math.Abs(maxZ) > radius)
|
||||||
|
radius = Math.Abs(maxZ);
|
||||||
|
|
||||||
|
Vector3 ac = group.AbsolutePosition - rayStart;
|
||||||
|
Vector3 bc = group.AbsolutePosition - rayEnd;
|
||||||
|
|
||||||
|
double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
|
||||||
|
|
||||||
|
// Too far off ray, don't bother
|
||||||
|
if (d > radius)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Behind ray, drop
|
||||||
|
double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
|
||||||
|
if (d2 > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
EntityIntersection intersection = group.TestIntersection(ray, true, false);
|
||||||
|
// Miss.
|
||||||
|
if (!intersection.HitTF)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ContactResult result = new ContactResult ();
|
||||||
|
result.ConsumerID = group.LocalId;
|
||||||
|
result.Depth = intersection.distance;
|
||||||
|
result.Normal = intersection.normal;
|
||||||
|
result.Pos = intersection.ipoint;
|
||||||
|
|
||||||
|
contacts.Add(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
return contacts.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
|
||||||
|
{
|
||||||
|
double[,] heightfield = World.Heightmap.GetDoubles();
|
||||||
|
List<ContactResult> contacts = new List<ContactResult>();
|
||||||
|
|
||||||
|
double min = 2048.0;
|
||||||
|
double max = 0.0;
|
||||||
|
|
||||||
|
// Find the min and max of the heightfield
|
||||||
|
for (int x = 0 ; x < World.Heightmap.Width ; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0 ; y < World.Heightmap.Height ; y++)
|
||||||
|
{
|
||||||
|
if (heightfield[x, y] > max)
|
||||||
|
max = heightfield[x, y];
|
||||||
|
if (heightfield[x, y] < min)
|
||||||
|
min = heightfield[x, y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A ray extends past rayEnd, but doesn't go back before
|
||||||
|
// rayStart. If the start is above the highest point of the ground
|
||||||
|
// and the ray goes up, we can't hit the ground. Ever.
|
||||||
|
if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Same for going down
|
||||||
|
if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<Tri> trilist = new List<Tri>();
|
||||||
|
|
||||||
|
// Create our triangle list
|
||||||
|
for (int x = 1 ; x < World.Heightmap.Width ; x++)
|
||||||
|
{
|
||||||
|
for (int y = 1 ; y < World.Heightmap.Height ; y++)
|
||||||
|
{
|
||||||
|
Tri t1 = new Tri();
|
||||||
|
Tri t2 = new Tri();
|
||||||
|
|
||||||
|
Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
|
||||||
|
Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
|
||||||
|
Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
|
||||||
|
Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
|
||||||
|
|
||||||
|
t1.p1 = p1;
|
||||||
|
t1.p2 = p2;
|
||||||
|
t1.p3 = p3;
|
||||||
|
|
||||||
|
t2.p1 = p3;
|
||||||
|
t2.p2 = p4;
|
||||||
|
t2.p3 = p1;
|
||||||
|
|
||||||
|
trilist.Add(t1);
|
||||||
|
trilist.Add(t2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ray direction
|
||||||
|
Vector3 rayDirection = rayEnd - rayStart;
|
||||||
|
|
||||||
|
foreach (Tri t in trilist)
|
||||||
|
{
|
||||||
|
// Compute triangle plane normal and edges
|
||||||
|
Vector3 u = t.p2 - t.p1;
|
||||||
|
Vector3 v = t.p3 - t.p1;
|
||||||
|
Vector3 n = Vector3.Cross(u, v);
|
||||||
|
|
||||||
|
if (n == Vector3.Zero)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector3 w0 = rayStart - t.p1;
|
||||||
|
double a = -Vector3.Dot(n, w0);
|
||||||
|
double b = Vector3.Dot(n, rayDirection);
|
||||||
|
|
||||||
|
// Not intersecting the plane, or in plane (same thing)
|
||||||
|
// Ignoring this MAY cause the ground to not be detected
|
||||||
|
// sometimes
|
||||||
|
if (Math.Abs(b) < 0.000001)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double r = a / b;
|
||||||
|
|
||||||
|
// ray points away from plane
|
||||||
|
if (r < 0.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
|
||||||
|
|
||||||
|
float uu = Vector3.Dot(u, u);
|
||||||
|
float uv = Vector3.Dot(u, v);
|
||||||
|
float vv = Vector3.Dot(v, v);
|
||||||
|
Vector3 w = ip - t.p1;
|
||||||
|
float wu = Vector3.Dot(w, u);
|
||||||
|
float wv = Vector3.Dot(w, v);
|
||||||
|
float d = uv * uv - uu * vv;
|
||||||
|
|
||||||
|
float cs = (uv * wv - vv * wu) / d;
|
||||||
|
if (cs < 0 || cs > 1.0)
|
||||||
|
continue;
|
||||||
|
float ct = (uv * wu - uu * wv) / d;
|
||||||
|
if (ct < 0 || (cs + ct) > 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Add contact point
|
||||||
|
ContactResult result = new ContactResult ();
|
||||||
|
result.ConsumerID = 0;
|
||||||
|
result.Depth = Vector3.Distance(rayStart, ip);
|
||||||
|
result.Normal = n;
|
||||||
|
result.Pos = ip;
|
||||||
|
|
||||||
|
contacts.Add(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contacts.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
contacts.Sort(delegate(ContactResult a, ContactResult b)
|
||||||
|
{
|
||||||
|
return (int)(a.Depth - b.Depth);
|
||||||
|
});
|
||||||
|
|
||||||
|
return contacts[0];
|
||||||
|
}
|
||||||
|
|
||||||
public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
|
public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
|
||||||
{
|
{
|
||||||
|
LSL_List list = new LSL_List();
|
||||||
|
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z);
|
Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
|
||||||
Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z);
|
Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
|
||||||
Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z);
|
Vector3 dir = rayEnd - rayStart;
|
||||||
|
|
||||||
int count = 0;
|
int count = 1;
|
||||||
// int detectPhantom = 0;
|
bool detectPhantom = false;
|
||||||
int dataFlags = 0;
|
int dataFlags = 0;
|
||||||
int rejectTypes = 0;
|
int rejectTypes = 0;
|
||||||
|
|
||||||
for (int i = 0; i < options.Length; i += 2)
|
for (int i = 0; i < options.Length; i += 2)
|
||||||
{
|
{
|
||||||
if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
|
if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
|
||||||
{
|
|
||||||
count = options.GetLSLIntegerItem(i + 1);
|
count = options.GetLSLIntegerItem(i + 1);
|
||||||
}
|
else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
|
||||||
// else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
|
detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
|
||||||
// {
|
|
||||||
// detectPhantom = options.GetLSLIntegerItem(i + 1);
|
|
||||||
// }
|
|
||||||
else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
|
else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
|
||||||
{
|
|
||||||
dataFlags = options.GetLSLIntegerItem(i + 1);
|
dataFlags = options.GetLSLIntegerItem(i + 1);
|
||||||
}
|
|
||||||
else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
|
else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
|
||||||
{
|
|
||||||
rejectTypes = options.GetLSLIntegerItem(i + 1);
|
rejectTypes = options.GetLSLIntegerItem(i + 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LSL_List list = new LSL_List();
|
if (count > 16)
|
||||||
List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count);
|
count = 16;
|
||||||
|
|
||||||
double distance = Util.GetDistanceTo(startvector, endvector);
|
List<ContactResult> results = new List<ContactResult>();
|
||||||
|
|
||||||
if (distance == 0)
|
|
||||||
distance = 0.001;
|
|
||||||
|
|
||||||
Vector3 posToCheck = startvector;
|
|
||||||
ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>();
|
|
||||||
|
|
||||||
bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
|
bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
|
||||||
bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
|
bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
|
||||||
bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
|
bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
|
||||||
bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
|
bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
|
||||||
|
|
||||||
for (float i = 0; i <= distance; i += 0.1f)
|
if (checkTerrain)
|
||||||
{
|
{
|
||||||
posToCheck = startvector + (dir * (i / (float)distance));
|
ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
|
||||||
|
if (groundContact != null)
|
||||||
if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z)
|
results.Add((ContactResult)groundContact);
|
||||||
{
|
|
||||||
ContactResult result = new ContactResult();
|
|
||||||
result.ConsumerID = 0;
|
|
||||||
result.Depth = 0;
|
|
||||||
result.Normal = Vector3.Zero;
|
|
||||||
result.Pos = posToCheck;
|
|
||||||
results.Add(result);
|
|
||||||
checkTerrain = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkAgents)
|
|
||||||
{
|
|
||||||
World.ForEachRootScenePresence(delegate(ScenePresence sp)
|
|
||||||
{
|
|
||||||
if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X))
|
|
||||||
{
|
|
||||||
ContactResult result = new ContactResult ();
|
|
||||||
result.ConsumerID = sp.LocalId;
|
|
||||||
result.Depth = 0;
|
|
||||||
result.Normal = Vector3.Zero;
|
|
||||||
result.Pos = posToCheck;
|
|
||||||
results.Add(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int refcount = 0;
|
if (checkAgents)
|
||||||
|
{
|
||||||
|
ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
|
||||||
|
foreach (ContactResult r in agentHits)
|
||||||
|
results.Add(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkPhysical || checkNonPhysical)
|
||||||
|
{
|
||||||
|
ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd);
|
||||||
|
foreach (ContactResult r in objectHits)
|
||||||
|
results.Add(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Sort(delegate(ContactResult a, ContactResult b)
|
||||||
|
{
|
||||||
|
return (int)(a.Depth - b.Depth);
|
||||||
|
});
|
||||||
|
|
||||||
|
int values = 0;
|
||||||
foreach (ContactResult result in results)
|
foreach (ContactResult result in results)
|
||||||
{
|
{
|
||||||
if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND)
|
UUID itemID = UUID.Zero;
|
||||||
== ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0)
|
int linkNum = 0;
|
||||||
continue;
|
|
||||||
|
|
||||||
ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID);
|
SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
|
||||||
|
// It's a prim!
|
||||||
if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS)
|
if (part != null)
|
||||||
entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents
|
|
||||||
|
|
||||||
if (entity == null)
|
|
||||||
{
|
{
|
||||||
list.Add(UUID.Zero);
|
if (part.PhysActor != null)
|
||||||
|
|
||||||
if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
|
|
||||||
list.Add(0);
|
|
||||||
|
|
||||||
list.Add(result.Pos);
|
|
||||||
|
|
||||||
if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
|
|
||||||
list.Add(result.Normal);
|
|
||||||
|
|
||||||
continue; //Can't find it, so add UUID.Zero
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity &&
|
|
||||||
((ISceneChildEntity)intersection.obj).PhysActor == null)
|
|
||||||
continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects
|
|
||||||
|
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
{
|
|
||||||
if (((SceneObjectPart)entity).PhysActor != null && ((SceneObjectPart)entity).PhysActor.IsPhysical)
|
|
||||||
{
|
{
|
||||||
if (!checkPhysical)
|
if (part.PhysActor.IsPhysical && !checkPhysical)
|
||||||
|
continue;
|
||||||
|
if (!part.PhysActor.IsPhysical && !checkNonPhysical)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!checkNonPhysical)
|
if (!detectPhantom)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
|
||||||
|
itemID = part.ParentGroup.UUID;
|
||||||
|
else
|
||||||
|
itemID = part.UUID;
|
||||||
|
|
||||||
|
linkNum = part.LinkNum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScenePresence sp = World.GetScenePresence(result.ConsumerID);
|
||||||
|
/// It it a boy? a girl?
|
||||||
|
if (sp != null)
|
||||||
|
itemID = sp.UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
refcount++;
|
list.Add(new LSL_String(itemID.ToString()));
|
||||||
if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart)
|
list.Add(new LSL_String(result.Pos.ToString()));
|
||||||
list.Add(((SceneObjectPart)entity).ParentGroup.UUID);
|
|
||||||
else
|
|
||||||
list.Add(entity.UUID);
|
|
||||||
|
|
||||||
if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
|
if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
|
||||||
{
|
list.Add(new LSL_Integer(linkNum));
|
||||||
if (entity is SceneObjectPart)
|
|
||||||
list.Add(((SceneObjectPart)entity).LinkNum);
|
|
||||||
else
|
|
||||||
list.Add(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(result.Pos);
|
|
||||||
|
|
||||||
if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
|
if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
|
||||||
list.Add(result.Normal);
|
list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
|
||||||
|
|
||||||
|
values++;
|
||||||
|
count--;
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED
|
list.Add(new LSL_Integer(values));
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||||
// avatar rotation. This may include a nonzero elevation if
|
// avatar rotation. This may include a nonzero elevation if
|
||||||
// in mouselook.
|
// in mouselook.
|
||||||
ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
|
ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
|
||||||
|
if (avatar == null)
|
||||||
|
return sensedEntities;
|
||||||
fromRegionPos = avatar.AbsolutePosition;
|
fromRegionPos = avatar.AbsolutePosition;
|
||||||
q = avatar.Rotation;
|
q = avatar.Rotation;
|
||||||
}
|
}
|
||||||
|
@ -444,6 +446,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||||
|
|
||||||
Action<ScenePresence> senseEntity = new Action<ScenePresence>(delegate(ScenePresence presence)
|
Action<ScenePresence> senseEntity = new Action<ScenePresence>(delegate(ScenePresence presence)
|
||||||
{
|
{
|
||||||
|
if (presence.PresenceType == PresenceType.Npc)
|
||||||
|
return;
|
||||||
|
|
||||||
if (presence.IsDeleted || presence.IsChildAgent || presence.GodLevel > 0.0)
|
if (presence.IsDeleted || presence.IsChildAgent || presence.GodLevel > 0.0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||||
m_LSL_Functions.llBreakLink(linknum);
|
m_LSL_Functions.llBreakLink(linknum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
|
||||||
|
{
|
||||||
|
return m_LSL_Functions.llCastRay(start, end, options);
|
||||||
|
}
|
||||||
|
|
||||||
public LSL_Integer llCeil(double f)
|
public LSL_Integer llCeil(double f)
|
||||||
{
|
{
|
||||||
return m_LSL_Functions.llCeil(f);
|
return m_LSL_Functions.llCeil(f);
|
||||||
|
|
Loading…
Reference in New Issue