aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
authorMagnuz Binder2015-04-20 21:30:06 +0200
committerMichael Cerquoni2015-04-20 16:23:34 -0400
commit263db441292956a8210a00c037848165667ab90e (patch)
treef9e5df1736925b4598d40a6f08ac3ed628078e15 /OpenSim/Region/ScriptEngine/Shared/Api/Implementation
parentRevert "Enable grab feature (Ctrl+Drag) for non-physical link-sets and add co... (diff)
downloadopensim-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/ScriptEngine/Shared/Api/Implementation')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs489
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 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Imaging;
31using System.Runtime.Remoting.Lifetime; 33using System.Runtime.Remoting.Lifetime;
32using System.Text; 34using System.Text;
33using System.Threading; 35using System.Threading;
@@ -35,7 +37,9 @@ using System.Text.RegularExpressions;
35using Nini.Config; 37using Nini.Config;
36using log4net; 38using log4net;
37using OpenMetaverse; 39using OpenMetaverse;
40using OpenMetaverse.Assets;
38using OpenMetaverse.Packets; 41using OpenMetaverse.Packets;
42using OpenMetaverse.Rendering;
39using OpenSim; 43using OpenSim;
40using OpenSim.Framework; 44using 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()