ODECharacter.cs 31 KB

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