BulletXPlugin.cs 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204
  1. #region Copyright
  2. /*
  3. * Copyright (c) Contributors, http://www.openmetaverse.org/
  4. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * * Neither the name of the OpenSim Project nor the
  14. * names of its contributors may be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. */
  29. #endregion
  30. #region References
  31. using System;
  32. using System.Collections.Generic;
  33. using OpenSim.Region.Physics.Manager;
  34. using OpenSim.Framework.Types;
  35. using Axiom.Math;
  36. using AxiomQuaternion = Axiom.Math.Quaternion;
  37. //Specific References for BulletXPlugin
  38. using MonoXnaCompactMaths;
  39. using XnaDevRu.BulletX;
  40. using XnaDevRu.BulletX.Dynamics;
  41. #endregion
  42. namespace OpenSim.Region.Physics.BulletXPlugin
  43. {
  44. /// <summary>
  45. /// This class is only here for compilations reasons
  46. /// </summary>
  47. public class Mesh
  48. {
  49. public Mesh()
  50. {
  51. }
  52. }
  53. /// <summary>
  54. /// BulletXConversions are called now BulletXMaths
  55. /// This Class converts objects and types for BulletX and give some operations
  56. /// </summary>
  57. public class BulletXMaths
  58. {
  59. //Vector3
  60. public static MonoXnaCompactMaths.Vector3 PhysicsVectorToXnaVector3(PhysicsVector physicsVector)
  61. {
  62. return new MonoXnaCompactMaths.Vector3(physicsVector.X, physicsVector.Y, physicsVector.Z);
  63. }
  64. public static PhysicsVector XnaVector3ToPhysicsVector(MonoXnaCompactMaths.Vector3 xnaVector3)
  65. {
  66. return new PhysicsVector(xnaVector3.X, xnaVector3.Y, xnaVector3.Z);
  67. }
  68. //Quaternion
  69. public static MonoXnaCompactMaths.Quaternion AxiomQuaternionToXnaQuaternion(AxiomQuaternion axiomQuaternion)
  70. {
  71. return new MonoXnaCompactMaths.Quaternion(axiomQuaternion.x, axiomQuaternion.y, axiomQuaternion.z, axiomQuaternion.w);
  72. }
  73. public static AxiomQuaternion XnaQuaternionToAxiomQuaternion(MonoXnaCompactMaths.Quaternion xnaQuaternion)
  74. {
  75. return new AxiomQuaternion(xnaQuaternion.W, xnaQuaternion.X, xnaQuaternion.Y, xnaQuaternion.Z);
  76. }
  77. //Next methods are extracted from XnaDevRu.BulletX(See 3rd party license):
  78. //- SetRotation (class MatrixOperations)
  79. //- GetRotation (class MatrixOperations)
  80. //- GetElement (class MathHelper)
  81. //- SetElement (class MathHelper)
  82. internal static void SetRotation(ref Matrix m, MonoXnaCompactMaths.Quaternion q)
  83. {
  84. float d = q.LengthSquared();
  85. float s = 2f / d;
  86. float xs = q.X * s, ys = q.Y * s, zs = q.Z * s;
  87. float wx = q.W * xs, wy = q.W * ys, wz = q.W * zs;
  88. float xx = q.X * xs, xy = q.X * ys, xz = q.X * zs;
  89. float yy = q.Y * ys, yz = q.Y * zs, zz = q.Z * zs;
  90. m = new Matrix(1 - (yy + zz), xy - wz, xz + wy, 0,
  91. xy + wz, 1 - (xx + zz), yz - wx, 0,
  92. xz - wy, yz + wx, 1 - (xx + yy), 0,
  93. m.M41, m.M42, m.M43, 1);
  94. }
  95. internal static MonoXnaCompactMaths.Quaternion GetRotation(Matrix m)
  96. {
  97. MonoXnaCompactMaths.Quaternion q = new MonoXnaCompactMaths.Quaternion();
  98. float trace = m.M11 + m.M22 + m.M33;
  99. if (trace > 0)
  100. {
  101. float s = (float)Math.Sqrt(trace + 1);
  102. q.W = s * 0.5f;
  103. s = 0.5f / s;
  104. q.X = (m.M32 - m.M23) * s;
  105. q.Y = (m.M13 - m.M31) * s;
  106. q.Z = (m.M21 - m.M12) * s;
  107. }
  108. else
  109. {
  110. int i = m.M11 < m.M22 ?
  111. (m.M22 < m.M33 ? 2 : 1) :
  112. (m.M11 < m.M33 ? 2 : 0);
  113. int j = (i + 1) % 3;
  114. int k = (i + 2) % 3;
  115. float s = (float)Math.Sqrt(GetElement(m, i, i) - GetElement(m, j, j) - GetElement(m, k, k) + 1);
  116. SetElement(ref q, i, s * 0.5f);
  117. s = 0.5f / s;
  118. q.W = (GetElement(m, k, j) - GetElement(m, j, k)) * s;
  119. SetElement(ref q, j, (GetElement(m, j, i) + GetElement(m, i, j)) * s);
  120. SetElement(ref q, k, (GetElement(m, k, i) + GetElement(m, i, k)) * s);
  121. }
  122. return q;
  123. }
  124. internal static float SetElement(ref MonoXnaCompactMaths.Quaternion q, int index, float value)
  125. {
  126. switch (index)
  127. {
  128. case 0:
  129. q.X = value; break;
  130. case 1:
  131. q.Y = value; break;
  132. case 2:
  133. q.Z = value; break;
  134. case 3:
  135. q.W = value; break;
  136. }
  137. return 0;
  138. }
  139. internal static float GetElement(Matrix mat, int row, int col)
  140. {
  141. switch (row)
  142. {
  143. case 0:
  144. switch (col)
  145. {
  146. case 0:
  147. return mat.M11;
  148. case 1:
  149. return mat.M12;
  150. case 2:
  151. return mat.M13;
  152. } break;
  153. case 1:
  154. switch (col)
  155. {
  156. case 0:
  157. return mat.M21;
  158. case 1:
  159. return mat.M22;
  160. case 2:
  161. return mat.M23;
  162. } break;
  163. case 2:
  164. switch (col)
  165. {
  166. case 0:
  167. return mat.M31;
  168. case 1:
  169. return mat.M32;
  170. case 2:
  171. return mat.M33;
  172. } break;
  173. }
  174. return 0;
  175. }
  176. }
  177. /// <summary>
  178. /// PhysicsPlugin Class for BulletX
  179. /// </summary>
  180. public class BulletXPlugin : IPhysicsPlugin
  181. {
  182. private BulletXScene _mScene;
  183. public BulletXPlugin()
  184. {
  185. }
  186. public bool Init()
  187. {
  188. return true;
  189. }
  190. public PhysicsScene GetScene()
  191. {
  192. if (_mScene == null)
  193. {
  194. _mScene = new BulletXScene();
  195. }
  196. return (_mScene);
  197. }
  198. public string GetName()
  199. {
  200. return ("modified_BulletX");//Changed!! "BulletXEngine" To "modified_BulletX"
  201. }
  202. public void Dispose()
  203. {
  204. }
  205. }
  206. /// <summary>
  207. /// PhysicsScene Class for BulletX
  208. /// </summary>
  209. public class BulletXScene : PhysicsScene
  210. {
  211. #region BulletXScene Fields
  212. public DiscreteDynamicsWorld ddWorld;
  213. private CollisionDispatcher cDispatcher;
  214. private OverlappingPairCache opCache;
  215. private SequentialImpulseConstraintSolver sicSolver;
  216. public static Object BulletXLock = new Object();
  217. private const int minXY = 0;
  218. private const int minZ = 0;
  219. private const int maxXY = 256;
  220. private const int maxZ = 4096;
  221. private const int maxHandles = 32766; //Why? I don't know
  222. private const float gravity = 9.8f;
  223. private const float heightLevel0 = 77.0f;
  224. private const float heightLevel1 = 200.0f;
  225. private const float lowGravityFactor = 0.2f;
  226. //OpenSim calls Simulate 10 times per seconds. So FPS = "Simulate Calls" * simulationSubSteps = 100 FPS
  227. private const int simulationSubSteps = 10;
  228. //private float[] _heightmap;
  229. private BulletXPlanet _simFlatPlanet;
  230. private List<BulletXCharacter> _characters = new List<BulletXCharacter>();
  231. private List<BulletXPrim> _prims = new List<BulletXPrim>();
  232. public static float Gravity { get { return gravity; } }
  233. public static float HeightLevel0 { get { return heightLevel0; } }
  234. public static float HeightLevel1 { get { return heightLevel1; } }
  235. public static float LowGravityFactor { get { return lowGravityFactor; } }
  236. public static int MaxXY { get { return maxXY; } }
  237. public static int MaxZ { get { return maxZ; } }
  238. private List<RigidBody> _forgottenRigidBodies = new List<RigidBody>();
  239. internal string is_ex_message = "Can't remove rigidBody!: ";
  240. #endregion
  241. public BulletXScene()
  242. {
  243. cDispatcher = new CollisionDispatcher();
  244. MonoXnaCompactMaths.Vector3 worldMinDim = new MonoXnaCompactMaths.Vector3((float)minXY, (float)minXY, (float)minZ);
  245. MonoXnaCompactMaths.Vector3 worldMaxDim = new MonoXnaCompactMaths.Vector3((float)maxXY, (float)maxXY, (float)maxZ);
  246. opCache = new AxisSweep3(worldMinDim, worldMaxDim, maxHandles);
  247. sicSolver = new SequentialImpulseConstraintSolver();
  248. lock (BulletXLock)
  249. {
  250. ddWorld = new DiscreteDynamicsWorld(cDispatcher, opCache, sicSolver);
  251. ddWorld.Gravity = new MonoXnaCompactMaths.Vector3(0, 0, -gravity);
  252. }
  253. //this._heightmap = new float[65536];
  254. }
  255. public override PhysicsActor AddAvatar(string avName, PhysicsVector position)
  256. {
  257. PhysicsVector pos = new PhysicsVector();
  258. pos.X = position.X;
  259. pos.Y = position.Y;
  260. pos.Z = position.Z + 20;
  261. BulletXCharacter newAv = null;
  262. lock (BulletXLock)
  263. {
  264. newAv = new BulletXCharacter(avName, this, pos);
  265. _characters.Add(newAv);
  266. }
  267. return newAv;
  268. }
  269. public override void RemoveAvatar(PhysicsActor actor)
  270. {
  271. if (actor is BulletXCharacter)
  272. {
  273. lock (BulletXLock)
  274. {
  275. try
  276. {
  277. ddWorld.RemoveRigidBody(((BulletXCharacter)actor).RigidBody);
  278. }
  279. catch (Exception ex)
  280. {
  281. BulletXMessage(is_ex_message + ex.Message, true);
  282. ((BulletXCharacter)actor).RigidBody.ActivationState = ActivationState.DisableSimulation;
  283. AddForgottenRigidBody(((BulletXCharacter)actor).RigidBody);
  284. }
  285. _characters.Remove((BulletXCharacter)actor);
  286. }
  287. GC.Collect();
  288. }
  289. }
  290. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation)
  291. {
  292. PhysicsActor result;
  293. switch (pbs.ProfileShape)
  294. {
  295. case ProfileShape.Square:
  296. /// support simple box & hollow box now; later, more shapes
  297. if (pbs.ProfileHollow == 0)
  298. {
  299. result = AddPrim(primName, position, size, rotation, null, null);
  300. }
  301. else
  302. {
  303. Mesh mesh = null;
  304. result = AddPrim(primName, position, size, rotation, mesh, pbs);
  305. }
  306. break;
  307. default:
  308. result = AddPrim(primName, position, size, rotation, null, null);
  309. break;
  310. }
  311. return result;
  312. }
  313. public PhysicsActor AddPrim(PhysicsVector position, PhysicsVector size, Axiom.Math.Quaternion rotation)
  314. {
  315. return AddPrim("", position, size, rotation, null, null);
  316. }
  317. public PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs)
  318. {
  319. BulletXPrim newPrim = null;
  320. lock (BulletXLock)
  321. {
  322. newPrim = new BulletXPrim(name, this, position, size, rotation, mesh, pbs);
  323. _prims.Add(newPrim);
  324. }
  325. return newPrim;
  326. }
  327. public override void RemovePrim(PhysicsActor prim)
  328. {
  329. if (prim is BulletXPrim)
  330. {
  331. lock (BulletXLock)
  332. {
  333. try
  334. {
  335. ddWorld.RemoveRigidBody(((BulletXPrim)prim).RigidBody);
  336. }
  337. catch (Exception ex)
  338. {
  339. BulletXMessage(is_ex_message + ex.Message, true);
  340. ((BulletXPrim)prim).RigidBody.ActivationState = ActivationState.DisableSimulation;
  341. AddForgottenRigidBody(((BulletXPrim)prim).RigidBody);
  342. }
  343. _prims.Remove((BulletXPrim)prim);
  344. }
  345. GC.Collect();
  346. }
  347. }
  348. public override void Simulate(float timeStep)
  349. {
  350. lock (BulletXLock)
  351. {
  352. //Try to remove garbage
  353. RemoveForgottenRigidBodies();
  354. //End of remove
  355. MoveAllObjects(timeStep);
  356. ddWorld.StepSimulation(timeStep, simulationSubSteps, timeStep);
  357. //Extra Heightmap Validation: BulletX's HeightFieldTerrain somestimes doesn't work so fine.
  358. ValidateHeightForAll();
  359. //End heightmap validation.
  360. UpdateKineticsForAll();
  361. }
  362. }
  363. private void MoveAllObjects(float timeStep)
  364. {
  365. foreach (BulletXCharacter actor in _characters)
  366. {
  367. actor.Move(timeStep);
  368. }
  369. foreach (BulletXPrim prim in _prims)
  370. {
  371. }
  372. }
  373. private void ValidateHeightForAll()
  374. {
  375. float _height;
  376. foreach (BulletXCharacter actor in _characters)
  377. {
  378. //_height = HeightValue(actor.RigidBodyPosition);
  379. _height = _simFlatPlanet.HeightValue(actor.RigidBodyPosition);
  380. actor.ValidateHeight(_height);
  381. //if (_simFlatPlanet.heightIsNotValid(actor.RigidBodyPosition, out _height)) actor.ValidateHeight(_height);
  382. }
  383. foreach (BulletXPrim prim in _prims)
  384. {
  385. //_height = HeightValue(prim.RigidBodyPosition);
  386. _height = _simFlatPlanet.HeightValue(prim.RigidBodyPosition);
  387. prim.ValidateHeight(_height);
  388. //if (_simFlatPlanet.heightIsNotValid(prim.RigidBodyPosition, out _height)) prim.ValidateHeight(_height);
  389. }
  390. //foreach (BulletXCharacter actor in _characters)
  391. //{
  392. // actor.ValidateHeight(0);
  393. //}
  394. //foreach (BulletXPrim prim in _prims)
  395. //{
  396. // prim.ValidateHeight(0);
  397. //}
  398. }
  399. private void UpdateKineticsForAll()
  400. {
  401. //UpdatePosition > UpdateKinetics.
  402. //Not only position will be updated, also velocity cause acceleration.
  403. foreach (BulletXCharacter actor in _characters)
  404. {
  405. actor.UpdateKinetics();
  406. }
  407. foreach (BulletXPrim prim in _prims)
  408. {
  409. prim.UpdateKinetics();
  410. }
  411. //if(this._simFlatPlanet!=null) this._simFlatPlanet.Restore();
  412. }
  413. public override void GetResults()
  414. {
  415. }
  416. public override bool IsThreaded
  417. {
  418. get
  419. {
  420. return (false); // for now we won't be multithreaded
  421. }
  422. }
  423. public override void SetTerrain(float[] heightMap)
  424. {
  425. ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
  426. //for (int i = 0; i < 65536; i++)
  427. //{
  428. // // this._heightmap[i] = (double)heightMap[i];
  429. // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
  430. // int x = i & 0xff;
  431. // int y = i >> 8;
  432. // this._heightmap[i] = heightMap[x * 256 + y];
  433. //}
  434. //float[] swappedHeightMap = new float[65536];
  435. ////As the same as ODE, heightmap (x,y) must be swapped for BulletX
  436. //for (int i = 0; i < 65536; i++)
  437. //{
  438. // // this._heightmap[i] = (double)heightMap[i];
  439. // // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
  440. // int x = i & 0xff;
  441. // int y = i >> 8;
  442. // swappedHeightMap[i] = heightMap[x * 256 + y];
  443. //}
  444. DeleteTerrain();
  445. //There is a BulletXLock inside the constructor of BulletXPlanet
  446. //this._simFlatPlanet = new BulletXPlanet(this, swappedHeightMap);
  447. this._simFlatPlanet = new BulletXPlanet(this, heightMap);
  448. //this._heightmap = heightMap;
  449. }
  450. public override void DeleteTerrain()
  451. {
  452. if (this._simFlatPlanet != null)
  453. {
  454. lock (BulletXLock)
  455. {
  456. try
  457. {
  458. ddWorld.RemoveRigidBody(this._simFlatPlanet.RigidBody);
  459. }
  460. catch (Exception ex)
  461. {
  462. BulletXMessage(is_ex_message + ex.Message, true);
  463. this._simFlatPlanet.RigidBody.ActivationState = ActivationState.DisableSimulation;
  464. AddForgottenRigidBody(this._simFlatPlanet.RigidBody);
  465. }
  466. }
  467. this._simFlatPlanet = null;
  468. GC.Collect();
  469. BulletXMessage("Terrain erased!", false);
  470. }
  471. //this._heightmap = null;
  472. }
  473. internal void AddForgottenRigidBody(RigidBody forgottenRigidBody)
  474. {
  475. _forgottenRigidBodies.Add(forgottenRigidBody);
  476. }
  477. private void RemoveForgottenRigidBodies()
  478. {
  479. RigidBody forgottenRigidBody;
  480. int nRigidBodies = _forgottenRigidBodies.Count;
  481. for(int i = nRigidBodies - 1; i >= 0; i--)
  482. {
  483. forgottenRigidBody = _forgottenRigidBodies[i];
  484. try
  485. {
  486. ddWorld.RemoveRigidBody(forgottenRigidBody);
  487. _forgottenRigidBodies.Remove(forgottenRigidBody);
  488. BulletXMessage("Forgotten Rigid Body Removed", false);
  489. }
  490. catch (Exception ex)
  491. {
  492. BulletXMessage("Can't remove forgottenRigidBody!: " + ex.Message, false);
  493. }
  494. }
  495. GC.Collect();
  496. }
  497. internal void BulletXMessage(string message, bool isWarning)
  498. {
  499. PhysicsPluginManager.PhysicsPluginMessage("[Modified BulletX]:\t" + message, isWarning);
  500. }
  501. //temp
  502. //private float HeightValue(MonoXnaCompactMaths.Vector3 position)
  503. //{
  504. // int li_x, li_y;
  505. // float height;
  506. // li_x = (int)Math.Round(position.X); if (li_x < 0) li_x = 0;
  507. // li_y = (int)Math.Round(position.Y); if (li_y < 0) li_y = 0;
  508. // height = this._heightmap[li_y * 256 + li_x];
  509. // if (height < 0) height = 0;
  510. // else if (height > maxZ) height = maxZ;
  511. // return height;
  512. //}
  513. }
  514. /// <summary>
  515. /// PhysicsActor Character Class for BulletX
  516. /// </summary>
  517. public class BulletXCharacter : PhysicsActor
  518. {
  519. private PhysicsVector _position;
  520. private PhysicsVector _velocity;
  521. private PhysicsVector _size;
  522. private PhysicsVector _acceleration;
  523. private AxiomQuaternion _orientation;
  524. private bool flying;
  525. private RigidBody rigidBody;
  526. public MonoXnaCompactMaths.Vector3 RigidBodyPosition
  527. {
  528. get { return this.rigidBody.CenterOfMassPosition; }
  529. }
  530. public BulletXCharacter(BulletXScene parent_scene, PhysicsVector pos)
  531. : this("", parent_scene, pos)
  532. {
  533. }
  534. public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos)
  535. : this(avName, parent_scene, pos, new PhysicsVector(), new PhysicsVector(), new PhysicsVector(),
  536. AxiomQuaternion.Identity)
  537. {
  538. }
  539. public BulletXCharacter(String avName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity,
  540. PhysicsVector size, PhysicsVector acceleration, AxiomQuaternion orientation)
  541. {
  542. //This fields will be removed. They're temporal
  543. float _sizeX = 0.5f;
  544. float _sizeY = 0.5f;
  545. float _sizeZ = 1.6f;
  546. //.
  547. _position = pos;
  548. _velocity = velocity;
  549. _size = size;
  550. //---
  551. _size.X = _sizeX;
  552. _size.Y = _sizeY;
  553. _size.Z = _sizeZ;
  554. //.
  555. _acceleration = acceleration;
  556. _orientation = orientation;
  557. float _mass = 50.0f; //This depends of avatar's dimensions
  558. //For RigidBody Constructor. The next values might change
  559. float _linearDamping = 0.0f;
  560. float _angularDamping = 0.0f;
  561. float _friction = 0.5f;
  562. float _restitution = 0.0f;
  563. Matrix _startTransform = Matrix.Identity;
  564. Matrix _centerOfMassOffset = Matrix.Identity;
  565. lock (BulletXScene.BulletXLock)
  566. {
  567. _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
  568. //CollisionShape _collisionShape = new BoxShape(new MonoXnaCompactMaths.Vector3(1.0f, 1.0f, 1.60f));
  569. //For now, like ODE, collisionShape = sphere of radious = 1.0
  570. CollisionShape _collisionShape = new SphereShape(1.0f);
  571. DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
  572. MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3();
  573. _collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
  574. rigidBody = new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution);
  575. //rigidBody.ActivationState = ActivationState.DisableDeactivation;
  576. //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
  577. MonoXnaCompactMaths.Vector3 _vDebugTranslation;
  578. _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
  579. rigidBody.Translate(_vDebugTranslation);
  580. parent_scene.ddWorld.AddRigidBody(rigidBody);
  581. }
  582. }
  583. public override PhysicsVector Position
  584. {
  585. get
  586. {
  587. return _position;
  588. }
  589. set
  590. {
  591. lock (BulletXScene.BulletXLock)
  592. {
  593. _position = value;
  594. Translate();
  595. }
  596. }
  597. }
  598. public override PhysicsVector Velocity
  599. {
  600. get
  601. {
  602. return _velocity;
  603. }
  604. set
  605. {
  606. lock (BulletXScene.BulletXLock)
  607. {
  608. _velocity = value;
  609. Speed();
  610. }
  611. }
  612. }
  613. public override PhysicsVector Size
  614. {
  615. get
  616. {
  617. return _size;
  618. }
  619. set
  620. {
  621. lock (BulletXScene.BulletXLock)
  622. {
  623. _size = value;
  624. }
  625. }
  626. }
  627. public override PhysicsVector Acceleration
  628. {
  629. get
  630. {
  631. return _acceleration;
  632. }
  633. }
  634. public override AxiomQuaternion Orientation
  635. {
  636. get
  637. {
  638. return _orientation;
  639. }
  640. set
  641. {
  642. lock (BulletXScene.BulletXLock)
  643. {
  644. _orientation = value;
  645. }
  646. }
  647. }
  648. public RigidBody RigidBody
  649. {
  650. get
  651. {
  652. return rigidBody;
  653. }
  654. }
  655. public override bool Flying
  656. {
  657. get
  658. {
  659. return flying;
  660. }
  661. set
  662. {
  663. flying = value;
  664. }
  665. }
  666. public void SetAcceleration(PhysicsVector accel)
  667. {
  668. lock (BulletXScene.BulletXLock)
  669. {
  670. _acceleration = accel;
  671. }
  672. }
  673. public override bool Kinematic
  674. {
  675. get
  676. {
  677. return false;
  678. }
  679. set
  680. {
  681. }
  682. }
  683. public override void AddForce(PhysicsVector force)
  684. {
  685. }
  686. public override void SetMomentum(PhysicsVector momentum)
  687. {
  688. }
  689. internal void Move(float timeStep)
  690. {
  691. MonoXnaCompactMaths.Vector3 vec = new MonoXnaCompactMaths.Vector3();
  692. //At this point it's supossed that:
  693. //_velocity == rigidBody.LinearVelocity
  694. vec.X = this._velocity.X;
  695. vec.Y = this._velocity.Y;
  696. vec.Z = this._velocity.Z;
  697. if ((vec.X != 0.0f) || (vec.Y != 0.0f) || (vec.Z != 0.0f)) rigidBody.Activate();
  698. if (flying)
  699. {
  700. //Antigravity with movement
  701. if (this._position.Z <= BulletXScene.HeightLevel0)
  702. {
  703. vec.Z += BulletXScene.Gravity * timeStep;
  704. }
  705. //Lowgravity with movement
  706. else if ((this._position.Z > BulletXScene.HeightLevel0)
  707. && (this._position.Z <= BulletXScene.HeightLevel1))
  708. {
  709. vec.Z += BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor);
  710. }
  711. //Lowgravity with...
  712. else if (this._position.Z > BulletXScene.HeightLevel1)
  713. {
  714. if (vec.Z > 0) //no movement
  715. vec.Z = BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor);
  716. else
  717. vec.Z += BulletXScene.Gravity * timeStep * (1.0f - BulletXScene.LowGravityFactor);
  718. }
  719. }
  720. rigidBody.LinearVelocity = vec;
  721. }
  722. //This validation is very basic
  723. internal void ValidateHeight(float heighmapPositionValue)
  724. {
  725. if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z / 2.0f)
  726. {
  727. Matrix m = rigidBody.WorldTransform;
  728. MonoXnaCompactMaths.Vector3 v3 = m.Translation;
  729. v3.Z = heighmapPositionValue + _size.Z / 2.0f;
  730. m.Translation = v3;
  731. rigidBody.WorldTransform = m;
  732. //When an Avie touch the ground it's vertical velocity it's reduced to ZERO
  733. Speed(new PhysicsVector(this.rigidBody.LinearVelocity.X, this.rigidBody.LinearVelocity.Y, 0.0f));
  734. }
  735. }
  736. internal void UpdateKinetics()
  737. {
  738. this._position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
  739. this._velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
  740. //Orientation it seems that it will be the default.
  741. ReOrient();
  742. }
  743. #region Methods for updating values of RigidBody
  744. private void Translate()
  745. {
  746. Translate(this._position);
  747. }
  748. private void Translate(PhysicsVector _newPos)
  749. {
  750. MonoXnaCompactMaths.Vector3 _translation;
  751. _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition;
  752. rigidBody.Translate(_translation);
  753. }
  754. private void Speed()
  755. {
  756. Speed(this._velocity);
  757. }
  758. private void Speed(PhysicsVector _newSpeed)
  759. {
  760. MonoXnaCompactMaths.Vector3 _speed;
  761. _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed);
  762. rigidBody.LinearVelocity = _speed;
  763. }
  764. private void ReOrient()
  765. {
  766. ReOrient(this._orientation);
  767. }
  768. private void ReOrient(AxiomQuaternion _newOrient)
  769. {
  770. MonoXnaCompactMaths.Quaternion _newOrientation;
  771. _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient);
  772. Matrix _comTransform = rigidBody.CenterOfMassTransform;
  773. BulletXMaths.SetRotation(ref _comTransform, _newOrientation);
  774. rigidBody.CenterOfMassTransform = _comTransform;
  775. }
  776. #endregion
  777. }
  778. /// <summary>
  779. /// PhysicsActor Prim Class for BulletX
  780. /// </summary>
  781. public class BulletXPrim : PhysicsActor
  782. {
  783. private PhysicsVector _position;
  784. private PhysicsVector _velocity;
  785. private PhysicsVector _size;
  786. private PhysicsVector _acceleration;
  787. private AxiomQuaternion _orientation;
  788. //Density it will depends of material.
  789. //For now all prims have the same density, all prims are made of water. Be water my friend! :D
  790. private const float _density = 1000.0f;
  791. private RigidBody rigidBody;
  792. private BulletXScene _parent_scene;
  793. //_physical value will be linked with the prim object value
  794. private Boolean _physical = false;
  795. public MonoXnaCompactMaths.Vector3 RigidBodyPosition
  796. {
  797. get { return this.rigidBody.CenterOfMassPosition; }
  798. }
  799. public BulletXPrim(BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size, AxiomQuaternion rotation)
  800. : this("", parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, null, null)
  801. {
  802. }
  803. public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector size,
  804. AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs)
  805. : this(primName, parent_scene, pos, new PhysicsVector(), size, new PhysicsVector(), rotation, mesh, pbs)
  806. {
  807. }
  808. public BulletXPrim(String primName, BulletXScene parent_scene, PhysicsVector pos, PhysicsVector velocity, PhysicsVector size,
  809. PhysicsVector aceleration, AxiomQuaternion rotation, Mesh mesh, PrimitiveBaseShape pbs)
  810. {
  811. if ((size.X == 0) || (size.Y == 0) || (size.Z == 0)) throw new Exception("Size 0");
  812. if (rotation.Norm == 0f) rotation = AxiomQuaternion.Identity;
  813. _position = pos;
  814. if (_physical) _velocity = velocity; else _velocity = new PhysicsVector();
  815. _size = size;
  816. _acceleration = aceleration;
  817. _orientation = rotation;
  818. _parent_scene = parent_scene;
  819. //For RigidBody Constructor. The next values might change
  820. float _linearDamping = 0.0f;
  821. float _angularDamping = 0.0f;
  822. float _friction = 0.5f;
  823. float _restitution = 0.0f;
  824. Matrix _startTransform = Matrix.Identity;
  825. Matrix _centerOfMassOffset = Matrix.Identity;
  826. lock (BulletXScene.BulletXLock)
  827. {
  828. _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(pos);
  829. //For now all prims are boxes
  830. CollisionShape _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(_size) / 2.0f);
  831. DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
  832. MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3();
  833. if(_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0
  834. rigidBody = new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution);
  835. //rigidBody.ActivationState = ActivationState.DisableDeactivation;
  836. //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
  837. MonoXnaCompactMaths.Vector3 _vDebugTranslation;
  838. _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
  839. rigidBody.Translate(_vDebugTranslation);
  840. //---
  841. parent_scene.ddWorld.AddRigidBody(rigidBody);
  842. }
  843. }
  844. public override PhysicsVector Position
  845. {
  846. get
  847. {
  848. return _position;
  849. }
  850. set
  851. {
  852. lock (BulletXScene.BulletXLock)
  853. {
  854. _position = value;
  855. Translate();
  856. }
  857. }
  858. }
  859. public override PhysicsVector Velocity
  860. {
  861. get
  862. {
  863. return _velocity;
  864. }
  865. set
  866. {
  867. lock (BulletXScene.BulletXLock)
  868. {
  869. //Static objects don' have linear velocity
  870. if (_physical)
  871. {
  872. _velocity = value;
  873. Speed();
  874. }
  875. else
  876. {
  877. _velocity = new PhysicsVector();
  878. }
  879. }
  880. }
  881. }
  882. public override PhysicsVector Size
  883. {
  884. get
  885. {
  886. return _size;
  887. }
  888. set
  889. {
  890. lock (BulletXScene.BulletXLock)
  891. {
  892. _size = value;
  893. ReSize();
  894. }
  895. }
  896. }
  897. public override PhysicsVector Acceleration
  898. {
  899. get
  900. {
  901. return _acceleration;
  902. }
  903. }
  904. public override AxiomQuaternion Orientation
  905. {
  906. get
  907. {
  908. return _orientation;
  909. }
  910. set
  911. {
  912. lock (BulletXScene.BulletXLock)
  913. {
  914. _orientation = value;
  915. ReOrient();
  916. }
  917. }
  918. }
  919. public float Mass
  920. {
  921. get
  922. {
  923. //For now all prims are boxes
  924. return (_physical ? 1 : 0) * _density * _size.X * _size.Y * _size.Z;
  925. }
  926. }
  927. public RigidBody RigidBody
  928. {
  929. get
  930. {
  931. return rigidBody;
  932. }
  933. }
  934. public override bool Flying
  935. {
  936. get
  937. {
  938. return false; //no flying prims for you
  939. }
  940. set
  941. {
  942. }
  943. }
  944. public Boolean Physical
  945. {
  946. get
  947. {
  948. return _physical;
  949. }
  950. set
  951. {
  952. _physical = value;
  953. }
  954. }
  955. public void SetAcceleration(PhysicsVector accel)
  956. {
  957. lock (BulletXScene.BulletXLock)
  958. {
  959. _acceleration = accel;
  960. }
  961. }
  962. public override bool Kinematic
  963. {
  964. get
  965. {
  966. return false;
  967. //return this._prim.Kinematic;
  968. }
  969. set
  970. {
  971. //this._prim.Kinematic = value;
  972. }
  973. }
  974. public override void AddForce(PhysicsVector force)
  975. {
  976. }
  977. public override void SetMomentum(PhysicsVector momentum)
  978. {
  979. }
  980. internal void ValidateHeight(float heighmapPositionValue)
  981. {
  982. if (rigidBody.CenterOfMassPosition.Z < heighmapPositionValue + _size.Z / 2.0f)
  983. {
  984. Matrix m = rigidBody.WorldTransform;
  985. MonoXnaCompactMaths.Vector3 v3 = m.Translation;
  986. v3.Z = heighmapPositionValue + _size.Z / 2.0f;
  987. m.Translation = v3;
  988. rigidBody.WorldTransform = m;
  989. //When a Prim touch the ground it's vertical velocity it's reduced to ZERO
  990. //Static objects don't have linear velocity
  991. if(_physical)
  992. Speed(new PhysicsVector(this.rigidBody.LinearVelocity.X, this.rigidBody.LinearVelocity.Y, 0.0f));
  993. }
  994. }
  995. internal void UpdateKinetics()
  996. {
  997. if (_physical) //Updates properties. Prim updates its properties physically
  998. {
  999. this._position = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.CenterOfMassPosition);
  1000. this._velocity = BulletXMaths.XnaVector3ToPhysicsVector(rigidBody.LinearVelocity);
  1001. this._orientation = BulletXMaths.XnaQuaternionToAxiomQuaternion(rigidBody.Orientation);
  1002. }
  1003. else //Doesn't updates properties. That's a cancel
  1004. {
  1005. Translate();
  1006. //Speed(); //<- Static objects don't have linear velocity
  1007. ReOrient();
  1008. }
  1009. }
  1010. #region Methods for updating values of RigidBody
  1011. private void Translate()
  1012. {
  1013. Translate(this._position);
  1014. }
  1015. private void Translate(PhysicsVector _newPos)
  1016. {
  1017. MonoXnaCompactMaths.Vector3 _translation;
  1018. _translation = BulletXMaths.PhysicsVectorToXnaVector3(_newPos) - rigidBody.CenterOfMassPosition;
  1019. rigidBody.Translate(_translation);
  1020. }
  1021. private void Speed()
  1022. {
  1023. Speed(this._velocity);
  1024. }
  1025. private void Speed(PhysicsVector _newSpeed)
  1026. {
  1027. MonoXnaCompactMaths.Vector3 _speed;
  1028. _speed = BulletXMaths.PhysicsVectorToXnaVector3(_newSpeed);
  1029. rigidBody.LinearVelocity = _speed;
  1030. }
  1031. private void ReSize()
  1032. {
  1033. ReSize(this._size);
  1034. }
  1035. private void ReSize(PhysicsVector _newSize)
  1036. {
  1037. //I wonder to know how to resize with a simple instruction in BulletX. It seems that for now there isn't
  1038. //so i have to do it manually. That's recreating rigidbody
  1039. MonoXnaCompactMaths.Vector3 _newsize;
  1040. _newsize = BulletXMaths.PhysicsVectorToXnaVector3(_newSize);
  1041. if ((_newsize.X == 0) || (_newsize.Y == 0) || (_newsize.Z == 0)) throw new Exception("Size 0");
  1042. //For RigidBody Constructor. The next values might change
  1043. float _linearDamping = 0.0f;
  1044. float _angularDamping = 0.0f;
  1045. float _friction = 0.5f;
  1046. float _restitution = 0.0f;
  1047. Matrix _startTransform = Matrix.Identity;
  1048. Matrix _centerOfMassOffset = Matrix.Identity;
  1049. RigidBody _tmpRigidBody;
  1050. _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(this._position);
  1051. //For now all prims are boxes
  1052. CollisionShape _collisionShape = new XnaDevRu.BulletX.BoxShape(BulletXMaths.PhysicsVectorToXnaVector3(_newSize) / 2.0f);
  1053. DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
  1054. MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3();
  1055. if (_physical) _collisionShape.CalculateLocalInertia(Mass, out _localInertia); //Always when mass > 0
  1056. _tmpRigidBody = new RigidBody(Mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution);
  1057. //rigidBody.ActivationState = ActivationState.DisableDeactivation;
  1058. //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
  1059. MonoXnaCompactMaths.Vector3 _vDebugTranslation;
  1060. _vDebugTranslation = _startTransform.Translation - rigidBody.CenterOfMassPosition;
  1061. _tmpRigidBody.Translate(_vDebugTranslation);
  1062. //---
  1063. //There is a bug when trying to remove a rigidBody that is colliding with something..
  1064. try
  1065. {
  1066. this._parent_scene.ddWorld.RemoveRigidBody(rigidBody);
  1067. }
  1068. catch(Exception ex)
  1069. {
  1070. this._parent_scene.BulletXMessage(this._parent_scene.is_ex_message + ex.Message, true);
  1071. rigidBody.ActivationState = ActivationState.DisableSimulation;
  1072. this._parent_scene.AddForgottenRigidBody(rigidBody);
  1073. }
  1074. rigidBody = _tmpRigidBody;
  1075. this._parent_scene.ddWorld.AddRigidBody(rigidBody);
  1076. if (_physical) Speed();//Static objects don't have linear velocity
  1077. ReOrient();
  1078. GC.Collect();
  1079. }
  1080. private void ReOrient()
  1081. {
  1082. ReOrient(this._orientation);
  1083. }
  1084. private void ReOrient(AxiomQuaternion _newOrient)
  1085. {
  1086. MonoXnaCompactMaths.Quaternion _newOrientation;
  1087. _newOrientation = BulletXMaths.AxiomQuaternionToXnaQuaternion(_newOrient);
  1088. Matrix _comTransform = rigidBody.CenterOfMassTransform;
  1089. BulletXMaths.SetRotation(ref _comTransform, _newOrientation);
  1090. rigidBody.CenterOfMassTransform = _comTransform;
  1091. }
  1092. #endregion
  1093. }
  1094. /// <summary>
  1095. /// This Class manage a HeighField as a RigidBody. This is for to be added in the BulletXScene
  1096. /// </summary>
  1097. internal class BulletXPlanet
  1098. {
  1099. private PhysicsVector _staticPosition;
  1100. private PhysicsVector _staticVelocity;
  1101. private AxiomQuaternion _staticOrientation;
  1102. private float _mass;
  1103. private BulletXScene _parentscene;
  1104. internal float[] _heightField;
  1105. private RigidBody _flatPlanet;
  1106. internal RigidBody RigidBody { get { return _flatPlanet; } }
  1107. internal BulletXPlanet(BulletXScene parent_scene, float[] heightField)
  1108. {
  1109. _staticPosition = new PhysicsVector(BulletXScene.MaxXY / 2, BulletXScene.MaxXY/2, 0);
  1110. _staticVelocity = new PhysicsVector();
  1111. _staticOrientation = AxiomQuaternion.Identity;
  1112. _mass = 0; //No active
  1113. _parentscene = parent_scene;
  1114. _heightField = heightField;
  1115. float _linearDamping = 0.0f;
  1116. float _angularDamping = 0.0f;
  1117. float _friction = 0.5f;
  1118. float _restitution = 0.0f;
  1119. Matrix _startTransform = Matrix.Identity;
  1120. Matrix _centerOfMassOffset = Matrix.Identity;
  1121. lock (BulletXScene.BulletXLock)
  1122. {
  1123. try
  1124. {
  1125. _startTransform.Translation = BulletXMaths.PhysicsVectorToXnaVector3(_staticPosition);
  1126. CollisionShape _collisionShape = new HeightfieldTerrainShape(BulletXScene.MaxXY, BulletXScene.MaxXY, _heightField, (float)BulletXScene.MaxZ, 2, true, false);
  1127. DefaultMotionState _motionState = new DefaultMotionState(_startTransform, _centerOfMassOffset);
  1128. MonoXnaCompactMaths.Vector3 _localInertia = new MonoXnaCompactMaths.Vector3();
  1129. //_collisionShape.CalculateLocalInertia(_mass, out _localInertia); //Always when mass > 0
  1130. _flatPlanet = new RigidBody(_mass, _motionState, _collisionShape, _localInertia, _linearDamping, _angularDamping, _friction, _restitution);
  1131. //It's seems that there are a bug with rigidBody constructor and its CenterOfMassPosition
  1132. MonoXnaCompactMaths.Vector3 _vDebugTranslation;
  1133. _vDebugTranslation = _startTransform.Translation - _flatPlanet.CenterOfMassPosition;
  1134. _flatPlanet.Translate(_vDebugTranslation);
  1135. parent_scene.ddWorld.AddRigidBody(_flatPlanet);
  1136. }
  1137. catch (Exception ex)
  1138. {
  1139. this._parentscene.BulletXMessage(ex.Message, true);
  1140. }
  1141. }
  1142. this._parentscene.BulletXMessage("BulletXPlanet created.", false);
  1143. }
  1144. internal float HeightValue(MonoXnaCompactMaths.Vector3 position)
  1145. {
  1146. int li_x, li_y;
  1147. float height;
  1148. li_x = (int)Math.Round(position.X);
  1149. if (li_x < 0) li_x = 0;
  1150. if (li_x >= BulletXScene.MaxXY) li_x = BulletXScene.MaxXY - 1;
  1151. li_y = (int)Math.Round(position.Y);
  1152. if (li_y < 0) li_y = 0;
  1153. if (li_y >= BulletXScene.MaxXY) li_y = BulletXScene.MaxXY - 1;
  1154. height = ((HeightfieldTerrainShape)this._flatPlanet.CollisionShape).getHeightFieldValue(li_x, li_y);
  1155. if (height < 0) height = 0;
  1156. else if (height > BulletXScene.MaxZ) height = BulletXScene.MaxZ;
  1157. return height;
  1158. }
  1159. }
  1160. }