BSCharacter.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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.Reflection;
  30. using log4net;
  31. using OMV = OpenMetaverse;
  32. using OpenSim.Framework;
  33. using OpenSim.Region.Physics.Manager;
  34. namespace OpenSim.Region.Physics.BulletSPlugin
  35. {
  36. public sealed class BSCharacter : BSPhysObject
  37. {
  38. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  39. private static readonly string LogHeader = "[BULLETS CHAR]";
  40. // private bool _stopped;
  41. private OMV.Vector3 _size;
  42. private bool _grabbed;
  43. private bool _selected;
  44. private OMV.Vector3 _position;
  45. private float _mass;
  46. private float _avatarDensity;
  47. private float _avatarVolume;
  48. private OMV.Vector3 _force;
  49. private OMV.Vector3 _velocity;
  50. private OMV.Vector3 _torque;
  51. private float _collisionScore;
  52. private OMV.Vector3 _acceleration;
  53. private OMV.Quaternion _orientation;
  54. private int _physicsActorType;
  55. private bool _isPhysical;
  56. private bool _flying;
  57. private bool _setAlwaysRun;
  58. private bool _throttleUpdates;
  59. private bool _isColliding;
  60. private bool _collidingObj;
  61. private bool _floatOnWater;
  62. private OMV.Vector3 _rotationalVelocity;
  63. private bool _kinematic;
  64. private float _buoyancy;
  65. // The friction and velocity of the avatar is modified depending on whether walking or not.
  66. private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar
  67. private float _currentFriction; // the friction currently being used (changed by setVelocity).
  68. private OMV.Vector3 _PIDTarget;
  69. private bool _usePID;
  70. private float _PIDTau;
  71. private bool _useHoverPID;
  72. private float _PIDHoverHeight;
  73. private PIDHoverType _PIDHoverType;
  74. private float _PIDHoverTao;
  75. public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
  76. {
  77. base.BaseInitialize(parent_scene, localID, avName, "BSCharacter");
  78. _physicsActorType = (int)ActorTypes.Agent;
  79. _position = pos;
  80. _size = size;
  81. _flying = isFlying;
  82. _orientation = OMV.Quaternion.Identity;
  83. _velocity = OMV.Vector3.Zero;
  84. _appliedVelocity = OMV.Vector3.Zero;
  85. _buoyancy = ComputeBuoyancyFromFlying(isFlying);
  86. _currentFriction = PhysicsScene.Params.avatarStandingFriction;
  87. _avatarDensity = PhysicsScene.Params.avatarDensity;
  88. // The dimensions of the avatar capsule are kept in the scale.
  89. // Physics creates a unit capsule which is scaled by the physics engine.
  90. ComputeAvatarScale(_size);
  91. // set _avatarVolume and _mass based on capsule size, _density and Scale
  92. ComputeAvatarVolumeAndMass();
  93. DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
  94. LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw);
  95. ShapeData shapeData = new ShapeData();
  96. shapeData.ID = LocalID;
  97. shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
  98. shapeData.Position = _position;
  99. shapeData.Rotation = _orientation;
  100. shapeData.Velocity = _velocity;
  101. shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1>
  102. shapeData.Scale = Scale;
  103. shapeData.Mass = _mass;
  104. shapeData.Buoyancy = _buoyancy;
  105. shapeData.Static = ShapeData.numericFalse;
  106. shapeData.Friction = PhysicsScene.Params.avatarStandingFriction;
  107. shapeData.Restitution = PhysicsScene.Params.avatarRestitution;
  108. // do actual create at taint time
  109. PhysicsScene.TaintedObject("BSCharacter.create", delegate()
  110. {
  111. DetailLog("{0},BSCharacter.create,taint", LocalID);
  112. // New body and shape into BSBody and BSShape
  113. PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null);
  114. SetPhysicalProperties();
  115. });
  116. return;
  117. }
  118. // called when this character is being destroyed and the resources should be released
  119. public override void Destroy()
  120. {
  121. DetailLog("{0},BSCharacter.Destroy", LocalID);
  122. PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
  123. {
  124. PhysicsScene.Shapes.DereferenceBody(BSBody, true, null);
  125. PhysicsScene.Shapes.DereferenceShape(BSShape, true, null);
  126. });
  127. }
  128. private void SetPhysicalProperties()
  129. {
  130. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
  131. ZeroMotion();
  132. ForcePosition = _position;
  133. // Set the velocity and compute the proper friction
  134. ForceVelocity = _velocity;
  135. BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution);
  136. BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin);
  137. BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
  138. BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
  139. if (PhysicsScene.Params.ccdMotionThreshold > 0f)
  140. {
  141. BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
  142. BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
  143. }
  144. OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
  145. BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
  146. // Make so capsule does not fall over
  147. BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero);
  148. BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
  149. BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
  150. // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
  151. BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION);
  152. BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
  153. // Do this after the object has been added to the world
  154. BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
  155. (uint)CollisionFilterGroups.AvatarFilter,
  156. (uint)CollisionFilterGroups.AvatarMask);
  157. }
  158. public override void RequestPhysicsterseUpdate()
  159. {
  160. base.RequestPhysicsterseUpdate();
  161. }
  162. // No one calls this method so I don't know what it could possibly mean
  163. public override bool Stopped { get { return false; } }
  164. public override OMV.Vector3 Size {
  165. get
  166. {
  167. // Avatar capsule size is kept in the scale parameter.
  168. // return _size;
  169. return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z);
  170. }
  171. set {
  172. // When an avatar's size is set, only the height is changed.
  173. _size = value;
  174. ComputeAvatarScale(_size);
  175. ComputeAvatarVolumeAndMass();
  176. DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}",
  177. LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw);
  178. PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
  179. {
  180. BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
  181. OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
  182. BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
  183. });
  184. }
  185. }
  186. public override OMV.Vector3 Scale { get; set; }
  187. public override PrimitiveBaseShape Shape
  188. {
  189. set { BaseShape = value; }
  190. }
  191. public override bool Grabbed {
  192. set { _grabbed = value; }
  193. }
  194. public override bool Selected {
  195. set { _selected = value; }
  196. }
  197. public override void CrossingFailure() { return; }
  198. public override void link(PhysicsActor obj) { return; }
  199. public override void delink() { return; }
  200. // Set motion values to zero.
  201. // Do it to the properties so the values get set in the physics engine.
  202. // Push the setting of the values to the viewer.
  203. // Called at taint time!
  204. public override void ZeroMotion()
  205. {
  206. _velocity = OMV.Vector3.Zero;
  207. _acceleration = OMV.Vector3.Zero;
  208. _rotationalVelocity = OMV.Vector3.Zero;
  209. // Zero some other properties directly into the physics engine
  210. BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero);
  211. BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero);
  212. BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
  213. BulletSimAPI.ClearForces2(BSBody.ptr);
  214. }
  215. public override void LockAngularMotion(OMV.Vector3 axis) { return; }
  216. public override OMV.Vector3 Position {
  217. get {
  218. // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID);
  219. return _position;
  220. }
  221. set {
  222. _position = value;
  223. PositionSanityCheck();
  224. PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
  225. {
  226. DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
  227. BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
  228. });
  229. }
  230. }
  231. public override OMV.Vector3 ForcePosition {
  232. get {
  233. _position = BulletSimAPI.GetPosition2(BSBody.ptr);
  234. return _position;
  235. }
  236. set {
  237. _position = value;
  238. PositionSanityCheck();
  239. BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
  240. }
  241. }
  242. // Check that the current position is sane and, if not, modify the position to make it so.
  243. // Check for being below terrain or on water.
  244. // Returns 'true' of the position was made sane by some action.
  245. private bool PositionSanityCheck()
  246. {
  247. bool ret = false;
  248. // If below the ground, move the avatar up
  249. float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
  250. if (Position.Z < terrainHeight)
  251. {
  252. DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
  253. _position.Z = terrainHeight + 2.0f;
  254. ret = true;
  255. }
  256. if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
  257. {
  258. float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
  259. if (Position.Z < waterHeight)
  260. {
  261. _position.Z = waterHeight;
  262. ret = true;
  263. }
  264. }
  265. // TODO: check for out of bounds
  266. return ret;
  267. }
  268. // A version of the sanity check that also makes sure a new position value is
  269. // pushed back to the physics engine. This routine would be used by anyone
  270. // who is not already pushing the value.
  271. private bool PositionSanityCheck(bool inTaintTime)
  272. {
  273. bool ret = false;
  274. if (PositionSanityCheck())
  275. {
  276. // The new position value must be pushed into the physics engine but we can't
  277. // just assign to "Position" because of potential call loops.
  278. BSScene.TaintCallback sanityOperation = delegate()
  279. {
  280. DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
  281. BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
  282. };
  283. if (inTaintTime)
  284. sanityOperation();
  285. else
  286. PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
  287. ret = true;
  288. }
  289. return ret;
  290. }
  291. public override float Mass { get { return _mass; } }
  292. // used when we only want this prim's mass and not the linkset thing
  293. public override float MassRaw { get {return _mass; } }
  294. public override OMV.Vector3 Force {
  295. get { return _force; }
  296. set {
  297. _force = value;
  298. // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
  299. PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
  300. {
  301. DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
  302. BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
  303. });
  304. }
  305. }
  306. // Avatars don't do vehicles
  307. public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } }
  308. public override void VehicleFloatParam(int param, float value) { }
  309. public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
  310. public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
  311. public override void VehicleFlags(int param, bool remove) { }
  312. // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
  313. public override void SetVolumeDetect(int param) { return; }
  314. public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
  315. public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
  316. public override OMV.Vector3 Velocity {
  317. get { return _velocity; }
  318. set {
  319. _velocity = value;
  320. // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
  321. PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
  322. {
  323. DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
  324. ForceVelocity = _velocity;
  325. });
  326. }
  327. }
  328. public override OMV.Vector3 ForceVelocity {
  329. get { return _velocity; }
  330. set {
  331. // Depending on whether the avatar is moving or not, change the friction
  332. // to keep the avatar from slipping around
  333. if (_velocity.Length() == 0)
  334. {
  335. if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
  336. {
  337. _currentFriction = PhysicsScene.Params.avatarStandingFriction;
  338. BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
  339. }
  340. }
  341. else
  342. {
  343. if (_currentFriction != PhysicsScene.Params.avatarFriction)
  344. {
  345. _currentFriction = PhysicsScene.Params.avatarFriction;
  346. BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
  347. }
  348. }
  349. _velocity = value;
  350. // Remember the set velocity so we can suppress the reduction by friction, ...
  351. _appliedVelocity = value;
  352. BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
  353. BulletSimAPI.Activate2(BSBody.ptr, true);
  354. }
  355. }
  356. public override OMV.Vector3 Torque {
  357. get { return _torque; }
  358. set { _torque = value;
  359. }
  360. }
  361. public override float CollisionScore {
  362. get { return _collisionScore; }
  363. set { _collisionScore = value;
  364. }
  365. }
  366. public override OMV.Vector3 Acceleration {
  367. get { return _acceleration; }
  368. set { _acceleration = value; }
  369. }
  370. public override OMV.Quaternion Orientation {
  371. get { return _orientation; }
  372. set {
  373. _orientation = value;
  374. // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
  375. PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
  376. {
  377. // _position = BulletSimAPI.GetPosition2(BSBody.ptr);
  378. BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
  379. });
  380. }
  381. }
  382. // Go directly to Bullet to get/set the value.
  383. public override OMV.Quaternion ForceOrientation
  384. {
  385. get
  386. {
  387. _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
  388. return _orientation;
  389. }
  390. set
  391. {
  392. _orientation = value;
  393. BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
  394. }
  395. }
  396. public override int PhysicsActorType {
  397. get { return _physicsActorType; }
  398. set { _physicsActorType = value;
  399. }
  400. }
  401. public override bool IsPhysical {
  402. get { return _isPhysical; }
  403. set { _isPhysical = value;
  404. }
  405. }
  406. public override bool IsSolid {
  407. get { return true; }
  408. }
  409. public override bool IsStatic {
  410. get { return false; }
  411. }
  412. public override bool Flying {
  413. get { return _flying; }
  414. set {
  415. _flying = value;
  416. // simulate flying by changing the effect of gravity
  417. Buoyancy = ComputeBuoyancyFromFlying(_flying);
  418. }
  419. }
  420. // Flying is implimented by changing the avatar's buoyancy.
  421. // Would this be done better with a vehicle type?
  422. private float ComputeBuoyancyFromFlying(bool ifFlying) {
  423. return ifFlying ? 1f : 0f;
  424. }
  425. public override bool
  426. SetAlwaysRun {
  427. get { return _setAlwaysRun; }
  428. set { _setAlwaysRun = value; }
  429. }
  430. public override bool ThrottleUpdates {
  431. get { return _throttleUpdates; }
  432. set { _throttleUpdates = value; }
  433. }
  434. public override bool IsColliding {
  435. get { return (CollidingStep == PhysicsScene.SimulationStep); }
  436. set { _isColliding = value; }
  437. }
  438. public override bool CollidingGround {
  439. get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
  440. set { CollidingGround = value; }
  441. }
  442. public override bool CollidingObj {
  443. get { return _collidingObj; }
  444. set { _collidingObj = value; }
  445. }
  446. public override bool FloatOnWater {
  447. set {
  448. _floatOnWater = value;
  449. PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
  450. {
  451. if (_floatOnWater)
  452. CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
  453. else
  454. CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
  455. });
  456. }
  457. }
  458. public override OMV.Vector3 RotationalVelocity {
  459. get { return _rotationalVelocity; }
  460. set { _rotationalVelocity = value; }
  461. }
  462. public override OMV.Vector3 ForceRotationalVelocity {
  463. get { return _rotationalVelocity; }
  464. set { _rotationalVelocity = value; }
  465. }
  466. public override bool Kinematic {
  467. get { return _kinematic; }
  468. set { _kinematic = value; }
  469. }
  470. // neg=fall quickly, 0=1g, 1=0g, pos=float up
  471. public override float Buoyancy {
  472. get { return _buoyancy; }
  473. set { _buoyancy = value;
  474. PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
  475. {
  476. DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
  477. ForceBuoyancy = _buoyancy;
  478. });
  479. }
  480. }
  481. public override float ForceBuoyancy {
  482. get { return _buoyancy; }
  483. set { _buoyancy = value;
  484. DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
  485. // Buoyancy is faked by changing the gravity applied to the object
  486. float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
  487. BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
  488. }
  489. }
  490. // Used for MoveTo
  491. public override OMV.Vector3 PIDTarget {
  492. set { _PIDTarget = value; }
  493. }
  494. public override bool PIDActive {
  495. set { _usePID = value; }
  496. }
  497. public override float PIDTau {
  498. set { _PIDTau = value; }
  499. }
  500. // Used for llSetHoverHeight and maybe vehicle height
  501. // Hover Height will override MoveTo target's Z
  502. public override bool PIDHoverActive {
  503. set { _useHoverPID = value; }
  504. }
  505. public override float PIDHoverHeight {
  506. set { _PIDHoverHeight = value; }
  507. }
  508. public override PIDHoverType PIDHoverType {
  509. set { _PIDHoverType = value; }
  510. }
  511. public override float PIDHoverTau {
  512. set { _PIDHoverTao = value; }
  513. }
  514. // For RotLookAt
  515. public override OMV.Quaternion APIDTarget { set { return; } }
  516. public override bool APIDActive { set { return; } }
  517. public override float APIDStrength { set { return; } }
  518. public override float APIDDamping { set { return; } }
  519. public override void AddForce(OMV.Vector3 force, bool pushforce) {
  520. if (force.IsFinite())
  521. {
  522. _force.X += force.X;
  523. _force.Y += force.Y;
  524. _force.Z += force.Z;
  525. // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
  526. PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
  527. {
  528. DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
  529. BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
  530. });
  531. }
  532. else
  533. {
  534. m_log.ErrorFormat("{0}: Got a NaN force applied to a Character", LogHeader);
  535. }
  536. //m_lastUpdateSent = false;
  537. }
  538. public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
  539. }
  540. public override void SetMomentum(OMV.Vector3 momentum) {
  541. }
  542. private void ComputeAvatarScale(OMV.Vector3 size)
  543. {
  544. // The 'size' given by the simulator is the mid-point of the avatar
  545. // and X and Y are unspecified.
  546. OMV.Vector3 newScale = OMV.Vector3.Zero;
  547. newScale.X = PhysicsScene.Params.avatarCapsuleRadius;
  548. newScale.Y = PhysicsScene.Params.avatarCapsuleRadius;
  549. // From the total height, remove the capsule half spheres that are at each end
  550. newScale.Z = size.Z- (newScale.X + newScale.Y);
  551. Scale = newScale;
  552. }
  553. // set _avatarVolume and _mass based on capsule size, _density and Scale
  554. private void ComputeAvatarVolumeAndMass()
  555. {
  556. _avatarVolume = (float)(
  557. Math.PI
  558. * Scale.X
  559. * Scale.Y // the area of capsule cylinder
  560. * Scale.Z // times height of capsule cylinder
  561. + 1.33333333f
  562. * Math.PI
  563. * Scale.X
  564. * Math.Min(Scale.X, Scale.Y)
  565. * Scale.Y // plus the volume of the capsule end caps
  566. );
  567. _mass = _avatarDensity * _avatarVolume;
  568. }
  569. // The physics engine says that properties have updated. Update same and inform
  570. // the world that things have changed.
  571. public override void UpdateProperties(EntityProperties entprop)
  572. {
  573. _position = entprop.Position;
  574. _orientation = entprop.Rotation;
  575. _velocity = entprop.Velocity;
  576. _acceleration = entprop.Acceleration;
  577. _rotationalVelocity = entprop.RotationalVelocity;
  578. // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
  579. PositionSanityCheck(true);
  580. // remember the current and last set values
  581. LastEntityProperties = CurrentEntityProperties;
  582. CurrentEntityProperties = entprop;
  583. if (entprop.Velocity != LastEntityProperties.Velocity)
  584. {
  585. // Changes in the velocity are suppressed in avatars.
  586. // That's just the way they are defined.
  587. OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
  588. _velocity = avVel;
  589. BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel);
  590. }
  591. // Tell the linkset about value changes
  592. Linkset.UpdateProperties(this);
  593. // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
  594. // base.RequestPhysicsterseUpdate();
  595. DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
  596. LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
  597. }
  598. }
  599. }