/Aurora/Physics/AuroraOpenDynamicsEngine/AODEPrim.cs

https://bitbucket.org/VirtualReality/software-testing · C# · 2988 lines · 2302 code · 400 blank · 286 comment · 430 complexity · 0bfd8d4544f79359a43b71071cd95f83 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.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. /*
  28. * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
  29. * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
  30. * ODEPrim.cs contains methods dealing with Prim editing, Prim
  31. * characteristics and Kinetic motion.
  32. * ODEDynamics.cs contains methods dealing with Prim Physical motion
  33. * (dynamics) and the associated settings. Old Linear and angular
  34. * motors for dynamic motion have been replace with MoveLinear()
  35. * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
  36. * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
  37. * switch between 'VEHICLE' parameter use and general dynamics
  38. * settings use.
  39. */
  40. using Aurora.Framework;
  41. using Aurora.Framework.ConsoleFramework;
  42. using Aurora.Framework.Physics;
  43. using Aurora.Framework.SceneInfo;
  44. using Aurora.Framework.Utilities;
  45. using OdeAPI;
  46. using OpenMetaverse;
  47. using System;
  48. using System.Collections.Generic;
  49. using System.Linq;
  50. //using Ode.NET;
  51. namespace Aurora.Physics.AuroraOpenDynamicsEngine
  52. {
  53. /// <summary>
  54. /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
  55. /// </summary>
  56. public class AuroraODEPrim : PhysicsObject
  57. {
  58. private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
  59. | CollisionCategories.Space
  60. | CollisionCategories.Body
  61. | CollisionCategories.Character
  62. );
  63. private static readonly Dictionary<ulong, IntPtr> m_MeshToTriMeshMap = new Dictionary<ulong, IntPtr>();
  64. private readonly AuroraODEPhysicsScene _parent_scene;
  65. private readonly Vector3 _torque = Vector3.Zero;
  66. private readonly int body_autodisable_frames = 20;
  67. private readonly AuroraODEDynamics m_vehicle;
  68. private IntPtr Amotor = IntPtr.Zero;
  69. public IntPtr Body { get; private set; }
  70. private CollisionEventUpdate CollisionEventsThisFrame;
  71. private float PID_D = 35f;
  72. private float PID_G = 25f;
  73. private Vector3 _acceleration;
  74. private float _mass; // prim or object mass
  75. private IMesh _mesh;
  76. private Quaternion _orientation;
  77. private PhysicsObject _parent;
  78. private ISceneChildEntity _parent_entity;
  79. private PrimitiveBaseShape _pbs;
  80. private Vector3 _position;
  81. private Vector3 _size;
  82. private IntPtr _triMeshData;
  83. private Vector3 _velocity;
  84. private bool _zeroFlag;
  85. private bool _zeroFlagForceSet;
  86. internal volatile bool childPrim;
  87. internal List<AuroraODEPrim> childrenPrim = new List<AuroraODEPrim>();
  88. private int fakeori; // control the use of above
  89. private int fakepos; // control the use of above
  90. private bool hasOOBoffsetFromMesh; // if true we did compute it form mesh centroid, else from aabb
  91. private bool iscolliding;
  92. private Vector3 m_angularforceacc;
  93. private Vector3 m_angularlock = Vector3.One;
  94. private bool m_blockPhysicalReconstruction;
  95. private bool m_buildingRepresentation;
  96. // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
  97. // and are for non-VEHICLES only.
  98. private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
  99. // private float m_tensor = 5f;
  100. private bool m_collidesLand = true;
  101. private bool m_collidesWater;
  102. // Default we're a Geometry
  103. private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
  104. // Default, Collide with Other Geometries, spaces and Bodies
  105. private CollisionCategories m_collisionFlags = m_default_collisionFlags;
  106. internal float m_collisionscore;
  107. private int m_crossingfailures;
  108. internal bool m_disabled;
  109. private bool m_eventsubscription;
  110. //This disables the prim so that it cannot do much anything at all
  111. private Vector3 m_force;
  112. private Vector3 m_forceacc;
  113. internal bool m_frozen;
  114. private bool m_isSelected;
  115. private bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
  116. private bool m_isphysical;
  117. private int m_lastUpdateSent;
  118. private Vector3 m_lastVelocity;
  119. private Quaternion m_lastorientation;
  120. private Vector3 m_lastposition;
  121. private uint m_localID;
  122. private int m_material = (int) Material.Wood;
  123. private bool m_primIsRemoved;
  124. private Vector3 m_pushForce;
  125. private Vector3 m_rotationalVelocity;
  126. internal IntPtr m_targetSpace = IntPtr.Zero;
  127. private bool m_throttleUpdates;
  128. private float primMass; // prim own mass
  129. public Vector3 primOOBoffset; // is centroid out of mesh or rest aabb
  130. public Vector3 primOOBsize; // prim real dimensions from mesh
  131. public IntPtr prim_geom;
  132. private d.Mass primdMass; // prim inertia information on it's own referencial
  133. private Quaternion showorientation; // tmp hack see showposition
  134. private Vector3 showposition; // a temp hack for now rest of code expects position to be changed immediately
  135. public AuroraODEPrim(ISceneChildEntity entity, AuroraODEPhysicsScene parent_scene, bool pisPhysical)
  136. {
  137. m_vehicle = new AuroraODEDynamics();
  138. //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
  139. // correct for changed timestep
  140. PID_D /= (parent_scene.ODE_STEPSIZE*50f); // original ode fps of 50
  141. PID_G /= (parent_scene.ODE_STEPSIZE*50f);
  142. body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
  143. prim_geom = IntPtr.Zero;
  144. _size = entity.Scale;
  145. _position = entity.AbsolutePosition;
  146. fakepos = 0;
  147. _orientation = entity.GetWorldRotation();
  148. fakeori = 0;
  149. _pbs = entity.Shape;
  150. _parent_entity = entity;
  151. _parent_scene = parent_scene;
  152. m_targetSpace = IntPtr.Zero;
  153. /*
  154. m_isphysical = pisPhysical;
  155. if (m_isphysical)
  156. m_targetSpace = _parent_scene.space;
  157. */
  158. m_isphysical = false;
  159. m_forceacc = Vector3.Zero;
  160. m_angularforceacc = Vector3.Zero;
  161. hasOOBoffsetFromMesh = false;
  162. _triMeshData = IntPtr.Zero;
  163. CalcPrimBodyData();
  164. _parent_scene.AddSimulationChange(() => changeadd());
  165. }
  166. public ISceneChildEntity ParentEntity
  167. {
  168. get { return _parent_entity; }
  169. }
  170. public override bool BuildingRepresentation
  171. {
  172. get { return m_buildingRepresentation; }
  173. set
  174. {
  175. if (value)
  176. m_buildingRepresentation = value;
  177. //else
  178. // _parent_scene.AddSimulationChange(() => m_buildingRepresentation = false);
  179. }
  180. }
  181. public override bool BlockPhysicalReconstruction
  182. {
  183. get { return m_blockPhysicalReconstruction; }
  184. set
  185. {
  186. if (value)
  187. m_blockPhysicalReconstruction = value;
  188. else
  189. _parent_scene.AddSimulationChange(() =>
  190. {
  191. if (value)
  192. DestroyBody();
  193. else
  194. {
  195. m_blockPhysicalReconstruction = false;
  196. if (!childPrim)
  197. MakeBody();
  198. }
  199. if (!childPrim && childrenPrim.Count > 0)
  200. {
  201. foreach (AuroraODEPrim prm in childrenPrim)
  202. prm.BlockPhysicalReconstruction = value;
  203. }
  204. });
  205. }
  206. }
  207. public PhysicsObject Parent
  208. {
  209. get { return _parent; }
  210. }
  211. public override int PhysicsActorType
  212. {
  213. get { return (int) ActorTypes.Prim; }
  214. }
  215. public override uint LocalID
  216. {
  217. get { return m_localID; }
  218. set
  219. {
  220. //MainConsole.Instance.Info("[PHYSICS]: Setting TrackerID: " + value);
  221. m_localID = value;
  222. }
  223. }
  224. public override bool VolumeDetect
  225. {
  226. get { return m_isVolumeDetect; }
  227. set { _parent_scene.AddSimulationChange(() => changevoldtc(value)); }
  228. }
  229. public override bool Selected
  230. {
  231. set
  232. {
  233. // This only makes the object not collidable if the object
  234. // is physical or the object is modified somehow *IN THE FUTURE*
  235. // without this, if an avatar selects prim, they can walk right
  236. // through it while it's selected
  237. if ((IsPhysical && !_zeroFlag) || !value)
  238. _parent_scene.AddSimulationChange(() => changeSelectedStatus(value));
  239. else
  240. m_isSelected = value;
  241. if (m_isSelected)
  242. disableBodySoft();
  243. }
  244. }
  245. public override bool IsPhysical
  246. {
  247. get
  248. {
  249. if (childPrim && _parent != null) // root prim defines if is physical or not
  250. return ((AuroraODEPrim) _parent).m_isphysical;
  251. else
  252. return m_isphysical;
  253. }
  254. set
  255. {
  256. _parent_scene.AddSimulationChange(() => changePhysicsStatus(value));
  257. if (!value) // Zero the remembered last velocity
  258. m_lastVelocity = Vector3.Zero;
  259. }
  260. }
  261. public override bool IsTruelyColliding { get; set; }
  262. public override bool IsColliding
  263. {
  264. get { return iscolliding; }
  265. set
  266. {
  267. if (value && _parent != null)
  268. _parent.LinkSetIsColliding = value;
  269. LinkSetIsColliding = value;
  270. iscolliding = value;
  271. }
  272. }
  273. public override bool LinkSetIsColliding { get; set; }
  274. public override bool ThrottleUpdates
  275. {
  276. get { return m_throttleUpdates; }
  277. set { m_throttleUpdates = value; }
  278. }
  279. public override Vector3 Position
  280. {
  281. get
  282. {
  283. if (fakepos > 0)
  284. return showposition;
  285. else
  286. return _position;
  287. }
  288. set
  289. {
  290. showposition = value;
  291. fakepos++;
  292. _parent_scene.AddSimulationChange(() => changePosition(value));
  293. }
  294. }
  295. public override Vector3 Size
  296. {
  297. get { return _size; }
  298. set
  299. {
  300. if (value.IsFinite())
  301. _parent_scene.AddSimulationChange(() => changesize(value));
  302. else
  303. MainConsole.Instance.Warn("[PHYSICS]: Got NaN Size on object");
  304. }
  305. }
  306. public override float Mass
  307. {
  308. get { return _mass; }
  309. }
  310. public override Vector3 Force
  311. {
  312. //get { return Vector3.Zero; }
  313. get { return m_force; }
  314. set
  315. {
  316. if (value.IsFinite())
  317. {
  318. _parent_scene.AddSimulationChange(() => changeforce(value, false));
  319. }
  320. else
  321. {
  322. MainConsole.Instance.Warn("[PHYSICS]: NaN in Force Applied to an Object");
  323. }
  324. }
  325. }
  326. public override int VehicleType
  327. {
  328. get { return (int) m_vehicle.Type; }
  329. set { _parent_scene.AddSimulationChange(() => changeVehicleType(value)); }
  330. }
  331. public override Vector3 CenterOfMass
  332. {
  333. get
  334. {
  335. d.Vector3 dtmp;
  336. if (IsPhysical && !childPrim && Body != IntPtr.Zero)
  337. {
  338. dtmp = d.BodyGetPosition(Body);
  339. return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
  340. }
  341. else if (prim_geom != IntPtr.Zero)
  342. {
  343. d.Quaternion dq;
  344. d.GeomCopyQuaternion(prim_geom, out dq);
  345. Quaternion q;
  346. q.X = dq.X;
  347. q.Y = dq.Y;
  348. q.Z = dq.Z;
  349. q.W = dq.W;
  350. Vector3 vtmp = primOOBoffset*q;
  351. dtmp = d.GeomGetPosition(prim_geom);
  352. return new Vector3(dtmp.X + vtmp.X, dtmp.Y + vtmp.Y, dtmp.Z + vtmp.Z);
  353. }
  354. else
  355. return Vector3.Zero;
  356. }
  357. }
  358. public override PrimitiveBaseShape Shape
  359. {
  360. set { _parent_scene.AddSimulationChange(() => changeshape(value)); }
  361. }
  362. public override Vector3 Velocity
  363. {
  364. get
  365. {
  366. // Averate previous velocity with the new one so
  367. // client object interpolation works a 'little' better
  368. if (_zeroFlag)
  369. return Vector3.Zero;
  370. Vector3 returnVelocity = Vector3.Zero;
  371. returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
  372. returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
  373. returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
  374. return returnVelocity;
  375. }
  376. set
  377. {
  378. if (value.IsFinite())
  379. _parent_scene.AddSimulationChange(() => changevelocity(value));
  380. else
  381. {
  382. MainConsole.Instance.Warn("[PHYSICS]: Got NaN Velocity in Object");
  383. }
  384. }
  385. }
  386. public override Vector3 Torque
  387. {
  388. get
  389. {
  390. if (childPrim || !m_isphysical || Body == IntPtr.Zero)
  391. return Vector3.Zero;
  392. return _torque;
  393. }
  394. set
  395. {
  396. if (value.IsFinite())
  397. _parent_scene.AddSimulationChange(() => changeSetTorque(value));
  398. else
  399. MainConsole.Instance.Warn("[PHYSICS]: Got NaN Torque in Object");
  400. }
  401. }
  402. public override float CollisionScore
  403. {
  404. get { return m_collisionscore; }
  405. set { m_collisionscore = value; }
  406. }
  407. public override Quaternion Orientation
  408. {
  409. get
  410. {
  411. if (fakeori > 0)
  412. return showorientation;
  413. else
  414. return _orientation;
  415. }
  416. set
  417. {
  418. if (QuaternionIsFinite(value))
  419. {
  420. showorientation = value;
  421. fakeori++;
  422. _parent_scene.AddSimulationChange(() => changeOrientation(value));
  423. }
  424. else
  425. MainConsole.Instance.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object");
  426. }
  427. }
  428. public override Vector3 Acceleration
  429. {
  430. get { return _acceleration; }
  431. }
  432. public override Vector3 RotationalVelocity
  433. {
  434. get
  435. {
  436. if (_zeroFlag)
  437. return Vector3.Zero;
  438. if (m_rotationalVelocity.ApproxEquals(Vector3.Zero, 0.00001f))
  439. return Vector3.Zero;
  440. return m_rotationalVelocity;
  441. }
  442. set
  443. {
  444. if (value.IsFinite())
  445. _parent_scene.AddSimulationChange(() => changeangvelocity(value));
  446. else
  447. MainConsole.Instance.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object");
  448. }
  449. }
  450. public override float Buoyancy
  451. {
  452. get { return m_buoyancy; }
  453. set { m_buoyancy = value; }
  454. }
  455. public override bool FloatOnWater
  456. {
  457. set { _parent_scene.AddSimulationChange(() => changefloatonwater(value)); }
  458. }
  459. public override void ClearVelocity()
  460. {
  461. _velocity = Vector3.Zero;
  462. _acceleration = Vector3.Zero;
  463. m_rotationalVelocity = Vector3.Zero;
  464. m_lastorientation = Orientation;
  465. m_lastposition = Position;
  466. m_lastVelocity = _velocity;
  467. if (Body != null && Body != IntPtr.Zero)
  468. d.BodySetLinearVel(Body, 0, 0, 0);
  469. }
  470. public override void ForceSetVelocity(Vector3 velocity)
  471. {
  472. _velocity = velocity;
  473. m_lastVelocity = velocity;
  474. if (Body != IntPtr.Zero)
  475. d.BodySetLinearVel(Body, velocity.X, velocity.Y, velocity.Z);
  476. }
  477. public void ForceSetRotVelocity(Vector3 velocity)
  478. {
  479. m_rotationalVelocity = velocity;
  480. if (Body != IntPtr.Zero)
  481. d.BodySetAngularVel(Body, velocity.X, velocity.Y, velocity.Z);
  482. }
  483. public void SetGeom(IntPtr geom)
  484. {
  485. prim_geom = geom;
  486. //Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName);
  487. if (prim_geom != IntPtr.Zero)
  488. {
  489. d.GeomSetCategoryBits(prim_geom, (int) m_collisionCategories);
  490. d.GeomSetCollideBits(prim_geom, (int) m_collisionFlags);
  491. CalcPrimBodyData();
  492. _parent_scene.actor_name_map[prim_geom] = this;
  493. }
  494. if (childPrim)
  495. {
  496. if (_parent != null && _parent is AuroraODEPrim)
  497. {
  498. AuroraODEPrim parent = (AuroraODEPrim) _parent;
  499. //Console.WriteLine("SetGeom calls ChildSetGeom");
  500. parent.ChildSetGeom(this);
  501. }
  502. }
  503. //MainConsole.Instance.Warn("Setting Geom to: " + prim_geom);
  504. }
  505. public void enableBodySoft()
  506. {
  507. if (!childPrim)
  508. {
  509. if (m_isphysical && Body != IntPtr.Zero)
  510. {
  511. d.BodyEnable(Body);
  512. if (m_vehicle.Type != Vehicle.TYPE_NONE)
  513. m_vehicle.Enable(Body, this, _parent_scene);
  514. }
  515. m_disabled = false;
  516. }
  517. }
  518. public void disableBodySoft()
  519. {
  520. if (!childPrim)
  521. {
  522. m_disabled = true;
  523. m_vehicle.Disable(this);
  524. if (IsPhysical && Body != IntPtr.Zero)
  525. d.BodyDisable(Body);
  526. }
  527. }
  528. private void MakeBody()
  529. {
  530. // d.Vector3 dvtmp;
  531. // d.Vector3 dbtmp;
  532. if (m_blockPhysicalReconstruction) // building is blocked
  533. return;
  534. if (childPrim) // child prims don't get own bodies;
  535. return;
  536. if (prim_geom == IntPtr.Zero)
  537. {
  538. MainConsole.Instance.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
  539. return;
  540. }
  541. if (!m_isphysical) // only physical things get a body
  542. return;
  543. if (Body != IntPtr.Zero) // who shouldn't have one already ?
  544. {
  545. d.BodyDestroy(Body);
  546. Body = IntPtr.Zero;
  547. MainConsole.Instance.Warn("[PHYSICS]: MakeBody called having a body");
  548. }
  549. d.Mass objdmass = new d.Mass {};
  550. d.Matrix3 mymat = new d.Matrix3();
  551. d.Quaternion myrot = new d.Quaternion();
  552. Body = d.BodyCreate(_parent_scene.world);
  553. DMassDup(ref primdMass, out objdmass);
  554. // rotate inertia
  555. myrot.X = _orientation.X;
  556. myrot.Y = _orientation.Y;
  557. myrot.Z = _orientation.Z;
  558. myrot.W = _orientation.W;
  559. d.RfromQ(out mymat, ref myrot);
  560. d.MassRotate(ref objdmass, ref mymat);
  561. // set the body rotation and position
  562. d.BodySetRotation(Body, ref mymat);
  563. // recompute full object inertia if needed
  564. if (childrenPrim.Count > 0)
  565. {
  566. d.Matrix3 mat = new d.Matrix3();
  567. d.Quaternion quat = new d.Quaternion();
  568. d.Mass tmpdmass = new d.Mass {};
  569. Vector3 rcm;
  570. rcm.X = _position.X + objdmass.c.X;
  571. rcm.Y = _position.Y + objdmass.c.Y;
  572. rcm.Z = _position.Z + objdmass.c.Z;
  573. lock (childrenPrim)
  574. {
  575. foreach (AuroraODEPrim prm in childrenPrim)
  576. {
  577. if (prm.prim_geom == IntPtr.Zero)
  578. {
  579. MainConsole.Instance.Warn(
  580. "[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
  581. continue;
  582. }
  583. DMassCopy(ref prm.primdMass, ref tmpdmass);
  584. // apply prim current rotation to inertia
  585. quat.W = prm._orientation.W;
  586. quat.X = prm._orientation.X;
  587. quat.Y = prm._orientation.Y;
  588. quat.Z = prm._orientation.Z;
  589. d.RfromQ(out mat, ref quat);
  590. d.MassRotate(ref tmpdmass, ref mat);
  591. Vector3 ppos = prm._position;
  592. ppos.X += tmpdmass.c.X - rcm.X;
  593. ppos.Y += tmpdmass.c.Y - rcm.Y;
  594. ppos.Z += tmpdmass.c.Z - rcm.Z;
  595. // refer inertia to root prim center of mass position
  596. d.MassTranslate(ref tmpdmass,
  597. ppos.X,
  598. ppos.Y,
  599. ppos.Z);
  600. d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
  601. // fix prim colision cats
  602. d.GeomClearOffset(prm.prim_geom);
  603. d.GeomSetBody(prm.prim_geom, Body);
  604. prm.Body = Body;
  605. d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
  606. }
  607. }
  608. }
  609. d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
  610. // associate root geom with body
  611. d.GeomSetBody(prim_geom, Body);
  612. d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
  613. d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
  614. d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z);
  615. // ode wants inertia at center of body
  616. myrot.W = -myrot.W;
  617. d.RfromQ(out mymat, ref myrot);
  618. d.MassRotate(ref objdmass, ref mymat);
  619. d.BodySetMass(Body, ref objdmass);
  620. _mass = objdmass.mass;
  621. m_collisionCategories |= CollisionCategories.Body;
  622. m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
  623. // disconnect from world gravity so we can apply buoyancy
  624. // if (!testRealGravity)
  625. d.BodySetGravityMode(Body, false);
  626. d.BodySetAutoDisableFlag(Body, true);
  627. d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
  628. d.BodySetDamping(Body, .001f, .0002f);
  629. m_disabled = false;
  630. d.GeomSetCategoryBits(prim_geom, (int) m_collisionCategories);
  631. d.GeomSetCollideBits(prim_geom, (int) m_collisionFlags);
  632. if (m_targetSpace != _parent_scene.space)
  633. {
  634. if (d.SpaceQuery(m_targetSpace, prim_geom))
  635. d.SpaceRemove(m_targetSpace, prim_geom);
  636. m_targetSpace = _parent_scene.space;
  637. d.SpaceAdd(m_targetSpace, prim_geom);
  638. }
  639. lock (childrenPrim)
  640. {
  641. foreach (AuroraODEPrim prm in childrenPrim)
  642. {
  643. if (prm.prim_geom == IntPtr.Zero)
  644. continue;
  645. Vector3 ppos = prm._position;
  646. d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
  647. prm.m_collisionCategories |= CollisionCategories.Body;
  648. prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
  649. d.GeomSetCategoryBits(prm.prim_geom, (int) prm.m_collisionCategories);
  650. d.GeomSetCollideBits(prm.prim_geom, (int) prm.m_collisionFlags);
  651. if (prm.m_targetSpace != _parent_scene.space)
  652. {
  653. if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
  654. d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
  655. prm.m_targetSpace = _parent_scene.space;
  656. d.SpaceAdd(m_targetSpace, prm.prim_geom);
  657. }
  658. prm.m_disabled = false;
  659. _parent_scene.addActivePrim(prm);
  660. }
  661. }
  662. // The body doesn't already have a finite rotation mode set here
  663. if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
  664. {
  665. createAMotor(m_angularlock);
  666. }
  667. if (m_vehicle.Type != Vehicle.TYPE_NONE)
  668. m_vehicle.Enable(Body, this, _parent_scene);
  669. _parent_scene.addActivePrim(this);
  670. }
  671. private void SetInStaticSpace(AuroraODEPrim prm)
  672. {
  673. if (prm.m_targetSpace != null && prm.m_targetSpace == _parent_scene.space)
  674. {
  675. if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
  676. d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
  677. }
  678. prm.m_targetSpace = _parent_scene.calculateSpaceForGeom(prm._position);
  679. d.SpaceAdd(prm.m_targetSpace, prm.prim_geom);
  680. }
  681. public void DestroyBody()
  682. // for now removes all colisions etc from childs, full body reconstruction is needed after this
  683. {
  684. //this kills the body so things like 'mesh' can re-create it.
  685. lock (this)
  686. {
  687. if (Body != IntPtr.Zero)
  688. {
  689. _parent_scene.remActivePrim(this);
  690. m_collisionCategories &= ~CollisionCategories.Body;
  691. m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
  692. if (prim_geom != IntPtr.Zero)
  693. {
  694. d.GeomSetCategoryBits(prim_geom, (int) m_collisionCategories);
  695. d.GeomSetCollideBits(prim_geom, (int) m_collisionFlags);
  696. UpdateDataFromGeom();
  697. SetInStaticSpace(this);
  698. }
  699. if (!childPrim)
  700. {
  701. lock (childrenPrim)
  702. {
  703. foreach (AuroraODEPrim prm in childrenPrim)
  704. {
  705. _parent_scene.remActivePrim(prm);
  706. prm.m_collisionCategories &= ~CollisionCategories.Body;
  707. prm.m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
  708. if (prm.prim_geom != IntPtr.Zero)
  709. {
  710. d.GeomSetCategoryBits(prm.prim_geom, (int) m_collisionCategories);
  711. d.GeomSetCollideBits(prm.prim_geom, (int) m_collisionFlags);
  712. prm.UpdateDataFromGeom();
  713. prm.Body = IntPtr.Zero;
  714. SetInStaticSpace(prm);
  715. }
  716. prm._mass = prm.primMass;
  717. }
  718. }
  719. m_vehicle.Disable(this);
  720. d.BodyDestroy(Body);
  721. }
  722. }
  723. Body = IntPtr.Zero;
  724. }
  725. _mass = primMass;
  726. m_disabled = true;
  727. }
  728. public bool setMesh(AuroraODEPhysicsScene parent_scene, IMesh mesh)
  729. {
  730. // This sleeper is there to moderate how long it takes between
  731. // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
  732. //Thread.Sleep(10);
  733. //Kill Body so that mesh can re-make the geom
  734. if (IsPhysical && Body != IntPtr.Zero)
  735. {
  736. if (childPrim)
  737. {
  738. if (_parent != null)
  739. {
  740. AuroraODEPrim parent = (AuroraODEPrim) _parent;
  741. parent.ChildDelink(this);
  742. }
  743. }
  744. else
  745. {
  746. DestroyBody();
  747. }
  748. }
  749. IntPtr vertices, indices;
  750. int vertexCount, indexCount;
  751. int vertexStride, triStride;
  752. mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
  753. // Note, that vertices are fixed in unmanaged heap
  754. mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
  755. // Also fixed, needs release after usage
  756. if (vertexCount == 0 || indexCount == 0)
  757. {
  758. MainConsole.Instance.WarnFormat(
  759. "[PHYSICS]: Got invalid mesh on prim at <{0},{1},{2}>. It can be a sculpt with alpha channel in map. Replacing it by a small box.",
  760. _position.X, _position.Y, _position.Z);
  761. _size.X = 0.01f;
  762. _size.Y = 0.01f;
  763. _size.Z = 0.01f;
  764. return false;
  765. }
  766. primOOBoffset = mesh.GetCentroid();
  767. hasOOBoffsetFromMesh = true;
  768. mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
  769. if (m_MeshToTriMeshMap.ContainsKey(mesh.Key))
  770. {
  771. _triMeshData = m_MeshToTriMeshMap[mesh.Key];
  772. }
  773. else
  774. {
  775. _triMeshData = d.GeomTriMeshDataCreate();
  776. d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount,
  777. triStride);
  778. d.GeomTriMeshDataPreprocess(_triMeshData);
  779. m_MeshToTriMeshMap[mesh.Key] = _triMeshData;
  780. }
  781. try
  782. {
  783. if (prim_geom == IntPtr.Zero)
  784. {
  785. SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
  786. }
  787. }
  788. catch (AccessViolationException)
  789. {
  790. MainConsole.Instance.Error("[PHYSICS]: MESH LOCKED");
  791. return false;
  792. }
  793. return true;
  794. }
  795. private void changeAngularLock(Vector3 newlock)
  796. {
  797. // do we have a Physical object?
  798. if (Body != IntPtr.Zero)
  799. {
  800. //Check that we have a Parent
  801. //If we have a parent then we're not authorative here
  802. if (_parent == null)
  803. {
  804. if (!newlock.ApproxEquals(Vector3.One, 0f))
  805. {
  806. createAMotor(newlock);
  807. }
  808. else
  809. {
  810. if (Amotor != IntPtr.Zero)
  811. {
  812. d.JointDestroy(Amotor);
  813. Amotor = IntPtr.Zero;
  814. }
  815. }
  816. }
  817. }
  818. // Store this for later in case we get turned into a separate body
  819. m_angularlock = newlock;
  820. }
  821. private void changelink(AuroraODEPrim newparent)
  822. {
  823. // If the newly set parent is not null
  824. // create link
  825. if (_parent == null && newparent != null)
  826. {
  827. newparent.ParentPrim(this);
  828. }
  829. // If the newly set parent is null
  830. // destroy link
  831. else if (_parent != null)
  832. {
  833. if (_parent is AuroraODEPrim)
  834. {
  835. if (newparent != _parent)
  836. {
  837. AuroraODEPrim obj = (AuroraODEPrim) _parent;
  838. obj.ChildDelink(this);
  839. childPrim = false;
  840. if (newparent != null)
  841. {
  842. newparent.ParentPrim(this);
  843. }
  844. }
  845. }
  846. }
  847. _parent = newparent;
  848. }
  849. // I'm the parent
  850. // prim is the child
  851. public void ParentPrim(AuroraODEPrim prim)
  852. {
  853. //Console.WriteLine("ParentPrim " + m_primName);
  854. if (this.m_localID != prim.m_localID)
  855. {
  856. DestroyBody();
  857. lock (childrenPrim)
  858. {
  859. #if (!ISWIN)
  860. foreach (AuroraODEPrim prm in prim.childrenPrim)
  861. {
  862. if (!childrenPrim.Contains(prm))
  863. {
  864. childrenPrim.Add(prm);
  865. }
  866. }
  867. #else
  868. foreach (AuroraODEPrim prm in prim.childrenPrim.Where(prm => !childrenPrim.Contains(prm)))
  869. {
  870. childrenPrim.Add(prm);
  871. }
  872. #endif
  873. if (!childrenPrim.Contains(prim)) // must allow full reconstruction
  874. childrenPrim.Add(prim);
  875. }
  876. //Remove old children
  877. prim.childrenPrim.Clear();
  878. prim.childPrim = true;
  879. prim._parent = this;
  880. if (prim.Body != IntPtr.Zero)
  881. {
  882. prim.DestroyBody(); // don't loose bodies around
  883. prim.Body = IntPtr.Zero;
  884. }
  885. MakeBody(); // full nasty reconstruction
  886. }
  887. }
  888. private void ChildSetGeom(AuroraODEPrim odePrim)
  889. {
  890. DestroyBody();
  891. MakeBody();
  892. }
  893. private void UpdateChildsfromgeom()
  894. {
  895. if (childrenPrim.Count > 0)
  896. {
  897. foreach (AuroraODEPrim prm in childrenPrim)
  898. prm.UpdateDataFromGeom();
  899. }
  900. }
  901. private void UpdateDataFromGeom()
  902. {
  903. if (prim_geom != IntPtr.Zero)
  904. {
  905. d.Vector3 lpos = d.GeomGetPosition(prim_geom);
  906. _position.X = lpos.X;
  907. _position.Y = lpos.Y;
  908. _position.Z = lpos.Z;
  909. d.Quaternion qtmp = new d.Quaternion
  910. {
  911. };
  912. d.GeomCopyQuaternion(prim_geom, out qtmp);
  913. _orientation.W = qtmp.W;
  914. _orientation.X = qtmp.X;
  915. _orientation.Y = qtmp.Y;
  916. _orientation.Z = qtmp.Z;
  917. }
  918. }
  919. private void ChildDelink(AuroraODEPrim odePrim)
  920. {
  921. // Okay, we have a delinked child.. destroy all body and remake
  922. if (odePrim != this && !childrenPrim.Contains(odePrim))
  923. return;
  924. DestroyBody();
  925. if (odePrim == this)
  926. {
  927. AuroraODEPrim newroot = null;
  928. lock (childrenPrim)
  929. {
  930. if (childrenPrim.Count > 0)
  931. {
  932. newroot = childrenPrim[0];
  933. childrenPrim.RemoveAt(0);
  934. foreach (AuroraODEPrim prm in childrenPrim)
  935. {
  936. newroot.childrenPrim.Add(prm);
  937. }
  938. childrenPrim.Clear();
  939. }
  940. if (newroot != null)
  941. {
  942. newroot.childPrim = false;
  943. newroot._parent = null;
  944. newroot.MakeBody();
  945. }
  946. }
  947. }
  948. else
  949. {
  950. lock (childrenPrim)
  951. {
  952. childrenPrim.Remove(odePrim);
  953. odePrim.childPrim = false;
  954. odePrim._parent = null;
  955. //odePrim.UpdateDataFromGeom ();
  956. odePrim.MakeBody();
  957. }
  958. }
  959. MakeBody();
  960. }
  961. private void ChildRemove(AuroraODEPrim odePrim)
  962. {
  963. // Okay, we have a delinked child.. destroy all body and remake
  964. if (odePrim != this && !childrenPrim.Contains(odePrim))
  965. return;
  966. DestroyBody();
  967. if (odePrim == this)
  968. {
  969. AuroraODEPrim newroot = null;
  970. lock (childrenPrim)
  971. {
  972. if (childrenPrim.Count > 0)
  973. {
  974. newroot = childrenPrim[0];
  975. childrenPrim.RemoveAt(0);
  976. foreach (AuroraODEPrim prm in childrenPrim)
  977. {
  978. newroot.childrenPrim.Add(prm);
  979. }
  980. childrenPrim.Clear();
  981. }
  982. if (newroot != null)
  983. {
  984. newroot.childPrim = false;
  985. newroot._parent = null;
  986. newroot.MakeBody();
  987. }
  988. }
  989. return;
  990. }
  991. else
  992. {
  993. lock (childrenPrim)
  994. {
  995. childrenPrim.Remove(odePrim);
  996. odePrim.childPrim = false;
  997. odePrim._parent = null;
  998. }
  999. }
  1000. MakeBody();
  1001. }
  1002. private void changeSelectedStatus(bool newsel)
  1003. {
  1004. bool isphys = IsPhysical;
  1005. if (newsel)
  1006. {
  1007. m_collisionCategories = CollisionCategories.Selected;
  1008. m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
  1009. // We do the body disable soft twice because 'in theory' a collision could have happened
  1010. // in between the disabling and the collision properties setting
  1011. // which would wake the physical body up from a soft disabling and potentially cause it to fall
  1012. // through the ground.
  1013. // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
  1014. // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
  1015. // so that causes the selected part to wake up and continue moving.
  1016. // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
  1017. // assembly will stop simulating during the selection, because of the lack of atomicity
  1018. // of select operations (their processing could be interrupted by a thread switch, causing
  1019. // simulation to continue before all of the selected object notifications trickle down to
  1020. // the physics engine).
  1021. // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
  1022. // selected and disabled. then, due to a thread switch, the selection processing is
  1023. // interrupted and the physics engine continues to simulate, so the last 50 items, whose
  1024. // selection was not yet processed, continues to simulate. this wakes up ALL of the
  1025. // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
  1026. // up, start simulating again, which in turn wakes up the last 50.
  1027. if (isphys)
  1028. {
  1029. disableBodySoft();
  1030. }
  1031. if (prim_geom != IntPtr.Zero)
  1032. {
  1033. d.GeomSetCategoryBits(prim_geom, (int) m_collisionCategories);
  1034. d.GeomSetCollideBits(prim_geom, (int) m_collisionFlags);
  1035. }
  1036. if (isphys)
  1037. {
  1038. disableBodySoft();
  1039. }
  1040. }
  1041. else
  1042. {
  1043. m_collisionCategories = CollisionCategories.Geom;
  1044. if (isphys)
  1045. m_collisionCategories |= CollisionCategories.Body;
  1046. m_collisionFlags = m_default_collisionFlags;
  1047. if (m_collidesLand)
  1048. m_collisionFlags |= CollisionCategories.Land;
  1049. if (m_collidesWater)
  1050. m_collisionFlags |= CollisionCategories.Water;
  1051. if (prim_geom != IntPtr.Zero)
  1052. {
  1053. d.GeomSetCategoryBits(prim_geom, (int) m_collisionCategories);
  1054. d.GeomSetCollideBits(prim_geom, (int) m_collisionFlags);
  1055. }
  1056. if (isphys)
  1057. {
  1058. if (Body != IntPtr.Zero)
  1059. {
  1060. d.BodySetLinearVel(Body, 0f, 0f, 0f);
  1061. d.BodySetAngularVel(Body, 0f, 0f, 0f);
  1062. d.BodySetForce(Body, 0, 0, 0);
  1063. d.BodySetTorque(Body, 0, 0, 0);
  1064. enableBodySoft();
  1065. }
  1066. }
  1067. }
  1068. resetCollisionAccounting();
  1069. m_isSelected = newsel;
  1070. if (!m_isSelected)
  1071. {
  1072. _zeroFlag = false;
  1073. }
  1074. }
  1075. //end changeSelectedStatus
  1076. public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh)
  1077. {
  1078. hasOOBoffsetFromMesh = false;
  1079. bool havemesh = false;
  1080. //Console.WriteLine("CreateGeom:");
  1081. if (_mesh != null)
  1082. {
  1083. havemesh = setMesh(_parent_scene, _mesh); // this will give a mesh to non trivial known prims
  1084. }
  1085. if (!havemesh)
  1086. {
  1087. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte) Extrusion.Curve1
  1088. && _size.X == _size.Y && _size.Y == _size.Z)
  1089. {
  1090. // it's a sphere
  1091. try
  1092. {
  1093. SetGeom(d.CreateSphere(m_targetSpace, _size.X*0.5f));
  1094. }
  1095. catch (Exception e)
  1096. {
  1097. MainConsole.Instance.Warn("[PHYSICS]: Create sphere failed: {0}", e);
  1098. return;
  1099. }
  1100. }
  1101. else
  1102. {
  1103. try
  1104. {
  1105. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1106. }
  1107. catch (Exception e)
  1108. {
  1109. MainConsole.Instance.Warn("[PHYSICS]: Create box failed: {0}", e);
  1110. return;
  1111. }
  1112. }
  1113. }
  1114. }
  1115. private void RemoveGeom()
  1116. {
  1117. if (prim_geom != IntPtr.Zero)
  1118. {
  1119. _parent_scene.actor_name_map.Remove(prim_geom);
  1120. try
  1121. {
  1122. d.GeomDestroy(prim_geom);
  1123. /*
  1124. if (_triMeshData != IntPtr.Zero)
  1125. {
  1126. d.GeomTriMeshDataDestroy(_triMeshData);
  1127. _triMeshData = IntPtr.Zero;
  1128. }
  1129. */
  1130. }
  1131. catch (Exception e)
  1132. {
  1133. MainConsole.Instance.ErrorFormat("[PHYSICS]: PrimGeom destruction failed {1}", e);
  1134. }
  1135. prim_geom = IntPtr.Zero;
  1136. }
  1137. else
  1138. {
  1139. MainConsole.Instance.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD");
  1140. }
  1141. Body = IntPtr.Zero;
  1142. hasOOBoffsetFromMesh = false;
  1143. CalcPrimBodyData();
  1144. }
  1145. public void changeadd()
  1146. {
  1147. // all prims are now created non physical
  1148. IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
  1149. m_targetSpace = targetspace;
  1150. if (_mesh == null)
  1151. {
  1152. if (_parent_scene.needsMeshing(_parent_entity))
  1153. {
  1154. // Don't need to re-enable body.. it's done in SetMesh
  1155. _mesh = _parent_scene.mesher.CreateMesh(_parent_entity.Name, _pbs, _size,
  1156. _parent_scene.meshSculptLOD, true);
  1157. //…