BulletDotNETCharacter.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  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 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.Reflection;
  29. using BulletDotNET;
  30. using OpenMetaverse;
  31. using OpenSim.Framework;
  32. using OpenSim.Region.Physics.Manager;
  33. using log4net;
  34. namespace OpenSim.Region.Physics.BulletDotNETPlugin
  35. {
  36. public class BulletDotNETCharacter : PhysicsActor
  37. {
  38. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  39. public btRigidBody Body;
  40. public btCollisionShape Shell;
  41. public btVector3 tempVector1;
  42. public btVector3 tempVector2;
  43. public btVector3 tempVector3;
  44. public btVector3 tempVector4;
  45. public btVector3 tempVector5RayCast;
  46. public btVector3 tempVector6RayCast;
  47. public btVector3 tempVector7RayCast;
  48. public btQuaternion tempQuat1;
  49. public btTransform tempTrans1;
  50. public ClosestNotMeRayResultCallback ClosestCastResult;
  51. private btTransform m_bodyTransform;
  52. private btVector3 m_bodyPosition;
  53. private btVector3 m_CapsuleOrientationAxis;
  54. private btQuaternion m_bodyOrientation;
  55. private btDefaultMotionState m_bodyMotionState;
  56. private btGeneric6DofConstraint m_aMotor;
  57. // private Vector3 m_movementComparision;
  58. private Vector3 m_position;
  59. private Vector3 m_zeroPosition;
  60. private bool m_zeroFlag = false;
  61. private bool m_lastUpdateSent = false;
  62. private Vector3 m_velocity;
  63. private Vector3 m_target_velocity;
  64. private Vector3 m_acceleration;
  65. private Vector3 m_rotationalVelocity;
  66. private bool m_pidControllerActive = true;
  67. public float PID_D = 80.0f;
  68. public float PID_P = 90.0f;
  69. public float CAPSULE_RADIUS = 0.37f;
  70. public float CAPSULE_LENGTH = 2.140599f;
  71. public float heightFudgeFactor = 0.52f;
  72. public float walkDivisor = 1.3f;
  73. public float runDivisor = 0.8f;
  74. private float m_mass = 80f;
  75. public float m_density = 60f;
  76. private bool m_flying = false;
  77. private bool m_iscolliding = false;
  78. private bool m_iscollidingGround = false;
  79. private bool m_wascolliding = false;
  80. private bool m_wascollidingGround = false;
  81. private bool m_iscollidingObj = false;
  82. private bool m_alwaysRun = false;
  83. private bool m_hackSentFall = false;
  84. private bool m_hackSentFly = false;
  85. public uint m_localID = 0;
  86. public bool m_returnCollisions = false;
  87. // taints and their non-tainted counterparts
  88. public bool m_isPhysical = false; // the current physical status
  89. public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
  90. private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
  91. private bool m_taintRemove = false;
  92. // private bool m_taintedPosition = false;
  93. // private Vector3 m_taintedPosition_value;
  94. private Vector3 m_taintedForce;
  95. private float m_buoyancy = 0f;
  96. // private CollisionLocker ode;
  97. // private string m_name = String.Empty;
  98. private bool[] m_colliderarr = new bool[11];
  99. private bool[] m_colliderGroundarr = new bool[11];
  100. private BulletDotNETScene m_parent_scene;
  101. public int m_eventsubscription = 0;
  102. private CollisionEventUpdate CollisionEventsThisFrame = null;
  103. private int m_requestedUpdateFrequency = 0;
  104. public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
  105. {
  106. m_position = pos;
  107. m_zeroPosition = pos;
  108. m_parent_scene = parent_scene;
  109. PID_D = pid_d;
  110. PID_P = pid_p;
  111. CAPSULE_RADIUS = capsule_radius;
  112. m_density = density;
  113. heightFudgeFactor = height_fudge_factor;
  114. walkDivisor = walk_divisor;
  115. runDivisor = rundivisor;
  116. for (int i = 0; i < 11; i++)
  117. {
  118. m_colliderarr[i] = false;
  119. }
  120. for (int i = 0; i < 11; i++)
  121. {
  122. m_colliderGroundarr[i] = false;
  123. }
  124. CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
  125. m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
  126. m_isPhysical = false; // current status: no ODE information exists
  127. m_tainted_isPhysical = true; // new tainted status: need to create ODE information
  128. m_parent_scene.AddPhysicsActorTaint(this);
  129. // m_name = avName;
  130. tempVector1 = new btVector3(0, 0, 0);
  131. tempVector2 = new btVector3(0, 0, 0);
  132. tempVector3 = new btVector3(0, 0, 0);
  133. tempVector4 = new btVector3(0, 0, 0);
  134. tempVector5RayCast = new btVector3(0, 0, 0);
  135. tempVector6RayCast = new btVector3(0, 0, 0);
  136. tempVector7RayCast = new btVector3(0, 0, 0);
  137. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  138. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  139. // m_movementComparision = new PhysicsVector(0, 0, 0);
  140. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  141. }
  142. /// <summary>
  143. /// This creates the Avatar's physical Surrogate at the position supplied
  144. /// </summary>
  145. /// <param name="npositionX"></param>
  146. /// <param name="npositionY"></param>
  147. /// <param name="npositionZ"></param>
  148. // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
  149. // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
  150. // place that is safe to call this routine AvatarGeomAndBodyCreation.
  151. private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
  152. {
  153. if (CAPSULE_LENGTH <= 0)
  154. {
  155. m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
  156. CAPSULE_LENGTH = 0.01f;
  157. }
  158. if (CAPSULE_RADIUS <= 0)
  159. {
  160. m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
  161. CAPSULE_RADIUS = 0.01f;
  162. }
  163. Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
  164. if (m_bodyPosition == null)
  165. m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
  166. m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
  167. if (m_bodyOrientation == null)
  168. m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
  169. if (m_bodyTransform == null)
  170. m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
  171. else
  172. {
  173. m_bodyTransform.Dispose();
  174. m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
  175. }
  176. if (m_bodyMotionState == null)
  177. m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
  178. else
  179. m_bodyMotionState.setWorldTransform(m_bodyTransform);
  180. m_mass = Mass;
  181. Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
  182. // this is used for self identification. User localID instead of body handle
  183. Body.setUserPointer(new IntPtr((int)m_localID));
  184. if (ClosestCastResult != null)
  185. ClosestCastResult.Dispose();
  186. ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
  187. m_parent_scene.AddRigidBody(Body);
  188. Body.setActivationState(4);
  189. if (m_aMotor != null)
  190. {
  191. if (m_aMotor.Handle != IntPtr.Zero)
  192. {
  193. m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
  194. m_aMotor.Dispose();
  195. }
  196. m_aMotor = null;
  197. }
  198. m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
  199. m_parent_scene.TransZero,
  200. m_parent_scene.TransZero, false);
  201. m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
  202. m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
  203. }
  204. public void Remove()
  205. {
  206. m_taintRemove = true;
  207. }
  208. public override bool Stopped
  209. {
  210. get { return m_zeroFlag; }
  211. }
  212. public override Vector3 Size
  213. {
  214. get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
  215. set
  216. {
  217. m_pidControllerActive = true;
  218. Vector3 SetSize = value;
  219. m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
  220. //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
  221. Velocity = Vector3.Zero;
  222. m_parent_scene.AddPhysicsActorTaint(this);
  223. }
  224. }
  225. /// <summary>
  226. /// turn the PID controller on or off.
  227. /// The PID Controller will turn on all by itself in many situations
  228. /// </summary>
  229. /// <param name="status"></param>
  230. public void SetPidStatus(bool status)
  231. {
  232. m_pidControllerActive = status;
  233. }
  234. public override PrimitiveBaseShape Shape
  235. {
  236. set { return; }
  237. }
  238. public override uint LocalID
  239. {
  240. set { m_localID = value; }
  241. }
  242. public override bool Grabbed
  243. {
  244. set { return; }
  245. }
  246. public override bool Selected
  247. {
  248. set { return; }
  249. }
  250. public override void CrossingFailure()
  251. {
  252. }
  253. public override void link(PhysicsActor obj)
  254. {
  255. }
  256. public override void delink()
  257. {
  258. }
  259. public override void LockAngularMotion(Vector3 axis)
  260. {
  261. }
  262. public override Vector3 Position
  263. {
  264. get { return m_position; }
  265. set
  266. {
  267. // m_taintedPosition_value = value;
  268. m_position = value;
  269. // m_taintedPosition = true;
  270. }
  271. }
  272. public override float Mass
  273. {
  274. get
  275. {
  276. float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
  277. return m_density * AVvolume;
  278. }
  279. }
  280. public override Vector3 Force
  281. {
  282. get { return m_target_velocity; }
  283. set { return; }
  284. }
  285. public override int VehicleType
  286. {
  287. get { return 0; }
  288. set { return; }
  289. }
  290. public override void VehicleFloatParam(int param, float value)
  291. {
  292. }
  293. public override void VehicleVectorParam(int param, Vector3 value)
  294. {
  295. }
  296. public override void VehicleRotationParam(int param, Quaternion rotation)
  297. {
  298. }
  299. public override void VehicleFlags(int param, bool remove)
  300. {
  301. }
  302. public override void SetVolumeDetect(int param)
  303. {
  304. }
  305. public override Vector3 GeometricCenter
  306. {
  307. get { return Vector3.Zero; }
  308. }
  309. public override Vector3 CenterOfMass
  310. {
  311. get { return Vector3.Zero; }
  312. }
  313. public override Vector3 Velocity
  314. {
  315. get
  316. {
  317. if (m_zeroFlag)
  318. return Vector3.Zero;
  319. m_lastUpdateSent = false;
  320. return m_velocity;
  321. }
  322. set
  323. {
  324. m_pidControllerActive = true;
  325. m_target_velocity = value;
  326. }
  327. }
  328. public override Vector3 Torque
  329. {
  330. get { return Vector3.Zero; }
  331. set { return; }
  332. }
  333. public override float CollisionScore
  334. {
  335. get { return 0f; }
  336. set { }
  337. }
  338. public override Vector3 Acceleration
  339. {
  340. get { return m_acceleration; }
  341. }
  342. public override Quaternion Orientation
  343. {
  344. get { return Quaternion.Identity; }
  345. set
  346. {
  347. }
  348. }
  349. public override int PhysicsActorType
  350. {
  351. get { return (int)ActorTypes.Agent; }
  352. set { return; }
  353. }
  354. public override bool IsPhysical
  355. {
  356. get { return false; }
  357. set { return; }
  358. }
  359. public override bool Flying
  360. {
  361. get { return m_flying; }
  362. set { m_flying = value; }
  363. }
  364. public override bool SetAlwaysRun
  365. {
  366. get { return m_alwaysRun; }
  367. set { m_alwaysRun = value; }
  368. }
  369. public override bool ThrottleUpdates
  370. {
  371. get { return false; }
  372. set { return; }
  373. }
  374. /// <summary>
  375. /// Returns if the avatar is colliding in general.
  376. /// This includes the ground and objects and avatar.
  377. /// </summary>
  378. public override bool IsColliding
  379. {
  380. get { return m_iscolliding; }
  381. set
  382. {
  383. int i;
  384. int truecount = 0;
  385. int falsecount = 0;
  386. if (m_colliderarr.Length >= 10)
  387. {
  388. for (i = 0; i < 10; i++)
  389. {
  390. m_colliderarr[i] = m_colliderarr[i + 1];
  391. }
  392. }
  393. m_colliderarr[10] = value;
  394. for (i = 0; i < 11; i++)
  395. {
  396. if (m_colliderarr[i])
  397. {
  398. truecount++;
  399. }
  400. else
  401. {
  402. falsecount++;
  403. }
  404. }
  405. // Equal truecounts and false counts means we're colliding with something.
  406. m_log.DebugFormat("[PHYSICS]: TrueCount:{0}, FalseCount:{1}",truecount,falsecount);
  407. if (falsecount > 1.2 * truecount)
  408. {
  409. m_iscolliding = false;
  410. }
  411. else
  412. {
  413. m_iscolliding = true;
  414. }
  415. if (m_wascolliding != m_iscolliding)
  416. {
  417. //base.SendCollisionUpdate(new CollisionEventUpdate());
  418. }
  419. m_wascolliding = m_iscolliding;
  420. }
  421. }
  422. /// <summary>
  423. /// Returns if an avatar is colliding with the ground
  424. /// </summary>
  425. public override bool CollidingGround
  426. {
  427. get { return m_iscollidingGround; }
  428. set
  429. {
  430. // Collisions against the ground are not really reliable
  431. // So, to get a consistant value we have to average the current result over time
  432. // Currently we use 1 second = 10 calls to this.
  433. int i;
  434. int truecount = 0;
  435. int falsecount = 0;
  436. if (m_colliderGroundarr.Length >= 10)
  437. {
  438. for (i = 0; i < 10; i++)
  439. {
  440. m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
  441. }
  442. }
  443. m_colliderGroundarr[10] = value;
  444. for (i = 0; i < 11; i++)
  445. {
  446. if (m_colliderGroundarr[i])
  447. {
  448. truecount++;
  449. }
  450. else
  451. {
  452. falsecount++;
  453. }
  454. }
  455. // Equal truecounts and false counts means we're colliding with something.
  456. if (falsecount > 1.2 * truecount)
  457. {
  458. m_iscollidingGround = false;
  459. }
  460. else
  461. {
  462. m_iscollidingGround = true;
  463. }
  464. if (m_wascollidingGround != m_iscollidingGround)
  465. {
  466. //base.SendCollisionUpdate(new CollisionEventUpdate());
  467. }
  468. m_wascollidingGround = m_iscollidingGround;
  469. }
  470. }
  471. /// <summary>
  472. /// Returns if the avatar is colliding with an object
  473. /// </summary>
  474. public override bool CollidingObj
  475. {
  476. get { return m_iscollidingObj; }
  477. set
  478. {
  479. m_iscollidingObj = value;
  480. if (value)
  481. m_pidControllerActive = false;
  482. else
  483. m_pidControllerActive = true;
  484. }
  485. }
  486. public override bool FloatOnWater
  487. {
  488. set { return; }
  489. }
  490. public override Vector3 RotationalVelocity
  491. {
  492. get { return m_rotationalVelocity; }
  493. set { m_rotationalVelocity = value; }
  494. }
  495. public override bool Kinematic
  496. {
  497. get { return false; }
  498. set { }
  499. }
  500. public override float Buoyancy
  501. {
  502. get { return m_buoyancy; }
  503. set { m_buoyancy = value; }
  504. }
  505. public override Vector3 PIDTarget { set { return; } }
  506. public override bool PIDActive { set { return; } }
  507. public override float PIDTau { set { return; } }
  508. public override bool PIDHoverActive
  509. {
  510. set { return; }
  511. }
  512. public override float PIDHoverHeight
  513. {
  514. set { return; }
  515. }
  516. public override PIDHoverType PIDHoverType
  517. {
  518. set { return; }
  519. }
  520. public override float PIDHoverTau
  521. {
  522. set { return; }
  523. }
  524. public override Quaternion APIDTarget
  525. {
  526. set { return; }
  527. }
  528. public override bool APIDActive
  529. {
  530. set { return; }
  531. }
  532. public override float APIDStrength
  533. {
  534. set { return; }
  535. }
  536. public override float APIDDamping
  537. {
  538. set { return; }
  539. }
  540. /// <summary>
  541. /// Adds the force supplied to the Target Velocity
  542. /// The PID controller takes this target velocity and tries to make it a reality
  543. /// </summary>
  544. /// <param name="force"></param>
  545. /// <param name="pushforce">Is this a push by a script?</param>
  546. public override void AddForce(Vector3 force, bool pushforce)
  547. {
  548. if (pushforce)
  549. {
  550. m_pidControllerActive = false;
  551. force *= 100f;
  552. doForce(force, false);
  553. //System.Console.WriteLine("Push!");
  554. //_target_velocity.X += force.X;
  555. // _target_velocity.Y += force.Y;
  556. //_target_velocity.Z += force.Z;
  557. }
  558. else
  559. {
  560. m_pidControllerActive = true;
  561. m_target_velocity.X += force.X;
  562. m_target_velocity.Y += force.Y;
  563. m_target_velocity.Z += force.Z;
  564. }
  565. //m_lastUpdateSent = false;
  566. }
  567. public void doForce(Vector3 force, bool now)
  568. {
  569. tempVector3.setValue(force.X, force.Y, force.Z);
  570. if (now)
  571. {
  572. Body.applyCentralForce(tempVector3);
  573. }
  574. else
  575. {
  576. m_taintedForce += force;
  577. m_parent_scene.AddPhysicsActorTaint(this);
  578. }
  579. }
  580. public void doImpulse(Vector3 force, bool now)
  581. {
  582. tempVector3.setValue(force.X, force.Y, force.Z);
  583. if (now)
  584. {
  585. Body.applyCentralImpulse(tempVector3);
  586. }
  587. else
  588. {
  589. m_taintedForce += force;
  590. m_parent_scene.AddPhysicsActorTaint(this);
  591. }
  592. }
  593. public override void AddAngularForce(Vector3 force, bool pushforce)
  594. {
  595. }
  596. public override void SetMomentum(Vector3 momentum)
  597. {
  598. }
  599. public override void SubscribeEvents(int ms)
  600. {
  601. m_eventsubscription = ms;
  602. m_requestedUpdateFrequency = ms;
  603. m_parent_scene.addCollisionEventReporting(this);
  604. }
  605. public override void UnSubscribeEvents()
  606. {
  607. m_parent_scene.remCollisionEventReporting(this);
  608. m_eventsubscription = 0;
  609. m_requestedUpdateFrequency = 0;
  610. }
  611. public override bool SubscribedEvents()
  612. {
  613. if (m_eventsubscription > 0)
  614. return true;
  615. return false;
  616. }
  617. public void AddCollision(uint collideWith, ContactPoint contact)
  618. {
  619. if (CollisionEventsThisFrame == null)
  620. {
  621. CollisionEventsThisFrame = new CollisionEventUpdate();
  622. }
  623. CollisionEventsThisFrame.addCollider(collideWith, contact);
  624. }
  625. public void SendCollisions()
  626. {
  627. if (m_eventsubscription >= m_requestedUpdateFrequency)
  628. {
  629. if (CollisionEventsThisFrame != null)
  630. {
  631. base.SendCollisionUpdate(CollisionEventsThisFrame);
  632. }
  633. CollisionEventsThisFrame = new CollisionEventUpdate();
  634. m_eventsubscription = 0;
  635. }
  636. return;
  637. }
  638. internal void Dispose()
  639. {
  640. if (Body.isInWorld())
  641. m_parent_scene.removeFromWorld(Body);
  642. if (m_aMotor.Handle != IntPtr.Zero)
  643. m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
  644. m_aMotor.Dispose(); m_aMotor = null;
  645. ClosestCastResult.Dispose(); ClosestCastResult = null;
  646. Body.Dispose(); Body = null;
  647. Shell.Dispose(); Shell = null;
  648. tempQuat1.Dispose();
  649. tempTrans1.Dispose();
  650. tempVector1.Dispose();
  651. tempVector2.Dispose();
  652. tempVector3.Dispose();
  653. tempVector4.Dispose();
  654. tempVector5RayCast.Dispose();
  655. tempVector6RayCast.Dispose();
  656. }
  657. public void ProcessTaints(float timestep)
  658. {
  659. if (m_tainted_isPhysical != m_isPhysical)
  660. {
  661. if (m_tainted_isPhysical)
  662. {
  663. // Create avatar capsule and related ODE data
  664. if (!(Shell == null && Body == null))
  665. {
  666. m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
  667. + (Shell != null ? "Shell " : "")
  668. + (Body != null ? "Body " : ""));
  669. }
  670. AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
  671. }
  672. else
  673. {
  674. // destroy avatar capsule and related ODE data
  675. Dispose();
  676. tempVector1 = new btVector3(0, 0, 0);
  677. tempVector2 = new btVector3(0, 0, 0);
  678. tempVector3 = new btVector3(0, 0, 0);
  679. tempVector4 = new btVector3(0, 0, 0);
  680. tempVector5RayCast = new btVector3(0, 0, 0);
  681. tempVector6RayCast = new btVector3(0, 0, 0);
  682. tempVector7RayCast = new btVector3(0, 0, 0);
  683. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  684. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  685. // m_movementComparision = new PhysicsVector(0, 0, 0);
  686. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  687. }
  688. m_isPhysical = m_tainted_isPhysical;
  689. }
  690. if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
  691. {
  692. if (Body != null)
  693. {
  694. m_pidControllerActive = true;
  695. // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
  696. //d.JointDestroy(Amotor);
  697. float prevCapsule = CAPSULE_LENGTH;
  698. CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
  699. //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
  700. Dispose();
  701. tempVector1 = new btVector3(0, 0, 0);
  702. tempVector2 = new btVector3(0, 0, 0);
  703. tempVector3 = new btVector3(0, 0, 0);
  704. tempVector4 = new btVector3(0, 0, 0);
  705. tempVector5RayCast = new btVector3(0, 0, 0);
  706. tempVector6RayCast = new btVector3(0, 0, 0);
  707. tempVector7RayCast = new btVector3(0, 0, 0);
  708. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  709. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  710. // m_movementComparision = new PhysicsVector(0, 0, 0);
  711. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  712. AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
  713. m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
  714. Velocity = Vector3.Zero;
  715. }
  716. else
  717. {
  718. m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
  719. + (Shell == null ? "Shell " : "")
  720. + (Body == null ? "Body " : ""));
  721. }
  722. }
  723. if (m_taintRemove)
  724. {
  725. Dispose();
  726. }
  727. }
  728. /// <summary>
  729. /// Called from Simulate
  730. /// This is the avatar's movement control + PID Controller
  731. /// </summary>
  732. /// <param name="timeStep"></param>
  733. public void Move(float timeStep)
  734. {
  735. // no lock; for now it's only called from within Simulate()
  736. // If the PID Controller isn't active then we set our force
  737. // calculating base velocity to the current position
  738. if (Body == null)
  739. return;
  740. tempTrans1.Dispose();
  741. tempTrans1 = Body.getInterpolationWorldTransform();
  742. tempVector1.Dispose();
  743. tempVector1 = tempTrans1.getOrigin();
  744. tempVector2.Dispose();
  745. tempVector2 = Body.getInterpolationLinearVelocity();
  746. if (m_pidControllerActive == false)
  747. {
  748. m_zeroPosition.X = tempVector1.getX();
  749. m_zeroPosition.Y = tempVector1.getY();
  750. m_zeroPosition.Z = tempVector1.getZ();
  751. }
  752. //PidStatus = true;
  753. Vector3 vec = Vector3.Zero;
  754. Vector3 vel = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
  755. float movementdivisor = 1f;
  756. if (!m_alwaysRun)
  757. {
  758. movementdivisor = walkDivisor;
  759. }
  760. else
  761. {
  762. movementdivisor = runDivisor;
  763. }
  764. // if velocity is zero, use position control; otherwise, velocity control
  765. if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
  766. {
  767. // keep track of where we stopped. No more slippin' & slidin'
  768. if (!m_zeroFlag)
  769. {
  770. m_zeroFlag = true;
  771. m_zeroPosition.X = tempVector1.getX();
  772. m_zeroPosition.Y = tempVector1.getY();
  773. m_zeroPosition.Z = tempVector1.getZ();
  774. }
  775. if (m_pidControllerActive)
  776. {
  777. // We only want to deactivate the PID Controller if we think we want to have our surrogate
  778. // react to the physics scene by moving it's position.
  779. // Avatar to Avatar collisions
  780. // Prim to avatar collisions
  781. Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
  782. vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
  783. vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
  784. if (m_flying)
  785. {
  786. vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
  787. }
  788. }
  789. //PidStatus = true;
  790. }
  791. else
  792. {
  793. m_pidControllerActive = true;
  794. m_zeroFlag = false;
  795. if (m_iscolliding && !m_flying)
  796. {
  797. // We're standing on something
  798. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
  799. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
  800. }
  801. else if (m_iscolliding && m_flying)
  802. {
  803. // We're flying and colliding with something
  804. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
  805. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
  806. }
  807. else if (!m_iscolliding && m_flying)
  808. {
  809. // we're in mid air suspended
  810. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
  811. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
  812. // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
  813. // rebound preventing
  814. if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
  815. m_zeroFlag = true;
  816. }
  817. if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
  818. {
  819. // We're colliding with something and we're not flying but we're moving
  820. // This means we're walking or running.
  821. Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
  822. vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
  823. if (m_target_velocity.X > 0)
  824. {
  825. vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
  826. }
  827. if (m_target_velocity.Y > 0)
  828. {
  829. vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
  830. }
  831. }
  832. else if (!m_iscolliding && !m_flying)
  833. {
  834. // we're not colliding and we're not flying so that means we're falling!
  835. // m_iscolliding includes collisions with the ground.
  836. // d.Vector3 pos = d.BodyGetPosition(Body);
  837. if (m_target_velocity.X > 0)
  838. {
  839. vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
  840. }
  841. if (m_target_velocity.Y > 0)
  842. {
  843. vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
  844. }
  845. }
  846. if (m_flying)
  847. {
  848. vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
  849. }
  850. }
  851. if (m_flying)
  852. {
  853. // Slight PID correction
  854. vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
  855. //auto fly height. Kitto Flora
  856. //d.Vector3 pos = d.BodyGetPosition(Body);
  857. float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
  858. if (m_position.Z < target_altitude)
  859. {
  860. vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
  861. }
  862. }
  863. if (Body != null && (((m_target_velocity.X > 0.2f || m_target_velocity.X < -0.2f) || (m_target_velocity.Y > 0.2f || m_target_velocity.Y < -0.2f))))
  864. {
  865. Body.setFriction(0.001f);
  866. //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
  867. }
  868. if (Body != null)
  869. {
  870. int activationstate = Body.getActivationState();
  871. if (activationstate == 0)
  872. {
  873. Body.forceActivationState(1);
  874. }
  875. }
  876. doImpulse(vec, true);
  877. }
  878. /// <summary>
  879. /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
  880. /// </summary>
  881. public void UpdatePositionAndVelocity()
  882. {
  883. if (Body == null)
  884. return;
  885. //int val = Environment.TickCount;
  886. CheckIfStandingOnObject();
  887. //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
  888. //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
  889. tempTrans1.Dispose();
  890. tempTrans1 = Body.getInterpolationWorldTransform();
  891. tempVector1.Dispose();
  892. tempVector1 = tempTrans1.getOrigin();
  893. tempVector2.Dispose();
  894. tempVector2 = Body.getInterpolationLinearVelocity();
  895. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  896. Vector3 vec = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
  897. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  898. if (vec.X < -10.0f) vec.X = 0.0f;
  899. if (vec.Y < -10.0f) vec.Y = 0.0f;
  900. if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
  901. if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
  902. m_position.X = vec.X;
  903. m_position.Y = vec.Y;
  904. m_position.Z = vec.Z;
  905. // Did we move last? = zeroflag
  906. // This helps keep us from sliding all over
  907. if (m_zeroFlag)
  908. {
  909. m_velocity.X = 0.0f;
  910. m_velocity.Y = 0.0f;
  911. m_velocity.Z = 0.0f;
  912. // Did we send out the 'stopped' message?
  913. if (!m_lastUpdateSent)
  914. {
  915. m_lastUpdateSent = true;
  916. //base.RequestPhysicsterseUpdate();
  917. }
  918. }
  919. else
  920. {
  921. m_lastUpdateSent = false;
  922. vec = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
  923. m_velocity.X = (vec.X);
  924. m_velocity.Y = (vec.Y);
  925. m_velocity.Z = (vec.Z);
  926. //m_log.Debug(m_target_velocity);
  927. if (m_velocity.Z < -6 && !m_hackSentFall)
  928. {
  929. m_hackSentFall = true;
  930. m_pidControllerActive = false;
  931. }
  932. else if (m_flying && !m_hackSentFly)
  933. {
  934. //m_hackSentFly = true;
  935. //base.SendCollisionUpdate(new CollisionEventUpdate());
  936. }
  937. else
  938. {
  939. m_hackSentFly = false;
  940. m_hackSentFall = false;
  941. }
  942. }
  943. if (Body != null)
  944. {
  945. if (Body.getFriction() < 0.9f)
  946. Body.setFriction(0.9f);
  947. }
  948. //if (Body != null)
  949. // Body.clearForces();
  950. }
  951. public void CheckIfStandingOnObject()
  952. {
  953. float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
  954. tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
  955. tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
  956. ClosestCastResult.Dispose();
  957. ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
  958. try
  959. {
  960. m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
  961. }
  962. catch (AccessViolationException)
  963. {
  964. m_log.Debug("BAD!");
  965. }
  966. if (ClosestCastResult.hasHit())
  967. {
  968. if (tempVector7RayCast != null)
  969. tempVector7RayCast.Dispose();
  970. //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
  971. /*if (tempVector7RayCast == null) // null == no result also
  972. {
  973. CollidingObj = false;
  974. IsColliding = false;
  975. CollidingGround = false;
  976. return;
  977. }
  978. float zVal = tempVector7RayCast.getZ();
  979. if (zVal != 0)
  980. m_log.Debug("[PHYSICS]: HAAAA");
  981. if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
  982. {
  983. CollidingObj = true;
  984. IsColliding = true;
  985. }
  986. else
  987. {
  988. CollidingObj = false;
  989. IsColliding = false;
  990. CollidingGround = false;
  991. }*/
  992. //height+2*radius = capsule full length
  993. //CollidingObj = true;
  994. //IsColliding = true;
  995. m_iscolliding = true;
  996. }
  997. else
  998. {
  999. //CollidingObj = false;
  1000. //IsColliding = false;
  1001. //CollidingGround = false;
  1002. m_iscolliding = false;
  1003. }
  1004. }
  1005. }
  1006. }