Primitive.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. using System;
  2. using System.Collections.Generic;
  3. using Axiom.Math;
  4. using libsecondlife;
  5. using libsecondlife.Packets;
  6. using OpenSim.Framework.Interfaces;
  7. using OpenSim.Framework.Inventory;
  8. using OpenSim.Framework.Types;
  9. namespace OpenSim.Region.Environment.Scenes
  10. {
  11. public class Primitive : EntityBase
  12. {
  13. private const uint FULL_MASK_PERMISSIONS = 2147483647;
  14. private LLVector3 positionLastFrame = new LLVector3(0, 0, 0);
  15. private ulong m_regionHandle;
  16. private byte updateFlag = 0;
  17. private uint m_flags = 32 + 65536 + 131072 + 256 + 4 + 8 + 2048 + 524288 + 268435456 + 128;
  18. private Dictionary<LLUUID, InventoryItem> inventoryItems;
  19. private string m_description = "";
  20. public string SitName = "";
  21. public string TouchName = "";
  22. public string Text = "";
  23. public LLUUID CreatorID;
  24. public LLUUID OwnerID;
  25. public LLUUID LastOwnerID;
  26. public Int32 CreationDate;
  27. public uint ParentID = 0;
  28. public uint OwnerMask = FULL_MASK_PERMISSIONS;
  29. public uint NextOwnerMask = FULL_MASK_PERMISSIONS;
  30. public uint GroupMask = FULL_MASK_PERMISSIONS;
  31. public uint EveryoneMask = FULL_MASK_PERMISSIONS;
  32. public uint BaseMask = FULL_MASK_PERMISSIONS;
  33. private PrimitiveBaseShape m_Shape;
  34. public SceneObject m_RootParent;
  35. public bool m_isRootPrim;
  36. public EntityBase m_Parent;
  37. #region Properties
  38. /// <summary>
  39. /// If rootprim, will return world position
  40. /// otherwise will return local offset from rootprim
  41. /// </summary>
  42. public override LLVector3 Pos
  43. {
  44. get
  45. {
  46. if (m_isRootPrim)
  47. {
  48. //if we are rootprim then our offset should be zero
  49. return this.m_pos + m_Parent.Pos;
  50. }
  51. else
  52. {
  53. return this.m_pos;
  54. }
  55. }
  56. set
  57. {
  58. if (m_isRootPrim)
  59. {
  60. m_Parent.Pos = value;
  61. }
  62. this.m_pos = value - m_Parent.Pos;
  63. }
  64. }
  65. public LLVector3 WorldPos
  66. {
  67. get
  68. {
  69. if (!this.m_isRootPrim)
  70. {
  71. Primitive parentPrim = (Primitive)this.m_Parent;
  72. Axiom.Math.Vector3 offsetPos = new Vector3(this.m_pos.X, this.m_pos.Y, this.m_pos.Z);
  73. offsetPos = parentPrim.Rotation * offsetPos;
  74. return parentPrim.WorldPos + new LLVector3(offsetPos.x, offsetPos.y, offsetPos.z);
  75. }
  76. else
  77. {
  78. return this.Pos;
  79. }
  80. }
  81. }
  82. public string Description
  83. {
  84. get
  85. {
  86. return this.m_description;
  87. }
  88. set
  89. {
  90. this.m_description = value;
  91. }
  92. }
  93. public LLVector3 Scale
  94. {
  95. set
  96. {
  97. this.m_Shape.Scale = value;
  98. }
  99. get
  100. {
  101. return this.m_Shape.Scale;
  102. }
  103. }
  104. #endregion
  105. #region Constructors
  106. /// <summary>
  107. ///
  108. /// </summary>
  109. /// <param name="regionHandle"></param>
  110. /// <param name="world"></param>
  111. /// <param name="addPacket"></param>
  112. /// <param name="ownerID"></param>
  113. /// <param name="localID"></param>
  114. /// <param name="isRoot"></param>
  115. /// <param name="parent"></param>
  116. /// <param name="rootObject"></param>
  117. public Primitive(ulong regionHandle, Scene world, ObjectAddPacket addPacket, LLUUID ownerID, uint localID, bool isRoot, EntityBase parent, SceneObject rootObject)
  118. {
  119. m_regionHandle = regionHandle;
  120. m_world = world;
  121. inventoryItems = new Dictionary<LLUUID, InventoryItem>();
  122. this.m_Parent = parent;
  123. this.m_isRootPrim = isRoot;
  124. this.m_RootParent = rootObject;
  125. this.CreateFromPacket(addPacket, ownerID, localID);
  126. this.Rotation = Axiom.Math.Quaternion.Identity;
  127. }
  128. /// <summary>
  129. ///
  130. /// </summary>
  131. /// <remarks>Empty constructor for duplication</remarks>
  132. public Primitive()
  133. {
  134. }
  135. #endregion
  136. #region Duplication
  137. public Primitive Copy(EntityBase parent, SceneObject rootParent)
  138. {
  139. Primitive dupe = (Primitive)this.MemberwiseClone();
  140. // TODO: Copy this properly.
  141. dupe.inventoryItems = this.inventoryItems;
  142. dupe.m_Parent = parent;
  143. dupe.m_RootParent = rootParent;
  144. // TODO: Copy this properly.
  145. dupe.m_Shape = this.m_Shape;
  146. uint newLocalID = this.m_world.PrimIDAllocate();
  147. dupe.LocalId = newLocalID;
  148. dupe.Scale = new LLVector3(this.Scale.X, this.Scale.Y, this.Scale.Z);
  149. dupe.Rotation = new Quaternion(this.Rotation.w, this.Rotation.x, this.Rotation.y, this.Rotation.z);
  150. dupe.Pos = new LLVector3(this.Pos.X, this.Pos.Y, this.Pos.Z);
  151. return dupe;
  152. }
  153. #endregion
  154. #region Override from EntityBase
  155. /// <summary>
  156. ///
  157. /// </summary>
  158. public override void update()
  159. {
  160. if (this.updateFlag == 1) // is a new prim just been created/reloaded or has major changes
  161. {
  162. this.SendFullUpdateToAllClients();
  163. this.updateFlag = 0;
  164. }
  165. if (this.updateFlag == 2) //some change has been made so update the clients
  166. {
  167. this.SendTerseUpdateToALLClients();
  168. this.updateFlag = 0;
  169. }
  170. foreach (EntityBase child in children)
  171. {
  172. child.update();
  173. }
  174. }
  175. #endregion
  176. #region Setup
  177. /// <summary>
  178. ///
  179. /// </summary>
  180. /// <param name="addPacket"></param>
  181. /// <param name="ownerID"></param>
  182. /// <param name="localID"></param>
  183. public void CreateFromPacket(ObjectAddPacket addPacket, LLUUID ownerID, uint localID)
  184. {
  185. this.CreationDate = (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
  186. this.OwnerID = ownerID;
  187. this.CreatorID = this.OwnerID;
  188. this.LastOwnerID = LLUUID.Zero;
  189. this.Pos = addPacket.ObjectData.RayEnd;
  190. this.uuid = LLUUID.Random();
  191. this.m_localId = (uint)(localID);
  192. PrimitiveBaseShape pShape = new PrimitiveBaseShape();
  193. this.m_Shape = pShape;
  194. pShape.PCode = addPacket.ObjectData.PCode;
  195. pShape.PathBegin = addPacket.ObjectData.PathBegin;
  196. pShape.PathEnd = addPacket.ObjectData.PathEnd;
  197. pShape.PathScaleX = addPacket.ObjectData.PathScaleX;
  198. pShape.PathScaleY = addPacket.ObjectData.PathScaleY;
  199. pShape.PathShearX = addPacket.ObjectData.PathShearX;
  200. pShape.PathShearY = addPacket.ObjectData.PathShearY;
  201. pShape.PathSkew = addPacket.ObjectData.PathSkew;
  202. pShape.ProfileBegin = addPacket.ObjectData.ProfileBegin;
  203. pShape.ProfileEnd = addPacket.ObjectData.ProfileEnd;
  204. pShape.Scale = addPacket.ObjectData.Scale;
  205. pShape.PathCurve = addPacket.ObjectData.PathCurve;
  206. pShape.ProfileCurve = addPacket.ObjectData.ProfileCurve;
  207. pShape.ProfileHollow = addPacket.ObjectData.ProfileHollow;
  208. pShape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
  209. pShape.PathRevolutions = addPacket.ObjectData.PathRevolutions;
  210. pShape.PathTaperX = addPacket.ObjectData.PathTaperX;
  211. pShape.PathTaperY = addPacket.ObjectData.PathTaperY;
  212. pShape.PathTwist = addPacket.ObjectData.PathTwist;
  213. pShape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
  214. this.updateFlag = 1;
  215. }
  216. #endregion
  217. #region Linking / unlinking
  218. /// <summary>
  219. ///
  220. /// </summary>
  221. /// <param name="linkObject"></param>
  222. public void AddNewChildren(SceneObject linkObject)
  223. {
  224. // Console.WriteLine("linking new prims " + linkObject.rootLocalID + " to me (" + this.LocalId + ")");
  225. //TODO check permissions
  226. this.children.Add(linkObject.rootPrimitive);
  227. linkObject.rootPrimitive.SetNewParent(this, this.m_RootParent);
  228. this.m_world.DeleteEntity(linkObject.rootUUID);
  229. linkObject.DeleteAllChildren();
  230. }
  231. /// <summary>
  232. ///
  233. /// </summary>
  234. /// <param name="newParent"></param>
  235. /// <param name="rootParent"></param>
  236. public void SetNewParent(Primitive newParent, SceneObject rootParent)
  237. {
  238. LLVector3 oldPos = new LLVector3(this.Pos.X, this.Pos.Y, this.Pos.Z);
  239. this.m_isRootPrim = false;
  240. this.m_Parent = newParent;
  241. this.ParentID = newParent.LocalId;
  242. this.m_RootParent = rootParent;
  243. this.m_RootParent.AddChildToList(this);
  244. this.Pos = oldPos;
  245. Axiom.Math.Vector3 axPos = new Axiom.Math.Vector3(this.m_pos.X, m_pos.Y, m_pos.Z);
  246. axPos = this.m_Parent.Rotation.Inverse() * axPos;
  247. this.m_pos = new LLVector3(axPos.x, axPos.y, axPos.z);
  248. Axiom.Math.Quaternion oldRot = new Quaternion(this.Rotation.w, this.Rotation.x, this.Rotation.y, this.Rotation.z);
  249. this.Rotation = this.m_Parent.Rotation.Inverse() * this.Rotation;
  250. this.updateFlag = 1;
  251. foreach (Primitive child in children)
  252. {
  253. child.SetRootParent(rootParent, newParent, oldPos, oldRot);
  254. }
  255. children.Clear();
  256. }
  257. /// <summary>
  258. ///
  259. /// </summary>
  260. /// <param name="newRoot"></param>
  261. public void SetRootParent(SceneObject newRoot , Primitive newParent, LLVector3 oldParentPosition, Axiom.Math.Quaternion oldParentRotation)
  262. {
  263. LLVector3 oldPos = new LLVector3(this.Pos.X, this.Pos.Y, this.Pos.Z);
  264. Axiom.Math.Vector3 axOldPos = new Vector3(oldPos.X, oldPos.Y, oldPos.Z);
  265. axOldPos = oldParentRotation * axOldPos;
  266. oldPos = new LLVector3(axOldPos.x, axOldPos.y, axOldPos.z);
  267. oldPos += oldParentPosition;
  268. Axiom.Math.Quaternion oldRot = new Quaternion(this.Rotation.w, this.Rotation.x, this.Rotation.y, this.Rotation.z);
  269. this.m_isRootPrim = false;
  270. this.m_Parent = newParent;
  271. this.ParentID = newParent.LocalId;
  272. newParent.AddToChildrenList(this);
  273. this.m_RootParent = newRoot;
  274. this.m_RootParent.AddChildToList(this);
  275. this.Pos = oldPos;
  276. Axiom.Math.Vector3 axPos = new Axiom.Math.Vector3(this.m_pos.X, m_pos.Y, m_pos.Z);
  277. axPos = this.m_Parent.Rotation.Inverse() * axPos;
  278. this.m_pos = new LLVector3(axPos.x, axPos.y, axPos.z);
  279. this.Rotation = oldParentRotation * this.Rotation;
  280. this.Rotation = this.m_Parent.Rotation.Inverse()* this.Rotation ;
  281. this.updateFlag = 1;
  282. foreach (Primitive child in children)
  283. {
  284. child.SetRootParent(newRoot, newParent, oldPos, oldRot);
  285. }
  286. children.Clear();
  287. }
  288. /// <summary>
  289. ///
  290. /// </summary>
  291. /// <param name="offset"></param>
  292. public void AddOffsetToChildren(LLVector3 offset)
  293. {
  294. foreach (Primitive prim in this.children)
  295. {
  296. prim.m_pos += offset;
  297. prim.updateFlag = 2;
  298. }
  299. }
  300. /// <summary>
  301. ///
  302. /// </summary>
  303. /// <param name="prim"></param>
  304. public void AddToChildrenList(Primitive prim)
  305. {
  306. this.children.Add(prim);
  307. }
  308. #endregion
  309. #region Resizing/Scale
  310. /// <summary>
  311. ///
  312. /// </summary>
  313. /// <param name="scale"></param>
  314. public void ResizeGoup(LLVector3 scale)
  315. {
  316. LLVector3 offset = (scale - this.m_Shape.Scale);
  317. offset.X /= 2;
  318. offset.Y /= 2;
  319. offset.Z /= 2;
  320. if (this.m_isRootPrim)
  321. {
  322. this.m_Parent.Pos += offset;
  323. }
  324. else
  325. {
  326. this.m_pos += offset;
  327. }
  328. this.AddOffsetToChildren(new LLVector3(-offset.X, -offset.Y, -offset.Z));
  329. this.m_Shape.Scale = scale;
  330. this.updateFlag = 1;
  331. }
  332. #endregion
  333. #region Position
  334. /// <summary>
  335. ///
  336. /// </summary>
  337. /// <param name="pos"></param>
  338. public void UpdateGroupPosition(LLVector3 pos)
  339. {
  340. LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
  341. this.Pos = newPos;
  342. this.updateFlag = 2;
  343. }
  344. /// <summary>
  345. ///
  346. /// </summary>
  347. /// <param name="pos"></param>
  348. public void UpdateSinglePosition(LLVector3 pos)
  349. {
  350. // Console.WriteLine("updating single prim position");
  351. if (this.m_isRootPrim)
  352. {
  353. LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
  354. LLVector3 oldPos = new LLVector3(Pos.X, Pos.Y, Pos.Z);
  355. LLVector3 diff = oldPos - newPos;
  356. Axiom.Math.Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
  357. axDiff = this.Rotation.Inverse() * axDiff;
  358. diff.X = axDiff.x;
  359. diff.Y = axDiff.y;
  360. diff.Z = axDiff.z;
  361. this.Pos = newPos;
  362. foreach (Primitive prim in this.children)
  363. {
  364. prim.m_pos += diff;
  365. prim.updateFlag = 2;
  366. }
  367. this.updateFlag = 2;
  368. }
  369. else
  370. {
  371. LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
  372. this.m_pos = newPos;
  373. this.updateFlag = 2;
  374. }
  375. }
  376. #endregion
  377. #region Rotation
  378. /// <summary>
  379. ///
  380. /// </summary>
  381. /// <param name="rot"></param>
  382. public void UpdateGroupRotation(LLQuaternion rot)
  383. {
  384. this.Rotation = new Axiom.Math.Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  385. this.updateFlag = 2;
  386. }
  387. /// <summary>
  388. ///
  389. /// </summary>
  390. /// <param name="pos"></param>
  391. /// <param name="rot"></param>
  392. public void UpdateGroupMouseRotation(LLVector3 pos, LLQuaternion rot)
  393. {
  394. this.Rotation = new Axiom.Math.Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  395. this.Pos = pos;
  396. this.updateFlag = 2;
  397. }
  398. /// <summary>
  399. ///
  400. /// </summary>
  401. /// <param name="rot"></param>
  402. public void UpdateSingleRotation(LLQuaternion rot)
  403. {
  404. //Console.WriteLine("updating single prim rotation");
  405. Axiom.Math.Quaternion axRot = new Axiom.Math.Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  406. Axiom.Math.Quaternion oldParentRot = new Quaternion(this.Rotation.w, this.Rotation.x, this.Rotation.y, this.Rotation.z);
  407. this.Rotation = axRot;
  408. foreach (Primitive prim in this.children)
  409. {
  410. Axiom.Math.Vector3 axPos = new Vector3(prim.m_pos.X, prim.m_pos.Y, prim.m_pos.Z);
  411. axPos = oldParentRot * axPos;
  412. axPos = axRot.Inverse() * axPos;
  413. prim.m_pos = new LLVector3(axPos.x, axPos.y, axPos.z);
  414. prim.Rotation = oldParentRot * prim.Rotation ;
  415. prim.Rotation = axRot.Inverse()* prim.Rotation;
  416. prim.updateFlag = 2;
  417. }
  418. this.updateFlag = 2;
  419. }
  420. #endregion
  421. #region Shape
  422. /// <summary>
  423. ///
  424. /// </summary>
  425. /// <param name="shapeBlock"></param>
  426. public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
  427. {
  428. this.m_Shape.PathBegin = shapeBlock.PathBegin;
  429. this.m_Shape.PathEnd = shapeBlock.PathEnd;
  430. this.m_Shape.PathScaleX = shapeBlock.PathScaleX;
  431. this.m_Shape.PathScaleY = shapeBlock.PathScaleY;
  432. this.m_Shape.PathShearX = shapeBlock.PathShearX;
  433. this.m_Shape.PathShearY = shapeBlock.PathShearY;
  434. this.m_Shape.PathSkew = shapeBlock.PathSkew;
  435. this.m_Shape.ProfileBegin = shapeBlock.ProfileBegin;
  436. this.m_Shape.ProfileEnd = shapeBlock.ProfileEnd;
  437. this.m_Shape.PathCurve = shapeBlock.PathCurve;
  438. this.m_Shape.ProfileCurve = shapeBlock.ProfileCurve;
  439. this.m_Shape.ProfileHollow = shapeBlock.ProfileHollow;
  440. this.m_Shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
  441. this.m_Shape.PathRevolutions = shapeBlock.PathRevolutions;
  442. this.m_Shape.PathTaperX = shapeBlock.PathTaperX;
  443. this.m_Shape.PathTaperY = shapeBlock.PathTaperY;
  444. this.m_Shape.PathTwist = shapeBlock.PathTwist;
  445. this.m_Shape.PathTwistBegin = shapeBlock.PathTwistBegin;
  446. this.updateFlag = 1;
  447. }
  448. #endregion
  449. #region Client Update Methods
  450. /// <summary>
  451. ///
  452. /// </summary>
  453. /// <param name="remoteClient"></param>
  454. public void SendFullUpdateForAllChildren(IClientAPI remoteClient)
  455. {
  456. this.SendFullUpdateToClient(remoteClient);
  457. for (int i = 0; i < this.children.Count; i++)
  458. {
  459. if (this.children[i] is Primitive)
  460. {
  461. ((Primitive)this.children[i]).SendFullUpdateForAllChildren(remoteClient);
  462. }
  463. }
  464. }
  465. /// <summary>
  466. ///
  467. /// </summary>
  468. /// <param name="remoteClient"></param>
  469. public void SendFullUpdateToClient(IClientAPI remoteClient)
  470. {
  471. LLVector3 lPos;
  472. lPos = this.Pos;
  473. LLQuaternion lRot;
  474. lRot = new LLQuaternion(this.Rotation.x, this.Rotation.y, this.Rotation.z, this.Rotation.w);
  475. remoteClient.SendPrimitiveToClient(this.m_regionHandle, 64096, this.LocalId, this.m_Shape, lPos, lRot, new LLUUID("00000000-0000-0000-9999-000000000005"), this.m_flags, this.uuid, this.OwnerID, this.Text, this.ParentID);
  476. }
  477. /// <summary>
  478. ///
  479. /// </summary>
  480. public void SendFullUpdateToAllClients()
  481. {
  482. List<ScenePresence> avatars = this.m_world.RequestAvatarList();
  483. for (int i = 0; i < avatars.Count; i++)
  484. {
  485. this.SendFullUpdateToClient(avatars[i].ControllingClient);
  486. }
  487. }
  488. /// <summary>
  489. ///
  490. /// </summary>
  491. /// <param name="remoteClient"></param>
  492. public void SendTerseUpdateForAllChildren(IClientAPI remoteClient)
  493. {
  494. this.SendTerseUpdateToClient(remoteClient);
  495. for (int i = 0; i < this.children.Count; i++)
  496. {
  497. if (this.children[i] is Primitive)
  498. {
  499. ((Primitive)this.children[i]).SendTerseUpdateForAllChildren(remoteClient);
  500. }
  501. }
  502. }
  503. /// <summary>
  504. ///
  505. /// </summary>
  506. /// <param name="RemoteClient"></param>
  507. public void SendTerseUpdateToClient(IClientAPI RemoteClient)
  508. {
  509. LLVector3 lPos;
  510. Quaternion lRot;
  511. lPos = this.Pos;
  512. lRot = this.Rotation;
  513. LLQuaternion mRot = new LLQuaternion(lRot.x, lRot.y, lRot.z, lRot.w);
  514. RemoteClient.SendPrimTerseUpdate(this.m_regionHandle, 64096, this.LocalId, lPos, mRot);
  515. }
  516. /// <summary>
  517. ///
  518. /// </summary>
  519. public void SendTerseUpdateToALLClients()
  520. {
  521. List<ScenePresence> avatars = this.m_world.RequestAvatarList();
  522. for (int i = 0; i < avatars.Count; i++)
  523. {
  524. this.SendTerseUpdateToClient(avatars[i].ControllingClient);
  525. }
  526. }
  527. #endregion
  528. }
  529. }