diff options
author | Magnuz Binder | 2015-04-20 21:30:06 +0200 |
---|---|---|
committer | Michael Cerquoni | 2015-04-20 16:23:34 -0400 |
commit | 263db441292956a8210a00c037848165667ab90e (patch) | |
tree | f9e5df1736925b4598d40a6f08ac3ed628078e15 /OpenSim/Region | |
parent | Revert "Enable grab feature (Ctrl+Drag) for non-physical link-sets and add co... (diff) | |
download | opensim-SC-263db441292956a8210a00c037848165667ab90e.zip opensim-SC-263db441292956a8210a00c037848165667ab90e.tar.gz opensim-SC-263db441292956a8210a00c037848165667ab90e.tar.bz2 opensim-SC-263db441292956a8210a00c037848165667ab90e.tar.xz |
Implement llGetBoundingBox fully.
Signed-off-by: Michael Cerquoni <nebadon2025@gmail.com>
Diffstat (limited to 'OpenSim/Region')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 489 |
1 files changed, 447 insertions, 42 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 40b7c35..5436888 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -28,6 +28,8 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Drawing; | ||
32 | using System.Drawing.Imaging; | ||
31 | using System.Runtime.Remoting.Lifetime; | 33 | using System.Runtime.Remoting.Lifetime; |
32 | using System.Text; | 34 | using System.Text; |
33 | using System.Threading; | 35 | using System.Threading; |
@@ -35,7 +37,9 @@ using System.Text.RegularExpressions; | |||
35 | using Nini.Config; | 37 | using Nini.Config; |
36 | using log4net; | 38 | using log4net; |
37 | using OpenMetaverse; | 39 | using OpenMetaverse; |
40 | using OpenMetaverse.Assets; | ||
38 | using OpenMetaverse.Packets; | 41 | using OpenMetaverse.Packets; |
42 | using OpenMetaverse.Rendering; | ||
39 | using OpenSim; | 43 | using OpenSim; |
40 | using OpenSim.Framework; | 44 | using OpenSim.Framework; |
41 | 45 | ||
@@ -182,6 +186,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
182 | protected bool m_restrictEmail = false; | 186 | protected bool m_restrictEmail = false; |
183 | protected ISoundModule m_SoundModule = null; | 187 | protected ISoundModule m_SoundModule = null; |
184 | 188 | ||
189 | protected float m_avatarHeightCorrection = 0.2f; | ||
190 | protected bool m_useSimpleBoxesInGetBoundingBox = false; | ||
191 | protected bool m_addStatsInGetBoundingBox = false; | ||
192 | |||
193 | //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), | ||
194 | //standing (Std), Groundsitting (Grs), Sitting (Sit), | ||
195 | //along X, Y and Z axes, constants (0) and coefficients (1) | ||
196 | protected float m_lABB1StdX0 = -0.275f; | ||
197 | protected float m_lABB2StdX0 = 0.275f; | ||
198 | protected float m_lABB1StdY0 = -0.35f; | ||
199 | protected float m_lABB2StdY0 = 0.35f; | ||
200 | protected float m_lABB1StdZ0 = -0.1f; | ||
201 | protected float m_lABB1StdZ1 = -0.5f; | ||
202 | protected float m_lABB2StdZ0 = 0.1f; | ||
203 | protected float m_lABB2StdZ1 = 0.5f; | ||
204 | protected float m_lABB1GrsX0 = -0.3875f; | ||
205 | protected float m_lABB2GrsX0 = 0.3875f; | ||
206 | protected float m_lABB1GrsY0 = -0.5f; | ||
207 | protected float m_lABB2GrsY0 = 0.5f; | ||
208 | protected float m_lABB1GrsZ0 = -0.05f; | ||
209 | protected float m_lABB1GrsZ1 = -0.375f; | ||
210 | protected float m_lABB2GrsZ0 = 0.5f; | ||
211 | protected float m_lABB2GrsZ1 = 0.0f; | ||
212 | protected float m_lABB1SitX0 = -0.5875f; | ||
213 | protected float m_lABB2SitX0 = 0.1875f; | ||
214 | protected float m_lABB1SitY0 = -0.35f; | ||
215 | protected float m_lABB2SitY0 = 0.35f; | ||
216 | protected float m_lABB1SitZ0 = -0.35f; | ||
217 | protected float m_lABB1SitZ1 = -0.375f; | ||
218 | protected float m_lABB2SitZ0 = -0.25f; | ||
219 | protected float m_lABB2SitZ1 = 0.25f; | ||
220 | |||
185 | //An array of HTTP/1.1 headers that are not allowed to be used | 221 | //An array of HTTP/1.1 headers that are not allowed to be used |
186 | //as custom headers by llHTTPRequest. | 222 | //as custom headers by llHTTPRequest. |
187 | private string[] HttpStandardHeaders = | 223 | private string[] HttpStandardHeaders = |
@@ -257,6 +293,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
257 | if (lslConfig != null) | 293 | if (lslConfig != null) |
258 | { | 294 | { |
259 | m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); | 295 | m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); |
296 | m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); | ||
297 | m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); | ||
298 | m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); | ||
299 | m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); | ||
300 | m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); | ||
301 | m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); | ||
302 | m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); | ||
303 | m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); | ||
304 | m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); | ||
305 | m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); | ||
306 | m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); | ||
307 | m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); | ||
308 | m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); | ||
309 | m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); | ||
310 | m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); | ||
311 | m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); | ||
312 | m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); | ||
313 | m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); | ||
314 | m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); | ||
315 | m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); | ||
316 | m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); | ||
317 | m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); | ||
318 | m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); | ||
319 | m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); | ||
320 | m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); | ||
321 | m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); | ||
322 | m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); | ||
260 | } | 323 | } |
261 | 324 | ||
262 | IConfig smtpConfig = seConfigSource.Configs["SMTP"]; | 325 | IConfig smtpConfig = seConfigSource.Configs["SMTP"]; |
@@ -9584,75 +9647,417 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9584 | } | 9647 | } |
9585 | 9648 | ||
9586 | /// <summary> | 9649 | /// <summary> |
9587 | /// A partial implementation. | 9650 | /// Full implementation of llGetBoundingBox according to SL 2015-04-15. |
9651 | /// http://wiki.secondlife.com/wiki/LlGetBoundingBox | ||
9588 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox | 9652 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox |
9589 | /// So far only valid for standing/flying/ground sitting avatars and single prim objects. | 9653 | /// Returns local bounding box of avatar without attachments |
9590 | /// If the object has multiple prims and/or a sitting avatar then the bounding | 9654 | /// if target is non-seated avatar or prim/mesh in avatar attachment. |
9591 | /// box is for the root prim only. | 9655 | /// Returns local bounding box of object including seated avatars |
9656 | /// if target is seated avatar or prim/mesh in object. | ||
9657 | /// Uses meshing of prims for high accuracy | ||
9658 | /// or less accurate box models for speed. | ||
9592 | /// </summary> | 9659 | /// </summary> |
9593 | public LSL_List llGetBoundingBox(string obj) | 9660 | public LSL_List llGetBoundingBox(string obj) |
9594 | { | 9661 | { |
9595 | m_host.AddScriptLPS(1); | 9662 | m_host.AddScriptLPS(1); |
9663 | |||
9664 | // Get target avatar if non-seated avatar or attachment, or prim and object | ||
9596 | UUID objID = UUID.Zero; | 9665 | UUID objID = UUID.Zero; |
9666 | UUID.TryParse(obj, out objID); | ||
9667 | ScenePresence agent = World.GetScenePresence(objID); | ||
9668 | if (agent != null) | ||
9669 | { | ||
9670 | if (agent.ParentPart != null) | ||
9671 | { | ||
9672 | objID = agent.ParentPart.UUID; | ||
9673 | agent = null; | ||
9674 | } | ||
9675 | } | ||
9676 | SceneObjectGroup group = null; | ||
9677 | SceneObjectPart target = World.GetSceneObjectPart(objID); | ||
9678 | if (target != null) | ||
9679 | { | ||
9680 | group = target.ParentGroup; | ||
9681 | if (group.IsAttachment) { | ||
9682 | objID = group.AttachedAvatar; | ||
9683 | agent = World.GetScenePresence(objID); | ||
9684 | group = null; | ||
9685 | target = null; | ||
9686 | } | ||
9687 | } | ||
9688 | |||
9689 | // Initialize but break if no target | ||
9597 | LSL_List result = new LSL_List(); | 9690 | LSL_List result = new LSL_List(); |
9598 | if (!UUID.TryParse(obj, out objID)) | 9691 | int groupCount = 0; |
9692 | int partCount = 0; | ||
9693 | int vertexCount = 0; | ||
9694 | if (target == null && agent == null) | ||
9599 | { | 9695 | { |
9600 | result.Add(new LSL_Vector()); | 9696 | result.Add(new LSL_Vector()); |
9601 | result.Add(new LSL_Vector()); | 9697 | result.Add(new LSL_Vector()); |
9698 | if (m_addStatsInGetBoundingBox) | ||
9699 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
9602 | return result; | 9700 | return result; |
9603 | } | 9701 | } |
9604 | ScenePresence presence = World.GetScenePresence(objID); | 9702 | Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); |
9605 | if (presence != null) | 9703 | Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); |
9704 | |||
9705 | // Try to get a mesher | ||
9706 | IRendering primMesher = null; | ||
9707 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); | ||
9708 | if (renderers.Count > 0) | ||
9709 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); | ||
9710 | |||
9711 | // Get bounding box of just avatar, seated or not | ||
9712 | if (agent != null) | ||
9713 | { | ||
9714 | bool hasParent = false; | ||
9715 | Vector3 lower; | ||
9716 | Vector3 upper; | ||
9717 | BoundingBoxOfScenePresence(agent, out lower, out upper); | ||
9718 | Vector3 offset = Vector3.Zero; | ||
9719 | |||
9720 | // Since local bounding box unrotated and untilted, keep it simple | ||
9721 | AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9722 | partCount++; | ||
9723 | groupCount++; | ||
9724 | |||
9725 | // Return lower and upper bounding box corners | ||
9726 | result.Add(new LSL_Vector(minPosition)); | ||
9727 | result.Add(new LSL_Vector(maxPosition)); | ||
9728 | if (m_addStatsInGetBoundingBox) | ||
9729 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
9730 | return result; | ||
9731 | } | ||
9732 | // Get bounding box of object including seated avatars | ||
9733 | else if (group != null) | ||
9606 | { | 9734 | { |
9607 | if (presence.ParentID == 0) // not sat on an object | 9735 | // Merge bounding boxes of all parts (prims and mesh) |
9736 | foreach (SceneObjectPart part in group.Parts) | ||
9608 | { | 9737 | { |
9609 | LSL_Vector lower; | 9738 | bool hasParent = (!part.IsRoot); |
9610 | LSL_Vector upper; | 9739 | // When requested or if no mesher, keep it simple |
9611 | if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID | 9740 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) |
9612 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | ||
9613 | { | 9741 | { |
9614 | // This is for ground sitting avatars | 9742 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9615 | float height = presence.Appearance.AvatarHeight / 2.66666667f; | ||
9616 | lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); | ||
9617 | upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); | ||
9618 | } | 9743 | } |
9744 | // Do the full mounty | ||
9619 | else | 9745 | else |
9620 | { | 9746 | { |
9621 | // This is for standing/flying avatars | 9747 | Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); |
9622 | float height = presence.Appearance.AvatarHeight / 2.0f; | 9748 | byte[] sculptAsset = null; |
9623 | lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); | 9749 | if (omvPrim.Sculpt != null) |
9624 | upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); | 9750 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); |
9751 | |||
9752 | // When part is mesh | ||
9753 | // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. | ||
9754 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) | ||
9755 | { | ||
9756 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | ||
9757 | FacetedMesh mesh = null; | ||
9758 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); | ||
9759 | meshAsset = null; | ||
9760 | if (mesh != null) | ||
9761 | { | ||
9762 | AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9763 | mesh = null; | ||
9764 | } | ||
9765 | } | ||
9766 | |||
9767 | // When part is sculpt | ||
9768 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. | ||
9769 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) | ||
9770 | { | ||
9771 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); | ||
9772 | if (imgDecoder != null) | ||
9773 | { | ||
9774 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | ||
9775 | if (sculpt != null) | ||
9776 | { | ||
9777 | SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); | ||
9778 | sculpt.Dispose(); | ||
9779 | if (mesh != null) | ||
9780 | { | ||
9781 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9782 | mesh = null; | ||
9783 | } | ||
9784 | } | ||
9785 | } | ||
9786 | } | ||
9787 | |||
9788 | // When part is prim | ||
9789 | else if (omvPrim.Sculpt == null) | ||
9790 | { | ||
9791 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); | ||
9792 | if (mesh != null) | ||
9793 | { | ||
9794 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9795 | mesh = null; | ||
9796 | } | ||
9797 | } | ||
9798 | |||
9799 | // When all else fails, try fallback to simple box | ||
9800 | else | ||
9801 | { | ||
9802 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9803 | } | ||
9625 | } | 9804 | } |
9626 | result.Add(lower); | 9805 | partCount++; |
9627 | result.Add(upper); | ||
9628 | return result; | ||
9629 | } | 9806 | } |
9807 | } | ||
9808 | |||
9809 | // Merge bounding boxes of seated avatars | ||
9810 | foreach (ScenePresence sp in group.GetSittingAvatars()) | ||
9811 | { | ||
9812 | Vector3 lower; | ||
9813 | Vector3 upper; | ||
9814 | BoundingBoxOfScenePresence(sp, out lower, out upper); | ||
9815 | Vector3 offset = sp.OffsetPosition; | ||
9816 | |||
9817 | bool hasParent = true; | ||
9818 | // When requested or if no mesher, keep it simple | ||
9819 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) | ||
9820 | { | ||
9821 | AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9822 | } | ||
9823 | // Do the full mounty | ||
9630 | else | 9824 | else |
9631 | { | 9825 | { |
9632 | // sitting on an object so we need the bounding box of that | 9826 | // Prim shapes don't do center offsets, so add it here. |
9633 | // which should include the avatar so set the UUID to the | 9827 | offset = offset + (lower + upper) * 0.5f * sp.Rotation; |
9634 | // UUID of the object the avatar is sat on and allow it to fall through | 9828 | Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); |
9635 | // to processing an object | 9829 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); |
9636 | SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); | 9830 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9637 | objID = p.UUID; | 9831 | mesh = null; |
9832 | } | ||
9833 | partCount++; | ||
9834 | } | ||
9835 | |||
9836 | groupCount++; | ||
9837 | |||
9838 | // Return lower and upper bounding box corners | ||
9839 | result.Add(new LSL_Vector(minPosition)); | ||
9840 | result.Add(new LSL_Vector(maxPosition)); | ||
9841 | if (m_addStatsInGetBoundingBox) | ||
9842 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
9843 | |||
9844 | primMesher = null; | ||
9845 | return result; | ||
9846 | } | ||
9847 | |||
9848 | /// <summary> | ||
9849 | /// Helper to calculate bounding box of an avatar. | ||
9850 | /// </summary> | ||
9851 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) | ||
9852 | { | ||
9853 | // Adjust from OS model | ||
9854 | // avatar height = visual height - 0.2, bounding box height = visual height | ||
9855 | // to SL model | ||
9856 | // avatar height = visual height, bounding box height = visual height + 0.2 | ||
9857 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; | ||
9858 | |||
9859 | // According to avatar bounding box in SL 2015-04-18: | ||
9860 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> | ||
9861 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> | ||
9862 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> | ||
9863 | |||
9864 | // When avatar is sitting | ||
9865 | if (sp.ParentPart != null) | ||
9866 | { | ||
9867 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); | ||
9868 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); | ||
9869 | } | ||
9870 | // When avatar is groundsitting | ||
9871 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | ||
9872 | { | ||
9873 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); | ||
9874 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); | ||
9875 | } | ||
9876 | // When avatar is standing or flying | ||
9877 | else | ||
9878 | { | ||
9879 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); | ||
9880 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); | ||
9881 | } | ||
9882 | } | ||
9883 | |||
9884 | /// <summary> | ||
9885 | /// Helper to approximate a part with a simple box. | ||
9886 | /// </summary> | ||
9887 | private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | ||
9888 | { | ||
9889 | // Parse the 8 box corners | ||
9890 | for (int i = 0; i < 8; i++) | ||
9891 | { | ||
9892 | // Calculate each box corner | ||
9893 | Vector3 position = corner1; | ||
9894 | if ((i & 1) != 0) | ||
9895 | position.X = corner2.X; | ||
9896 | if ((i & 2) != 0) | ||
9897 | position.Y = corner2.Y; | ||
9898 | if ((i & 4) != 0) | ||
9899 | position.Z = corner2.Z; | ||
9900 | // Rotate part unless part is root | ||
9901 | if (hasParent) | ||
9902 | position = position * rotation; | ||
9903 | position = position + offset; | ||
9904 | // Adjust lower and upper bounding box corners if needed | ||
9905 | lower = Vector3.Min(lower, position); | ||
9906 | upper = Vector3.Max(upper, position); | ||
9907 | count++; | ||
9908 | } | ||
9909 | } | ||
9910 | |||
9911 | /// <summary> | ||
9912 | /// Helper to parse a meshed prim and needed especially | ||
9913 | /// for accuracy with tortured prims and sculpts. | ||
9914 | /// </summary> | ||
9915 | private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | ||
9916 | { | ||
9917 | // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. | ||
9918 | if (mesh != null) | ||
9919 | { | ||
9920 | // Parse each vertex in mesh | ||
9921 | foreach (Vertex vertex in mesh.Vertices) | ||
9922 | { | ||
9923 | Vector3 position = vertex.Position; | ||
9924 | position = position * prim.Scale; | ||
9925 | // Rotate part unless part is root | ||
9926 | if (hasParent) | ||
9927 | position = position * prim.Rotation; | ||
9928 | position = position + prim.Position; | ||
9929 | // Adjust lower and upper bounding box corners if needed | ||
9930 | lower = Vector3.Min(lower, position); | ||
9931 | upper = Vector3.Max(upper, position); | ||
9932 | count++; | ||
9638 | } | 9933 | } |
9639 | } | 9934 | } |
9640 | SceneObjectPart part = World.GetSceneObjectPart(objID); | 9935 | } |
9641 | // Currently only works for single prims without a sitting avatar | 9936 | |
9642 | if (part != null) | 9937 | /// <summary> |
9938 | /// Helper to parse mesh because no method exists | ||
9939 | /// to parse mesh assets to SimpleMesh. | ||
9940 | /// </summary> | ||
9941 | private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | ||
9942 | { | ||
9943 | if (mesh != null) | ||
9643 | { | 9944 | { |
9644 | Vector3 halfSize = part.Scale / 2.0f; | 9945 | // Parse each face in mesh |
9645 | LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; | 9946 | // since vertex array isn't populated. |
9646 | LSL_Vector upper = new LSL_Vector(halfSize); | 9947 | // This parses each unique vertex 3-6 times. |
9647 | result.Add(lower); | 9948 | foreach (Face face in mesh.Faces) |
9648 | result.Add(upper); | 9949 | { |
9649 | return result; | 9950 | // Parse each vertex in face |
9951 | foreach (Vertex vertex in face.Vertices) | ||
9952 | { | ||
9953 | Vector3 position = vertex.Position; | ||
9954 | position = position * prim.Scale; | ||
9955 | // Rotate part unless part is root | ||
9956 | if (hasParent) | ||
9957 | position = position * prim.Rotation; | ||
9958 | position = position + prim.Position; | ||
9959 | // Adjust lower and upper bounding box corners if needed | ||
9960 | lower = Vector3.Min(lower, position); | ||
9961 | upper = Vector3.Max(upper, position); | ||
9962 | count++; | ||
9963 | } | ||
9964 | } | ||
9650 | } | 9965 | } |
9966 | } | ||
9651 | 9967 | ||
9652 | // Not found so return empty values | 9968 | /// <summary> |
9653 | result.Add(new LSL_Vector()); | 9969 | /// Helper to make up an OpenMetaverse prim |
9654 | result.Add(new LSL_Vector()); | 9970 | /// needed to create mesh from parts. |
9655 | return result; | 9971 | /// </summary> |
9972 | private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) | ||
9973 | { | ||
9974 | // Initialize and set common parameters | ||
9975 | Primitive prim = new OpenMetaverse.Primitive(); | ||
9976 | prim.Scale = scale; | ||
9977 | prim.Position = position; | ||
9978 | prim.Rotation = rotation; | ||
9979 | prim.PrimData.PathShearX = 0.0f; | ||
9980 | prim.PrimData.PathShearY = 0.0f; | ||
9981 | prim.PrimData.PathBegin = 0.0f; | ||
9982 | prim.PrimData.PathEnd = 1.0f; | ||
9983 | prim.PrimData.PathScaleX = 1.0f; | ||
9984 | prim.PrimData.PathScaleY = 1.0f; | ||
9985 | prim.PrimData.PathTaperX = 0.0f; | ||
9986 | prim.PrimData.PathTaperY = 0.0f; | ||
9987 | prim.PrimData.PathTwistBegin = 0.0f; | ||
9988 | prim.PrimData.PathTwist = 0.0f; | ||
9989 | prim.PrimData.ProfileBegin = 0.0f; | ||
9990 | prim.PrimData.ProfileEnd = 1.0f; | ||
9991 | prim.PrimData.ProfileHollow = 0.0f; | ||
9992 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
9993 | prim.PrimData.ProfileHole = (HoleType)0; | ||
9994 | prim.PrimData.PathCurve = (PathCurve)16; | ||
9995 | prim.PrimData.PathRadiusOffset = 0.0f; | ||
9996 | prim.PrimData.PathRevolutions = 1.0f; | ||
9997 | prim.PrimData.PathSkew = 0.0f; | ||
9998 | prim.PrimData.PCode = OpenMetaverse.PCode.Prim; | ||
9999 | prim.PrimData.State = (byte)0; | ||
10000 | |||
10001 | // Set type specific parameters | ||
10002 | switch (primType) | ||
10003 | { | ||
10004 | // Set specific parameters for box | ||
10005 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
10006 | prim.PrimData.PathScaleY = 1.0f; | ||
10007 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10008 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10009 | break; | ||
10010 | // Set specific parameters for cylinder | ||
10011 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
10012 | prim.PrimData.PathScaleY = 1.0f; | ||
10013 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | ||
10014 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10015 | break; | ||
10016 | // Set specific parameters for prism | ||
10017 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
10018 | prim.PrimData.PathScaleY = 1.0f; | ||
10019 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | ||
10020 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10021 | break; | ||
10022 | // Set specific parameters for sphere | ||
10023 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
10024 | prim.PrimData.PathScaleY = 1.0f; | ||
10025 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | ||
10026 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10027 | break; | ||
10028 | // Set specific parameters for torus | ||
10029 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
10030 | prim.PrimData.PathScaleY = 0.5f; | ||
10031 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | ||
10032 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10033 | break; | ||
10034 | // Set specific parameters for tube | ||
10035 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
10036 | prim.PrimData.PathScaleY = 0.5f; | ||
10037 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10038 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10039 | break; | ||
10040 | // Set specific parameters for ring | ||
10041 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
10042 | prim.PrimData.PathScaleY = 0.5f; | ||
10043 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | ||
10044 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10045 | break; | ||
10046 | // Set specific parameters for sculpt | ||
10047 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
10048 | prim.PrimData.PathScaleY = 1.0f; | ||
10049 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | ||
10050 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10051 | break; | ||
10052 | // Default to specific parameters for box | ||
10053 | default: | ||
10054 | prim.PrimData.PathScaleY = 1.0f; | ||
10055 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10056 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10057 | break; | ||
10058 | } | ||
10059 | |||
10060 | return prim; | ||
9656 | } | 10061 | } |
9657 | 10062 | ||
9658 | public LSL_Vector llGetGeometricCenter() | 10063 | public LSL_Vector llGetGeometricCenter() |