PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 2ms

/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs

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

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