BSCharacter.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  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 float _mass;
  45. private float _avatarVolume;
  46. private float _collisionScore;
  47. private OMV.Vector3 _acceleration;
  48. private int _physicsActorType;
  49. private bool _isPhysical;
  50. private bool _flying;
  51. private bool _setAlwaysRun;
  52. private bool _throttleUpdates;
  53. private bool _floatOnWater;
  54. private OMV.Vector3 _rotationalVelocity;
  55. private bool _kinematic;
  56. private float _buoyancy;
  57. private BSActorAvatarMove m_moveActor;
  58. private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
  59. private OMV.Vector3 _PIDTarget;
  60. private bool _usePID;
  61. private float _PIDTau;
  62. // public override OMV.Vector3 RawVelocity
  63. // { get { return base.RawVelocity; }
  64. // set {
  65. // if (value != base.RawVelocity)
  66. // Util.PrintCallStack();
  67. // Console.WriteLine("Set rawvel to {0}", value);
  68. // base.RawVelocity = value; }
  69. // }
  70. // Avatars are always complete (in the physics engine sense)
  71. public override bool IsIncomplete { get { return false; } }
  72. public BSCharacter(
  73. uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 vel, OMV.Vector3 size, bool isFlying)
  74. : base(parent_scene, localID, avName, "BSCharacter")
  75. {
  76. _physicsActorType = (int)ActorTypes.Agent;
  77. RawPosition = pos;
  78. _flying = isFlying;
  79. RawOrientation = OMV.Quaternion.Identity;
  80. RawVelocity = vel;
  81. _buoyancy = ComputeBuoyancyFromFlying(isFlying);
  82. Friction = BSParam.AvatarStandingFriction;
  83. Density = BSParam.AvatarDensity;
  84. // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
  85. // replace with the default values.
  86. _size = size;
  87. if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
  88. if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
  89. // The dimensions of the physical capsule are kept in the scale.
  90. // Physics creates a unit capsule which is scaled by the physics engine.
  91. Scale = ComputeAvatarScale(_size);
  92. // set _avatarVolume and _mass based on capsule size, _density and Scale
  93. ComputeAvatarVolumeAndMass();
  94. DetailLog(
  95. "{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6},vel={7}",
  96. LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos, vel);
  97. // do actual creation in taint time
  98. PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
  99. {
  100. DetailLog("{0},BSCharacter.create,taint", LocalID);
  101. // New body and shape into PhysBody and PhysShape
  102. PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);
  103. // The avatar's movement is controlled by this motor that speeds up and slows down
  104. // the avatar seeking to reach the motor's target speed.
  105. // This motor runs as a prestep action for the avatar so it will keep the avatar
  106. // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
  107. m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
  108. PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
  109. SetPhysicalProperties();
  110. IsInitialized = true;
  111. });
  112. return;
  113. }
  114. // called when this character is being destroyed and the resources should be released
  115. public override void Destroy()
  116. {
  117. IsInitialized = false;
  118. base.Destroy();
  119. DetailLog("{0},BSCharacter.Destroy", LocalID);
  120. PhysScene.TaintedObject(LocalID, "BSCharacter.destroy", delegate()
  121. {
  122. PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
  123. PhysBody.Clear();
  124. PhysShape.Dereference(PhysScene);
  125. PhysShape = new BSShapeNull();
  126. });
  127. }
  128. private void SetPhysicalProperties()
  129. {
  130. PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
  131. ForcePosition = RawPosition;
  132. // Set the velocity
  133. if (m_moveActor != null)
  134. m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
  135. ForceVelocity = RawVelocity;
  136. TargetVelocity = RawVelocity;
  137. // This will enable or disable the flying buoyancy of the avatar.
  138. // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
  139. Flying = _flying;
  140. PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
  141. PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
  142. PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
  143. PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
  144. if (BSParam.CcdMotionThreshold > 0f)
  145. {
  146. PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
  147. PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
  148. }
  149. UpdatePhysicalMassProperties(RawMass, false);
  150. // Make so capsule does not fall over
  151. PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
  152. // The avatar mover sets some parameters.
  153. PhysicalActors.Refresh();
  154. PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
  155. PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
  156. // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
  157. PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
  158. PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
  159. // Do this after the object has been added to the world
  160. if (BSParam.AvatarToAvatarCollisionsByDefault)
  161. PhysBody.collisionType = CollisionType.Avatar;
  162. else
  163. PhysBody.collisionType = CollisionType.PhantomToOthersAvatar;
  164. PhysBody.ApplyCollisionMask(PhysScene);
  165. }
  166. public override void RequestPhysicsterseUpdate()
  167. {
  168. base.RequestPhysicsterseUpdate();
  169. }
  170. // No one calls this method so I don't know what it could possibly mean
  171. public override bool Stopped { get { return false; } }
  172. public override OMV.Vector3 Size {
  173. get
  174. {
  175. // Avatar capsule size is kept in the scale parameter.
  176. return _size;
  177. }
  178. set {
  179. // This is how much the avatar size is changing. Positive means getting bigger.
  180. // The avatar altitude must be adjusted for this change.
  181. float heightChange = value.Z - _size.Z;
  182. _size = value;
  183. // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
  184. // replace with the default values.
  185. if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
  186. if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
  187. Scale = ComputeAvatarScale(_size);
  188. ComputeAvatarVolumeAndMass();
  189. DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
  190. LocalID, _size, Scale, Density, _avatarVolume, RawMass);
  191. PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
  192. {
  193. if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
  194. {
  195. PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
  196. UpdatePhysicalMassProperties(RawMass, true);
  197. // Adjust the avatar's position to account for the increase/decrease in size
  198. ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
  199. // Make sure this change appears as a property update event
  200. PhysScene.PE.PushUpdate(PhysBody);
  201. }
  202. });
  203. }
  204. }
  205. public override PrimitiveBaseShape Shape
  206. {
  207. set { BaseShape = value; }
  208. }
  209. public override bool Grabbed {
  210. set { _grabbed = value; }
  211. }
  212. public override bool Selected {
  213. set { _selected = value; }
  214. }
  215. public override bool IsSelected
  216. {
  217. get { return _selected; }
  218. }
  219. public override void CrossingFailure() { return; }
  220. public override void link(PhysicsActor obj) { return; }
  221. public override void delink() { return; }
  222. // Set motion values to zero.
  223. // Do it to the properties so the values get set in the physics engine.
  224. // Push the setting of the values to the viewer.
  225. // Called at taint time!
  226. public override void ZeroMotion(bool inTaintTime)
  227. {
  228. RawVelocity = OMV.Vector3.Zero;
  229. _acceleration = OMV.Vector3.Zero;
  230. _rotationalVelocity = OMV.Vector3.Zero;
  231. // Zero some other properties directly into the physics engine
  232. PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
  233. {
  234. if (PhysBody.HasPhysicalBody)
  235. PhysScene.PE.ClearAllForces(PhysBody);
  236. });
  237. }
  238. public override void ZeroAngularMotion(bool inTaintTime)
  239. {
  240. _rotationalVelocity = OMV.Vector3.Zero;
  241. PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
  242. {
  243. if (PhysBody.HasPhysicalBody)
  244. {
  245. PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
  246. PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
  247. // The next also get rid of applied linear force but the linear velocity is untouched.
  248. PhysScene.PE.ClearForces(PhysBody);
  249. }
  250. });
  251. }
  252. public override void LockAngularMotion(OMV.Vector3 axis) { return; }
  253. public override OMV.Vector3 Position {
  254. get {
  255. // Don't refetch the position because this function is called a zillion times
  256. // RawPosition = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID);
  257. return RawPosition;
  258. }
  259. set {
  260. RawPosition = value;
  261. PhysScene.TaintedObject(LocalID, "BSCharacter.setPosition", delegate()
  262. {
  263. DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
  264. PositionSanityCheck();
  265. ForcePosition = RawPosition;
  266. });
  267. }
  268. }
  269. public override OMV.Vector3 ForcePosition {
  270. get {
  271. RawPosition = PhysScene.PE.GetPosition(PhysBody);
  272. return RawPosition;
  273. }
  274. set {
  275. RawPosition = value;
  276. if (PhysBody.HasPhysicalBody)
  277. {
  278. PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
  279. }
  280. }
  281. }
  282. // Check that the current position is sane and, if not, modify the position to make it so.
  283. // Check for being below terrain or on water.
  284. // Returns 'true' of the position was made sane by some action.
  285. private bool PositionSanityCheck()
  286. {
  287. bool ret = false;
  288. // TODO: check for out of bounds
  289. if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
  290. {
  291. // The character is out of the known/simulated area.
  292. // Force the avatar position to be within known. ScenePresence will use the position
  293. // plus the velocity to decide if the avatar is moving out of the region.
  294. RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
  295. DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
  296. return true;
  297. }
  298. // If below the ground, move the avatar up
  299. float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
  300. if (Position.Z < terrainHeight)
  301. {
  302. DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
  303. RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters);
  304. ret = true;
  305. }
  306. if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
  307. {
  308. float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
  309. if (Position.Z < waterHeight)
  310. {
  311. RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, waterHeight);
  312. ret = true;
  313. }
  314. }
  315. return ret;
  316. }
  317. // A version of the sanity check that also makes sure a new position value is
  318. // pushed back to the physics engine. This routine would be used by anyone
  319. // who is not already pushing the value.
  320. private bool PositionSanityCheck(bool inTaintTime)
  321. {
  322. bool ret = false;
  323. if (PositionSanityCheck())
  324. {
  325. // The new position value must be pushed into the physics engine but we can't
  326. // just assign to "Position" because of potential call loops.
  327. PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.PositionSanityCheck", delegate()
  328. {
  329. DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
  330. ForcePosition = RawPosition;
  331. });
  332. ret = true;
  333. }
  334. return ret;
  335. }
  336. public override float Mass { get { return _mass; } }
  337. // used when we only want this prim's mass and not the linkset thing
  338. public override float RawMass {
  339. get {return _mass; }
  340. }
  341. public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
  342. {
  343. OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
  344. PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
  345. }
  346. public override OMV.Vector3 Force {
  347. get { return RawForce; }
  348. set {
  349. RawForce = value;
  350. // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
  351. PhysScene.TaintedObject(LocalID, "BSCharacter.SetForce", delegate()
  352. {
  353. DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
  354. if (PhysBody.HasPhysicalBody)
  355. PhysScene.PE.SetObjectForce(PhysBody, RawForce);
  356. });
  357. }
  358. }
  359. // Avatars don't do vehicles
  360. public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } }
  361. public override void VehicleFloatParam(int param, float value) { }
  362. public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
  363. public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
  364. public override void VehicleFlags(int param, bool remove) { }
  365. // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
  366. public override void SetVolumeDetect(int param) { return; }
  367. public override bool IsVolumeDetect { get { return false; } }
  368. public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
  369. public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
  370. // Sets the target in the motor. This starts the changing of the avatar's velocity.
  371. public override OMV.Vector3 TargetVelocity
  372. {
  373. get
  374. {
  375. return base.m_targetVelocity;
  376. }
  377. set
  378. {
  379. DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
  380. m_targetVelocity = value;
  381. OMV.Vector3 targetVel = value;
  382. if (_setAlwaysRun && !_flying)
  383. targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 1f);
  384. if (m_moveActor != null)
  385. m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
  386. }
  387. }
  388. // Directly setting velocity means this is what the user really wants now.
  389. public override OMV.Vector3 Velocity {
  390. get { return RawVelocity; }
  391. set {
  392. RawVelocity = value;
  393. OMV.Vector3 vel = RawVelocity;
  394. DetailLog("{0}: set Velocity = {1}", LogHeader, value);
  395. PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
  396. {
  397. if (m_moveActor != null)
  398. m_moveActor.SetVelocityAndTarget(vel, vel, true /* inTaintTime */);
  399. DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, vel);
  400. ForceVelocity = vel;
  401. });
  402. }
  403. }
  404. public override OMV.Vector3 ForceVelocity {
  405. get { return RawVelocity; }
  406. set {
  407. PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
  408. // Util.PrintCallStack();
  409. DetailLog("{0}: set ForceVelocity = {1}", LogHeader, value);
  410. RawVelocity = value;
  411. PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
  412. PhysScene.PE.Activate(PhysBody, true);
  413. }
  414. }
  415. public override OMV.Vector3 Torque {
  416. get { return RawTorque; }
  417. set { RawTorque = value;
  418. }
  419. }
  420. public override float CollisionScore {
  421. get { return _collisionScore; }
  422. set { _collisionScore = value;
  423. }
  424. }
  425. public override OMV.Vector3 Acceleration {
  426. get { return _acceleration; }
  427. set { _acceleration = value; }
  428. }
  429. public override OMV.Quaternion Orientation {
  430. get { return RawOrientation; }
  431. set {
  432. // Orientation is set zillions of times when an avatar is walking. It's like
  433. // the viewer doesn't trust us.
  434. if (RawOrientation != value)
  435. {
  436. RawOrientation = value;
  437. PhysScene.TaintedObject(LocalID, "BSCharacter.setOrientation", delegate()
  438. {
  439. // Bullet assumes we know what we are doing when forcing orientation
  440. // so it lets us go against all the rules and just compensates for them later.
  441. // This forces rotation to be only around the Z axis and doesn't change any of the other axis.
  442. // This keeps us from flipping the capsule over which the veiwer does not understand.
  443. float oRoll, oPitch, oYaw;
  444. RawOrientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
  445. OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
  446. // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}",
  447. // LocalID, RawOrientation, OMV.Vector3.UnitX * RawOrientation,
  448. // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation);
  449. ForceOrientation = trimmedOrientation;
  450. });
  451. }
  452. }
  453. }
  454. // Go directly to Bullet to get/set the value.
  455. public override OMV.Quaternion ForceOrientation
  456. {
  457. get
  458. {
  459. RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
  460. return RawOrientation;
  461. }
  462. set
  463. {
  464. RawOrientation = value;
  465. if (PhysBody.HasPhysicalBody)
  466. {
  467. // RawPosition = PhysicsScene.PE.GetPosition(BSBody);
  468. PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
  469. }
  470. }
  471. }
  472. public override int PhysicsActorType {
  473. get { return _physicsActorType; }
  474. set { _physicsActorType = value;
  475. }
  476. }
  477. public override bool IsPhysical {
  478. get { return _isPhysical; }
  479. set { _isPhysical = value;
  480. }
  481. }
  482. public override bool IsSolid {
  483. get { return true; }
  484. }
  485. public override bool IsStatic {
  486. get { return false; }
  487. }
  488. public override bool IsPhysicallyActive {
  489. get { return true; }
  490. }
  491. public override bool Flying {
  492. get { return _flying; }
  493. set {
  494. _flying = value;
  495. // simulate flying by changing the effect of gravity
  496. Buoyancy = ComputeBuoyancyFromFlying(_flying);
  497. }
  498. }
  499. // Flying is implimented by changing the avatar's buoyancy.
  500. // Would this be done better with a vehicle type?
  501. private float ComputeBuoyancyFromFlying(bool ifFlying) {
  502. return ifFlying ? 1f : 0f;
  503. }
  504. public override bool
  505. SetAlwaysRun {
  506. get { return _setAlwaysRun; }
  507. set { _setAlwaysRun = value; }
  508. }
  509. public override bool ThrottleUpdates {
  510. get { return _throttleUpdates; }
  511. set { _throttleUpdates = value; }
  512. }
  513. public override bool FloatOnWater {
  514. set {
  515. _floatOnWater = value;
  516. PhysScene.TaintedObject(LocalID, "BSCharacter.setFloatOnWater", delegate()
  517. {
  518. if (PhysBody.HasPhysicalBody)
  519. {
  520. if (_floatOnWater)
  521. CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
  522. else
  523. CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
  524. }
  525. });
  526. }
  527. }
  528. public override OMV.Vector3 RotationalVelocity {
  529. get { return _rotationalVelocity; }
  530. set { _rotationalVelocity = value; }
  531. }
  532. public override OMV.Vector3 ForceRotationalVelocity {
  533. get { return _rotationalVelocity; }
  534. set { _rotationalVelocity = value; }
  535. }
  536. public override bool Kinematic {
  537. get { return _kinematic; }
  538. set { _kinematic = value; }
  539. }
  540. // neg=fall quickly, 0=1g, 1=0g, pos=float up
  541. public override float Buoyancy {
  542. get { return _buoyancy; }
  543. set { _buoyancy = value;
  544. PhysScene.TaintedObject(LocalID, "BSCharacter.setBuoyancy", delegate()
  545. {
  546. DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
  547. ForceBuoyancy = _buoyancy;
  548. });
  549. }
  550. }
  551. public override float ForceBuoyancy {
  552. get { return _buoyancy; }
  553. set {
  554. PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
  555. _buoyancy = value;
  556. DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
  557. // Buoyancy is faked by changing the gravity applied to the object
  558. float grav = BSParam.Gravity * (1f - _buoyancy);
  559. Gravity = new OMV.Vector3(0f, 0f, grav);
  560. if (PhysBody.HasPhysicalBody)
  561. PhysScene.PE.SetGravity(PhysBody, Gravity);
  562. }
  563. }
  564. // Used for MoveTo
  565. public override OMV.Vector3 PIDTarget {
  566. set { _PIDTarget = value; }
  567. }
  568. public override bool PIDActive { get; set; }
  569. public override float PIDTau {
  570. set { _PIDTau = value; }
  571. }
  572. public override void AddForce(OMV.Vector3 force, bool pushforce)
  573. {
  574. // Since this force is being applied in only one step, make this a force per second.
  575. OMV.Vector3 addForce = force / PhysScene.LastTimeStep;
  576. AddForce(addForce, pushforce, false);
  577. }
  578. public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
  579. if (force.IsFinite())
  580. {
  581. OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
  582. // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
  583. PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
  584. {
  585. // Bullet adds this central force to the total force for this tick
  586. // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
  587. if (PhysBody.HasPhysicalBody)
  588. {
  589. PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
  590. }
  591. });
  592. }
  593. else
  594. {
  595. m_log.WarnFormat("{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID);
  596. return;
  597. }
  598. }
  599. public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
  600. }
  601. public override void SetMomentum(OMV.Vector3 momentum) {
  602. }
  603. private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
  604. {
  605. OMV.Vector3 newScale = size;
  606. // Bullet's capsule total height is the "passed height + radius * 2";
  607. // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1)
  608. // The number we pass in for 'scaling' is the multiplier to get that base
  609. // shape to be the size desired.
  610. // So, when creating the scale for the avatar height, we take the passed height
  611. // (size.Z) and remove the caps.
  612. // An oddity of the Bullet capsule implementation is that it presumes the Y
  613. // dimension is the radius of the capsule. Even though some of the code allows
  614. // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
  615. // Scale is multiplier of radius with one of "0.5"
  616. float heightAdjust = BSParam.AvatarHeightMidFudge;
  617. if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
  618. {
  619. const float AVATAR_LOW = 1.1f;
  620. const float AVATAR_MID = 1.775f; // 1.87f
  621. const float AVATAR_HI = 2.45f;
  622. // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
  623. float midHeightOffset = size.Z - AVATAR_MID;
  624. if (midHeightOffset < 0f)
  625. {
  626. // Small avatar. Add the adjustment based on the distance from midheight
  627. heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
  628. }
  629. else
  630. {
  631. // Large avatar. Add the adjustment based on the distance from midheight
  632. heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
  633. }
  634. }
  635. if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule)
  636. {
  637. newScale.X = size.X / 2f;
  638. newScale.Y = size.Y / 2f;
  639. // The total scale height is the central cylindar plus the caps on the two ends.
  640. newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f;
  641. }
  642. else
  643. {
  644. newScale.Z = size.Z + heightAdjust;
  645. }
  646. // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale);
  647. // If smaller than the endcaps, just fake like we're almost that small
  648. if (newScale.Z < 0)
  649. newScale.Z = 0.1f;
  650. DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
  651. LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
  652. return newScale;
  653. }
  654. // set _avatarVolume and _mass based on capsule size, _density and Scale
  655. private void ComputeAvatarVolumeAndMass()
  656. {
  657. _avatarVolume = (float)(
  658. Math.PI
  659. * Size.X / 2f
  660. * Size.Y / 2f // the area of capsule cylinder
  661. * Size.Z // times height of capsule cylinder
  662. + 1.33333333f
  663. * Math.PI
  664. * Size.X / 2f
  665. * Math.Min(Size.X, Size.Y) / 2
  666. * Size.Y / 2f // plus the volume of the capsule end caps
  667. );
  668. _mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
  669. }
  670. // The physics engine says that properties have updated. Update same and inform
  671. // the world that things have changed.
  672. public override void UpdateProperties(EntityProperties entprop)
  673. {
  674. // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
  675. TriggerPreUpdatePropertyAction(ref entprop);
  676. RawPosition = entprop.Position;
  677. RawOrientation = entprop.Rotation;
  678. // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
  679. // and will send agent updates to the clients if velocity changes by more than
  680. // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
  681. // extra updates.
  682. //
  683. // XXX: Contrary to the above comment, setting an update threshold here above 0.4 actually introduces jitter to
  684. // avatar movement rather than removes it. The larger the threshold, the bigger the jitter.
  685. // This is most noticeable in level flight and can be seen with
  686. // the "show updates" option in a viewer. With an update threshold, the RawVelocity cycles between a lower
  687. // bound and an upper bound, where the difference between the two is enough to trigger a large delta v update
  688. // and subsequently trigger an update in ScenePresence.SendTerseUpdateToAllClients(). The cause of this cycle (feedback?)
  689. // has not yet been identified.
  690. //
  691. // If there is a threshold below 0.4 or no threshold check at all (as in ODE), then RawVelocity stays constant and extra
  692. // updates are not triggered in ScenePresence.SendTerseUpdateToAllClients().
  693. // if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
  694. RawVelocity = entprop.Velocity;
  695. _acceleration = entprop.Acceleration;
  696. _rotationalVelocity = entprop.RotationalVelocity;
  697. // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
  698. if (PositionSanityCheck(true))
  699. {
  700. DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, RawPosition);
  701. entprop.Position = RawPosition;
  702. }
  703. // remember the current and last set values
  704. LastEntityProperties = CurrentEntityProperties;
  705. CurrentEntityProperties = entprop;
  706. // Tell the linkset about value changes
  707. // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
  708. // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
  709. // PhysScene.PostUpdate(this);
  710. DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
  711. LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
  712. }
  713. }
  714. }