1
0

ODECharacter.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  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. */
  28. using System;
  29. using Axiom.Math;
  30. using Ode.NET;
  31. using OpenSim.Framework;
  32. using OpenSim.Region.Physics.Manager;
  33. using System.Runtime.InteropServices; // rex
  34. namespace OpenSim.Region.Physics.OdePlugin
  35. {
  36. public class OdeCharacter : PhysicsActor
  37. {
  38. private PhysicsVector _position;
  39. private d.Vector3 _zeroPosition;
  40. private d.Matrix3 m_StandUpRotation;
  41. private bool _zeroFlag = false;
  42. private bool m_lastUpdateSent = false;
  43. private PhysicsVector _velocity;
  44. private PhysicsVector _target_velocity;
  45. private PhysicsVector _acceleration;
  46. private PhysicsVector m_rotationalVelocity;
  47. private float m_density = 50f;
  48. private bool m_pidControllerActive = true;
  49. private static float PID_D = 3020.0f;
  50. private static float PID_P = 7000.0f;
  51. private static float POSTURE_SERVO = 10000.0f;
  52. public static float CAPSULE_RADIUS = 0.5f;
  53. public float CAPSULE_LENGTH = 0.79f;
  54. private bool flying = false;
  55. private bool m_iscolliding = false;
  56. private bool m_iscollidingGround = false;
  57. private bool m_wascolliding = false;
  58. private bool m_wascollidingGround = false;
  59. private bool m_iscollidingObj = false;
  60. private bool m_wascollidingObj = false;
  61. private bool m_alwaysRun = false;
  62. private bool m_hackSentFall = false;
  63. private bool m_hackSentFly = false;
  64. private string m_name = "";
  65. private bool[] m_colliderarr = new bool[11];
  66. private bool[] m_colliderGroundarr = new bool[11];
  67. private bool jumping = false;
  68. //private float gravityAccel;
  69. public IntPtr Body;
  70. private GCHandle gchBody; // rex
  71. private OdeScene _parent_scene;
  72. public IntPtr Shell;
  73. private GCHandle gchShell; // rex
  74. public IntPtr Amotor;
  75. public d.Mass ShellMass;
  76. public bool collidelock = false;
  77. public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, uint localID) // rex, localID added
  78. {
  79. m_localID = localID; // rex
  80. _velocity = new PhysicsVector();
  81. _target_velocity = new PhysicsVector();
  82. _position = pos;
  83. _acceleration = new PhysicsVector();
  84. _parent_scene = parent_scene;
  85. m_StandUpRotation =
  86. new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f,
  87. -0.004689182f, 0.9998941f);
  88. for (int i = 0; i < 11; i++)
  89. {
  90. m_colliderarr[i] = false;
  91. }
  92. lock (OdeScene.OdeLock)
  93. {
  94. int dAMotorEuler = 1;
  95. Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
  96. gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex
  97. d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
  98. Body = d.BodyCreate(parent_scene.world);
  99. gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex
  100. d.BodySetMass(Body, ref ShellMass);
  101. d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
  102. d.GeomSetBody(Shell, Body);
  103. d.BodySetRotation(Body, ref m_StandUpRotation);
  104. //Amotor = d.JointCreateAMotor(parent_scene.world, IntPtr.Zero);
  105. //d.JointAttach(Amotor, Body, IntPtr.Zero);
  106. //d.JointSetAMotorMode(Amotor, dAMotorEuler);
  107. //d.JointSetAMotorNumAxes(Amotor, 3);
  108. //d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
  109. //d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
  110. ///d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
  111. //d.JointSetAMotorAngle(Amotor, 0, 0);
  112. //d.JointSetAMotorAngle(Amotor, 1, 0);
  113. //d.JointSetAMotorAngle(Amotor, 2, 0);
  114. //d.JointSetAMotorParam(Amotor, 0, -0);
  115. //d.JointSetAMotorParam(Amotor, 0x200, -0);
  116. //d.JointSetAMotorParam(Amotor, 0x100, -0);
  117. // d.JointSetAMotorParam(Amotor, 0, 0);
  118. // d.JointSetAMotorParam(Amotor, 3, 0);
  119. // d.JointSetAMotorParam(Amotor, 2, 0);
  120. }
  121. m_name = avName;
  122. parent_scene.geom_name_map[Shell] = avName;
  123. parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
  124. }
  125. public override int PhysicsActorType
  126. {
  127. get { return (int) ActorTypes.Agent; }
  128. set { return; }
  129. }
  130. public override bool SetAlwaysRun
  131. {
  132. get { return m_alwaysRun; }
  133. set { m_alwaysRun = value; }
  134. }
  135. public override bool IsPhysical
  136. {
  137. get { return false; }
  138. set { return; }
  139. }
  140. public override bool ThrottleUpdates
  141. {
  142. get { return false; }
  143. set { return; }
  144. }
  145. public override bool Flying
  146. {
  147. get { return flying; }
  148. set { flying = value; }
  149. }
  150. public override bool IsColliding
  151. {
  152. get { return m_iscolliding; }
  153. set
  154. {
  155. int i;
  156. int truecount = 0;
  157. int falsecount = 0;
  158. if (m_colliderarr.Length >= 10)
  159. {
  160. for (i = 0; i < 10; i++)
  161. {
  162. m_colliderarr[i] = m_colliderarr[i + 1];
  163. }
  164. }
  165. m_colliderarr[10] = value;
  166. for (i = 0; i < 11; i++)
  167. {
  168. if (m_colliderarr[i])
  169. {
  170. truecount++;
  171. }
  172. else
  173. {
  174. falsecount++;
  175. }
  176. }
  177. // Equal truecounts and false counts means we're colliding with something.
  178. if (falsecount > 1.2*truecount)
  179. {
  180. m_iscolliding = false;
  181. }
  182. else
  183. {
  184. m_iscolliding = true;
  185. }
  186. if (m_wascolliding != m_iscolliding)
  187. {
  188. //base.SendCollisionUpdate(new CollisionEventUpdate());
  189. }
  190. m_wascolliding = m_iscolliding;
  191. }
  192. }
  193. public override bool CollidingGround
  194. {
  195. get { return m_iscollidingGround; }
  196. set
  197. {
  198. int i;
  199. int truecount = 0;
  200. int falsecount = 0;
  201. if (m_colliderGroundarr.Length >= 10)
  202. {
  203. for (i = 0; i < 10; i++)
  204. {
  205. m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
  206. }
  207. }
  208. m_colliderGroundarr[10] = value;
  209. for (i = 0; i < 11; i++)
  210. {
  211. if (m_colliderGroundarr[i])
  212. {
  213. truecount++;
  214. }
  215. else
  216. {
  217. falsecount++;
  218. }
  219. }
  220. // Equal truecounts and false counts means we're colliding with something.
  221. if (falsecount > 1.2*truecount)
  222. {
  223. m_iscollidingGround = false;
  224. }
  225. else
  226. {
  227. m_iscollidingGround = true;
  228. }
  229. if (m_wascollidingGround != m_iscollidingGround)
  230. {
  231. //base.SendCollisionUpdate(new CollisionEventUpdate());
  232. }
  233. m_wascollidingGround = m_iscollidingGround;
  234. }
  235. }
  236. public override bool CollidingObj
  237. {
  238. get { return m_iscollidingObj; }
  239. set
  240. {
  241. m_iscollidingObj = value;
  242. if (value)
  243. m_pidControllerActive = false;
  244. else
  245. m_pidControllerActive = true;
  246. }
  247. }
  248. public void SetPidStatus(bool status)
  249. {
  250. m_pidControllerActive = status;
  251. }
  252. public override PhysicsVector Position
  253. {
  254. get { return _position; }
  255. set
  256. {
  257. lock (OdeScene.OdeLock)
  258. {
  259. d.BodySetPosition(Body, value.X, value.Y, value.Z);
  260. _position = value;
  261. }
  262. }
  263. }
  264. public override PhysicsVector RotationalVelocity
  265. {
  266. get { return m_rotationalVelocity; }
  267. set { m_rotationalVelocity = value; }
  268. }
  269. public override PhysicsVector Size
  270. {
  271. get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); }
  272. set
  273. {
  274. m_pidControllerActive = true;
  275. lock (OdeScene.OdeLock)
  276. {
  277. PhysicsVector SetSize = value;
  278. float prevCapsule = CAPSULE_LENGTH;
  279. float capsuleradius = CAPSULE_RADIUS;
  280. capsuleradius = 0.2f;
  281. CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.43f))); // subtract 43% of the size
  282. d.BodyDestroy(Body);
  283. gchBody.Free(); // rex
  284. d.GeomDestroy(Shell);
  285. gchShell.Free(); // rex
  286. //MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH));
  287. Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH);
  288. gchShell = GCHandle.Alloc(Shell, GCHandleType.Pinned); // rex
  289. d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
  290. Body = d.BodyCreate(_parent_scene.world);
  291. gchBody = GCHandle.Alloc(Body, GCHandleType.Pinned); // rex
  292. d.BodySetMass(Body, ref ShellMass);
  293. d.BodySetPosition(Body, _position.X, _position.Y,
  294. _position.Z + Math.Abs(CAPSULE_LENGTH - prevCapsule));
  295. d.GeomSetBody(Shell, Body);
  296. }
  297. _parent_scene.geom_name_map[Shell] = m_name;
  298. _parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
  299. }
  300. }
  301. public override float Mass
  302. {
  303. get
  304. {
  305. float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH);
  306. return m_density*AVvolume;
  307. }
  308. }
  309. public override PhysicsVector Force
  310. {
  311. get { return new PhysicsVector(_target_velocity.X, _target_velocity.Y, _target_velocity.Z); }
  312. }
  313. public override PhysicsVector CenterOfMass
  314. {
  315. get { return PhysicsVector.Zero; }
  316. }
  317. public override PhysicsVector GeometricCenter
  318. {
  319. get { return PhysicsVector.Zero; }
  320. }
  321. public override PrimitiveBaseShape Shape
  322. {
  323. set { return; }
  324. }
  325. public override PhysicsVector Velocity
  326. {
  327. get { return _velocity; }
  328. set
  329. {
  330. m_pidControllerActive = true;
  331. _target_velocity = value;
  332. }
  333. }
  334. public override bool Kinematic
  335. {
  336. get { return false; }
  337. set { }
  338. }
  339. public override Quaternion Orientation
  340. {
  341. get { return Quaternion.Identity; }
  342. set { }
  343. }
  344. public override PhysicsVector Acceleration
  345. {
  346. get { return _acceleration; }
  347. }
  348. public void SetAcceleration(PhysicsVector accel)
  349. {
  350. m_pidControllerActive = true;
  351. _acceleration = accel;
  352. }
  353. public override void AddForce(PhysicsVector force)
  354. {
  355. m_pidControllerActive = true;
  356. _target_velocity.X += force.X;
  357. _target_velocity.Y += force.Y;
  358. _target_velocity.Z += force.Z;
  359. //m_lastUpdateSent = false;
  360. }
  361. public void doForce(PhysicsVector force)
  362. {
  363. if (!collidelock)
  364. {
  365. d.BodyAddForce(Body, force.X, force.Y, force.Z);
  366. // ok -- let's stand up straight!
  367. //d.Matrix3 StandUpRotationalMatrix = new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f, -0.004689182f, 0.9998941f);
  368. //d.BodySetRotation(Body, ref StandUpRotationalMatrix);
  369. //d.BodySetRotation(Body, ref m_StandUpRotation);
  370. // The above matrix was generated with the amazing standup routine below by danX0r *cheer*
  371. d.Vector3 feet;
  372. d.Vector3 head;
  373. d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
  374. d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
  375. float posture = head.Z - feet.Z;
  376. // restoring force proportional to lack of posture:
  377. float servo = (2.5f - posture) * POSTURE_SERVO;
  378. d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
  379. d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
  380. //m_lastUpdateSent = false;
  381. }
  382. }
  383. public override void SetMomentum(PhysicsVector momentum)
  384. {
  385. }
  386. public void Move(float timeStep)
  387. {
  388. // no lock; for now it's only called from within Simulate()
  389. if (m_pidControllerActive == false)
  390. {
  391. _zeroPosition = d.BodyGetPosition(Body);
  392. }
  393. //PidStatus = true;
  394. PhysicsVector vec = new PhysicsVector();
  395. d.Vector3 vel = d.BodyGetLinearVel(Body);
  396. float movementdivisor = 1f;
  397. if (!m_alwaysRun)
  398. {
  399. movementdivisor = 1.3f;
  400. }
  401. else
  402. {
  403. movementdivisor = 0.8f;
  404. }
  405. // if velocity is zero, use position control; otherwise, velocity control
  406. if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding)
  407. {
  408. // keep track of where we stopped. No more slippin' & slidin'
  409. if (!_zeroFlag)
  410. {
  411. _zeroFlag = true;
  412. _zeroPosition = d.BodyGetPosition(Body);
  413. }
  414. if (m_pidControllerActive)
  415. {
  416. d.Vector3 pos = d.BodyGetPosition(Body);
  417. vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P;
  418. vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P;
  419. if (flying)
  420. {
  421. vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100) + (_zeroPosition.Z - pos.Z)*PID_P;
  422. }
  423. }
  424. //PidStatus = true;
  425. }
  426. else
  427. {
  428. m_pidControllerActive = true;
  429. _zeroFlag = false;
  430. if (m_iscolliding || flying)
  431. {
  432. vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*PID_D;
  433. vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*PID_D;
  434. }
  435. if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
  436. {
  437. d.Vector3 pos = d.BodyGetPosition(Body);
  438. vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
  439. if (_target_velocity.X > 0)
  440. {
  441. vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
  442. }
  443. if (_target_velocity.Y > 0)
  444. {
  445. vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
  446. }
  447. }
  448. else if (!m_iscolliding && !flying)
  449. {
  450. d.Vector3 pos = d.BodyGetPosition(Body);
  451. if (_target_velocity.X > 0)
  452. {
  453. vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D;
  454. }
  455. if (_target_velocity.Y > 0)
  456. {
  457. vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D;
  458. }
  459. }
  460. if (flying)
  461. {
  462. vec.Z = (_target_velocity.Z - vel.Z)*(PID_D + 5100);
  463. }
  464. }
  465. if (flying)
  466. {
  467. vec.Z += 10.0f;
  468. }
  469. doForce(vec);
  470. }
  471. public void UpdatePositionAndVelocity()
  472. {
  473. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  474. d.Vector3 vec = d.BodyGetPosition(Body);
  475. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  476. if (vec.X < 0.0f) vec.X = 0.0f;
  477. if (vec.Y < 0.0f) vec.Y = 0.0f;
  478. if (vec.X > 255.95f) vec.X = 255.95f;
  479. if (vec.Y > 255.95f) vec.Y = 255.95f;
  480. _position.X = vec.X;
  481. _position.Y = vec.Y;
  482. _position.Z = vec.Z;
  483. if (_zeroFlag)
  484. {
  485. _velocity.X = 0.0f;
  486. _velocity.Y = 0.0f;
  487. _velocity.Z = 0.0f;
  488. if (!m_lastUpdateSent)
  489. {
  490. m_lastUpdateSent = true;
  491. base.RequestPhysicsterseUpdate();
  492. //string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
  493. //int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  494. //if (primScenAvatarIn == "0")
  495. //{
  496. //MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
  497. //}
  498. //else
  499. //{
  500. // MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
  501. //}
  502. }
  503. }
  504. else
  505. {
  506. m_lastUpdateSent = false;
  507. vec = d.BodyGetLinearVel(Body);
  508. _velocity.X = (vec.X);
  509. _velocity.Y = (vec.Y);
  510. _velocity.Z = (vec.Z);
  511. if (_velocity.Z < -6 && !m_hackSentFall)
  512. {
  513. m_hackSentFall = true;
  514. //base.SendCollisionUpdate(new CollisionEventUpdate());
  515. m_pidControllerActive = false;
  516. }
  517. else if (flying && !m_hackSentFly)
  518. {
  519. //m_hackSentFly = true;
  520. //base.SendCollisionUpdate(new CollisionEventUpdate());
  521. }
  522. else
  523. {
  524. m_hackSentFly = false;
  525. m_hackSentFall = false;
  526. }
  527. }
  528. }
  529. public void Destroy()
  530. {
  531. lock (OdeScene.OdeLock)
  532. {
  533. // d.JointDestroy(Amotor);
  534. d.GeomDestroy(Shell);
  535. _parent_scene.geom_name_map.Remove(Shell);
  536. d.BodyDestroy(Body);
  537. }
  538. }
  539. }
  540. }