ODECharacter.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  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 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 OpenSim 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 Axiom.Math;
  29. using Ode.NET;
  30. using OpenSim.Framework;
  31. using OpenSim.Region.Physics.Manager;
  32. namespace OpenSim.Region.Physics.OdePlugin
  33. {
  34. /// <summary>
  35. /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
  36. /// </summary>
  37. public enum dParam : int
  38. {
  39. LowStop = 0,
  40. HiStop = 1,
  41. Vel = 2,
  42. FMax = 3,
  43. FudgeFactor = 4,
  44. Bounce = 5,
  45. CFM = 6,
  46. ERP = 7,
  47. StopCFM = 8,
  48. LoStop2 = 256,
  49. HiStop2 = 257,
  50. LoStop3 = 512,
  51. HiStop3 = 513
  52. }
  53. public class OdeCharacter : PhysicsActor
  54. {
  55. //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  56. private PhysicsVector _position;
  57. private d.Vector3 _zeroPosition;
  58. private d.Matrix3 m_StandUpRotation;
  59. private bool _zeroFlag = false;
  60. private bool m_lastUpdateSent = false;
  61. private PhysicsVector _velocity;
  62. private PhysicsVector _target_velocity;
  63. private PhysicsVector _acceleration;
  64. private PhysicsVector m_rotationalVelocity;
  65. private float m_mass = 80f;
  66. private float m_density = 60f;
  67. private bool m_pidControllerActive = true;
  68. private float PID_D = 800.0f;
  69. private float PID_P = 900.0f;
  70. //private static float POSTURE_SERVO = 10000.0f;
  71. public static float CAPSULE_RADIUS = 0.37f;
  72. public float CAPSULE_LENGTH = 2.140599f;
  73. private float m_tensor = 3800000f;
  74. private bool flying = false;
  75. private bool m_iscolliding = false;
  76. private bool m_iscollidingGround = false;
  77. private bool m_wascolliding = false;
  78. private bool m_wascollidingGround = false;
  79. private bool m_iscollidingObj = false;
  80. private bool m_alwaysRun = false;
  81. private bool m_hackSentFall = false;
  82. private bool m_hackSentFly = false;
  83. public uint m_localID = 0;
  84. public bool m_returnCollisions = false;
  85. private float m_buoyancy = 0f;
  86. private CollisionLocker ode;
  87. private string m_name = String.Empty;
  88. private bool[] m_colliderarr = new bool[11];
  89. private bool[] m_colliderGroundarr = new bool[11];
  90. // Default we're a Character
  91. private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
  92. // Default, Collide with Other Geometries, spaces, bodies and characters.
  93. private CollisionCategories m_collisionFlags = (CollisionCategories.Geom
  94. | CollisionCategories.Space
  95. | CollisionCategories.Body
  96. | CollisionCategories.Character
  97. | CollisionCategories.Land);
  98. public IntPtr Body;
  99. private OdeScene _parent_scene;
  100. public IntPtr Shell;
  101. public IntPtr Amotor;
  102. public d.Mass ShellMass;
  103. public bool collidelock = false;
  104. public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size)
  105. {
  106. ode = dode;
  107. _velocity = new PhysicsVector();
  108. _target_velocity = new PhysicsVector();
  109. _position = pos;
  110. _acceleration = new PhysicsVector();
  111. _parent_scene = parent_scene;
  112. if (Environment.OSVersion.Platform == PlatformID.Unix)
  113. {
  114. m_tensor = 2000000f;
  115. }
  116. else
  117. {
  118. m_tensor = 1300000f;
  119. }
  120. m_StandUpRotation =
  121. new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f,
  122. 0.5f);
  123. for (int i = 0; i < 11; i++)
  124. {
  125. m_colliderarr[i] = false;
  126. }
  127. CAPSULE_LENGTH = (size.Z - ((size.Z * 0.52f)));
  128. lock (OdeScene.OdeLock)
  129. {
  130. AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z, m_tensor);
  131. }
  132. m_name = avName;
  133. parent_scene.geom_name_map[Shell] = avName;
  134. parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
  135. }
  136. public override int PhysicsActorType
  137. {
  138. get { return (int) ActorTypes.Agent; }
  139. set { return; }
  140. }
  141. /// <summary>
  142. /// If this is set, the avatar will move faster
  143. /// </summary>
  144. public override bool SetAlwaysRun
  145. {
  146. get { return m_alwaysRun; }
  147. set { m_alwaysRun = value; }
  148. }
  149. public override uint LocalID
  150. {
  151. set { m_localID = value; }
  152. }
  153. public override bool Grabbed
  154. {
  155. set { return; }
  156. }
  157. public override bool Selected
  158. {
  159. set { return; }
  160. }
  161. public override float Buoyancy
  162. {
  163. get { return m_buoyancy; }
  164. set { m_buoyancy = value; }
  165. }
  166. public override bool FloatOnWater
  167. {
  168. set { return; }
  169. }
  170. public override bool IsPhysical
  171. {
  172. get { return false; }
  173. set { return; }
  174. }
  175. public override bool ThrottleUpdates
  176. {
  177. get { return false; }
  178. set { return; }
  179. }
  180. public override bool Flying
  181. {
  182. get { return flying; }
  183. set { flying = value; }
  184. }
  185. /// <summary>
  186. /// Returns if the avatar is colliding in general.
  187. /// This includes the ground and objects and avatar.
  188. /// </summary>
  189. public override bool IsColliding
  190. {
  191. get { return m_iscolliding; }
  192. set
  193. {
  194. int i;
  195. int truecount = 0;
  196. int falsecount = 0;
  197. if (m_colliderarr.Length >= 10)
  198. {
  199. for (i = 0; i < 10; i++)
  200. {
  201. m_colliderarr[i] = m_colliderarr[i + 1];
  202. }
  203. }
  204. m_colliderarr[10] = value;
  205. for (i = 0; i < 11; i++)
  206. {
  207. if (m_colliderarr[i])
  208. {
  209. truecount++;
  210. }
  211. else
  212. {
  213. falsecount++;
  214. }
  215. }
  216. // Equal truecounts and false counts means we're colliding with something.
  217. if (falsecount > 1.2*truecount)
  218. {
  219. m_iscolliding = false;
  220. }
  221. else
  222. {
  223. m_iscolliding = true;
  224. }
  225. if (m_wascolliding != m_iscolliding)
  226. {
  227. //base.SendCollisionUpdate(new CollisionEventUpdate());
  228. }
  229. m_wascolliding = m_iscolliding;
  230. }
  231. }
  232. /// <summary>
  233. /// Returns if an avatar is colliding with the ground
  234. /// </summary>
  235. public override bool CollidingGround
  236. {
  237. get { return m_iscollidingGround; }
  238. set
  239. {
  240. // Collisions against the ground are not really reliable
  241. // So, to get a consistant value we have to average the current result over time
  242. // Currently we use 1 second = 10 calls to this.
  243. int i;
  244. int truecount = 0;
  245. int falsecount = 0;
  246. if (m_colliderGroundarr.Length >= 10)
  247. {
  248. for (i = 0; i < 10; i++)
  249. {
  250. m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
  251. }
  252. }
  253. m_colliderGroundarr[10] = value;
  254. for (i = 0; i < 11; i++)
  255. {
  256. if (m_colliderGroundarr[i])
  257. {
  258. truecount++;
  259. }
  260. else
  261. {
  262. falsecount++;
  263. }
  264. }
  265. // Equal truecounts and false counts means we're colliding with something.
  266. if (falsecount > 1.2*truecount)
  267. {
  268. m_iscollidingGround = false;
  269. }
  270. else
  271. {
  272. m_iscollidingGround = true;
  273. }
  274. if (m_wascollidingGround != m_iscollidingGround)
  275. {
  276. //base.SendCollisionUpdate(new CollisionEventUpdate());
  277. }
  278. m_wascollidingGround = m_iscollidingGround;
  279. }
  280. }
  281. /// <summary>
  282. /// Returns if the avatar is colliding with an object
  283. /// </summary>
  284. public override bool CollidingObj
  285. {
  286. get { return m_iscollidingObj; }
  287. set
  288. {
  289. m_iscollidingObj = value;
  290. if (value)
  291. m_pidControllerActive = false;
  292. else
  293. m_pidControllerActive = true;
  294. }
  295. }
  296. /// <summary>
  297. /// turn the PID controller on or off.
  298. /// The PID Controller will turn on all by itself in many situations
  299. /// </summary>
  300. /// <param name="status"></param>
  301. public void SetPidStatus(bool status)
  302. {
  303. m_pidControllerActive = status;
  304. }
  305. public override bool Stopped
  306. {
  307. get { return _zeroFlag; }
  308. }
  309. /// <summary>
  310. /// This 'puts' an avatar somewhere in the physics space.
  311. /// Not really a good choice unless you 'know' it's a good
  312. /// spot otherwise you're likely to orbit the avatar.
  313. /// </summary>
  314. public override PhysicsVector Position
  315. {
  316. get { return _position; }
  317. set
  318. {
  319. lock (OdeScene.OdeLock)
  320. {
  321. d.BodySetPosition(Body, value.X, value.Y, value.Z);
  322. _position = value;
  323. }
  324. }
  325. }
  326. public override PhysicsVector RotationalVelocity
  327. {
  328. get { return m_rotationalVelocity; }
  329. set { m_rotationalVelocity = value; }
  330. }
  331. /// <summary>
  332. /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
  333. /// and use it to offset landings properly
  334. /// </summary>
  335. public override PhysicsVector Size
  336. {
  337. get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); }
  338. set
  339. {
  340. m_pidControllerActive = true;
  341. lock (OdeScene.OdeLock)
  342. {
  343. d.JointDestroy(Amotor);
  344. PhysicsVector SetSize = value;
  345. float prevCapsule = CAPSULE_LENGTH;
  346. float capsuleradius = CAPSULE_RADIUS;
  347. //capsuleradius = 0.2f;
  348. CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.52f))); // subtract 43% of the size
  349. //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
  350. d.BodyDestroy(Body);
  351. _parent_scene.waitForSpaceUnlock(_parent_scene.space);
  352. d.GeomDestroy(Shell);
  353. AvatarGeomAndBodyCreation(_position.X, _position.Y,
  354. _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
  355. Velocity = new PhysicsVector(0f, 0f, 0f);
  356. }
  357. _parent_scene.geom_name_map[Shell] = m_name;
  358. _parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
  359. }
  360. }
  361. /// <summary>
  362. /// This creates the Avatar's physical Surrogate at the position supplied
  363. /// </summary>
  364. /// <param name="npositionX"></param>
  365. /// <param name="npositionY"></param>
  366. /// <param name="npositionZ"></param>
  367. private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
  368. {
  369. if (Environment.OSVersion.Platform == PlatformID.Unix)
  370. {
  371. m_tensor = 2000000f;
  372. }
  373. else
  374. {
  375. m_tensor = 550000f;
  376. }
  377. int dAMotorEuler = 1;
  378. _parent_scene.waitForSpaceUnlock(_parent_scene.space);
  379. Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
  380. d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
  381. d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
  382. d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
  383. Body = d.BodyCreate(_parent_scene.world);
  384. d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
  385. d.BodySetMass(Body, ref ShellMass);
  386. d.Matrix3 m_caprot;
  387. // 90 Stand up on the cap of the capped cyllinder
  388. d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
  389. d.GeomSetRotation(Shell, ref m_caprot);
  390. d.BodySetRotation(Body, ref m_caprot);
  391. d.GeomSetBody(Shell, Body);
  392. // The purpose of the AMotor here is to keep the avatar's physical
  393. // surrogate from rotating while moving
  394. Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
  395. d.JointAttach(Amotor, Body, IntPtr.Zero);
  396. d.JointSetAMotorMode(Amotor, dAMotorEuler);
  397. d.JointSetAMotorNumAxes(Amotor, 3);
  398. d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
  399. d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
  400. d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
  401. d.JointSetAMotorAngle(Amotor, 0, 0);
  402. d.JointSetAMotorAngle(Amotor, 1, 0);
  403. d.JointSetAMotorAngle(Amotor, 2, 0);
  404. // These lowstops and high stops are effectively (no wiggle room)
  405. d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
  406. d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
  407. d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
  408. d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
  409. d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
  410. d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
  411. // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
  412. // capped cyllinder will fall over
  413. d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
  414. d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
  415. //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
  416. //d.QfromR(
  417. //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
  418. //
  419. //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
  420. //standupStraight();
  421. }
  422. //
  423. /// <summary>
  424. /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
  425. /// This may be used in calculations in the scene/scenepresence
  426. /// </summary>
  427. public override float Mass
  428. {
  429. get
  430. {
  431. float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
  432. return m_density*AVvolume;
  433. }
  434. }
  435. public override void link(PhysicsActor obj)
  436. {
  437. }
  438. public override void delink()
  439. {
  440. }
  441. public override void LockAngularMotion(PhysicsVector axis)
  442. {
  443. }
  444. // This code is very useful. Written by DanX0r. We're just not using it right now.
  445. // Commented out to prevent a warning.
  446. //
  447. // private void standupStraight()
  448. // {
  449. // // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
  450. // // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
  451. // // change appearance and when you enter the simulator
  452. // // After this routine is done, the amotor stabilizes much quicker
  453. // d.Vector3 feet;
  454. // d.Vector3 head;
  455. // d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
  456. // d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
  457. // float posture = head.Z - feet.Z;
  458. // // restoring force proportional to lack of posture:
  459. // float servo = (2.5f - posture) * POSTURE_SERVO;
  460. // d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
  461. // d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
  462. // //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
  463. // //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
  464. // }
  465. public override PhysicsVector Force
  466. {
  467. get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); }
  468. }
  469. public override PhysicsVector CenterOfMass
  470. {
  471. get { return PhysicsVector.Zero; }
  472. }
  473. public override PhysicsVector GeometricCenter
  474. {
  475. get { return PhysicsVector.Zero; }
  476. }
  477. public override PrimitiveBaseShape Shape
  478. {
  479. set { return; }
  480. }
  481. public override PhysicsVector Velocity
  482. {
  483. get {
  484. // There's a problem with PhysicsVector.Zero! Don't Use it Here!
  485. if (_zeroFlag)
  486. return new PhysicsVector(0f, 0f, 0f);
  487. m_lastUpdateSent = false;
  488. return _velocity;
  489. }
  490. set
  491. {
  492. m_pidControllerActive = true;
  493. _target_velocity = value;
  494. }
  495. }
  496. public override float CollisionScore
  497. {
  498. get { return 0f; }
  499. }
  500. public override bool Kinematic
  501. {
  502. get { return false; }
  503. set { }
  504. }
  505. public override Quaternion Orientation
  506. {
  507. get { return Quaternion.Identity; }
  508. set {
  509. //Matrix3 or = Orientation.ToRotationMatrix();
  510. //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22);
  511. //d.BodySetRotation(Body, ref ord);
  512. }
  513. }
  514. public override PhysicsVector Acceleration
  515. {
  516. get { return _acceleration; }
  517. }
  518. public void SetAcceleration(PhysicsVector accel)
  519. {
  520. m_pidControllerActive = true;
  521. _acceleration = accel;
  522. }
  523. /// <summary>
  524. /// Adds the force supplied to the Target Velocity
  525. /// The PID controller takes this target velocity and tries to make it a reality
  526. /// </summary>
  527. /// <param name="force"></param>
  528. public override void AddForce(PhysicsVector force)
  529. {
  530. m_pidControllerActive = true;
  531. _target_velocity.X += force.X;
  532. _target_velocity.Y += force.Y;
  533. _target_velocity.Z += force.Z;
  534. //m_lastUpdateSent = false;
  535. }
  536. /// <summary>
  537. /// After all of the forces add up with 'add force' we apply them with doForce
  538. /// </summary>
  539. /// <param name="force"></param>
  540. public void doForce(PhysicsVector force)
  541. {
  542. if (!collidelock)
  543. {
  544. d.BodyAddForce(Body, force.X, force.Y, force.Z);
  545. //d.BodySetRotation(Body, ref m_StandUpRotation);
  546. //standupStraight();
  547. }
  548. }
  549. public override void SetMomentum(PhysicsVector momentum)
  550. {
  551. }
  552. /// <summary>
  553. /// Called from Simulate
  554. /// This is the avatar's movement control + PID Controller
  555. /// </summary>
  556. /// <param name="timeStep"></param>
  557. public void Move(float timeStep)
  558. {
  559. // no lock; for now it's only called from within Simulate()
  560. // If the PID Controller isn't active then we set our force
  561. // calculating base velocity to the current position
  562. if (Environment.OSVersion.Platform == PlatformID.Unix)
  563. {
  564. PID_D = 3200.0f;
  565. PID_P = 1400.0f;
  566. }
  567. else
  568. {
  569. PID_D = 2200.0f;
  570. PID_P = 900.0f;
  571. }
  572. if (m_pidControllerActive == false)
  573. {
  574. _zeroPosition = d.BodyGetPosition(Body);
  575. }
  576. //PidStatus = true;
  577. PhysicsVector vec = new PhysicsVector();
  578. d.Vector3 vel = d.BodyGetLinearVel(Body);
  579. float movementdivisor = 1f;
  580. if (!m_alwaysRun)
  581. {
  582. movementdivisor = 1.3f;
  583. }
  584. else
  585. {
  586. movementdivisor = 0.8f;
  587. }
  588. // if velocity is zero, use position control; otherwise, velocity control
  589. if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
  590. {
  591. // keep track of where we stopped. No more slippin' & slidin'
  592. if (!_zeroFlag)
  593. {
  594. _zeroFlag = true;
  595. _zeroPosition = d.BodyGetPosition(Body);
  596. }
  597. if (m_pidControllerActive)
  598. {
  599. // We only want to deactivate the PID Controller if we think we want to have our surrogate
  600. // react to the physics scene by moving it's position.
  601. // Avatar to Avatar collisions
  602. // Prim to avatar collisions
  603. d.Vector3 pos = d.BodyGetPosition(Body);
  604. vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
  605. vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2);
  606. if (flying)
  607. {
  608. vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
  609. }
  610. }
  611. //PidStatus = true;
  612. }
  613. else
  614. {
  615. m_pidControllerActive = true;
  616. _zeroFlag = false;
  617. if (m_iscolliding && !flying)
  618. {
  619. // We're standing on something
  620. vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
  621. vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
  622. }
  623. else if (m_iscolliding && flying)
  624. {
  625. // We're flying and colliding with something
  626. vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16);
  627. vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16);
  628. }
  629. else if (!m_iscolliding && flying)
  630. {
  631. // we're in mid air suspended
  632. vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6);
  633. vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6);
  634. }
  635. if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
  636. {
  637. // We're colliding with something and we're not flying but we're moving
  638. // This means we're walking or running.
  639. d.Vector3 pos = d.BodyGetPosition(Body);
  640. vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
  641. if (_target_velocity.X > 0)
  642. {
  643. vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
  644. }
  645. if (_target_velocity.Y > 0)
  646. {
  647. vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
  648. }
  649. }
  650. else if (!m_iscolliding && !flying)
  651. {
  652. // we're not colliding and we're not flying so that means we're falling!
  653. // m_iscolliding includes collisions with the ground.
  654. d.Vector3 pos = d.BodyGetPosition(Body);
  655. if (_target_velocity.X > 0)
  656. {
  657. vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
  658. }
  659. if (_target_velocity.Y > 0)
  660. {
  661. vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
  662. }
  663. }
  664. if (flying)
  665. {
  666. vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
  667. }
  668. }
  669. if (flying)
  670. {
  671. vec.Z += (9.8f*m_mass);
  672. }
  673. doForce(vec);
  674. }
  675. /// <summary>
  676. /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
  677. /// </summary>
  678. public void UpdatePositionAndVelocity()
  679. {
  680. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  681. d.Vector3 vec = d.BodyGetPosition(Body);
  682. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  683. if (vec.X < 0.0f) vec.X = 0.0f;
  684. if (vec.Y < 0.0f) vec.Y = 0.0f;
  685. if (vec.X > 255.95f) vec.X = 255.95f;
  686. if (vec.Y > 255.95f) vec.Y = 255.95f;
  687. _position.X = vec.X;
  688. _position.Y = vec.Y;
  689. _position.Z = vec.Z;
  690. // Did we move last? = zeroflag
  691. // This helps keep us from sliding all over
  692. if (_zeroFlag)
  693. {
  694. _velocity.X = 0.0f;
  695. _velocity.Y = 0.0f;
  696. _velocity.Z = 0.0f;
  697. // Did we send out the 'stopped' message?
  698. if (!m_lastUpdateSent)
  699. {
  700. m_lastUpdateSent = true;
  701. //base.RequestPhysicsterseUpdate();
  702. }
  703. }
  704. else
  705. {
  706. m_lastUpdateSent = false;
  707. vec = d.BodyGetLinearVel(Body);
  708. _velocity.X = (vec.X);
  709. _velocity.Y = (vec.Y);
  710. _velocity.Z = (vec.Z);
  711. if (_velocity.Z < -6 && !m_hackSentFall)
  712. {
  713. // Collisionupdates will be used in the future, right now the're not being used.
  714. m_hackSentFall = true;
  715. //base.SendCollisionUpdate(new CollisionEventUpdate());
  716. m_pidControllerActive = false;
  717. }
  718. else if (flying && !m_hackSentFly)
  719. {
  720. //m_hackSentFly = true;
  721. //base.SendCollisionUpdate(new CollisionEventUpdate());
  722. }
  723. else
  724. {
  725. m_hackSentFly = false;
  726. m_hackSentFall = false;
  727. }
  728. }
  729. }
  730. /// <summary>
  731. /// Cleanup the things we use in the scene.
  732. /// </summary>
  733. public void Destroy()
  734. {
  735. lock (OdeScene.OdeLock)
  736. {
  737. // Kill the Amotor
  738. d.JointDestroy(Amotor);
  739. //kill the Geometry
  740. _parent_scene.waitForSpaceUnlock(_parent_scene.space);
  741. d.GeomDestroy(Shell);
  742. _parent_scene.geom_name_map.Remove(Shell);
  743. //kill the body
  744. d.BodyDestroy(Body);
  745. }
  746. }
  747. public override void CrossingFailure()
  748. {
  749. }
  750. public override PhysicsVector PIDTarget { set { return; } }
  751. public override bool PIDActive { set { return; } }
  752. public override float PIDTau { set { return; } }
  753. }
  754. }