BSPhysObject.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (c) Contributors, 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 copyrightD
  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 OpenSimulator 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.Text;
  30. using OMV = OpenMetaverse;
  31. using OpenSim.Framework;
  32. using OpenSim.Region.Physics.Manager;
  33. namespace OpenSim.Region.Physics.BulletSPlugin
  34. {
  35. // Class to wrap all objects.
  36. // The rest of BulletSim doesn't need to keep checking for avatars or prims
  37. // unless the difference is significant.
  38. public abstract class BSPhysObject : PhysicsActor
  39. {
  40. protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName)
  41. {
  42. PhysicsScene = parentScene;
  43. LocalID = localID;
  44. PhysObjectName = name;
  45. TypeName = typeName;
  46. Linkset = BSLinkset.Factory(PhysicsScene, this);
  47. LastAssetBuildFailed = false;
  48. CollisionCollection = new CollisionEventUpdate();
  49. SubscribedEventsMs = 0;
  50. CollidingStep = 0;
  51. CollidingGroundStep = 0;
  52. }
  53. public BSScene PhysicsScene { get; protected set; }
  54. // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
  55. public string PhysObjectName { get; protected set; }
  56. public string TypeName { get; protected set; }
  57. public BSLinkset Linkset { get; set; }
  58. // Return the object mass without calculating it or having side effects
  59. public abstract float MassRaw { get; }
  60. // Reference to the physical body (btCollisionObject) of this object
  61. public BulletBody BSBody;
  62. // Reference to the physical shape (btCollisionShape) of this object
  63. public BulletShape BSShape;
  64. // 'true' if the mesh's underlying asset failed to build.
  65. // This will keep us from looping after the first time the build failed.
  66. public bool LastAssetBuildFailed { get; set; }
  67. // The objects base shape information. Null if not a prim type shape.
  68. public PrimitiveBaseShape BaseShape { get; protected set; }
  69. // When the physical properties are updated, an EntityProperty holds the update values.
  70. // Keep the current and last EntityProperties to enable computation of differences
  71. // between the current update and the previous values.
  72. public EntityProperties CurrentEntityProperties { get; set; }
  73. public EntityProperties LastEntityProperties { get; set; }
  74. public abstract OMV.Vector3 Scale { get; set; }
  75. public abstract bool IsSolid { get; }
  76. public abstract bool IsStatic { get; }
  77. // Stop all physical motion.
  78. public abstract void ZeroMotion();
  79. // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
  80. public virtual void StepVehicle(float timeStep) { }
  81. // Update the physical location and motion of the object. Called with data from Bullet.
  82. public abstract void UpdateProperties(EntityProperties entprop);
  83. // Tell the object to clean up.
  84. public abstract void Destroy();
  85. public abstract OMV.Vector3 ForcePosition { get; set; }
  86. public abstract OMV.Quaternion ForceOrientation { get; set; }
  87. public abstract OMV.Vector3 ForceVelocity { get; set; }
  88. public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
  89. public abstract float ForceBuoyancy { get; set; }
  90. public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
  91. #region Collisions
  92. // Requested number of milliseconds between collision events. Zero means disabled.
  93. protected int SubscribedEventsMs { get; set; }
  94. // Given subscription, the time that a collision may be passed up
  95. protected int NextCollisionOkTime { get; set; }
  96. // The simulation step that last had a collision
  97. protected long CollidingStep { get; set; }
  98. // The simulation step that last had a collision with the ground
  99. protected long CollidingGroundStep { get; set; }
  100. // The collision flags we think are set in Bullet
  101. protected CollisionFlags CurrentCollisionFlags { get; set; }
  102. // The collisions that have been collected this tick
  103. protected CollisionEventUpdate CollisionCollection;
  104. // The simulation step is telling this object about a collision.
  105. // Return 'true' if a collision was processed and should be sent up.
  106. // Called at taint time from within the Step() function
  107. public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
  108. OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
  109. {
  110. bool ret = false;
  111. // The following lines make IsColliding() and IsCollidingGround() work
  112. CollidingStep = PhysicsScene.SimulationStep;
  113. if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
  114. {
  115. CollidingGroundStep = PhysicsScene.SimulationStep;
  116. }
  117. // prims in the same linkset cannot collide with each other
  118. if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
  119. {
  120. return ret;
  121. }
  122. // if someone has subscribed for collision events....
  123. if (SubscribedEvents()) {
  124. CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
  125. DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
  126. LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
  127. ret = true;
  128. }
  129. return ret;
  130. }
  131. // Send the collected collisions into the simulator.
  132. // Called at taint time from within the Step() function thus no locking problems
  133. // with CollisionCollection and ObjectsWithNoMoreCollisions.
  134. // Return 'true' if there were some actual collisions passed up
  135. public virtual bool SendCollisions()
  136. {
  137. bool ret = true;
  138. // If the 'no collision' call, force it to happen right now so quick collision_end
  139. bool force = CollisionCollection.Count == 0;
  140. // throttle the collisions to the number of milliseconds specified in the subscription
  141. if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
  142. {
  143. NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
  144. // We are called if we previously had collisions. If there are no collisions
  145. // this time, send up one last empty event so OpenSim can sense collision end.
  146. if (CollisionCollection.Count == 0)
  147. {
  148. // If I have no collisions this time, remove me from the list of objects with collisions.
  149. ret = false;
  150. }
  151. // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
  152. base.SendCollisionUpdate(CollisionCollection);
  153. // The collisionCollection structure is passed around in the simulator.
  154. // Make sure we don't have a handle to that one and that a new one is used for next time.
  155. CollisionCollection = new CollisionEventUpdate();
  156. }
  157. return ret;
  158. }
  159. // Subscribe for collision events.
  160. // Parameter is the millisecond rate the caller wishes collision events to occur.
  161. public override void SubscribeEvents(int ms) {
  162. // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
  163. SubscribedEventsMs = ms;
  164. if (ms > 0)
  165. {
  166. // make sure first collision happens
  167. NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
  168. PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
  169. {
  170. CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
  171. });
  172. }
  173. else
  174. {
  175. // Subscribing for zero or less is the same as unsubscribing
  176. UnSubscribeEvents();
  177. }
  178. }
  179. public override void UnSubscribeEvents() {
  180. // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
  181. SubscribedEventsMs = 0;
  182. PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
  183. {
  184. CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
  185. });
  186. }
  187. // Return 'true' if the simulator wants collision events
  188. public override bool SubscribedEvents() {
  189. return (SubscribedEventsMs > 0);
  190. }
  191. #endregion // Collisions
  192. // High performance detailed logging routine used by the physical objects.
  193. protected void DetailLog(string msg, params Object[] args)
  194. {
  195. if (PhysicsScene.PhysicsLogging.Enabled)
  196. PhysicsScene.DetailLog(msg, args);
  197. }
  198. }
  199. }