BulletDotNETCharacter.cs 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  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 PhysicsVector m_movementComparision;
  58. private PhysicsVector m_position;
  59. private PhysicsVector m_zeroPosition;
  60. private bool m_zeroFlag = false;
  61. private bool m_lastUpdateSent = false;
  62. private PhysicsVector m_velocity;
  63. private PhysicsVector m_target_velocity;
  64. private PhysicsVector m_acceleration;
  65. private PhysicsVector 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 PhysicsVector m_taintedPosition_value;
  94. private PhysicsVector 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 = new CollisionEventUpdate();
  103. public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, PhysicsVector pos, PhysicsVector size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
  104. {
  105. m_taintedForce = new PhysicsVector();
  106. m_velocity = new PhysicsVector();
  107. m_target_velocity = new PhysicsVector();
  108. m_position = pos;
  109. m_zeroPosition = new PhysicsVector(pos.X, pos.Y, pos.Z); // this is a class, not a struct. Must make new, or m_zeroPosition will == position regardless
  110. m_acceleration = new PhysicsVector();
  111. m_parent_scene = parent_scene;
  112. PID_D = pid_d;
  113. PID_P = pid_p;
  114. CAPSULE_RADIUS = capsule_radius;
  115. m_density = density;
  116. heightFudgeFactor = height_fudge_factor;
  117. walkDivisor = walk_divisor;
  118. runDivisor = rundivisor;
  119. for (int i = 0; i < 11; i++)
  120. {
  121. m_colliderarr[i] = false;
  122. }
  123. for (int i = 0; i < 11; i++)
  124. {
  125. m_colliderGroundarr[i] = false;
  126. }
  127. CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
  128. m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
  129. m_isPhysical = false; // current status: no ODE information exists
  130. m_tainted_isPhysical = true; // new tainted status: need to create ODE information
  131. m_parent_scene.AddPhysicsActorTaint(this);
  132. // m_name = avName;
  133. tempVector1 = new btVector3(0, 0, 0);
  134. tempVector2 = new btVector3(0, 0, 0);
  135. tempVector3 = new btVector3(0, 0, 0);
  136. tempVector4 = new btVector3(0, 0, 0);
  137. tempVector5RayCast = new btVector3(0, 0, 0);
  138. tempVector6RayCast = new btVector3(0, 0, 0);
  139. tempVector7RayCast = new btVector3(0, 0, 0);
  140. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  141. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  142. // m_movementComparision = new PhysicsVector(0, 0, 0);
  143. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  144. }
  145. /// <summary>
  146. /// This creates the Avatar's physical Surrogate at the position supplied
  147. /// </summary>
  148. /// <param name="npositionX"></param>
  149. /// <param name="npositionY"></param>
  150. /// <param name="npositionZ"></param>
  151. // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
  152. // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
  153. // place that is safe to call this routine AvatarGeomAndBodyCreation.
  154. private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
  155. {
  156. if (CAPSULE_LENGTH <= 0)
  157. {
  158. m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
  159. CAPSULE_LENGTH = 0.01f;
  160. }
  161. if (CAPSULE_RADIUS <= 0)
  162. {
  163. m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
  164. CAPSULE_RADIUS = 0.01f;
  165. }
  166. Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
  167. if (m_bodyPosition == null)
  168. m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
  169. m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
  170. if (m_bodyOrientation == null)
  171. m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
  172. if (m_bodyTransform == null)
  173. m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
  174. else
  175. {
  176. m_bodyTransform.Dispose();
  177. m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
  178. }
  179. if (m_bodyMotionState == null)
  180. m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
  181. else
  182. m_bodyMotionState.setWorldTransform(m_bodyTransform);
  183. m_mass = Mass;
  184. Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
  185. Body.setUserPointer(new IntPtr((int)Body.Handle));
  186. if (ClosestCastResult != null)
  187. ClosestCastResult.Dispose();
  188. ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
  189. m_parent_scene.AddRigidBody(Body);
  190. Body.setActivationState(4);
  191. if (m_aMotor != null)
  192. {
  193. if (m_aMotor.Handle != IntPtr.Zero)
  194. {
  195. m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
  196. m_aMotor.Dispose();
  197. }
  198. m_aMotor = null;
  199. }
  200. m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
  201. m_parent_scene.TransZero,
  202. m_parent_scene.TransZero, false);
  203. m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
  204. m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
  205. }
  206. public void Remove()
  207. {
  208. m_taintRemove = true;
  209. }
  210. public override bool Stopped
  211. {
  212. get { return m_zeroFlag; }
  213. }
  214. public override PhysicsVector Size
  215. {
  216. get { return new PhysicsVector(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
  217. set
  218. {
  219. m_pidControllerActive = true;
  220. PhysicsVector SetSize = value;
  221. m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
  222. //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
  223. Velocity = new PhysicsVector(0f, 0f, 0f);
  224. m_parent_scene.AddPhysicsActorTaint(this);
  225. }
  226. }
  227. /// <summary>
  228. /// turn the PID controller on or off.
  229. /// The PID Controller will turn on all by itself in many situations
  230. /// </summary>
  231. /// <param name="status"></param>
  232. public void SetPidStatus(bool status)
  233. {
  234. m_pidControllerActive = status;
  235. }
  236. public override PrimitiveBaseShape Shape
  237. {
  238. set { return; }
  239. }
  240. public override uint LocalID
  241. {
  242. set { m_localID = value; }
  243. }
  244. public override bool Grabbed
  245. {
  246. set { return; }
  247. }
  248. public override bool Selected
  249. {
  250. set { return; }
  251. }
  252. public override void CrossingFailure()
  253. {
  254. }
  255. public override void link(PhysicsActor obj)
  256. {
  257. }
  258. public override void delink()
  259. {
  260. }
  261. public override void LockAngularMotion(PhysicsVector axis)
  262. {
  263. }
  264. public override PhysicsVector Position
  265. {
  266. get { return m_position; }
  267. set
  268. {
  269. // m_taintedPosition_value = value;
  270. m_position = value;
  271. // m_taintedPosition = true;
  272. }
  273. }
  274. public override float Mass
  275. {
  276. get
  277. {
  278. float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
  279. return m_density * AVvolume;
  280. }
  281. }
  282. public override PhysicsVector Force
  283. {
  284. get { return new PhysicsVector(m_target_velocity.X, m_target_velocity.Y, m_target_velocity.Z); }
  285. set { return; }
  286. }
  287. public override int VehicleType
  288. {
  289. get { return 0; }
  290. set { return; }
  291. }
  292. public override void VehicleFloatParam(int param, float value)
  293. {
  294. }
  295. public override void VehicleVectorParam(int param, PhysicsVector value)
  296. {
  297. }
  298. public override void VehicleRotationParam(int param, Quaternion rotation)
  299. {
  300. }
  301. public override void SetVolumeDetect(int param)
  302. {
  303. }
  304. public override PhysicsVector GeometricCenter
  305. {
  306. get { return PhysicsVector.Zero; }
  307. }
  308. public override PhysicsVector CenterOfMass
  309. {
  310. get { return PhysicsVector.Zero; }
  311. }
  312. public override PhysicsVector Velocity
  313. {
  314. get
  315. {
  316. // There's a problem with PhysicsVector.Zero! Don't Use it Here!
  317. if (m_zeroFlag)
  318. return new PhysicsVector(0f, 0f, 0f);
  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 PhysicsVector Torque
  329. {
  330. get { return PhysicsVector.Zero; }
  331. set { return; }
  332. }
  333. public override float CollisionScore
  334. {
  335. get { return 0f; }
  336. set { }
  337. }
  338. public override PhysicsVector 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 PhysicsVector 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 PhysicsVector 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. /// <summary>
  525. /// Adds the force supplied to the Target Velocity
  526. /// The PID controller takes this target velocity and tries to make it a reality
  527. /// </summary>
  528. /// <param name="force"></param>
  529. /// <param name="pushforce">Is this a push by a script?</param>
  530. public override void AddForce(PhysicsVector force, bool pushforce)
  531. {
  532. if (pushforce)
  533. {
  534. m_pidControllerActive = false;
  535. force *= 100f;
  536. doForce(force, false);
  537. //System.Console.WriteLine("Push!");
  538. //_target_velocity.X += force.X;
  539. // _target_velocity.Y += force.Y;
  540. //_target_velocity.Z += force.Z;
  541. }
  542. else
  543. {
  544. m_pidControllerActive = true;
  545. m_target_velocity.X += force.X;
  546. m_target_velocity.Y += force.Y;
  547. m_target_velocity.Z += force.Z;
  548. }
  549. //m_lastUpdateSent = false;
  550. }
  551. public void doForce(PhysicsVector force, bool now)
  552. {
  553. tempVector3.setValue(force.X, force.Y, force.Z);
  554. if (now)
  555. {
  556. Body.applyCentralForce(tempVector3);
  557. }
  558. else
  559. {
  560. m_taintedForce += force;
  561. m_parent_scene.AddPhysicsActorTaint(this);
  562. }
  563. }
  564. public void doImpulse(PhysicsVector force, bool now)
  565. {
  566. tempVector3.setValue(force.X, force.Y, force.Z);
  567. if (now)
  568. {
  569. Body.applyCentralImpulse(tempVector3);
  570. }
  571. else
  572. {
  573. m_taintedForce += force;
  574. m_parent_scene.AddPhysicsActorTaint(this);
  575. }
  576. }
  577. public override void AddAngularForce(PhysicsVector force, bool pushforce)
  578. {
  579. }
  580. public override void SetMomentum(PhysicsVector momentum)
  581. {
  582. }
  583. public override void SubscribeEvents(int ms)
  584. {
  585. m_eventsubscription = ms;
  586. m_parent_scene.addCollisionEventReporting(this);
  587. }
  588. public override void UnSubscribeEvents()
  589. {
  590. m_parent_scene.remCollisionEventReporting(this);
  591. m_eventsubscription = 0;
  592. }
  593. public override bool SubscribedEvents()
  594. {
  595. if (m_eventsubscription > 0)
  596. return true;
  597. return false;
  598. }
  599. internal void Dispose()
  600. {
  601. if (Body.isInWorld())
  602. m_parent_scene.removeFromWorld(Body);
  603. if (m_aMotor.Handle != IntPtr.Zero)
  604. m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
  605. m_aMotor.Dispose(); m_aMotor = null;
  606. ClosestCastResult.Dispose(); ClosestCastResult = null;
  607. Body.Dispose(); Body = null;
  608. Shell.Dispose(); Shell = null;
  609. tempQuat1.Dispose();
  610. tempTrans1.Dispose();
  611. tempVector1.Dispose();
  612. tempVector2.Dispose();
  613. tempVector3.Dispose();
  614. tempVector4.Dispose();
  615. tempVector5RayCast.Dispose();
  616. tempVector6RayCast.Dispose();
  617. }
  618. public void ProcessTaints(float timestep)
  619. {
  620. if (m_tainted_isPhysical != m_isPhysical)
  621. {
  622. if (m_tainted_isPhysical)
  623. {
  624. // Create avatar capsule and related ODE data
  625. if (!(Shell == null && Body == null))
  626. {
  627. m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
  628. + (Shell != null ? "Shell " : "")
  629. + (Body != null ? "Body " : ""));
  630. }
  631. AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
  632. }
  633. else
  634. {
  635. // destroy avatar capsule and related ODE data
  636. Dispose();
  637. tempVector1 = new btVector3(0, 0, 0);
  638. tempVector2 = new btVector3(0, 0, 0);
  639. tempVector3 = new btVector3(0, 0, 0);
  640. tempVector4 = new btVector3(0, 0, 0);
  641. tempVector5RayCast = new btVector3(0, 0, 0);
  642. tempVector6RayCast = new btVector3(0, 0, 0);
  643. tempVector7RayCast = new btVector3(0, 0, 0);
  644. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  645. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  646. // m_movementComparision = new PhysicsVector(0, 0, 0);
  647. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  648. }
  649. m_isPhysical = m_tainted_isPhysical;
  650. }
  651. if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
  652. {
  653. if (Body != null)
  654. {
  655. m_pidControllerActive = true;
  656. // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
  657. //d.JointDestroy(Amotor);
  658. float prevCapsule = CAPSULE_LENGTH;
  659. CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
  660. //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
  661. Dispose();
  662. tempVector1 = new btVector3(0, 0, 0);
  663. tempVector2 = new btVector3(0, 0, 0);
  664. tempVector3 = new btVector3(0, 0, 0);
  665. tempVector4 = new btVector3(0, 0, 0);
  666. tempVector5RayCast = new btVector3(0, 0, 0);
  667. tempVector6RayCast = new btVector3(0, 0, 0);
  668. tempVector7RayCast = new btVector3(0, 0, 0);
  669. tempQuat1 = new btQuaternion(0, 0, 0, 1);
  670. tempTrans1 = new btTransform(tempQuat1, tempVector1);
  671. // m_movementComparision = new PhysicsVector(0, 0, 0);
  672. m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
  673. AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
  674. m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
  675. Velocity = new PhysicsVector(0f, 0f, 0f);
  676. }
  677. else
  678. {
  679. m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
  680. + (Shell == null ? "Shell " : "")
  681. + (Body == null ? "Body " : ""));
  682. }
  683. }
  684. if (m_taintRemove)
  685. {
  686. Dispose();
  687. }
  688. }
  689. /// <summary>
  690. /// Called from Simulate
  691. /// This is the avatar's movement control + PID Controller
  692. /// </summary>
  693. /// <param name="timeStep"></param>
  694. public void Move(float timeStep)
  695. {
  696. // no lock; for now it's only called from within Simulate()
  697. // If the PID Controller isn't active then we set our force
  698. // calculating base velocity to the current position
  699. if (Body == null)
  700. return;
  701. tempTrans1.Dispose();
  702. tempTrans1 = Body.getInterpolationWorldTransform();
  703. tempVector1.Dispose();
  704. tempVector1 = tempTrans1.getOrigin();
  705. tempVector2.Dispose();
  706. tempVector2 = Body.getInterpolationLinearVelocity();
  707. if (m_pidControllerActive == false)
  708. {
  709. m_zeroPosition.X = tempVector1.getX();
  710. m_zeroPosition.Y = tempVector1.getY();
  711. m_zeroPosition.Z = tempVector1.getZ();
  712. }
  713. //PidStatus = true;
  714. PhysicsVector vec = new PhysicsVector();
  715. PhysicsVector vel = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
  716. float movementdivisor = 1f;
  717. if (!m_alwaysRun)
  718. {
  719. movementdivisor = walkDivisor;
  720. }
  721. else
  722. {
  723. movementdivisor = runDivisor;
  724. }
  725. // if velocity is zero, use position control; otherwise, velocity control
  726. if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
  727. {
  728. // keep track of where we stopped. No more slippin' & slidin'
  729. if (!m_zeroFlag)
  730. {
  731. m_zeroFlag = true;
  732. m_zeroPosition.X = tempVector1.getX();
  733. m_zeroPosition.Y = tempVector1.getY();
  734. m_zeroPosition.Z = tempVector1.getZ();
  735. }
  736. if (m_pidControllerActive)
  737. {
  738. // We only want to deactivate the PID Controller if we think we want to have our surrogate
  739. // react to the physics scene by moving it's position.
  740. // Avatar to Avatar collisions
  741. // Prim to avatar collisions
  742. PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
  743. vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
  744. vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
  745. if (m_flying)
  746. {
  747. vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
  748. }
  749. }
  750. //PidStatus = true;
  751. }
  752. else
  753. {
  754. m_pidControllerActive = true;
  755. m_zeroFlag = false;
  756. if (m_iscolliding && !m_flying)
  757. {
  758. // We're standing on something
  759. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
  760. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
  761. }
  762. else if (m_iscolliding && m_flying)
  763. {
  764. // We're flying and colliding with something
  765. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
  766. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
  767. }
  768. else if (!m_iscolliding && m_flying)
  769. {
  770. // we're in mid air suspended
  771. vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
  772. vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
  773. // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
  774. // rebound preventing
  775. if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
  776. m_zeroFlag = true;
  777. }
  778. if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
  779. {
  780. // We're colliding with something and we're not flying but we're moving
  781. // This means we're walking or running.
  782. PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
  783. vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
  784. if (m_target_velocity.X > 0)
  785. {
  786. vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
  787. }
  788. if (m_target_velocity.Y > 0)
  789. {
  790. vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
  791. }
  792. }
  793. else if (!m_iscolliding && !m_flying)
  794. {
  795. // we're not colliding and we're not flying so that means we're falling!
  796. // m_iscolliding includes collisions with the ground.
  797. // d.Vector3 pos = d.BodyGetPosition(Body);
  798. if (m_target_velocity.X > 0)
  799. {
  800. vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
  801. }
  802. if (m_target_velocity.Y > 0)
  803. {
  804. vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
  805. }
  806. }
  807. if (m_flying)
  808. {
  809. vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
  810. }
  811. }
  812. if (m_flying)
  813. {
  814. // Slight PID correction
  815. vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
  816. //auto fly height. Kitto Flora
  817. //d.Vector3 pos = d.BodyGetPosition(Body);
  818. float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
  819. if (m_position.Z < target_altitude)
  820. {
  821. vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
  822. }
  823. }
  824. 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))))
  825. {
  826. Body.setFriction(0.001f);
  827. //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
  828. }
  829. if (Body != null)
  830. {
  831. int activationstate = Body.getActivationState();
  832. if (activationstate == 0)
  833. {
  834. Body.forceActivationState(1);
  835. }
  836. }
  837. doImpulse(vec, true);
  838. }
  839. /// <summary>
  840. /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
  841. /// </summary>
  842. public void UpdatePositionAndVelocity()
  843. {
  844. if (Body == null)
  845. return;
  846. //int val = Environment.TickCount;
  847. CheckIfStandingOnObject();
  848. //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
  849. //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
  850. tempTrans1.Dispose();
  851. tempTrans1 = Body.getInterpolationWorldTransform();
  852. tempVector1.Dispose();
  853. tempVector1 = tempTrans1.getOrigin();
  854. tempVector2.Dispose();
  855. tempVector2 = Body.getInterpolationLinearVelocity();
  856. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  857. PhysicsVector vec = new PhysicsVector(tempVector1.getX(),tempVector1.getY(),tempVector1.getZ());
  858. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  859. if (vec.X < -10.0f) vec.X = 0.0f;
  860. if (vec.Y < -10.0f) vec.Y = 0.0f;
  861. if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
  862. if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
  863. m_position.X = vec.X;
  864. m_position.Y = vec.Y;
  865. m_position.Z = vec.Z;
  866. // Did we move last? = zeroflag
  867. // This helps keep us from sliding all over
  868. if (m_zeroFlag)
  869. {
  870. m_velocity.X = 0.0f;
  871. m_velocity.Y = 0.0f;
  872. m_velocity.Z = 0.0f;
  873. // Did we send out the 'stopped' message?
  874. if (!m_lastUpdateSent)
  875. {
  876. m_lastUpdateSent = true;
  877. //base.RequestPhysicsterseUpdate();
  878. }
  879. }
  880. else
  881. {
  882. m_lastUpdateSent = false;
  883. vec = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
  884. m_velocity.X = (vec.X);
  885. m_velocity.Y = (vec.Y);
  886. m_velocity.Z = (vec.Z);
  887. //m_log.Debug(m_target_velocity);
  888. if (m_velocity.Z < -6 && !m_hackSentFall)
  889. {
  890. m_hackSentFall = true;
  891. m_pidControllerActive = false;
  892. }
  893. else if (m_flying && !m_hackSentFly)
  894. {
  895. //m_hackSentFly = true;
  896. //base.SendCollisionUpdate(new CollisionEventUpdate());
  897. }
  898. else
  899. {
  900. m_hackSentFly = false;
  901. m_hackSentFall = false;
  902. }
  903. }
  904. if (Body != null)
  905. {
  906. if (Body.getFriction() < 0.9f)
  907. Body.setFriction(0.9f);
  908. }
  909. //if (Body != null)
  910. // Body.clearForces();
  911. }
  912. public void CheckIfStandingOnObject()
  913. {
  914. float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
  915. tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
  916. tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
  917. ClosestCastResult.Dispose();
  918. ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
  919. try
  920. {
  921. m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
  922. }
  923. catch (AccessViolationException)
  924. {
  925. m_log.Debug("BAD!");
  926. }
  927. if (ClosestCastResult.hasHit())
  928. {
  929. if (tempVector7RayCast != null)
  930. tempVector7RayCast.Dispose();
  931. //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
  932. /*if (tempVector7RayCast == null) // null == no result also
  933. {
  934. CollidingObj = false;
  935. IsColliding = false;
  936. CollidingGround = false;
  937. return;
  938. }
  939. float zVal = tempVector7RayCast.getZ();
  940. if (zVal != 0)
  941. m_log.Debug("[PHYSICS]: HAAAA");
  942. if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
  943. {
  944. CollidingObj = true;
  945. IsColliding = true;
  946. }
  947. else
  948. {
  949. CollidingObj = false;
  950. IsColliding = false;
  951. CollidingGround = false;
  952. }*/
  953. //height+2*radius = capsule full length
  954. //CollidingObj = true;
  955. //IsColliding = true;
  956. m_iscolliding = true;
  957. }
  958. else
  959. {
  960. //CollidingObj = false;
  961. //IsColliding = false;
  962. //CollidingGround = false;
  963. m_iscolliding = false;
  964. }
  965. }
  966. }
  967. }