diff options
author | Melanie | 2012-06-13 02:32:25 +0100 |
---|---|---|
committer | Melanie | 2012-06-13 02:32:25 +0100 |
commit | 4e18e71089eb1ef84bad8f09dd4a9d18f09bec5e (patch) | |
tree | bcdbc3683480c3cdc9f8889dfb0bf65441dfbd77 /OpenSim/Region/ScriptEngine | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC_OLD-4e18e71089eb1ef84bad8f09dd4a9d18f09bec5e.zip opensim-SC_OLD-4e18e71089eb1ef84bad8f09dd4a9d18f09bec5e.tar.gz opensim-SC_OLD-4e18e71089eb1ef84bad8f09dd4a9d18f09bec5e.tar.bz2 opensim-SC_OLD-4e18e71089eb1ef84bad8f09dd4a9d18f09bec5e.tar.xz |
Committing the Avination implementation of llCastRay. This is a complete rewrite
wich does it's thing independently of physics. Enjoy!
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 445 |
1 files changed, 345 insertions, 100 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 89f2068..a8679e2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -10781,155 +10781,400 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10781 | return rq.ToString(); | 10781 | return rq.ToString(); |
10782 | } | 10782 | } |
10783 | 10783 | ||
10784 | private struct Tri | ||
10785 | { | ||
10786 | public Vector3 p1; | ||
10787 | public Vector3 p2; | ||
10788 | public Vector3 p3; | ||
10789 | } | ||
10790 | |||
10791 | private bool InBoundingBox(ScenePresence avatar, Vector3 point) | ||
10792 | { | ||
10793 | float height = avatar.Appearance.AvatarHeight; | ||
10794 | Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2); | ||
10795 | Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2); | ||
10796 | |||
10797 | if (point.X > b1.X && point.X < b2.X && | ||
10798 | point.Y > b1.Y && point.Y < b2.Y && | ||
10799 | point.Z > b1.Z && point.Z < b2.Z) | ||
10800 | return true; | ||
10801 | return false; | ||
10802 | } | ||
10803 | |||
10804 | private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd) | ||
10805 | { | ||
10806 | List<ContactResult> contacts = new List<ContactResult>(); | ||
10807 | |||
10808 | Vector3 ab = rayEnd - rayStart; | ||
10809 | |||
10810 | World.ForEachScenePresence(delegate(ScenePresence sp) | ||
10811 | { | ||
10812 | Vector3 ac = sp.AbsolutePosition - rayStart; | ||
10813 | Vector3 bc = sp.AbsolutePosition - rayEnd; | ||
10814 | |||
10815 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | ||
10816 | |||
10817 | if (d > 1.5) | ||
10818 | return; | ||
10819 | |||
10820 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); | ||
10821 | |||
10822 | if (d2 > 0) | ||
10823 | return; | ||
10824 | |||
10825 | double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d); | ||
10826 | Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab)); | ||
10827 | |||
10828 | if (!InBoundingBox(sp, p)) | ||
10829 | return; | ||
10830 | |||
10831 | ContactResult result = new ContactResult (); | ||
10832 | result.ConsumerID = sp.LocalId; | ||
10833 | result.Depth = Vector3.Distance(rayStart, p); | ||
10834 | result.Normal = Vector3.Zero; | ||
10835 | result.Pos = p; | ||
10836 | |||
10837 | contacts.Add(result); | ||
10838 | }); | ||
10839 | |||
10840 | return contacts.ToArray(); | ||
10841 | } | ||
10842 | |||
10843 | private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom) | ||
10844 | { | ||
10845 | Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); | ||
10846 | List<ContactResult> contacts = new List<ContactResult>(); | ||
10847 | |||
10848 | Vector3 ab = rayEnd - rayStart; | ||
10849 | |||
10850 | World.ForEachSOG(delegate(SceneObjectGroup group) | ||
10851 | { | ||
10852 | if (m_host.ParentGroup == group) | ||
10853 | return; | ||
10854 | |||
10855 | if (group.IsAttachment) | ||
10856 | return; | ||
10857 | |||
10858 | if (group.RootPart.PhysActor == null) | ||
10859 | { | ||
10860 | if (!includePhantom) | ||
10861 | return; | ||
10862 | } | ||
10863 | else | ||
10864 | { | ||
10865 | if (group.RootPart.PhysActor.IsPhysical) | ||
10866 | { | ||
10867 | if (!includePhysical) | ||
10868 | return; | ||
10869 | } | ||
10870 | else | ||
10871 | { | ||
10872 | if (!includeNonPhysical) | ||
10873 | return; | ||
10874 | } | ||
10875 | } | ||
10876 | |||
10877 | // Find the radius ouside of which we don't even need to hit test | ||
10878 | float minX; | ||
10879 | float maxX; | ||
10880 | float minY; | ||
10881 | float maxY; | ||
10882 | float minZ; | ||
10883 | float maxZ; | ||
10884 | |||
10885 | float radius = 0.0f; | ||
10886 | |||
10887 | group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ); | ||
10888 | |||
10889 | if (Math.Abs(minX) > radius) | ||
10890 | radius = Math.Abs(minX); | ||
10891 | if (Math.Abs(minY) > radius) | ||
10892 | radius = Math.Abs(minY); | ||
10893 | if (Math.Abs(minZ) > radius) | ||
10894 | radius = Math.Abs(minZ); | ||
10895 | if (Math.Abs(maxX) > radius) | ||
10896 | radius = Math.Abs(maxX); | ||
10897 | if (Math.Abs(maxY) > radius) | ||
10898 | radius = Math.Abs(maxY); | ||
10899 | if (Math.Abs(maxZ) > radius) | ||
10900 | radius = Math.Abs(maxZ); | ||
10901 | |||
10902 | Vector3 ac = group.AbsolutePosition - rayStart; | ||
10903 | Vector3 bc = group.AbsolutePosition - rayEnd; | ||
10904 | |||
10905 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | ||
10906 | |||
10907 | // Too far off ray, don't bother | ||
10908 | if (d > radius) | ||
10909 | return; | ||
10910 | |||
10911 | // Behind ray, drop | ||
10912 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); | ||
10913 | if (d2 > 0) | ||
10914 | return; | ||
10915 | |||
10916 | EntityIntersection intersection = group.TestIntersection(ray, true, false); | ||
10917 | // Miss. | ||
10918 | if (!intersection.HitTF) | ||
10919 | return; | ||
10920 | |||
10921 | ContactResult result = new ContactResult (); | ||
10922 | result.ConsumerID = group.LocalId; | ||
10923 | result.Depth = intersection.distance; | ||
10924 | result.Normal = intersection.normal; | ||
10925 | result.Pos = intersection.ipoint; | ||
10926 | |||
10927 | contacts.Add(result); | ||
10928 | }); | ||
10929 | |||
10930 | return contacts.ToArray(); | ||
10931 | } | ||
10932 | |||
10933 | private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd) | ||
10934 | { | ||
10935 | double[,] heightfield = World.Heightmap.GetDoubles(); | ||
10936 | List<ContactResult> contacts = new List<ContactResult>(); | ||
10937 | |||
10938 | double min = 2048.0; | ||
10939 | double max = 0.0; | ||
10940 | |||
10941 | // Find the min and max of the heightfield | ||
10942 | for (int x = 0 ; x < World.Heightmap.Width ; x++) | ||
10943 | { | ||
10944 | for (int y = 0 ; y < World.Heightmap.Height ; y++) | ||
10945 | { | ||
10946 | if (heightfield[x, y] > max) | ||
10947 | max = heightfield[x, y]; | ||
10948 | if (heightfield[x, y] < min) | ||
10949 | min = heightfield[x, y]; | ||
10950 | } | ||
10951 | } | ||
10952 | |||
10953 | |||
10954 | // A ray extends past rayEnd, but doesn't go back before | ||
10955 | // rayStart. If the start is above the highest point of the ground | ||
10956 | // and the ray goes up, we can't hit the ground. Ever. | ||
10957 | if (rayStart.Z > max && rayEnd.Z >= rayStart.Z) | ||
10958 | return null; | ||
10959 | |||
10960 | // Same for going down | ||
10961 | if (rayStart.Z < min && rayEnd.Z <= rayStart.Z) | ||
10962 | return null; | ||
10963 | |||
10964 | List<Tri> trilist = new List<Tri>(); | ||
10965 | |||
10966 | // Create our triangle list | ||
10967 | for (int x = 1 ; x < World.Heightmap.Width ; x++) | ||
10968 | { | ||
10969 | for (int y = 1 ; y < World.Heightmap.Height ; y++) | ||
10970 | { | ||
10971 | Tri t1 = new Tri(); | ||
10972 | Tri t2 = new Tri(); | ||
10973 | |||
10974 | Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]); | ||
10975 | Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]); | ||
10976 | Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]); | ||
10977 | Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]); | ||
10978 | |||
10979 | t1.p1 = p1; | ||
10980 | t1.p2 = p2; | ||
10981 | t1.p3 = p3; | ||
10982 | |||
10983 | t2.p1 = p3; | ||
10984 | t2.p2 = p4; | ||
10985 | t2.p3 = p1; | ||
10986 | |||
10987 | trilist.Add(t1); | ||
10988 | trilist.Add(t2); | ||
10989 | } | ||
10990 | } | ||
10991 | |||
10992 | // Ray direction | ||
10993 | Vector3 rayDirection = rayEnd - rayStart; | ||
10994 | |||
10995 | foreach (Tri t in trilist) | ||
10996 | { | ||
10997 | // Compute triangle plane normal and edges | ||
10998 | Vector3 u = t.p2 - t.p1; | ||
10999 | Vector3 v = t.p3 - t.p1; | ||
11000 | Vector3 n = Vector3.Cross(u, v); | ||
11001 | |||
11002 | if (n == Vector3.Zero) | ||
11003 | continue; | ||
11004 | |||
11005 | Vector3 w0 = rayStart - t.p1; | ||
11006 | double a = -Vector3.Dot(n, w0); | ||
11007 | double b = Vector3.Dot(n, rayDirection); | ||
11008 | |||
11009 | // Not intersecting the plane, or in plane (same thing) | ||
11010 | // Ignoring this MAY cause the ground to not be detected | ||
11011 | // sometimes | ||
11012 | if (Math.Abs(b) < 0.000001) | ||
11013 | continue; | ||
11014 | |||
11015 | double r = a / b; | ||
11016 | |||
11017 | // ray points away from plane | ||
11018 | if (r < 0.0) | ||
11019 | continue; | ||
11020 | |||
11021 | Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r); | ||
11022 | |||
11023 | float uu = Vector3.Dot(u, u); | ||
11024 | float uv = Vector3.Dot(u, v); | ||
11025 | float vv = Vector3.Dot(v, v); | ||
11026 | Vector3 w = ip - t.p1; | ||
11027 | float wu = Vector3.Dot(w, u); | ||
11028 | float wv = Vector3.Dot(w, v); | ||
11029 | float d = uv * uv - uu * vv; | ||
11030 | |||
11031 | float cs = (uv * wv - vv * wu) / d; | ||
11032 | if (cs < 0 || cs > 1.0) | ||
11033 | continue; | ||
11034 | float ct = (uv * wu - uu * wv) / d; | ||
11035 | if (ct < 0 || (cs + ct) > 1.0) | ||
11036 | continue; | ||
11037 | |||
11038 | // Add contact point | ||
11039 | ContactResult result = new ContactResult (); | ||
11040 | result.ConsumerID = 0; | ||
11041 | result.Depth = Vector3.Distance(rayStart, ip); | ||
11042 | result.Normal = n; | ||
11043 | result.Pos = ip; | ||
11044 | |||
11045 | contacts.Add(result); | ||
11046 | } | ||
11047 | |||
11048 | if (contacts.Count == 0) | ||
11049 | return null; | ||
11050 | |||
11051 | contacts.Sort(delegate(ContactResult a, ContactResult b) | ||
11052 | { | ||
11053 | return (int)(a.Depth - b.Depth); | ||
11054 | }); | ||
11055 | |||
11056 | return contacts[0]; | ||
11057 | } | ||
11058 | |||
10784 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) | 11059 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) |
10785 | { | 11060 | { |
11061 | LSL_List list = new LSL_List(); | ||
11062 | |||
10786 | m_host.AddScriptLPS(1); | 11063 | m_host.AddScriptLPS(1); |
10787 | 11064 | ||
10788 | Vector3 dir = new Vector3((float)(end-start).x, (float)(end-start).y, (float)(end-start).z); | 11065 | Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); |
10789 | Vector3 startvector = new Vector3((float)start.x, (float)start.y, (float)start.z); | 11066 | Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); |
10790 | Vector3 endvector = new Vector3((float)end.x, (float)end.y, (float)end.z); | 11067 | Vector3 dir = rayEnd - rayStart; |
10791 | 11068 | ||
10792 | int count = 0; | 11069 | float dist = Vector3.Mag(dir); |
10793 | // int detectPhantom = 0; | 11070 | |
11071 | int count = 1; | ||
11072 | bool detectPhantom = false; | ||
10794 | int dataFlags = 0; | 11073 | int dataFlags = 0; |
10795 | int rejectTypes = 0; | 11074 | int rejectTypes = 0; |
10796 | 11075 | ||
10797 | for (int i = 0; i < options.Length; i += 2) | 11076 | for (int i = 0; i < options.Length; i += 2) |
10798 | { | 11077 | { |
10799 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) | 11078 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) |
10800 | { | ||
10801 | count = options.GetLSLIntegerItem(i + 1); | 11079 | count = options.GetLSLIntegerItem(i + 1); |
10802 | } | 11080 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) |
10803 | // else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) | 11081 | detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0); |
10804 | // { | ||
10805 | // detectPhantom = options.GetLSLIntegerItem(i + 1); | ||
10806 | // } | ||
10807 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) | 11082 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) |
10808 | { | ||
10809 | dataFlags = options.GetLSLIntegerItem(i + 1); | 11083 | dataFlags = options.GetLSLIntegerItem(i + 1); |
10810 | } | ||
10811 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) | 11084 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) |
10812 | { | ||
10813 | rejectTypes = options.GetLSLIntegerItem(i + 1); | 11085 | rejectTypes = options.GetLSLIntegerItem(i + 1); |
10814 | } | ||
10815 | } | 11086 | } |
10816 | 11087 | ||
10817 | LSL_List list = new LSL_List(); | 11088 | if (count > 16) |
10818 | List<ContactResult> results = World.PhysicsScene.RaycastWorld(startvector, dir, dir.Length(), count); | 11089 | count = 16; |
10819 | |||
10820 | double distance = Util.GetDistanceTo(startvector, endvector); | ||
10821 | 11090 | ||
10822 | if (distance == 0) | 11091 | List<ContactResult> results = new List<ContactResult>(); |
10823 | distance = 0.001; | ||
10824 | |||
10825 | Vector3 posToCheck = startvector; | ||
10826 | ITerrainChannel channel = World.RequestModuleInterface<ITerrainChannel>(); | ||
10827 | 11092 | ||
10828 | bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); | 11093 | bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); |
10829 | bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); | 11094 | bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); |
10830 | bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); | 11095 | bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); |
10831 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); | 11096 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); |
10832 | 11097 | ||
10833 | for (float i = 0; i <= distance; i += 0.1f) | 11098 | |
11099 | if (checkTerrain) | ||
10834 | { | 11100 | { |
10835 | posToCheck = startvector + (dir * (i / (float)distance)); | 11101 | ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); |
11102 | if (groundContact != null) | ||
11103 | results.Add((ContactResult)groundContact); | ||
11104 | } | ||
10836 | 11105 | ||
10837 | if (checkTerrain && channel[(int)(posToCheck.X + startvector.X), (int)(posToCheck.Y + startvector.Y)] < posToCheck.Z) | 11106 | if (checkAgents) |
10838 | { | 11107 | { |
10839 | ContactResult result = new ContactResult(); | 11108 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); |
10840 | result.ConsumerID = 0; | 11109 | foreach (ContactResult r in agentHits) |
10841 | result.Depth = 0; | 11110 | results.Add(r); |
10842 | result.Normal = Vector3.Zero; | 11111 | } |
10843 | result.Pos = posToCheck; | ||
10844 | results.Add(result); | ||
10845 | checkTerrain = false; | ||
10846 | } | ||
10847 | 11112 | ||
10848 | if (checkAgents) | 11113 | if (checkPhysical || checkNonPhysical || detectPhantom) |
10849 | { | 11114 | { |
10850 | World.ForEachRootScenePresence(delegate(ScenePresence sp) | 11115 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); |
10851 | { | 11116 | foreach (ContactResult r in objectHits) |
10852 | if (sp.AbsolutePosition.ApproxEquals(posToCheck, sp.PhysicsActor.Size.X)) | 11117 | results.Add(r); |
10853 | { | ||
10854 | ContactResult result = new ContactResult (); | ||
10855 | result.ConsumerID = sp.LocalId; | ||
10856 | result.Depth = 0; | ||
10857 | result.Normal = Vector3.Zero; | ||
10858 | result.Pos = posToCheck; | ||
10859 | results.Add(result); | ||
10860 | } | ||
10861 | }); | ||
10862 | } | ||
10863 | } | 11118 | } |
10864 | 11119 | ||
10865 | int refcount = 0; | 11120 | results.Sort(delegate(ContactResult a, ContactResult b) |
11121 | { | ||
11122 | return a.Depth.CompareTo(b.Depth); | ||
11123 | }); | ||
11124 | |||
11125 | int values = 0; | ||
11126 | SceneObjectGroup thisgrp = m_host.ParentGroup; | ||
11127 | |||
10866 | foreach (ContactResult result in results) | 11128 | foreach (ContactResult result in results) |
10867 | { | 11129 | { |
10868 | if ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) | 11130 | if (result.Depth > dist) |
10869 | == ScriptBaseClass.RC_REJECT_LAND && result.ConsumerID == 0) | ||
10870 | continue; | 11131 | continue; |
10871 | 11132 | ||
10872 | ISceneEntity entity = World.GetSceneObjectPart(result.ConsumerID); | 11133 | // physics ray can return colisions with host prim |
11134 | if (m_host.LocalId == result.ConsumerID) | ||
11135 | continue; | ||
10873 | 11136 | ||
10874 | if (entity == null && (rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != ScriptBaseClass.RC_REJECT_AGENTS) | 11137 | UUID itemID = UUID.Zero; |
10875 | entity = World.GetScenePresence(result.ConsumerID); //Only check if we should be looking for agents | 11138 | int linkNum = 0; |
10876 | 11139 | ||
10877 | if (entity == null) | 11140 | SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID); |
11141 | // It's a prim! | ||
11142 | if (part != null) | ||
10878 | { | 11143 | { |
10879 | list.Add(UUID.Zero); | 11144 | // dont detect members of same object ??? |
10880 | 11145 | if (part.ParentGroup == thisgrp) | |
10881 | if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) | 11146 | continue; |
10882 | list.Add(0); | ||
10883 | 11147 | ||
10884 | list.Add(result.Pos); | 11148 | if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY) |
10885 | 11149 | itemID = part.ParentGroup.UUID; | |
10886 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) | 11150 | else |
10887 | list.Add(result.Normal); | 11151 | itemID = part.UUID; |
10888 | 11152 | ||
10889 | continue; //Can't find it, so add UUID.Zero | 11153 | linkNum = part.LinkNum; |
10890 | } | 11154 | } |
10891 | 11155 | else | |
10892 | /*if (detectPhantom == 0 && intersection.obj is ISceneChildEntity && | ||
10893 | ((ISceneChildEntity)intersection.obj).PhysActor == null) | ||
10894 | continue;*/ //Can't do this ATM, physics engine knows only of non phantom objects | ||
10895 | |||
10896 | if (entity is SceneObjectPart) | ||
10897 | { | 11156 | { |
10898 | PhysicsActor pa = ((SceneObjectPart)entity).PhysActor; | 11157 | ScenePresence sp = World.GetScenePresence(result.ConsumerID); |
10899 | 11158 | /// It it a boy? a girl? | |
10900 | if (pa != null && pa.IsPhysical) | 11159 | if (sp != null) |
10901 | { | 11160 | itemID = sp.UUID; |
10902 | if (!checkPhysical) | ||
10903 | continue; | ||
10904 | } | ||
10905 | else | ||
10906 | { | ||
10907 | if (!checkNonPhysical) | ||
10908 | continue; | ||
10909 | } | ||
10910 | } | 11161 | } |
10911 | 11162 | ||
10912 | refcount++; | 11163 | list.Add(new LSL_String(itemID.ToString())); |
10913 | if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY && entity is SceneObjectPart) | 11164 | list.Add(new LSL_String(result.Pos.ToString())); |
10914 | list.Add(((SceneObjectPart)entity).ParentGroup.UUID); | ||
10915 | else | ||
10916 | list.Add(entity.UUID); | ||
10917 | 11165 | ||
10918 | if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) | 11166 | if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) |
10919 | { | 11167 | list.Add(new LSL_Integer(linkNum)); |
10920 | if (entity is SceneObjectPart) | ||
10921 | list.Add(((SceneObjectPart)entity).LinkNum); | ||
10922 | else | ||
10923 | list.Add(0); | ||
10924 | } | ||
10925 | |||
10926 | list.Add(result.Pos); | ||
10927 | 11168 | ||
10928 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) | 11169 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) |
10929 | list.Add(result.Normal); | 11170 | list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); |
11171 | |||
11172 | values++; | ||
11173 | if (values >= count) | ||
11174 | break; | ||
10930 | } | 11175 | } |
10931 | 11176 | ||
10932 | list.Add(refcount); //The status code, either the # of contacts, RCERR_SIM_PERF_LOW, or RCERR_CAST_TIME_EXCEEDED | 11177 | list.Add(new LSL_Integer(values)); |
10933 | 11178 | ||
10934 | return list; | 11179 | return list; |
10935 | } | 11180 | } |