/Aurora/Region/SceneObjectGroup.cs
C# | 4443 lines | 3090 code | 440 blank | 913 comment | 667 complexity | eb39fe50da51eea0a51eb78162e0ea63 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Aurora-Sim Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- using Aurora.Framework;
- using Aurora.Framework.ClientInterfaces;
- using Aurora.Framework.ConsoleFramework;
- using Aurora.Framework.Modules;
- using Aurora.Framework.Physics;
- using Aurora.Framework.PresenceInfo;
- using Aurora.Framework.SceneInfo;
- using Aurora.Framework.SceneInfo.Entities;
- using Aurora.Framework.Serialization;
- using Aurora.Framework.Utilities;
- using OpenMetaverse;
- using OpenMetaverse.Packets;
- using OpenMetaverse.StructuredData;
- using ProtoBuf;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Xml.Serialization;
- using GridRegion = Aurora.Framework.Services.GridRegion;
-
- namespace Aurora.Region
- {
- internal struct scriptPosTarget
- {
- public uint handle;
- public Vector3 targetPos;
- public float tolerance;
- }
-
- internal struct scriptRotTarget
- {
- public uint handle;
- public Quaternion targetRot;
- public float tolerance;
- }
-
- /// <summary>
- /// A scene object group is conceptually an object in the scene. The object is constituted of SceneObjectParts
- /// (often known as prims), one of which is considered the root part.
- /// </summary>
- [Serializable, ProtoContract()]
- public partial class SceneObjectGroup : ISceneEntity
- //(ISceneObject implements ISceneEntity and IEntity)
- {
- private readonly List<uint> m_lastColliders = new List<uint>();
- private readonly Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>();
- private readonly Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
- [XmlIgnore] private bool m_ValidgrpOOB; // control recalcutation
- [XmlIgnore] private float m_grpBSphereRadiusSQ; // the square of the radius of a sphere containing the oob
- [XmlIgnore] private Vector3 m_grpOOBoffset; // the position center of the bounding box relative to it's Position
-
- [XmlIgnore] private Vector3 m_grpOOBsize;
- // the size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
-
- public bool IsInTransit { get; set; }
-
- private UUID m_lastParcelUUID = UUID.Zero;
- private Vector3 m_lastSignificantPosition = Vector3.Zero;
- protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
- //Same as m_parts, but this is used for fast linear operations
- protected List<SceneObjectPart> m_partsList = new List<SceneObjectPart>();
- //This is the lock for m_parts and m_partsList
- protected object m_partsLock = new object();
- protected ulong m_regionHandle;
- protected SceneObjectPart m_rootPart;
- private bool m_scriptListens_atRotTarget;
- private bool m_scriptListens_atTarget;
- private bool m_scriptListens_notAtRotTarget;
- private bool m_scriptListens_notAtTarget;
-
- #region Properties
-
- private List<ISceneChildEntity> m_LoopSoundSlavePrims = new List<ISceneChildEntity>();
- private List<ISceneChildEntity> m_PlaySoundSlavePrims = new List<ISceneChildEntity>();
-
- /// <summary>
- /// Added because the Parcel code seems to use it
- /// but not sure a object should have this
- /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
- /// think really there should be a list (or whatever) in each scenepresence
- /// saying what prim(s) that user has selected.
- /// </summary>
- protected bool m_isSelected;
-
- protected Quaternion m_rotation = Quaternion.Identity;
-
- public SceneObjectPart[] Parts
- {
- get { return m_partsList.ToArray(); }
- }
-
- /// <value>
- /// The parts of this scene object group. You must lock this property before using it.
- /// </value>
- [ProtoMember(1)]
- public List<SceneObjectPart> ChildrenList
- {
- get { return m_partsList; }
- set { m_partsList = value; }
- }
-
- /// <value>
- /// The root part of this scene object
- /// </value>
- public SceneObjectPart RootPart
- {
- get { return m_rootPart; }
- }
-
- public Color Color
- {
- get { return m_rootPart.Color; }
- set
- {
- if (m_rootPart != null)
- m_rootPart.UpdateColor(value, true);
- }
- }
-
- public string Text
- {
- get
- {
- string returnstr = m_rootPart.Text;
- if (returnstr.Length > 255)
- {
- returnstr = returnstr.Substring(0, 255);
- }
- return returnstr;
- }
- set
- {
- if (m_rootPart != null && m_rootPart.Text != value)
- m_rootPart.Text = value;
- }
- }
-
- public ISceneChildEntity PlaySoundMasterPrim { get; set; }
-
- public List<ISceneChildEntity> PlaySoundSlavePrims
- {
- get { return m_PlaySoundSlavePrims; }
- set { m_PlaySoundSlavePrims = value; }
- }
-
- public UUID RegionUUID
- {
- get
- {
- if (m_scene != null)
- {
- return m_scene.RegionInfo.RegionID;
- }
- return UUID.Zero;
- }
- }
-
- /// <summary>
- /// The name of an object grouping is always the same as its root part
- /// </summary>
- public override string Name
- {
- get
- {
- if (RootPart == null)
- return String.Empty;
- return RootPart.Name;
- }
- set { RootPart.Name = value; }
- }
-
- /// <summary>
- /// Number of prims in this group
- /// </summary>
- public int PrimCount
- {
- get { return m_parts.Count; }
- }
-
- public override Quaternion Rotation
- {
- get { return m_rotation; }
- set
- {
- HasGroupChanged = true;
- m_rotation = value;
- }
- }
-
- public Quaternion GroupRotation
- {
- get { return m_rootPart.GetRotationOffset(); }
- }
-
- public UUID GroupID
- {
- get { return m_rootPart.GroupID; }
- set
- {
- HasGroupChanged = true;
- m_rootPart.GroupID = value;
- }
- }
-
- public List<ISceneChildEntity> ChildrenEntities()
- {
- return new List<SceneObjectPart>(m_partsList).Cast<ISceneChildEntity>().ToList();
- }
-
- public List<UUID> SitTargetAvatar
- {
- get
- {
- List<UUID> sittingAvatars = new List<UUID>();
- foreach (var prim in ChildrenEntities())
- sittingAvatars.AddRange(new List<UUID>(prim.SitTargetAvatar));
- return sittingAvatars;
- }
- }
-
- /// <summary>
- /// The absolute position of this scene object in the scene
- /// </summary>
- public override Vector3 AbsolutePosition
- {
- get { return m_rootPart.GroupPosition; }
- set { SetAbsolutePosition(true, value); }
- }
-
- public override uint LocalId
- {
- get { return m_rootPart.LocalId; }
- set { m_rootPart.LocalId = value; }
- }
-
- public override UUID UUID
- {
- get { return m_rootPart.UUID; }
- set { Scene.SceneGraph.UpdateEntity(this, value); }
- }
-
- public UUID OwnerID
- {
- get { return m_rootPart.OwnerID; }
- set
- {
- HasGroupChanged = true;
- m_rootPart.OwnerID = value;
- }
- }
-
- public float Damage
- {
- get { return m_rootPart.Damage; }
- set
- {
- HasGroupChanged = true;
- m_rootPart.Damage = value;
- }
- }
-
- public bool IsSelected
- {
- get { return m_isSelected; }
- set
- {
- m_isSelected = value;
- // Tell physics engine that group is selected
- if (m_rootPart.PhysActor != null)
- {
- m_rootPart.PhysActor.Selected = value;
- // Pass it on to the children.
- #if (!ISWIN)
- foreach (SceneObjectPart child in ChildrenList)
- {
- if (child.PhysActor != null)
- {
- child.PhysActor.Selected = value;
- }
- }
- #else
- foreach (SceneObjectPart child in ChildrenList.Where(child => child.PhysActor != null))
- {
- child.PhysActor.Selected = value;
- }
- #endif
- }
- }
- }
-
- public ISceneChildEntity LoopSoundMasterPrim { get; set; }
-
- public List<ISceneChildEntity> LoopSoundSlavePrims
- {
- get { return m_LoopSoundSlavePrims; }
- set { m_LoopSoundSlavePrims = value; }
- }
-
- public bool ContainsPart(UUID partID)
- {
- return m_parts.ContainsKey(partID);
- }
-
- /// <summary>
- /// Check both the attachment property and the relevant properties of the underlying root part.
- /// </summary>
- /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
- /// have the IsAttachment property yet checked.
- ///
- /// FIXME: However, this should be fixed so that this property
- /// propertly reflects the underlying status.
- /// <returns></returns>
- public bool IsAttachmentCheckFull()
- {
- return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
- }
-
- // The UUID for the Region this Object is in.
-
- #endregion
-
- #region Constructors
-
- public SceneObjectGroup()
- {
- }
-
- /// <summary>
- /// THIS IS ONLY FOR SERIALIZATION AND AS A BASE CONSTRUCTOR
- /// </summary>
- public SceneObjectGroup(IScene scene)
- {
- m_scene = scene;
- }
-
- /// <summary>
- /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
- /// The original SceneObjectPart will be used rather than a copy, preserving
- /// its existing localID and UUID.
- /// </summary>
- public SceneObjectGroup(SceneObjectPart part, IScene scene) : this(scene)
- {
- SetRootPart(part);
- part.Scale = part.Shape.Scale; // temporary hack to update oobb
- m_ValidgrpOOB = false;
- }
-
- public SceneObjectGroup(SceneObjectPart part, IScene scene, bool AddToScene)
- : this(scene)
- {
- if (!AddToScene)
- m_isDeleted = true;
-
- SetRootPart(part);
- part.Scale = part.Shape.Scale; // temporary hack to update oobb
- m_ValidgrpOOB = false;
- }
-
- /// <summary>
- /// Constructor. This object is added to the scene later via AttachToScene()
- /// </summary>
- public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape, string name,
- IScene scene) : this(scene)
- {
- SceneObjectPart part = new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero, name);
- SetRootPart(part);
-
- //This has to be set, otherwise it will break things like rezzing objects in an area where crossing is disabled, but rez isn't
- m_lastSignificantPosition = pos;
-
- m_ValidgrpOOB = false;
- }
-
- public void SetFromItemID(UUID itemID, UUID assetID)
- {
- foreach (SceneObjectPart part in m_partsList)
- {
- part.FromUserInventoryItemID = itemID;
- part.FromUserInventoryAssetID = assetID;
- }
- }
-
- /// <summary>
- /// Attach this object to a scene. It will also now apply to agents.
- /// </summary>
- /// <param name="scene"></param>
- public void AttachToScene(IScene scene)
- {
- m_scene = scene;
-
- if (m_rootPart.Shape == null)
- {
- MainConsole.Instance.Warn("[SceneObjectGroup]: Found null shape for prim " + UUID +
- ", creating default box shape");
- m_rootPart.Shape = new PrimitiveBaseShape();
- }
-
- IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
- if (WSModule != null)
- {
- foreach (SceneObjectPart part in ChildrenList)
- {
- //It's being rezzed, add it to the scene if it doesn't already have a rez date
- if (part.Rezzed != Util.ToDateTime(Util.EnvironmentTickCount()))
- part.Rezzed = DateTime.UtcNow;
- if (part.Shape == null)
- continue;
-
- Vector3 scale = part.Shape.Scale;
-
- if (WSModule.MinimumPrimScale != -1)
- {
- if (scale.X < WSModule.MinimumPrimScale)
- scale.X = WSModule.MinimumPrimScale;
- if (scale.Y < WSModule.MinimumPrimScale)
- scale.Y = WSModule.MinimumPrimScale;
- if (scale.Z < WSModule.MinimumPrimScale)
- scale.Z = WSModule.MinimumPrimScale;
- }
-
- if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical &&
- WSModule.MaximumPhysPrimScale != -1)
- {
- if (scale.X > WSModule.MaximumPhysPrimScale)
- scale.X = WSModule.MaximumPhysPrimScale;
- if (scale.Y > WSModule.MaximumPhysPrimScale)
- scale.Y = WSModule.MaximumPhysPrimScale;
- if (scale.Z > WSModule.MaximumPhysPrimScale)
- scale.Z = WSModule.MaximumPhysPrimScale;
- }
-
- if (WSModule.MaximumPrimScale != -1)
- {
- if (scale.X > WSModule.MaximumPrimScale)
- scale.X = WSModule.MaximumPrimScale;
- if (scale.Y > WSModule.MaximumPrimScale)
- scale.Y = WSModule.MaximumPrimScale;
- if (scale.Z > WSModule.MaximumPrimScale)
- scale.Z = WSModule.MaximumPrimScale;
- }
-
- part.Scale = scale;
- }
- }
-
- //Trigger our event
- Scene.EventManager.TriggerObjectBeingAddedToScene(this);
-
- RebuildPhysicalRepresentation(false);
-
- m_ValidgrpOOB = false;
- }
-
- public Vector3 GroupScale()
- {
- if (m_partsList.Count == 1)
- return RootPart.Scale;
-
- Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
- Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
- Vector3 finalScale;
-
- foreach (SceneObjectPart part in m_partsList)
- {
- Vector3 partscale = part.Scale*0.5f;
-
- // not assuming root is at index 0
- if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
- {
- // if root is always at index 0 this can be just assigns
-
- if (partscale.X > maxScale.X)
- maxScale.X = partscale.X;
- if (partscale.Y > maxScale.Y)
- maxScale.Y = partscale.Y;
- if (partscale.Z > maxScale.Z)
- maxScale.Z = partscale.Z;
-
- partscale = -partscale;
- if (partscale.X < minScale.X)
- minScale.X = partscale.X;
- if (partscale.Y < minScale.Y)
- minScale.Y = partscale.Y;
- if (partscale.Z < minScale.Z)
- minScale.Z = partscale.Z;
- }
-
- else // prims are in their local frame of reference
- {
- Vector3 partoffset = part.OffsetPosition;
- Quaternion partrot = part.GetRotationOffset();
-
- // bring into this frame
-
- partscale *= partrot;
- partoffset *= partrot;
- partoffset += part.OffsetPosition;
-
- // now just 2 vertices in a diagonal
- Vector3 deltam = partoffset - partscale;
- Vector3 deltaM = partoffset + partscale;
-
- if (deltaM.X > deltam.X) // right vertices order for extrem X
- {
- if (deltam.X < minScale.X)
- minScale.X = deltam.X;
- if (deltaM.X > maxScale.X)
- maxScale.X = deltaM.X;
- }
- else // nopes inverse one
- {
- if (deltaM.X < minScale.X)
- minScale.X = deltaM.X;
- if (deltam.X > maxScale.X)
- maxScale.X = deltam.X;
- }
-
- if (deltaM.Y > deltam.Y)
- {
- if (deltam.Y < minScale.Y)
- minScale.Y = deltam.Y;
- if (deltaM.Y > maxScale.Y)
- maxScale.Y = deltaM.Y;
- }
- else
- {
- if (deltaM.Y < minScale.Y)
- minScale.Y = deltaM.Y;
- if (deltam.Y > maxScale.Y)
- maxScale.Y = deltam.Y;
- }
-
- if (deltaM.Z > deltam.Z)
- {
- if (deltam.Z < minScale.Z)
- minScale.Z = deltam.Z;
- if (deltaM.Z > maxScale.Z)
- maxScale.Z = deltaM.Z;
- }
- else
- {
- if (deltaM.Z < minScale.Z)
- minScale.Z = deltaM.Z;
- if (deltam.Z > maxScale.Z)
- maxScale.Z = deltam.Z;
- }
- }
- }
-
- finalScale.X = Math.Abs(maxScale.X - minScale.X);
- finalScale.Y = Math.Abs(maxScale.Y - minScale.Y);
- finalScale.Z = Math.Abs(maxScale.Z - minScale.Z);
- return finalScale;
- }
-
- public override int GetHashCode()
- {
- return UUID.GetHashCode();
- }
-
- public bool IsPhysical()
- {
- return ((RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics);
- }
-
- public void UpdateOOBfromOOBs()
- {
- if (m_partsList.Count == 1)
- {
- SceneObjectPart part = m_partsList.First();
- m_grpOOBsize = part.OOBsize;
- m_grpOOBoffset = part.OOBoffset;
- m_grpBSphereRadiusSQ = part.BSphereRadiusSQ;
- m_ValidgrpOOB = true;
- return;
- }
-
- Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
- Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
-
- foreach (SceneObjectPart part in m_partsList)
- {
- Vector3 partscale = part.OOBsize; // (oobsize == vector with box vertice with all coords positive)
- Vector3 partoffset = part.OOBoffset;
-
- // not assuming root is at index 0
- Vector3 deltam;
- Vector3 deltaM;
- if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
- {
- //2 vertices in the right extrem sides:
- deltam = partoffset - partscale;
- deltaM = partoffset + partscale;
-
- // if root is always at index 0 this can be just assigns
- if (deltam.X < minScale.X)
- minScale.X = deltam.X;
- if (deltam.Y < minScale.Y)
- minScale.Y = deltam.Y;
- if (deltam.Z < minScale.Z)
- minScale.Z = deltam.Z;
-
- if (deltaM.X > maxScale.X)
- maxScale.X = deltaM.X;
- if (deltaM.Y > maxScale.Y)
- maxScale.Y = deltaM.Y;
- if (deltaM.Z > maxScale.Z)
- maxScale.Z = deltaM.Z;
- }
-
- else // prims are in their local frame of reference
- {
- // bring into this frame
- Quaternion partrot = part.GetRotationOffset();
- partscale *= partrot;
- partoffset *= partrot;
- partoffset += part.OffsetPosition;
-
- // now just 2 vertices in a diagonal
- deltam = partoffset - partscale;
- deltaM = partoffset + partscale;
-
- if (deltaM.X > deltam.X) // right vertices order for extrem X
- {
- if (deltam.X < minScale.X)
- minScale.X = deltam.X;
- if (deltaM.X > maxScale.X)
- maxScale.X = deltaM.X;
- }
- else // nopes inverse one
- {
- if (deltaM.X < minScale.X)
- minScale.X = deltaM.X;
- if (deltam.X > maxScale.X)
- maxScale.X = deltam.X;
- }
-
- if (deltaM.Y > deltam.Y)
- {
- if (deltam.Y < minScale.Y)
- minScale.Y = deltam.Y;
- if (deltaM.Y > maxScale.Y)
- maxScale.Y = deltaM.Y;
- }
- else
- {
- if (deltaM.Y < minScale.Y)
- minScale.Y = deltaM.Y;
- if (deltam.Y > maxScale.Y)
- maxScale.Y = deltam.Y;
- }
-
- if (deltaM.Z > deltam.Z)
- {
- if (deltam.Z < minScale.Z)
- minScale.Z = deltam.Z;
- if (deltaM.Z > maxScale.Z)
- maxScale.Z = deltaM.Z;
- }
- else
- {
- if (deltaM.Z < minScale.Z)
- minScale.Z = deltaM.Z;
- if (deltam.Z > maxScale.Z)
- maxScale.Z = deltam.Z;
- }
- }
- }
- // size == the vertice of box with all coords positive
- m_grpOOBsize.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
- m_grpOOBsize.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
- m_grpOOBsize.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
- // centroid:
- m_grpOOBoffset.X = 0.5f*(maxScale.X + minScale.X);
- m_grpOOBoffset.Y = 0.5f*(maxScale.Y + minScale.Y);
- m_grpOOBoffset.Z = 0.5f*(maxScale.Z + minScale.Z);
- // containing sphere:
- m_grpBSphereRadiusSQ = m_grpOOBsize.LengthSquared();
-
- m_ValidgrpOOB = true;
- }
-
- public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
- {
- // We got a request from the inner_scene to raytrace along the Ray hRay
- // We're going to check all of the prim in this group for intersection with the ray
- // If we get a result, we're going to find the closest result to the origin of the ray
- // and send back the intersection information back to the innerscene.
-
- EntityIntersection result = new EntityIntersection();
-
- foreach (SceneObjectPart part in m_partsList)
- {
- // Temporary commented to stop compiler warning
- //Vector3 partPosition =
- // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
- Quaternion parentrotation = GroupRotation;
- // Telling the prim to raytrace.
- //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
- 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.
- if (m_scene != null)
- {
- float idist = (m_scene.RegionInfo.RegionSizeX + m_scene.RegionInfo.RegionSizeY)/2;
- if (inter.HitTF)
- {
- // We need to find the closest prim to return to the testcaller along the ray
- if (inter.distance < idist)
- {
- result.HitTF = true;
- result.ipoint = inter.ipoint;
- result.obj = part;
- result.normal = inter.normal;
- result.distance = inter.distance;
- }
- }
- }
- }
-
- return result;
- }
-
- /// <summary>
- /// Gets a vector representing the size of the bounding box containing all the prims in the group
- /// Treats all prims as rectangular, so no shape (cut etc) is taken into account
- /// offsetHeight is the offset in the Z axis from the centre of the bounding box to the centre of the root prim
- /// </summary>
- /// <returns></returns>
- public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY,
- out float minZ, out float maxZ)
- {
- Vector3 pos = m_rootPart.AbsolutePosition;
- Quaternion rot = m_rootPart.GetRotationOffset();
- // Vector3 size = GroupScale();
- Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
- Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
- //limits in group frame
- foreach (SceneObjectPart part in m_partsList)
- {
- Vector3 partscale = part.Scale*0.5f;
- Vector3 partoffset = part.OffsetPosition;
- if (part.ParentID != 0) // prims are rotated in group
- {
- partscale *= part.GetRotationOffset();
- partscale.X = Math.Abs(partscale.X);
- partscale.Y = Math.Abs(partscale.Y);
- partscale.Z = Math.Abs(partscale.Z);
- }
-
- Vector3 deltam = partoffset - partscale;
- Vector3 deltaM = partoffset + partscale;
-
- if (deltam.X < minScale.X)
- minScale.X = deltam.X;
- if (deltam.Y < minScale.Y)
- minScale.Y = deltam.Y;
- if (deltam.Z < minScale.Z)
- minScale.Z = deltam.Z;
-
- if (deltaM.X > maxScale.X)
- maxScale.X = deltaM.X;
- if (deltaM.Y > maxScale.Y)
- maxScale.Y = deltaM.Y;
- if (deltaM.Z > maxScale.Z)
- maxScale.Z = deltaM.Z;
- }
-
- Vector3 tmp;
- tmp.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
- tmp.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
- tmp.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
- // tmp has half scale
-
- // group rotation
- tmp = tmp*rot;
- // scale is positive
- tmp.X = Math.Abs(tmp.X);
- tmp.Y = Math.Abs(tmp.Y);
- tmp.Z = Math.Abs(tmp.Z);
-
- // group position
- minX = pos.X - tmp.X;
- minY = pos.Y - tmp.Y;
- minZ = pos.Z - tmp.Z;
- maxX = pos.X + tmp.X;
- maxY = pos.Y + tmp.Y;
- maxZ = pos.Z + tmp.Z;
-
- /*
- maxX = -256f;
- maxY = -256f;
- maxZ = -256f;
- minX = 256f;
- minY = 256f;
- minZ = 8192f;
-
- foreach (SceneObjectPart part in m_partsList)
- {
- Vector3 worldPos = part.GetWorldPosition();
- Vector3 offset = worldPos - AbsolutePosition;
- Quaternion worldRot;
- if (part.ParentID == 0)
- worldRot = part.RotationOffset;
- else
- worldRot = part.GetWorldRotation();
- Vector3 frontTopLeft;
- Vector3 frontTopRight;
- Vector3 frontBottomLeft;
- Vector3 frontBottomRight;
- Vector3 backTopLeft;
- Vector3 backTopRight;
- Vector3 backBottomLeft;
- Vector3 backBottomRight;
- Vector3 orig = Vector3.Zero;
-
- frontTopLeft.X = orig.X - (part.Scale.X / 2);
- frontTopLeft.Y = orig.Y - (part.Scale.Y / 2);
- frontTopLeft.Z = orig.Z + (part.Scale.Z / 2);
-
- frontTopRight.X = orig.X - (part.Scale.X / 2);
- frontTopRight.Y = orig.Y + (part.Scale.Y / 2);
- frontTopRight.Z = orig.Z + (part.Scale.Z / 2);
-
- frontBottomLeft.X = orig.X - (part.Scale.X / 2);
- frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
- frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
-
- frontBottomRight.X = orig.X - (part.Scale.X / 2);
- frontBottomRight.Y = orig.Y + (part.Scale.Y / 2);
- frontBottomRight.Z = orig.Z - (part.Scale.Z / 2);
-
- backTopLeft.X = orig.X + (part.Scale.X / 2);
- backTopLeft.Y = orig.Y - (part.Scale.Y / 2);
- backTopLeft.Z = orig.Z + (part.Scale.Z / 2);
-
- backTopRight.X = orig.X + (part.Scale.X / 2);
- backTopRight.Y = orig.Y + (part.Scale.Y / 2);
- backTopRight.Z = orig.Z + (part.Scale.Z / 2);
-
- backBottomLeft.X = orig.X + (part.Scale.X / 2);
- backBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
- backBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
-
- backBottomRight.X = orig.X + (part.Scale.X / 2);
- backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
- backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
-
- frontTopLeft = frontTopLeft * worldRot;
- frontTopRight = frontTopRight * worldRot;
- frontBottomLeft = frontBottomLeft * worldRot;
- frontBottomRight = frontBottomRight * worldRot;
-
- backBottomLeft = backBottomLeft * worldRot;
- backBottomRight = backBottomRight * worldRot;
- backTopLeft = backTopLeft * worldRot;
- backTopRight = backTopRight * worldRot;
-
- frontTopLeft += offset;
- frontTopRight += offset;
- frontBottomLeft += offset;
- frontBottomRight += offset;
-
- backBottomLeft += offset;
- backBottomRight += offset;
- backTopLeft += offset;
- backTopRight += offset;
-
- if (frontTopRight.X > maxX)
- maxX = frontTopRight.X;
- if (frontTopLeft.X > maxX)
- maxX = frontTopLeft.X;
- if (frontBottomRight.X > maxX)
- maxX = frontBottomRight.X;
- if (frontBottomLeft.X > maxX)
- maxX = frontBottomLeft.X;
-
- if (backTopRight.X > maxX)
- maxX = backTopRight.X;
- if (backTopLeft.X > maxX)
- maxX = backTopLeft.X;
- if (backBottomRight.X > maxX)
- maxX = backBottomRight.X;
- if (backBottomLeft.X > maxX)
- maxX = backBottomLeft.X;
-
- if (frontTopRight.X < minX)
- minX = frontTopRight.X;
- if (frontTopLeft.X < minX)
- minX = frontTopLeft.X;
- if (frontBottomRight.X < minX)
- minX = frontBottomRight.X;
- if (frontBottomLeft.X < minX)
- minX = frontBottomLeft.X;
-
- if (backTopRight.X < minX)
- minX = backTopRight.X;
- if (backTopLeft.X < minX)
- minX = backTopLeft.X;
- if (backBottomRight.X < minX)
- minX = backBottomRight.X;
- if (backBottomLeft.X < minX)
- minX = backBottomLeft.X;
-
- if (frontTopRight.Y > maxY)
- maxY = frontTopRight.Y;
- if (frontTopLeft.Y > maxY)
- maxY = frontTopLeft.Y;
- if (frontBottomRight.Y > maxY)
- maxY = frontBottomRight.Y;
- if (frontBottomLeft.Y > maxY)
- maxY = frontBottomLeft.Y;
-
- if (backTopRight.Y > maxY)
- maxY = backTopRight.Y;
- if (backTopLeft.Y > maxY)
- maxY = backTopLeft.Y;
- if (backBottomRight.Y > maxY)
- maxY = backBottomRight.Y;
- if (backBottomLeft.Y > maxY)
- maxY = backBottomLeft.Y;
-
- if (backTopRight.Y < minY)
- minY = backTopRight.Y;
- if (backTopLeft.Y < minY)
- minY = backTopLeft.Y;
- if (backBottomRight.Y < minY)
- minY = backBottomRight.Y;
- if (backBottomLeft.Y < minY)
- minY = backBottomLeft.Y;
-
- if (backTopRight.Y < minY)
- minY = backTopRight.Y;
- if (backTopLeft.Y < minY)
- minY = backTopLeft.Y;
- if (backBottomRight.Y < minY)
- minY = backBottomRight.Y;
- if (backBottomLeft.Y < minY)
- minY = backBottomLeft.Y;
-
- if (frontTopRight.Z > maxZ)
- maxZ = frontTopRight.Z;
- if (frontTopLeft.Z > maxZ)
- maxZ = frontTopLeft.Z;
- if (frontBottomRight.Z > maxZ)
- maxZ = frontBottomRight.Z;
- if (frontBottomLeft.Z > maxZ)
- maxZ = frontBottomLeft.Z;
-
- if (backTopRight.Z > maxZ)
- maxZ = backTopRight.Z;
- if (backTopLeft.Z > maxZ)
- maxZ = backTopLeft.Z;
- if (backBottomRight.Z > maxZ)
- maxZ = backBottomRight.Z;
- if (backBottomLeft.Z > maxZ)
- maxZ = backBottomLeft.Z;
-
- if (frontTopRight.Z < minZ)
- minZ = frontTopRight.Z;
- if (frontTopLeft.Z < minZ)
- minZ = frontTopLeft.Z;
- if (frontBottomRight.Z < minZ)
- minZ = frontBottomRight.Z;
- if (frontBottomLeft.Z < minZ)
- minZ = frontBottomLeft.Z;
-
- if (backTopRight.Z < minZ)
- minZ = backTopRight.Z;
- if (backTopLeft.Z < minZ)
- minZ = backTopLeft.Z;
- if (backBottomRight.Z < minZ)
- minZ = backBottomRight.Z;
- if (backBottomLeft.Z < minZ)
- minZ = backBottomLeft.Z;
- }
- */
- }
-
- public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
- {
- float minX;
- float maxX;
- float minY;
- float maxY;
- float minZ;
- float maxZ;
-
- GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
- Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
-
-
- offsetHeight = 0.5f*(maxZ + minZ);
- offsetHeight -= m_rootPart.AbsolutePosition.Z;
-
- /*
- offsetHeight = 0;
- float lower = (minZ * -1);
- if (lower > maxZ)
- {
- offsetHeight = lower - (boundingBox.Z / 2);
-
- }
- else if (maxZ > lower)
- {
- offsetHeight = maxZ - (boundingBox.Z / 2);
- offsetHeight *= -1;
- }
- */
- // MainConsole.Instance.InfoFormat("BoundingBox is {0} , {1} , {2} ", boundingBox.X, boundingBox.Y, boundingBox.Z);
- return boundingBox;
- }
-
- #region Adding/Removing children from this group
-
- /// <summary>
- /// Clear all children from this group
- /// </summary>
- public void ClearChildren()
- {
- lock (m_partsLock)
- {
- m_parts.Clear();
- m_partsList.Clear();
- m_ValidgrpOOB = false;
- }
- }
-
- /// <summary>
- /// Add a child to the group, set the parent id's and then set the link number
- /// </summary>
- /// <param name="child"></param>
- /// <param name="linkNum"></param>
- /// <returns></returns>
- public bool AddChild(ISceneChildEntity child, int linkNum)
- {
- lock (m_partsLock)
- {
- if (child is SceneObjectPart)
- {
- SceneObjectPart part = (SceneObjectPart) child;
- //Root part is first
- if (m_partsList.Count == 0)
- {
- m_rootPart = part;
- }
- //Set the parent prim
- part.SetParent(this);
- if (m_rootPart.LocalId != 0 && !part.IsRoot)
- part.SetParentLocalId(m_rootPart.LocalId);
- else
- part.SetParentLocalId(0);
-
- //Fix the link num
- part.LinkNum = linkNum;
-
- if (!m_parts.ContainsKey(child.UUID))
- {
- m_parts.Add(child.UUID, part);
- m_partsList.Add(part);
- m_ValidgrpOOB = false;
- }
- return true;
- }
- }
- return false;
- }
-
- /// <summary>
- /// Add this child to the group and set the parent ID's,
- /// but do NOT set the link number,
- /// the caller wants to deal with it if they call this
- /// </summary>
- /// <param name="child"></param>
- /// <returns></returns>
- public bool LinkChild(ISceneChildEntity child)
- {
- lock (m_partsLock)
- {
- if (child is SceneObjectPart)
- {
- SceneObjectPart part = (SceneObjectPart) child;
- //Root part is first
- if (m_partsList.Count == 0)
- {
- m_rootPart = part;
- }
- //Set the parent prim
- part.SetParent(this);
- part.SetParentLocalId(m_rootPart.LocalId);
-
- if (!m_parts.ContainsKey(child.UUID))
- {
- m_parts.Add(child.UUID, part);
- m_partsList.Add(part);
- m_ValidgrpOOB = false;
- }
- m_partsList.Sort(m_scene.SceneGraph.LinkSetSorter);
- return true;
- }
- }
- return false;
- }
-
- /// <summary>
- /// Remove this child from the group and then update the link numbers so that there is not a hole
- /// </summary>
- /// <param name="child"></param>
- /// <returns></returns>
- public bool RemoveChild(ISceneChildEntity child)
- {
- lock (m_partsLock)
- {
- if (child is SceneObjectPart)
- {
- SceneObjectPart part = (SceneObjectPart) child;
- m_parts.Remove(part.UUID);
- m_partsList.Remove(part);
- m_ValidgrpOOB = false;
-
- //Fix the link numbers now
- FixLinkNumbers();
- return true;
- }
- }
- return false;
- }
-
- /// <summary>
- /// After a prim is removed, fix the link numbers so that they are correct
- /// </summary>
- private void FixLinkNumbers()
- {
- if (m_partsList.Count == 1)
- {
- m_partsList[0].LinkNum = 0;
- return;
- }
-
- lock (m_partsLock)
- {
- // has prims so starts at 1
- int lastSeenLinkNum = 1;
- m_partsList.Sort(Scene.SceneGraph.LinkSetSorter);
- foreach (SceneObjectPart t in m_partsList)
- {
- //If it isn't the same as the last seen +1, fix it
- if (t != null && t.LinkNum != lastSeenLinkNum)
- t.LinkNum = lastSeenLinkNum;
-
- //Go onto the next prim
- lastSeenLinkNum++;
- }
- }
- }
-
- #endregion
-
- #endregion
-
- /// <summary>
- /// The position center of the bounding box relative to it's Position
- /// </summary>
- [XmlIgnore]
- public Vector3 OOBoffset
- {
- get
- {
- if (!m_ValidgrpOOB)
- UpdateOOBfromOOBs();
- return m_grpOOBoffset;
- }
- }
-
- public object ChildrenListLock
- {
- get { return m_partsLock; }
- }
-
- #region ISceneObject Members
-
- public event BlankHandler OnFinishedPhysicalRepresentationBuilding;
-
- public Vector3 LastSignificantPosition
- {
- get { return m_lastSignificantPosition; }
- }
-
- public UUID LastParcelUUID
- {
- get { return m_lastParcelUUID; }
- set { m_lastParcelUUID = value; }
- }
-
- /// <summary>
- /// The size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
- /// </summary>
- [XmlIgnore]
- public Vector3 OOBsize
- {
- get
- {
- if (!m_ValidgrpOOB)
- UpdateOOBfromOOBs();
- return m_grpOOBsize;
- }
- }
-
- /// <summary>
- /// The square of the radius of a sphere containing the oob
- /// </summary>
- [XmlIgnore]
- public float BSphereRadiusSQ
- {
- get
- {
- if (!m_ValidgrpOOB)
- UpdateOOBfromOOBs();
- return m_grpBSphereRadiusSQ;
- }
- }
-
- public override bool HasGroupChanged
- {
- get { return m_hasGroupChanged; }
- set
- {
- if (value)
- {
- if (m_scene != null)
- {
- IBackupModule backup = m_scene.RequestModuleInterface<IBackupModule>();
- if (backup != null)
- {
- if (!backup.LoadingPrims) //Do NOT add to backup while still loading prims
- backup.AddPrimBackupTaint(this);
- }
- }
- }
- m_hasGroupChanged = value;
- }
- }
-
- /// <summary>
- /// Force all prims in the scene object to persist
- /// </summary>
- public void ForcePersistence()
- {
- //Force normal backup
- HasGroupChanged = true;
- ForceInventoryPersistence();
- }
-
- /// <summary>
- /// Clears all undo states from this group
- /// </summary>
- public void ClearUndoState()
- {
- foreach (SceneObjectPart child in ChildrenList)
- {
- child.ClearUndoState();
- }
- }
-
- /// <value>
- /// Is this scene object acting as an attachment?
- /// We return false if the group has already been deleted.
- /// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I
- /// presume either all or no parts in a linkset can be part of an attachment (in which
- /// case the value would get proprogated down into all the descendent parts).
- /// </value>
- public bool IsAttachment
- {
- get { return m_rootPart.IsAttachment; }
- }
-
- //private bool m_isBackedUp = false;
-
- public byte GetAttachmentPoint()
- {
- return m_rootPart.Shape.State;
- }
-
- public Vector3 GetAttachmentPos()
- {
- return m_rootPart.SavedAttachedPos;
- }
-
- public byte GetSavedAttachmentPoint()
- {
- return (byte) m_rootPart.SavedAttachmentPoint;
- }
-
- public void FinishedSerializingGenericProperties()
- {
- foreach (…
Large files files are truncated, but you can click here to view the full file