PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Aurora/Region/SceneObjectGroup.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 4312 lines | 2965 code | 441 blank | 906 comment | 641 complexity | 4ad08d56799c7a9ddeadc1e4d86b728d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.Physics;
  32. using Aurora.Framework.PresenceInfo;
  33. using Aurora.Framework.SceneInfo;
  34. using Aurora.Framework.SceneInfo.Entities;
  35. using Aurora.Framework.Serialization;
  36. using Aurora.Framework.Utilities;
  37. using OpenMetaverse;
  38. using OpenMetaverse.Packets;
  39. using OpenMetaverse.StructuredData;
  40. using ProtoBuf;
  41. using System;
  42. using System.Collections.Generic;
  43. using System.Drawing;
  44. using System.Linq;
  45. using System.Xml.Serialization;
  46. using GridRegion = Aurora.Framework.Services.GridRegion;
  47. namespace Aurora.Region
  48. {
  49. internal struct scriptPosTarget
  50. {
  51. public uint handle;
  52. public Vector3 targetPos;
  53. public float tolerance;
  54. }
  55. internal struct scriptRotTarget
  56. {
  57. public uint handle;
  58. public Quaternion targetRot;
  59. public float tolerance;
  60. }
  61. /// <summary>
  62. /// A scene object group is conceptually an object in the scene. The object is constituted of SceneObjectParts
  63. /// (often known as prims), one of which is considered the root part.
  64. /// </summary>
  65. [Serializable, ProtoContract()]
  66. public partial class SceneObjectGroup : ISceneEntity
  67. //(ISceneObject implements ISceneEntity and IEntity)
  68. {
  69. private readonly List<uint> m_lastColliders = new List<uint>();
  70. private readonly Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>();
  71. private readonly Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
  72. [XmlIgnore] private bool m_ValidgrpOOB; // control recalcutation
  73. [XmlIgnore] private float m_grpBSphereRadiusSQ; // the square of the radius of a sphere containing the oob
  74. [XmlIgnore] private Vector3 m_grpOOBoffset; // the position center of the bounding box relative to it's Position
  75. [XmlIgnore] private Vector3 m_grpOOBsize;
  76. // the size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
  77. public bool IsInTransit { get; set; }
  78. private UUID m_lastParcelUUID = UUID.Zero;
  79. private Vector3 m_lastSignificantPosition = Vector3.Zero;
  80. protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
  81. //Same as m_parts, but this is used for fast linear operations
  82. protected List<SceneObjectPart> m_partsList = new List<SceneObjectPart>();
  83. //This is the lock for m_parts and m_partsList
  84. protected object m_partsLock = new object();
  85. protected ulong m_regionHandle;
  86. protected SceneObjectPart m_rootPart;
  87. private bool m_scriptListens_atRotTarget;
  88. private bool m_scriptListens_atTarget;
  89. private bool m_scriptListens_notAtRotTarget;
  90. private bool m_scriptListens_notAtTarget;
  91. #region Properties
  92. private List<ISceneChildEntity> m_LoopSoundSlavePrims = new List<ISceneChildEntity>();
  93. private List<ISceneChildEntity> m_PlaySoundSlavePrims = new List<ISceneChildEntity>();
  94. /// <summary>
  95. /// Added because the Parcel code seems to use it
  96. /// but not sure a object should have this
  97. /// as what does it tell us? that some avatar has selected it (but not what Avatar/user)
  98. /// think really there should be a list (or whatever) in each scenepresence
  99. /// saying what prim(s) that user has selected.
  100. /// </summary>
  101. protected bool m_isSelected;
  102. protected Quaternion m_rotation = Quaternion.Identity;
  103. public SceneObjectPart[] Parts
  104. {
  105. get { return m_partsList.ToArray(); }
  106. }
  107. /// <value>
  108. /// The parts of this scene object group. You must lock this property before using it.
  109. /// </value>
  110. [ProtoMember(1)]
  111. public List<SceneObjectPart> ChildrenList
  112. {
  113. get { return m_partsList; }
  114. set { m_partsList = value; }
  115. }
  116. /// <value>
  117. /// The root part of this scene object
  118. /// </value>
  119. public SceneObjectPart RootPart
  120. {
  121. get { return m_rootPart; }
  122. }
  123. public Color Color
  124. {
  125. get { return m_rootPart.Color; }
  126. set
  127. {
  128. if (m_rootPart != null)
  129. m_rootPart.UpdateColor(value, true);
  130. }
  131. }
  132. public string Text
  133. {
  134. get
  135. {
  136. string returnstr = m_rootPart.Text;
  137. if (returnstr.Length > 255)
  138. {
  139. returnstr = returnstr.Substring(0, 255);
  140. }
  141. return returnstr;
  142. }
  143. set
  144. {
  145. if (m_rootPart != null && m_rootPart.Text != value)
  146. m_rootPart.Text = value;
  147. }
  148. }
  149. public ISceneChildEntity PlaySoundMasterPrim { get; set; }
  150. public List<ISceneChildEntity> PlaySoundSlavePrims
  151. {
  152. get { return m_PlaySoundSlavePrims; }
  153. set { m_PlaySoundSlavePrims = value; }
  154. }
  155. public UUID RegionUUID
  156. {
  157. get
  158. {
  159. if (m_scene != null)
  160. {
  161. return m_scene.RegionInfo.RegionID;
  162. }
  163. return UUID.Zero;
  164. }
  165. }
  166. /// <summary>
  167. /// The name of an object grouping is always the same as its root part
  168. /// </summary>
  169. public override string Name
  170. {
  171. get
  172. {
  173. if (RootPart == null)
  174. return String.Empty;
  175. return RootPart.Name;
  176. }
  177. set { RootPart.Name = value; }
  178. }
  179. /// <summary>
  180. /// Number of prims in this group
  181. /// </summary>
  182. public int PrimCount
  183. {
  184. get { return m_parts.Count; }
  185. }
  186. public override Quaternion Rotation
  187. {
  188. get { return m_rotation; }
  189. set
  190. {
  191. HasGroupChanged = true;
  192. m_rotation = value;
  193. }
  194. }
  195. public Quaternion GroupRotation
  196. {
  197. get { return m_rootPart.GetRotationOffset(); }
  198. }
  199. public UUID GroupID
  200. {
  201. get { return m_rootPart.GroupID; }
  202. set
  203. {
  204. HasGroupChanged = true;
  205. m_rootPart.GroupID = value;
  206. }
  207. }
  208. public List<ISceneChildEntity> ChildrenEntities()
  209. {
  210. return new List<SceneObjectPart>(m_partsList).Cast<ISceneChildEntity>().ToList();
  211. }
  212. public List<UUID> SitTargetAvatar
  213. {
  214. get
  215. {
  216. List<UUID> sittingAvatars = new List<UUID>();
  217. foreach (var prim in ChildrenEntities())
  218. sittingAvatars.AddRange(new List<UUID>(prim.SitTargetAvatar));
  219. return sittingAvatars;
  220. }
  221. }
  222. /// <summary>
  223. /// The absolute position of this scene object in the scene
  224. /// </summary>
  225. public override Vector3 AbsolutePosition
  226. {
  227. get { return m_rootPart.GroupPosition; }
  228. set { SetAbsolutePosition(true, value); }
  229. }
  230. public override uint LocalId
  231. {
  232. get { return m_rootPart.LocalId; }
  233. set { m_rootPart.LocalId = value; }
  234. }
  235. public override UUID UUID
  236. {
  237. get { return m_rootPart.UUID; }
  238. set { Scene.SceneGraph.UpdateEntity(this, value); }
  239. }
  240. public UUID OwnerID
  241. {
  242. get { return m_rootPart.OwnerID; }
  243. set
  244. {
  245. HasGroupChanged = true;
  246. m_rootPart.OwnerID = value;
  247. }
  248. }
  249. public float Damage
  250. {
  251. get { return m_rootPart.Damage; }
  252. set
  253. {
  254. HasGroupChanged = true;
  255. m_rootPart.Damage = value;
  256. }
  257. }
  258. public bool IsSelected
  259. {
  260. get { return m_isSelected; }
  261. set
  262. {
  263. m_isSelected = value;
  264. // Tell physics engine that group is selected
  265. if (m_rootPart.PhysActor != null)
  266. {
  267. m_rootPart.PhysActor.Selected = value;
  268. // Pass it on to the children.
  269. foreach (SceneObjectPart child in ChildrenList.Where(child => child.PhysActor != null))
  270. {
  271. child.PhysActor.Selected = value;
  272. }
  273. }
  274. }
  275. }
  276. public ISceneChildEntity LoopSoundMasterPrim { get; set; }
  277. public List<ISceneChildEntity> LoopSoundSlavePrims
  278. {
  279. get { return m_LoopSoundSlavePrims; }
  280. set { m_LoopSoundSlavePrims = value; }
  281. }
  282. public bool ContainsPart(UUID partID)
  283. {
  284. return m_parts.ContainsKey(partID);
  285. }
  286. /// <summary>
  287. /// Check both the attachment property and the relevant properties of the underlying root part.
  288. /// </summary>
  289. /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
  290. /// have the IsAttachment property yet checked.
  291. ///
  292. /// FIXME: However, this should be fixed so that this property
  293. /// propertly reflects the underlying status.
  294. /// <returns></returns>
  295. public bool IsAttachmentCheckFull()
  296. {
  297. return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
  298. }
  299. // The UUID for the Region this Object is in.
  300. #endregion
  301. #region Constructors
  302. public SceneObjectGroup()
  303. {
  304. }
  305. /// <summary>
  306. /// THIS IS ONLY FOR SERIALIZATION AND AS A BASE CONSTRUCTOR
  307. /// </summary>
  308. public SceneObjectGroup(IScene scene)
  309. {
  310. m_scene = scene;
  311. }
  312. /// <summary>
  313. /// This constructor creates a SceneObjectGroup using a pre-existing SceneObjectPart.
  314. /// The original SceneObjectPart will be used rather than a copy, preserving
  315. /// its existing localID and UUID.
  316. /// </summary>
  317. public SceneObjectGroup(SceneObjectPart part, IScene scene) : this(scene)
  318. {
  319. SetRootPart(part);
  320. part.Scale = part.Shape.Scale; // temporary hack to update oobb
  321. m_ValidgrpOOB = false;
  322. }
  323. public SceneObjectGroup(SceneObjectPart part, IScene scene, bool AddToScene)
  324. : this(scene)
  325. {
  326. if (!AddToScene)
  327. m_isDeleted = true;
  328. SetRootPart(part);
  329. part.Scale = part.Shape.Scale; // temporary hack to update oobb
  330. m_ValidgrpOOB = false;
  331. }
  332. /// <summary>
  333. /// Constructor. This object is added to the scene later via AttachToScene()
  334. /// </summary>
  335. public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape, string name,
  336. IScene scene) : this(scene)
  337. {
  338. SceneObjectPart part = new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero, name);
  339. SetRootPart(part);
  340. //This has to be set, otherwise it will break things like rezzing objects in an area where crossing is disabled, but rez isn't
  341. m_lastSignificantPosition = pos;
  342. m_ValidgrpOOB = false;
  343. }
  344. public void SetFromItemID(UUID itemID, UUID assetID)
  345. {
  346. foreach (SceneObjectPart part in m_partsList)
  347. {
  348. part.FromUserInventoryItemID = itemID;
  349. part.FromUserInventoryAssetID = assetID;
  350. }
  351. }
  352. /// <summary>
  353. /// Attach this object to a scene. It will also now apply to agents.
  354. /// </summary>
  355. /// <param name="scene"></param>
  356. public void AttachToScene(IScene scene)
  357. {
  358. m_scene = scene;
  359. if (m_rootPart.Shape == null)
  360. {
  361. MainConsole.Instance.Warn("[SceneObjectGroup]: Found null shape for prim " + UUID +
  362. ", creating default box shape");
  363. m_rootPart.Shape = new PrimitiveBaseShape();
  364. }
  365. IOpenRegionSettingsModule WSModule = Scene.RequestModuleInterface<IOpenRegionSettingsModule>();
  366. if (WSModule != null)
  367. {
  368. foreach (SceneObjectPart part in ChildrenList)
  369. {
  370. //It's being rezzed, add it to the scene if it doesn't already have a rez date
  371. if (part.Rezzed != Util.ToDateTime(Util.EnvironmentTickCount()))
  372. part.Rezzed = DateTime.UtcNow;
  373. if (part.Shape == null)
  374. continue;
  375. Vector3 scale = part.Shape.Scale;
  376. if (WSModule.MinimumPrimScale != -1)
  377. {
  378. if (scale.X < WSModule.MinimumPrimScale)
  379. scale.X = WSModule.MinimumPrimScale;
  380. if (scale.Y < WSModule.MinimumPrimScale)
  381. scale.Y = WSModule.MinimumPrimScale;
  382. if (scale.Z < WSModule.MinimumPrimScale)
  383. scale.Z = WSModule.MinimumPrimScale;
  384. }
  385. if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical &&
  386. WSModule.MaximumPhysPrimScale != -1)
  387. {
  388. if (scale.X > WSModule.MaximumPhysPrimScale)
  389. scale.X = WSModule.MaximumPhysPrimScale;
  390. if (scale.Y > WSModule.MaximumPhysPrimScale)
  391. scale.Y = WSModule.MaximumPhysPrimScale;
  392. if (scale.Z > WSModule.MaximumPhysPrimScale)
  393. scale.Z = WSModule.MaximumPhysPrimScale;
  394. }
  395. if (WSModule.MaximumPrimScale != -1)
  396. {
  397. if (scale.X > WSModule.MaximumPrimScale)
  398. scale.X = WSModule.MaximumPrimScale;
  399. if (scale.Y > WSModule.MaximumPrimScale)
  400. scale.Y = WSModule.MaximumPrimScale;
  401. if (scale.Z > WSModule.MaximumPrimScale)
  402. scale.Z = WSModule.MaximumPrimScale;
  403. }
  404. part.Scale = scale;
  405. }
  406. }
  407. //Trigger our event
  408. Scene.EventManager.TriggerObjectBeingAddedToScene(this);
  409. RebuildPhysicalRepresentation(false);
  410. m_ValidgrpOOB = false;
  411. }
  412. public Vector3 GroupScale()
  413. {
  414. if (m_partsList.Count == 1)
  415. return RootPart.Scale;
  416. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  417. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  418. Vector3 finalScale;
  419. foreach (SceneObjectPart part in m_partsList)
  420. {
  421. Vector3 partscale = part.Scale*0.5f;
  422. // not assuming root is at index 0
  423. if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
  424. {
  425. // if root is always at index 0 this can be just assigns
  426. if (partscale.X > maxScale.X)
  427. maxScale.X = partscale.X;
  428. if (partscale.Y > maxScale.Y)
  429. maxScale.Y = partscale.Y;
  430. if (partscale.Z > maxScale.Z)
  431. maxScale.Z = partscale.Z;
  432. partscale = -partscale;
  433. if (partscale.X < minScale.X)
  434. minScale.X = partscale.X;
  435. if (partscale.Y < minScale.Y)
  436. minScale.Y = partscale.Y;
  437. if (partscale.Z < minScale.Z)
  438. minScale.Z = partscale.Z;
  439. }
  440. else // prims are in their local frame of reference
  441. {
  442. Vector3 partoffset = part.OffsetPosition;
  443. Quaternion partrot = part.GetRotationOffset();
  444. // bring into this frame
  445. partscale *= partrot;
  446. partoffset *= partrot;
  447. partoffset += part.OffsetPosition;
  448. // now just 2 vertices in a diagonal
  449. Vector3 deltam = partoffset - partscale;
  450. Vector3 deltaM = partoffset + partscale;
  451. if (deltaM.X > deltam.X) // right vertices order for extrem X
  452. {
  453. if (deltam.X < minScale.X)
  454. minScale.X = deltam.X;
  455. if (deltaM.X > maxScale.X)
  456. maxScale.X = deltaM.X;
  457. }
  458. else // nopes inverse one
  459. {
  460. if (deltaM.X < minScale.X)
  461. minScale.X = deltaM.X;
  462. if (deltam.X > maxScale.X)
  463. maxScale.X = deltam.X;
  464. }
  465. if (deltaM.Y > deltam.Y)
  466. {
  467. if (deltam.Y < minScale.Y)
  468. minScale.Y = deltam.Y;
  469. if (deltaM.Y > maxScale.Y)
  470. maxScale.Y = deltaM.Y;
  471. }
  472. else
  473. {
  474. if (deltaM.Y < minScale.Y)
  475. minScale.Y = deltaM.Y;
  476. if (deltam.Y > maxScale.Y)
  477. maxScale.Y = deltam.Y;
  478. }
  479. if (deltaM.Z > deltam.Z)
  480. {
  481. if (deltam.Z < minScale.Z)
  482. minScale.Z = deltam.Z;
  483. if (deltaM.Z > maxScale.Z)
  484. maxScale.Z = deltaM.Z;
  485. }
  486. else
  487. {
  488. if (deltaM.Z < minScale.Z)
  489. minScale.Z = deltaM.Z;
  490. if (deltam.Z > maxScale.Z)
  491. maxScale.Z = deltam.Z;
  492. }
  493. }
  494. }
  495. finalScale.X = Math.Abs(maxScale.X - minScale.X);
  496. finalScale.Y = Math.Abs(maxScale.Y - minScale.Y);
  497. finalScale.Z = Math.Abs(maxScale.Z - minScale.Z);
  498. return finalScale;
  499. }
  500. public override int GetHashCode()
  501. {
  502. return UUID.GetHashCode();
  503. }
  504. public bool IsPhysical()
  505. {
  506. return ((RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics);
  507. }
  508. public void UpdateOOBfromOOBs()
  509. {
  510. if (m_partsList.Count == 1)
  511. {
  512. SceneObjectPart part = m_partsList.First();
  513. m_grpOOBsize = part.OOBsize;
  514. m_grpOOBoffset = part.OOBoffset;
  515. m_grpBSphereRadiusSQ = part.BSphereRadiusSQ;
  516. m_ValidgrpOOB = true;
  517. return;
  518. }
  519. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  520. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  521. foreach (SceneObjectPart part in m_partsList)
  522. {
  523. Vector3 partscale = part.OOBsize; // (oobsize == vector with box vertice with all coords positive)
  524. Vector3 partoffset = part.OOBoffset;
  525. // not assuming root is at index 0
  526. Vector3 deltam;
  527. Vector3 deltaM;
  528. if (part.ParentID == 0) // root is in local frame of reference, partscale.? are positive, no rotations
  529. {
  530. //2 vertices in the right extrem sides:
  531. deltam = partoffset - partscale;
  532. deltaM = partoffset + partscale;
  533. // if root is always at index 0 this can be just assigns
  534. if (deltam.X < minScale.X)
  535. minScale.X = deltam.X;
  536. if (deltam.Y < minScale.Y)
  537. minScale.Y = deltam.Y;
  538. if (deltam.Z < minScale.Z)
  539. minScale.Z = deltam.Z;
  540. if (deltaM.X > maxScale.X)
  541. maxScale.X = deltaM.X;
  542. if (deltaM.Y > maxScale.Y)
  543. maxScale.Y = deltaM.Y;
  544. if (deltaM.Z > maxScale.Z)
  545. maxScale.Z = deltaM.Z;
  546. }
  547. else // prims are in their local frame of reference
  548. {
  549. // bring into this frame
  550. Quaternion partrot = part.GetRotationOffset();
  551. partscale *= partrot;
  552. partoffset *= partrot;
  553. partoffset += part.OffsetPosition;
  554. // now just 2 vertices in a diagonal
  555. deltam = partoffset - partscale;
  556. deltaM = partoffset + partscale;
  557. if (deltaM.X > deltam.X) // right vertices order for extrem X
  558. {
  559. if (deltam.X < minScale.X)
  560. minScale.X = deltam.X;
  561. if (deltaM.X > maxScale.X)
  562. maxScale.X = deltaM.X;
  563. }
  564. else // nopes inverse one
  565. {
  566. if (deltaM.X < minScale.X)
  567. minScale.X = deltaM.X;
  568. if (deltam.X > maxScale.X)
  569. maxScale.X = deltam.X;
  570. }
  571. if (deltaM.Y > deltam.Y)
  572. {
  573. if (deltam.Y < minScale.Y)
  574. minScale.Y = deltam.Y;
  575. if (deltaM.Y > maxScale.Y)
  576. maxScale.Y = deltaM.Y;
  577. }
  578. else
  579. {
  580. if (deltaM.Y < minScale.Y)
  581. minScale.Y = deltaM.Y;
  582. if (deltam.Y > maxScale.Y)
  583. maxScale.Y = deltam.Y;
  584. }
  585. if (deltaM.Z > deltam.Z)
  586. {
  587. if (deltam.Z < minScale.Z)
  588. minScale.Z = deltam.Z;
  589. if (deltaM.Z > maxScale.Z)
  590. maxScale.Z = deltaM.Z;
  591. }
  592. else
  593. {
  594. if (deltaM.Z < minScale.Z)
  595. minScale.Z = deltaM.Z;
  596. if (deltam.Z > maxScale.Z)
  597. maxScale.Z = deltam.Z;
  598. }
  599. }
  600. }
  601. // size == the vertice of box with all coords positive
  602. m_grpOOBsize.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
  603. m_grpOOBsize.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
  604. m_grpOOBsize.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
  605. // centroid:
  606. m_grpOOBoffset.X = 0.5f*(maxScale.X + minScale.X);
  607. m_grpOOBoffset.Y = 0.5f*(maxScale.Y + minScale.Y);
  608. m_grpOOBoffset.Z = 0.5f*(maxScale.Z + minScale.Z);
  609. // containing sphere:
  610. m_grpBSphereRadiusSQ = m_grpOOBsize.LengthSquared();
  611. m_ValidgrpOOB = true;
  612. }
  613. public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
  614. {
  615. // We got a request from the inner_scene to raytrace along the Ray hRay
  616. // We're going to check all of the prim in this group for intersection with the ray
  617. // If we get a result, we're going to find the closest result to the origin of the ray
  618. // and send back the intersection information back to the innerscene.
  619. EntityIntersection result = new EntityIntersection();
  620. foreach (SceneObjectPart part in m_partsList)
  621. {
  622. // Temporary commented to stop compiler warning
  623. //Vector3 partPosition =
  624. // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
  625. Quaternion parentrotation = GroupRotation;
  626. // Telling the prim to raytrace.
  627. //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
  628. EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
  629. // This may need to be updated to the maximum draw distance possible..
  630. // We might (and probably will) be checking for prim creation from other sims
  631. // when the camera crosses the border.
  632. if (m_scene != null)
  633. {
  634. float idist = (m_scene.RegionInfo.RegionSizeX + m_scene.RegionInfo.RegionSizeY)/2;
  635. if (inter.HitTF)
  636. {
  637. // We need to find the closest prim to return to the testcaller along the ray
  638. if (inter.distance < idist)
  639. {
  640. result.HitTF = true;
  641. result.ipoint = inter.ipoint;
  642. result.obj = part;
  643. result.normal = inter.normal;
  644. result.distance = inter.distance;
  645. }
  646. }
  647. }
  648. }
  649. return result;
  650. }
  651. /// <summary>
  652. /// Gets a vector representing the size of the bounding box containing all the prims in the group
  653. /// Treats all prims as rectangular, so no shape (cut etc) is taken into account
  654. /// offsetHeight is the offset in the Z axis from the centre of the bounding box to the centre of the root prim
  655. /// </summary>
  656. /// <returns></returns>
  657. public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY,
  658. out float minZ, out float maxZ)
  659. {
  660. Vector3 pos = m_rootPart.AbsolutePosition;
  661. Quaternion rot = m_rootPart.GetRotationOffset();
  662. // Vector3 size = GroupScale();
  663. Vector3 minScale = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  664. Vector3 maxScale = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  665. //limits in group frame
  666. foreach (SceneObjectPart part in m_partsList)
  667. {
  668. Vector3 partscale = part.Scale*0.5f;
  669. Vector3 partoffset = part.OffsetPosition;
  670. if (part.ParentID != 0) // prims are rotated in group
  671. {
  672. partscale *= part.GetRotationOffset();
  673. partscale.X = Math.Abs(partscale.X);
  674. partscale.Y = Math.Abs(partscale.Y);
  675. partscale.Z = Math.Abs(partscale.Z);
  676. }
  677. Vector3 deltam = partoffset - partscale;
  678. Vector3 deltaM = partoffset + partscale;
  679. if (deltam.X < minScale.X)
  680. minScale.X = deltam.X;
  681. if (deltam.Y < minScale.Y)
  682. minScale.Y = deltam.Y;
  683. if (deltam.Z < minScale.Z)
  684. minScale.Z = deltam.Z;
  685. if (deltaM.X > maxScale.X)
  686. maxScale.X = deltaM.X;
  687. if (deltaM.Y > maxScale.Y)
  688. maxScale.Y = deltaM.Y;
  689. if (deltaM.Z > maxScale.Z)
  690. maxScale.Z = deltaM.Z;
  691. }
  692. Vector3 tmp;
  693. tmp.X = 0.5f*Math.Abs(maxScale.X - minScale.X);
  694. tmp.Y = 0.5f*Math.Abs(maxScale.Y - minScale.Y);
  695. tmp.Z = 0.5f*Math.Abs(maxScale.Z - minScale.Z);
  696. // tmp has half scale
  697. // group rotation
  698. tmp = tmp*rot;
  699. // scale is positive
  700. tmp.X = Math.Abs(tmp.X);
  701. tmp.Y = Math.Abs(tmp.Y);
  702. tmp.Z = Math.Abs(tmp.Z);
  703. // group position
  704. minX = pos.X - tmp.X;
  705. minY = pos.Y - tmp.Y;
  706. minZ = pos.Z - tmp.Z;
  707. maxX = pos.X + tmp.X;
  708. maxY = pos.Y + tmp.Y;
  709. maxZ = pos.Z + tmp.Z;
  710. /*
  711. maxX = -256f;
  712. maxY = -256f;
  713. maxZ = -256f;
  714. minX = 256f;
  715. minY = 256f;
  716. minZ = 8192f;
  717. foreach (SceneObjectPart part in m_partsList)
  718. {
  719. Vector3 worldPos = part.GetWorldPosition();
  720. Vector3 offset = worldPos - AbsolutePosition;
  721. Quaternion worldRot;
  722. if (part.ParentID == 0)
  723. worldRot = part.RotationOffset;
  724. else
  725. worldRot = part.GetWorldRotation();
  726. Vector3 frontTopLeft;
  727. Vector3 frontTopRight;
  728. Vector3 frontBottomLeft;
  729. Vector3 frontBottomRight;
  730. Vector3 backTopLeft;
  731. Vector3 backTopRight;
  732. Vector3 backBottomLeft;
  733. Vector3 backBottomRight;
  734. Vector3 orig = Vector3.Zero;
  735. frontTopLeft.X = orig.X - (part.Scale.X / 2);
  736. frontTopLeft.Y = orig.Y - (part.Scale.Y / 2);
  737. frontTopLeft.Z = orig.Z + (part.Scale.Z / 2);
  738. frontTopRight.X = orig.X - (part.Scale.X / 2);
  739. frontTopRight.Y = orig.Y + (part.Scale.Y / 2);
  740. frontTopRight.Z = orig.Z + (part.Scale.Z / 2);
  741. frontBottomLeft.X = orig.X - (part.Scale.X / 2);
  742. frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
  743. frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
  744. frontBottomRight.X = orig.X - (part.Scale.X / 2);
  745. frontBottomRight.Y = orig.Y + (part.Scale.Y / 2);
  746. frontBottomRight.Z = orig.Z - (part.Scale.Z / 2);
  747. backTopLeft.X = orig.X + (part.Scale.X / 2);
  748. backTopLeft.Y = orig.Y - (part.Scale.Y / 2);
  749. backTopLeft.Z = orig.Z + (part.Scale.Z / 2);
  750. backTopRight.X = orig.X + (part.Scale.X / 2);
  751. backTopRight.Y = orig.Y + (part.Scale.Y / 2);
  752. backTopRight.Z = orig.Z + (part.Scale.Z / 2);
  753. backBottomLeft.X = orig.X + (part.Scale.X / 2);
  754. backBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
  755. backBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
  756. backBottomRight.X = orig.X + (part.Scale.X / 2);
  757. backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
  758. backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
  759. frontTopLeft = frontTopLeft * worldRot;
  760. frontTopRight = frontTopRight * worldRot;
  761. frontBottomLeft = frontBottomLeft * worldRot;
  762. frontBottomRight = frontBottomRight * worldRot;
  763. backBottomLeft = backBottomLeft * worldRot;
  764. backBottomRight = backBottomRight * worldRot;
  765. backTopLeft = backTopLeft * worldRot;
  766. backTopRight = backTopRight * worldRot;
  767. frontTopLeft += offset;
  768. frontTopRight += offset;
  769. frontBottomLeft += offset;
  770. frontBottomRight += offset;
  771. backBottomLeft += offset;
  772. backBottomRight += offset;
  773. backTopLeft += offset;
  774. backTopRight += offset;
  775. if (frontTopRight.X > maxX)
  776. maxX = frontTopRight.X;
  777. if (frontTopLeft.X > maxX)
  778. maxX = frontTopLeft.X;
  779. if (frontBottomRight.X > maxX)
  780. maxX = frontBottomRight.X;
  781. if (frontBottomLeft.X > maxX)
  782. maxX = frontBottomLeft.X;
  783. if (backTopRight.X > maxX)
  784. maxX = backTopRight.X;
  785. if (backTopLeft.X > maxX)
  786. maxX = backTopLeft.X;
  787. if (backBottomRight.X > maxX)
  788. maxX = backBottomRight.X;
  789. if (backBottomLeft.X > maxX)
  790. maxX = backBottomLeft.X;
  791. if (frontTopRight.X < minX)
  792. minX = frontTopRight.X;
  793. if (frontTopLeft.X < minX)
  794. minX = frontTopLeft.X;
  795. if (frontBottomRight.X < minX)
  796. minX = frontBottomRight.X;
  797. if (frontBottomLeft.X < minX)
  798. minX = frontBottomLeft.X;
  799. if (backTopRight.X < minX)
  800. minX = backTopRight.X;
  801. if (backTopLeft.X < minX)
  802. minX = backTopLeft.X;
  803. if (backBottomRight.X < minX)
  804. minX = backBottomRight.X;
  805. if (backBottomLeft.X < minX)
  806. minX = backBottomLeft.X;
  807. if (frontTopRight.Y > maxY)
  808. maxY = frontTopRight.Y;
  809. if (frontTopLeft.Y > maxY)
  810. maxY = frontTopLeft.Y;
  811. if (frontBottomRight.Y > maxY)
  812. maxY = frontBottomRight.Y;
  813. if (frontBottomLeft.Y > maxY)
  814. maxY = frontBottomLeft.Y;
  815. if (backTopRight.Y > maxY)
  816. maxY = backTopRight.Y;
  817. if (backTopLeft.Y > maxY)
  818. maxY = backTopLeft.Y;
  819. if (backBottomRight.Y > maxY)
  820. maxY = backBottomRight.Y;
  821. if (backBottomLeft.Y > maxY)
  822. maxY = backBottomLeft.Y;
  823. if (backTopRight.Y < minY)
  824. minY = backTopRight.Y;
  825. if (backTopLeft.Y < minY)
  826. minY = backTopLeft.Y;
  827. if (backBottomRight.Y < minY)
  828. minY = backBottomRight.Y;
  829. if (backBottomLeft.Y < minY)
  830. minY = backBottomLeft.Y;
  831. if (backTopRight.Y < minY)
  832. minY = backTopRight.Y;
  833. if (backTopLeft.Y < minY)
  834. minY = backTopLeft.Y;
  835. if (backBottomRight.Y < minY)
  836. minY = backBottomRight.Y;
  837. if (backBottomLeft.Y < minY)
  838. minY = backBottomLeft.Y;
  839. if (frontTopRight.Z > maxZ)
  840. maxZ = frontTopRight.Z;
  841. if (frontTopLeft.Z > maxZ)
  842. maxZ = frontTopLeft.Z;
  843. if (frontBottomRight.Z > maxZ)
  844. maxZ = frontBottomRight.Z;
  845. if (frontBottomLeft.Z > maxZ)
  846. maxZ = frontBottomLeft.Z;
  847. if (backTopRight.Z > maxZ)
  848. maxZ = backTopRight.Z;
  849. if (backTopLeft.Z > maxZ)
  850. maxZ = backTopLeft.Z;
  851. if (backBottomRight.Z > maxZ)
  852. maxZ = backBottomRight.Z;
  853. if (backBottomLeft.Z > maxZ)
  854. maxZ = backBottomLeft.Z;
  855. if (frontTopRight.Z < minZ)
  856. minZ = frontTopRight.Z;
  857. if (frontTopLeft.Z < minZ)
  858. minZ = frontTopLeft.Z;
  859. if (frontBottomRight.Z < minZ)
  860. minZ = frontBottomRight.Z;
  861. if (frontBottomLeft.Z < minZ)
  862. minZ = frontBottomLeft.Z;
  863. if (backTopRight.Z < minZ)
  864. minZ = backTopRight.Z;
  865. if (backTopLeft.Z < minZ)
  866. minZ = backTopLeft.Z;
  867. if (backBottomRight.Z < minZ)
  868. minZ = backBottomRight.Z;
  869. if (backBottomLeft.Z < minZ)
  870. minZ = backBottomLeft.Z;
  871. }
  872. */
  873. }
  874. public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
  875. {
  876. float minX;
  877. float maxX;
  878. float minY;
  879. float maxY;
  880. float minZ;
  881. float maxZ;
  882. GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
  883. Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
  884. offsetHeight = 0.5f*(maxZ + minZ);
  885. offsetHeight -= m_rootPart.AbsolutePosition.Z;
  886. /*
  887. offsetHeight = 0;
  888. float lower = (minZ * -1);
  889. if (lower > maxZ)
  890. {
  891. offsetHeight = lower - (boundingBox.Z / 2);
  892. }
  893. else if (maxZ > lower)
  894. {
  895. offsetHeight = maxZ - (boundingBox.Z / 2);
  896. offsetHeight *= -1;
  897. }
  898. */
  899. // MainConsole.Instance.InfoFormat("BoundingBox is {0} , {1} , {2} ", boundingBox.X, boundingBox.Y, boundingBox.Z);
  900. return boundingBox;
  901. }
  902. #region Adding/Removing children from this group
  903. /// <summary>
  904. /// Clear all children from this group
  905. /// </summary>
  906. public void ClearChildren()
  907. {
  908. lock (m_partsLock)
  909. {
  910. m_parts.Clear();
  911. m_partsList.Clear();
  912. m_ValidgrpOOB = false;
  913. }
  914. }
  915. /// <summary>
  916. /// Add a child to the group, set the parent id's and then set the link number
  917. /// </summary>
  918. /// <param name="child"></param>
  919. /// <param name="linkNum"></param>
  920. /// <returns></returns>
  921. public bool AddChild(ISceneChildEntity child, int linkNum)
  922. {
  923. lock (m_partsLock)
  924. {
  925. if (child is SceneObjectPart)
  926. {
  927. SceneObjectPart part = (SceneObjectPart) child;
  928. //Root part is first
  929. if (m_partsList.Count == 0)
  930. {
  931. m_rootPart = part;
  932. }
  933. //Set the parent prim
  934. part.SetParent(this);
  935. if (m_rootPart.LocalId != 0 && !part.IsRoot)
  936. part.SetParentLocalId(m_rootPart.LocalId);
  937. else
  938. part.SetParentLocalId(0);
  939. //Fix the link num
  940. part.LinkNum = linkNum;
  941. if (!m_parts.ContainsKey(child.UUID))
  942. {
  943. m_parts.Add(child.UUID, part);
  944. m_partsList.Add(part);
  945. m_ValidgrpOOB = false;
  946. }
  947. return true;
  948. }
  949. }
  950. return false;
  951. }
  952. /// <summary>
  953. /// Add this child to the group and set the parent ID's,
  954. /// but do NOT set the link number,
  955. /// the caller wants to deal with it if they call this
  956. /// </summary>
  957. /// <param name="child"></param>
  958. /// <returns></returns>
  959. public bool LinkChild(ISceneChildEntity child)
  960. {
  961. lock (m_partsLock)
  962. {
  963. if (child is SceneObjectPart)
  964. {
  965. SceneObjectPart part = (SceneObjectPart) child;
  966. //Root part is first
  967. if (m_partsList.Count == 0)
  968. {
  969. m_rootPart = part;
  970. }
  971. //Set the parent prim
  972. part.SetParent(this);
  973. part.SetParentLocalId(m_rootPart.LocalId);
  974. if (!m_parts.ContainsKey(child.UUID))
  975. {
  976. m_parts.Add(child.UUID, part);
  977. m_partsList.Add(part);
  978. m_ValidgrpOOB = false;
  979. }
  980. m_partsList.Sort(m_scene.SceneGraph.LinkSetSorter);
  981. return true;
  982. }
  983. }
  984. return false;
  985. }
  986. /// <summary>
  987. /// Remove this child from the group and then update the link numbers so that there is not a hole
  988. /// </summary>
  989. /// <param name="child"></param>
  990. /// <returns></returns>
  991. public bool RemoveChild(ISceneChildEntity child)
  992. {
  993. lock (m_partsLock)
  994. {
  995. if (child is SceneObjectPart)
  996. {
  997. SceneObjectPart part = (SceneObjectPart) child;
  998. m_parts.Remove(part.UUID);
  999. m_partsList.Remove(part);
  1000. m_ValidgrpOOB = false;
  1001. //Fix the link numbers now
  1002. FixLinkNumbers();
  1003. return true;
  1004. }
  1005. }
  1006. return false;
  1007. }
  1008. /// <summary>
  1009. /// After a prim is removed, fix the link numbers so that they are correct
  1010. /// </summary>
  1011. private void FixLinkNumbers()
  1012. {
  1013. if (m_partsList.Count == 1)
  1014. {
  1015. m_partsList[0].LinkNum = 0;
  1016. return;
  1017. }
  1018. lock (m_partsLock)
  1019. {
  1020. // has prims so starts at 1
  1021. int lastSeenLinkNum = 1;
  1022. m_partsList.Sort(Scene.SceneGraph.LinkSetSorter);
  1023. foreach (SceneObjectPart t in m_partsList)
  1024. {
  1025. //If it isn't the same as the last seen +1, fix it
  1026. if (t != null && t.LinkNum != lastSeenLinkNum)
  1027. t.LinkNum = lastSeenLinkNum;
  1028. //Go onto the next prim
  1029. lastSeenLinkNum++;
  1030. }
  1031. }
  1032. }
  1033. #endregion
  1034. #endregion
  1035. /// <summary>
  1036. /// The position center of the bounding box relative to it's Position
  1037. /// </summary>
  1038. [XmlIgnore]
  1039. public Vector3 OOBoffset
  1040. {
  1041. get
  1042. {
  1043. if (!m_ValidgrpOOB)
  1044. UpdateOOBfromOOBs();
  1045. return m_grpOOBoffset;
  1046. }
  1047. }
  1048. public object ChildrenListLock
  1049. {
  1050. get { return m_partsLock; }
  1051. }
  1052. #region ISceneObject Members
  1053. public event BlankHandler OnFinishedPhysicalRepresentationBuilding;
  1054. public Vector3 LastSignificantPosition
  1055. {
  1056. get { return m_lastSignificantPosition; }
  1057. }
  1058. public UUID LastParcelUUID
  1059. {
  1060. get { return m_lastParcelUUID; }
  1061. set { m_lastParcelUUID = value; }
  1062. }
  1063. /// <summary>
  1064. /// The size of a bounding box oriented as prim, is future will consider cutted prims, meshs etc
  1065. /// </summary>
  1066. [XmlIgnore]
  1067. public Vector3 OOBsize
  1068. {
  1069. get
  1070. {
  1071. if (!m_ValidgrpOOB)
  1072. UpdateOOBfromOOBs();
  1073. return m_grpOOBsize;
  1074. }
  1075. }
  1076. /// <summary>
  1077. /// The square of the radius of a sphere containing the oob
  1078. /// </summary>
  1079. [XmlIgnore]
  1080. public float BSphereRadiusSQ
  1081. {
  1082. get
  1083. {
  1084. if (!m_ValidgrpOOB)
  1085. UpdateOOBfromOOBs();
  1086. return m_grpBSphereRadiusSQ;
  1087. }
  1088. }
  1089. public override bool HasGroupChanged
  1090. {
  1091. get { return m_hasGroupChanged; }
  1092. set
  1093. {
  1094. if (value)
  1095. {
  1096. if (m_scene != null)
  1097. {
  1098. IBackupModule backup = m_scene.RequestModuleInterface<IBackupModule>();
  1099. if (backup != null)
  1100. {
  1101. if (!backup.LoadingPrims) //Do NOT add to backup while still loading prims
  1102. backup.AddPrimBackupTaint(this);
  1103. }
  1104. }
  1105. }
  1106. m_hasGroupChanged = value;
  1107. }
  1108. }
  1109. /// <summary>
  1110. /// Force all prims in the scene object to persist
  1111. /// </summary>
  1112. public void ForcePersistence()
  1113. {
  1114. //Force normal backup
  1115. HasGroupChanged = true;
  1116. ForceInventoryPersistence();
  1117. }
  1118. /// <summary>
  1119. /// Clears all undo states from this group
  1120. /// </summary>
  1121. public void ClearUndoState()
  1122. {
  1123. foreach (SceneObjectPart child in ChildrenList)
  1124. {
  1125. child.ClearUndoState();
  1126. }
  1127. }
  1128. /// <value>
  1129. /// Is this scene object acting as an attachment?
  1130. /// We return false if the group has already been deleted.
  1131. /// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I
  1132. /// presume either all or no parts in a linkset can be part of an attachment (in which
  1133. /// case the value would get proprogated down into all the descendent parts).
  1134. /// </value>
  1135. public bool IsAttachment
  1136. {
  1137. get { return m_rootPart.IsAttachment; }
  1138. }
  1139. //private bool m_isBackedUp = false;
  1140. public byte GetAttachmentPoint()
  1141. {
  1142. return m_rootPart.Shape.State;
  1143. }
  1144. public Vector3 GetAttachmentPos()
  1145. {
  1146. return m_rootPart.SavedAttachedPos;
  1147. }
  1148. public byte GetSavedAttachmentPoint()
  1149. {
  1150. return (byte) m_rootPart.SavedAttachmentPoint;
  1151. }
  1152. public void FinishedSerializingGenericProperties()
  1153. {
  1154. foreach (ISceneChildEntity ent in ChildrenEntities())
  1155. ent.FinishedSerializingGenericProperties();
  1156. }
  1157. public void DetachToGround()
  1158. {
  1159. IScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
  1160. if (avatar == null)
  1161. return;

Large files files are truncated, but you can click here to view the full file