From f05a977afaacca2df4406f2d4aefed960a4b7f1c Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 16 Apr 2012 16:35:35 +0100
Subject:  Let llCastRay use ubitODE raycast if avaiable plus a few
 changes/fixes that should be checked. PROBLEM: it will not detect nonphysical
 phantons :(

---
 .../Shared/Api/Implementation/LSL_Api.cs           | 108 ++++++++++++++++-----
 1 file changed, 86 insertions(+), 22 deletions(-)

diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 2f61b70..5b5e23e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -11869,38 +11869,101 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
             bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
 
-            if (checkTerrain)
-            {
-                ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
-                if (groundContact != null)
-                    results.Add((ContactResult)groundContact);
-            }
 
-            if (checkAgents)
+            if (World.SuportsRayCastFiltered())
             {
-                ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
-                foreach (ContactResult r in agentHits)
-                    results.Add(r);
-            }
+                if (dist == 0)
+                    return list;
+
+                RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
+                if (checkTerrain)
+                    rayfilter |= RayFilterFlags.land;
+//                if (checkAgents)
+//                    rayfilter |= RayFilterFlags.agent;
+                if (checkPhysical)
+                    rayfilter |= RayFilterFlags.physical;
+                if (checkNonPhysical)
+                    rayfilter |= RayFilterFlags.nonphysical;
+                if (detectPhantom)
+                    rayfilter |= RayFilterFlags.LSLPhanton;
+
+                Vector3 direction = dir * ( 1/dist);
+
+                if(rayfilter == 0)
+                {
+                    list.Add(new LSL_Integer(0));
+                    return list;
+                }
+
+                // get some more contacts to sort ???
+                int physcount = 4 * count;
+                if (physcount > 20)
+                    physcount = 20;
+
+                object physresults;
+                physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
 
-            if (checkPhysical || checkNonPhysical)
+                if (physresults == null)
+                {
+                    list.Add(new LSL_Integer(-3)); // timeout error
+                    return list;
+                }
+
+                results = (List<ContactResult>)physresults;
+
+                // for now physics doesn't detect sitted avatars so do it outside physics
+                if (checkAgents)
+                {
+                    ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
+                    foreach (ContactResult r in agentHits)
+                        results.Add(r);
+                }
+
+            // bug: will not detect phantom unless they are physical
+            // don't use ObjectIntersection because its also bad
+
+            }
+            else
             {
-                ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
-                foreach (ContactResult r in objectHits)
-                    results.Add(r);
+                if (checkTerrain)
+                {
+                    ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
+                    if (groundContact != null)
+                        results.Add((ContactResult)groundContact);
+                }
+
+                if (checkAgents)
+                {
+                    ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
+                    foreach (ContactResult r in agentHits)
+                        results.Add(r);
+                }
+
+                if (checkPhysical || checkNonPhysical || detectPhantom)
+                {
+                    ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
+                    foreach (ContactResult r in objectHits)
+                        results.Add(r);
+                }
             }
 
             results.Sort(delegate(ContactResult a, ContactResult b)
             {
-                return (int)(a.Depth - b.Depth);
+                return a.Depth.CompareTo(b.Depth);
             });
             
             int values = 0;
+            SceneObjectGroup thisgrp = m_host.ParentGroup;
+
             foreach (ContactResult result in results)
             {
                 if (result.Depth > dist)
                     continue;
 
+                // physics ray can return colisions with host prim
+                if (m_host.LocalId == result.ConsumerID)
+                    continue;
+
                 UUID itemID = UUID.Zero;
                 int linkNum = 0;
 
@@ -11908,6 +11971,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 // It's a prim!
                 if (part != null)
                 {
+                    // dont detect members of same object ???
+                    if (part.ParentGroup == thisgrp)
+                        continue;
+
                     if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
                         itemID = part.ParentGroup.UUID;
                     else
@@ -11918,7 +11985,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 else
                 {
                     ScenePresence sp = World.GetScenePresence(result.ConsumerID);
-                    /// It it a boy? a girl?
+                    /// It it a boy? a girl? 
                     if (sp != null)
                         itemID = sp.UUID;
                 }
@@ -11929,14 +11996,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
                     list.Add(new LSL_Integer(linkNum));
 
-
                 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
                     list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z));
-                
-                values++;
-                count--;
 
-                if (count == 0)
+                values++;
+                if (values >= count)
                     break;
             }
 
-- 
cgit v1.1