ODEDynamics.cs 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  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. /* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
  28. * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
  29. * ODEPrim.cs contains methods dealing with Prim editing, Prim
  30. * characteristics and Kinetic motion.
  31. * ODEDynamics.cs contains methods dealing with Prim Physical motion
  32. * (dynamics) and the associated settings. Old Linear and angular
  33. * motors for dynamic motion have been replace with MoveLinear()
  34. * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
  35. * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
  36. * switch between 'VEHICLE' parameter use and general dynamics
  37. * settings use.
  38. */
  39. // Extensive change Ubit 2012
  40. using System;
  41. using OpenMetaverse;
  42. using OpenSim.Region.PhysicsModules.SharedBase;
  43. namespace OpenSim.Region.PhysicsModule.ubOde
  44. {
  45. public class ODEDynamics
  46. {
  47. public Vehicle Type
  48. {
  49. get { return m_type; }
  50. }
  51. private readonly OdePrim rootPrim;
  52. private readonly ODEScene _pParentScene;
  53. // Vehicle properties
  54. // WARNING this are working copies for internel use
  55. // their values may not be the corresponding parameter
  56. private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
  57. private Quaternion m_RollreferenceFrame = Quaternion.Identity; // what hell is this ?
  58. private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
  59. private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
  60. // HOVER_TERRAIN_ONLY
  61. // HOVER_GLOBAL_HEIGHT
  62. // NO_DEFLECTION_UP
  63. // HOVER_WATER_ONLY
  64. // HOVER_UP_ONLY
  65. // LIMIT_MOTOR_UP
  66. // LIMIT_ROLL_ONLY
  67. private Vector3 m_BlockingEndPoint = Vector3.Zero; // not sl
  68. // Linear properties
  69. private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
  70. private Vector3 m_linearFrictionTimescale = new(1000f, 1000f, 1000f);
  71. private float m_linearMotorDecayTimescale = 120f;
  72. private float m_linearMotorTimescale = 1000f;
  73. private Vector3 m_linearMotorOffset = Vector3.Zero;
  74. //Angular properties
  75. private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
  76. private float m_angularMotorTimescale = 1000f; // motor angular velocity ramp up rate
  77. private float m_angularMotorDecayTimescale = 120f; // motor angular velocity decay rate
  78. private Vector3 m_angularFrictionTimescale = new(1000f, 1000f, 1000f); // body angular velocity decay rate
  79. //Deflection properties
  80. private float m_angularDeflectionEfficiency = 0f;
  81. private float m_angularDeflectionTimescale = 1000f;
  82. private float m_linearDeflectionEfficiency = 0f;
  83. private float m_linearDeflectionTimescale = 1000f;
  84. //Banking properties
  85. private float m_bankingEfficiency = 0f;
  86. private float m_bankingMix = 0f;
  87. private float m_bankingTimescale = 1000f;
  88. //Hover and Buoyancy properties
  89. private float m_VhoverHeight = 0f;
  90. private float m_VhoverEfficiency = 0f;
  91. private float m_VhoverTimescale = 1000f;
  92. private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
  93. // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
  94. // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
  95. // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
  96. //Attractor properties
  97. private float m_verticalAttractionEfficiency = 1.0f; // damped
  98. private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
  99. // auxiliar
  100. private float m_lmEfect = 0f; // current linear motor eficiency
  101. private float m_lmDecay = 0f; // current linear decay
  102. private float m_amEfect = 0; // current angular motor eficiency
  103. private float m_amDecay = 0f; // current linear decay
  104. private float m_ffactor = 1.0f;
  105. private readonly float m_timestep = 0.02f;
  106. private readonly float m_invtimestep = 50;
  107. float m_ampwr;
  108. float m_amdampX;
  109. float m_amdampY;
  110. float m_amdampZ;
  111. float m_gravmod;
  112. public float FrictionFactor
  113. {
  114. get
  115. {
  116. return m_ffactor;
  117. }
  118. }
  119. public float GravMod
  120. {
  121. set
  122. {
  123. m_gravmod = value;
  124. }
  125. }
  126. public ODEDynamics(OdePrim rootp)
  127. {
  128. rootPrim = rootp;
  129. _pParentScene = rootPrim.m_parentScene;
  130. m_timestep = _pParentScene.ODE_STEPSIZE;
  131. m_invtimestep = 1.0f / m_timestep;
  132. m_gravmod = rootPrim.GravModifier;
  133. }
  134. public void DoSetVehicle(VehicleData vd)
  135. {
  136. m_type = vd.m_type;
  137. m_flags = vd.m_flags;
  138. // Linear properties
  139. m_linearMotorDirection = vd.m_linearMotorDirection;
  140. m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
  141. if (m_linearFrictionTimescale.X < m_timestep) m_linearFrictionTimescale.X = m_timestep;
  142. if (m_linearFrictionTimescale.Y < m_timestep) m_linearFrictionTimescale.Y = m_timestep;
  143. if (m_linearFrictionTimescale.Z < m_timestep) m_linearFrictionTimescale.Z = m_timestep;
  144. m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
  145. if (m_linearMotorDecayTimescale < m_timestep) m_linearMotorDecayTimescale = m_timestep;
  146. m_linearMotorDecayTimescale += 0.2f;
  147. m_linearMotorDecayTimescale *= m_invtimestep;
  148. m_linearMotorTimescale = vd.m_linearMotorTimescale;
  149. if (m_linearMotorTimescale < m_timestep) m_linearMotorTimescale = m_timestep;
  150. m_linearMotorOffset = vd.m_linearMotorOffset;
  151. //Angular properties
  152. m_angularMotorDirection = vd.m_angularMotorDirection;
  153. m_angularMotorTimescale = vd.m_angularMotorTimescale;
  154. if (m_angularMotorTimescale < m_timestep) m_angularMotorTimescale = m_timestep;
  155. m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
  156. if (m_angularMotorDecayTimescale < m_timestep) m_angularMotorDecayTimescale = m_timestep;
  157. m_angularMotorDecayTimescale *= m_invtimestep;
  158. m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
  159. if (m_angularFrictionTimescale.X < m_timestep) m_angularFrictionTimescale.X = m_timestep;
  160. if (m_angularFrictionTimescale.Y < m_timestep) m_angularFrictionTimescale.Y = m_timestep;
  161. if (m_angularFrictionTimescale.Z < m_timestep) m_angularFrictionTimescale.Z = m_timestep;
  162. //Deflection properties
  163. m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
  164. m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
  165. if (m_angularDeflectionTimescale < m_timestep) m_angularDeflectionTimescale = m_timestep;
  166. m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
  167. m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
  168. if (m_linearDeflectionTimescale < m_timestep) m_linearDeflectionTimescale = m_timestep;
  169. //Banking properties
  170. m_bankingEfficiency = vd.m_bankingEfficiency;
  171. m_bankingMix = vd.m_bankingMix;
  172. m_bankingTimescale = vd.m_bankingTimescale;
  173. if (m_bankingTimescale < m_timestep) m_bankingTimescale = m_timestep;
  174. //Hover and Buoyancy properties
  175. m_VhoverHeight = vd.m_VhoverHeight;
  176. m_VhoverEfficiency = vd.m_VhoverEfficiency;
  177. m_VhoverTimescale = vd.m_VhoverTimescale;
  178. if (m_VhoverTimescale < m_timestep) m_VhoverTimescale = m_timestep;
  179. m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
  180. //Attractor properties
  181. m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
  182. m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
  183. if (m_verticalAttractionTimescale < m_timestep) m_verticalAttractionTimescale = m_timestep;
  184. // Axis
  185. m_referenceFrame = vd.m_referenceFrame;
  186. m_lmEfect = 0;
  187. m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
  188. m_amEfect = 0;
  189. m_ffactor = 1.0f;
  190. }
  191. internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
  192. {
  193. float len;
  194. if(float.IsNaN(pValue) || float.IsInfinity(pValue))
  195. return;
  196. switch (pParam)
  197. {
  198. case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
  199. if (pValue < 0f) pValue = 0f;
  200. if (pValue > 1f) pValue = 1f;
  201. m_angularDeflectionEfficiency = pValue;
  202. break;
  203. case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
  204. if (pValue < m_timestep) pValue = m_timestep;
  205. m_angularDeflectionTimescale = pValue;
  206. break;
  207. case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
  208. if (pValue < m_timestep) pValue = m_timestep;
  209. else if (pValue > 120) pValue = 120;
  210. m_angularMotorDecayTimescale = pValue * m_invtimestep;
  211. m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
  212. break;
  213. case Vehicle.ANGULAR_MOTOR_TIMESCALE:
  214. if (pValue < m_timestep) pValue = m_timestep;
  215. m_angularMotorTimescale = pValue;
  216. break;
  217. case Vehicle.BANKING_EFFICIENCY:
  218. if (pValue < -1f) pValue = -1f;
  219. if (pValue > 1f) pValue = 1f;
  220. m_bankingEfficiency = pValue;
  221. break;
  222. case Vehicle.BANKING_MIX:
  223. if (pValue < 0f) pValue = 0f;
  224. if (pValue > 1f) pValue = 1f;
  225. m_bankingMix = pValue;
  226. break;
  227. case Vehicle.BANKING_TIMESCALE:
  228. if (pValue < m_timestep) pValue = m_timestep;
  229. m_bankingTimescale = pValue;
  230. break;
  231. case Vehicle.BUOYANCY:
  232. if (pValue < -1f) pValue = -1f;
  233. if (pValue > 1f) pValue = 1f;
  234. m_VehicleBuoyancy = pValue;
  235. break;
  236. case Vehicle.HOVER_EFFICIENCY:
  237. if (pValue < 0f) pValue = 0f;
  238. if (pValue > 1f) pValue = 1f;
  239. m_VhoverEfficiency = pValue;
  240. break;
  241. case Vehicle.HOVER_HEIGHT:
  242. m_VhoverHeight = pValue;
  243. break;
  244. case Vehicle.HOVER_TIMESCALE:
  245. if (pValue < m_timestep) pValue = m_timestep;
  246. m_VhoverTimescale = pValue;
  247. break;
  248. case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
  249. if (pValue < 0f) pValue = 0f;
  250. if (pValue > 1f) pValue = 1f;
  251. m_linearDeflectionEfficiency = pValue;
  252. break;
  253. case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
  254. if (pValue < m_timestep) pValue = m_timestep;
  255. m_linearDeflectionTimescale = pValue;
  256. break;
  257. case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
  258. if (pValue < m_timestep) pValue = m_timestep;
  259. else if (pValue > 120) pValue = 120;
  260. m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
  261. m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
  262. break;
  263. case Vehicle.LINEAR_MOTOR_TIMESCALE:
  264. if (pValue < m_timestep) pValue = m_timestep;
  265. m_linearMotorTimescale = pValue;
  266. break;
  267. case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
  268. if (pValue < 0f) pValue = 0f;
  269. if (pValue > 1f) pValue = 1f;
  270. m_verticalAttractionEfficiency = pValue;
  271. break;
  272. case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
  273. if (pValue < m_timestep) pValue = m_timestep;
  274. m_verticalAttractionTimescale = pValue;
  275. break;
  276. // These are vector properties but the engine lets you use a single float value to
  277. // set all of the components to the same value
  278. case Vehicle.ANGULAR_FRICTION_TIMESCALE:
  279. if (pValue < m_timestep) pValue = m_timestep;
  280. m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
  281. break;
  282. case Vehicle.ANGULAR_MOTOR_DIRECTION:
  283. m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
  284. len = m_angularMotorDirection.Length();
  285. if (len > 12.566f)
  286. m_angularMotorDirection *= (12.566f / len);
  287. m_amEfect = 1.0f ; // turn it on
  288. m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
  289. if (rootPrim.Body != IntPtr.Zero && !UBOdeNative.BodyIsEnabled(rootPrim.Body)
  290. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  291. UBOdeNative.BodyEnable(rootPrim.Body);
  292. break;
  293. case Vehicle.LINEAR_FRICTION_TIMESCALE:
  294. if (pValue < m_timestep) pValue = m_timestep;
  295. m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
  296. break;
  297. case Vehicle.LINEAR_MOTOR_DIRECTION:
  298. m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
  299. len = m_linearMotorDirection.Length();
  300. if (len > 100.0f)
  301. m_linearMotorDirection *= (100.0f / len);
  302. m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
  303. m_lmEfect = 1.0f; // turn it on
  304. m_ffactor = 0.0f;
  305. if (rootPrim.Body != IntPtr.Zero && !UBOdeNative.BodyIsEnabled(rootPrim.Body)
  306. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  307. UBOdeNative.BodyEnable(rootPrim.Body);
  308. break;
  309. case Vehicle.LINEAR_MOTOR_OFFSET:
  310. m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
  311. len = m_linearMotorOffset.Length();
  312. if (len > 100.0f)
  313. m_linearMotorOffset *= (100.0f / len);
  314. break;
  315. }
  316. }//end ProcessFloatVehicleParam
  317. internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
  318. {
  319. float len;
  320. if(!pValue.IsFinite())
  321. return;
  322. switch (pParam)
  323. {
  324. case Vehicle.ANGULAR_FRICTION_TIMESCALE:
  325. if (pValue.X < m_timestep) pValue.X = m_timestep;
  326. if (pValue.Y < m_timestep) pValue.Y = m_timestep;
  327. if (pValue.Z < m_timestep) pValue.Z = m_timestep;
  328. m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
  329. break;
  330. case Vehicle.ANGULAR_MOTOR_DIRECTION:
  331. m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
  332. // Limit requested angular speed to 2 rps= 4 pi rads/sec
  333. len = m_angularMotorDirection.Length();
  334. if (len > 12.566f)
  335. m_angularMotorDirection *= (12.566f / len);
  336. m_amEfect = 1.0f; // turn it on
  337. m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
  338. if (rootPrim.Body != IntPtr.Zero && !UBOdeNative.BodyIsEnabled(rootPrim.Body)
  339. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  340. UBOdeNative.BodyEnable(rootPrim.Body);
  341. break;
  342. case Vehicle.LINEAR_FRICTION_TIMESCALE:
  343. if (pValue.X < m_timestep) pValue.X = m_timestep;
  344. if (pValue.Y < m_timestep) pValue.Y = m_timestep;
  345. if (pValue.Z < m_timestep) pValue.Z = m_timestep;
  346. m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
  347. break;
  348. case Vehicle.LINEAR_MOTOR_DIRECTION:
  349. m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
  350. len = m_linearMotorDirection.Length();
  351. if (len > 100.0f)
  352. m_linearMotorDirection *= (100.0f / len);
  353. m_lmEfect = 1.0f; // turn it on
  354. m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
  355. m_ffactor = 0.0f;
  356. if (rootPrim.Body != IntPtr.Zero && !UBOdeNative.BodyIsEnabled(rootPrim.Body)
  357. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  358. UBOdeNative.BodyEnable(rootPrim.Body);
  359. break;
  360. case Vehicle.LINEAR_MOTOR_OFFSET:
  361. m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
  362. len = m_linearMotorOffset.Length();
  363. if (len > 100.0f)
  364. m_linearMotorOffset *= (100.0f / len);
  365. break;
  366. case Vehicle.BLOCK_EXIT:
  367. m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
  368. break;
  369. }
  370. }//end ProcessVectorVehicleParam
  371. internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
  372. {
  373. switch (pParam)
  374. {
  375. case Vehicle.REFERENCE_FRAME:
  376. // m_referenceFrame = Quaternion.Inverse(pValue);
  377. m_referenceFrame = pValue;
  378. break;
  379. case Vehicle.ROLL_FRAME:
  380. m_RollreferenceFrame = pValue;
  381. break;
  382. }
  383. }//end ProcessRotationVehicleParam
  384. internal void ProcessVehicleFlags(int pParam, bool remove)
  385. {
  386. if (remove)
  387. {
  388. m_flags &= ~((VehicleFlag)pParam);
  389. }
  390. else
  391. {
  392. m_flags |= (VehicleFlag)pParam;
  393. }
  394. }//end ProcessVehicleFlags
  395. internal void ProcessTypeChange(Vehicle pType)
  396. {
  397. m_lmEfect = 0;
  398. m_amEfect = 0;
  399. m_ffactor = 1f;
  400. m_linearMotorDirection = Vector3.Zero;
  401. m_angularMotorDirection = Vector3.Zero;
  402. m_BlockingEndPoint = Vector3.Zero;
  403. m_RollreferenceFrame = Quaternion.Identity;
  404. m_linearMotorOffset = Vector3.Zero;
  405. m_referenceFrame = Quaternion.Identity;
  406. // Set Defaults For Type
  407. m_type = pType;
  408. switch (pType)
  409. {
  410. case Vehicle.TYPE_NONE:
  411. m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
  412. m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
  413. m_linearMotorTimescale = 1000;
  414. m_linearMotorDecayTimescale = 120 * m_invtimestep;
  415. m_angularMotorTimescale = 1000;
  416. m_angularMotorDecayTimescale = 1000 * m_invtimestep;
  417. m_VhoverHeight = 0;
  418. m_VhoverEfficiency = 1;
  419. m_VhoverTimescale = 1000;
  420. m_VehicleBuoyancy = 0;
  421. m_linearDeflectionEfficiency = 0;
  422. m_linearDeflectionTimescale = 1000;
  423. m_angularDeflectionEfficiency = 0;
  424. m_angularDeflectionTimescale = 1000;
  425. m_bankingEfficiency = 0;
  426. m_bankingMix = 1;
  427. m_bankingTimescale = 1000;
  428. m_verticalAttractionEfficiency = 0;
  429. m_verticalAttractionTimescale = 1000;
  430. m_flags = (VehicleFlag)0;
  431. break;
  432. case Vehicle.TYPE_SLED:
  433. m_linearFrictionTimescale = new Vector3(30, 1, 1000);
  434. m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
  435. m_linearMotorTimescale = 1000;
  436. m_linearMotorDecayTimescale = 120 * m_invtimestep;
  437. m_angularMotorTimescale = 1000;
  438. m_angularMotorDecayTimescale = 120 * m_invtimestep;
  439. m_VhoverHeight = 0;
  440. m_VhoverEfficiency = 1;
  441. m_VhoverTimescale = 10;
  442. m_VehicleBuoyancy = 0;
  443. m_linearDeflectionEfficiency = 1;
  444. m_linearDeflectionTimescale = 1;
  445. m_angularDeflectionEfficiency = 0;
  446. m_angularDeflectionTimescale = 10;
  447. m_verticalAttractionEfficiency = 1;
  448. m_verticalAttractionTimescale = 1000;
  449. m_bankingEfficiency = 0;
  450. m_bankingMix = 1;
  451. m_bankingTimescale = 10;
  452. m_flags &=
  453. ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
  454. VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
  455. m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
  456. VehicleFlag.LIMIT_ROLL_ONLY |
  457. VehicleFlag.LIMIT_MOTOR_UP);
  458. break;
  459. case Vehicle.TYPE_CAR:
  460. m_linearFrictionTimescale = new Vector3(100, 2, 1000);
  461. m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
  462. m_linearMotorTimescale = 1;
  463. m_linearMotorDecayTimescale = 60 * m_invtimestep;
  464. m_angularMotorTimescale = 1;
  465. m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
  466. m_VhoverHeight = 0;
  467. m_VhoverEfficiency = 0;
  468. m_VhoverTimescale = 1000;
  469. m_VehicleBuoyancy = 0;
  470. m_linearDeflectionEfficiency = 1;
  471. m_linearDeflectionTimescale = 2;
  472. m_angularDeflectionEfficiency = 0;
  473. m_angularDeflectionTimescale = 10;
  474. m_verticalAttractionEfficiency = 1f;
  475. m_verticalAttractionTimescale = 10f;
  476. m_bankingEfficiency = -0.2f;
  477. m_bankingMix = 1;
  478. m_bankingTimescale = 1;
  479. m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
  480. VehicleFlag.HOVER_TERRAIN_ONLY |
  481. VehicleFlag.HOVER_GLOBAL_HEIGHT);
  482. m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
  483. VehicleFlag.LIMIT_ROLL_ONLY |
  484. VehicleFlag.LIMIT_MOTOR_UP |
  485. VehicleFlag.HOVER_UP_ONLY);
  486. break;
  487. case Vehicle.TYPE_BOAT:
  488. m_linearFrictionTimescale = new Vector3(10, 3, 2);
  489. m_angularFrictionTimescale = new Vector3(10, 10, 10);
  490. m_linearMotorTimescale = 5;
  491. m_linearMotorDecayTimescale = 60 * m_invtimestep;
  492. m_angularMotorTimescale = 4;
  493. m_angularMotorDecayTimescale = 4 * m_invtimestep;
  494. m_VhoverHeight = 0;
  495. m_VhoverEfficiency = 0.5f;
  496. m_VhoverTimescale = 2;
  497. m_VehicleBuoyancy = 1;
  498. m_linearDeflectionEfficiency = 0.5f;
  499. m_linearDeflectionTimescale = 3;
  500. m_angularDeflectionEfficiency = 0.5f;
  501. m_angularDeflectionTimescale = 5;
  502. m_verticalAttractionEfficiency = 0.5f;
  503. m_verticalAttractionTimescale = 5f;
  504. m_bankingEfficiency = -0.3f;
  505. m_bankingMix = 0.8f;
  506. m_bankingTimescale = 1;
  507. m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
  508. VehicleFlag.HOVER_GLOBAL_HEIGHT |
  509. VehicleFlag.HOVER_UP_ONLY); // |
  510. // VehicleFlag.LIMIT_ROLL_ONLY);
  511. m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
  512. VehicleFlag.LIMIT_MOTOR_UP |
  513. VehicleFlag.HOVER_UP_ONLY | // new sl
  514. VehicleFlag.HOVER_WATER_ONLY);
  515. break;
  516. case Vehicle.TYPE_AIRPLANE:
  517. m_linearFrictionTimescale = new Vector3(200, 10, 5);
  518. m_angularFrictionTimescale = new Vector3(20, 20, 20);
  519. m_linearMotorTimescale = 2;
  520. m_linearMotorDecayTimescale = 60 * m_invtimestep;
  521. m_angularMotorTimescale = 4;
  522. m_angularMotorDecayTimescale = 8 * m_invtimestep;
  523. m_VhoverHeight = 0;
  524. m_VhoverEfficiency = 0.5f;
  525. m_VhoverTimescale = 1000;
  526. m_VehicleBuoyancy = 0;
  527. m_linearDeflectionEfficiency = 0.5f;
  528. m_linearDeflectionTimescale = 0.5f;
  529. m_angularDeflectionEfficiency = 1;
  530. m_angularDeflectionTimescale = 2;
  531. m_verticalAttractionEfficiency = 0.9f;
  532. m_verticalAttractionTimescale = 2f;
  533. m_bankingEfficiency = 1;
  534. m_bankingMix = 0.7f;
  535. m_bankingTimescale = 2;
  536. m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
  537. VehicleFlag.HOVER_TERRAIN_ONLY |
  538. VehicleFlag.HOVER_GLOBAL_HEIGHT |
  539. VehicleFlag.HOVER_UP_ONLY |
  540. VehicleFlag.NO_DEFLECTION_UP |
  541. VehicleFlag.LIMIT_MOTOR_UP);
  542. m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
  543. break;
  544. case Vehicle.TYPE_BALLOON:
  545. m_linearFrictionTimescale = new Vector3(5, 5, 5);
  546. m_angularFrictionTimescale = new Vector3(10, 10, 10);
  547. m_linearMotorTimescale = 5;
  548. m_linearMotorDecayTimescale = 60 * m_invtimestep;
  549. m_angularMotorTimescale = 6;
  550. m_angularMotorDecayTimescale = 10 * m_invtimestep;
  551. m_VhoverHeight = 5;
  552. m_VhoverEfficiency = 0.8f;
  553. m_VhoverTimescale = 10;
  554. m_VehicleBuoyancy = 1;
  555. m_linearDeflectionEfficiency = 0;
  556. m_linearDeflectionTimescale = 5 * m_invtimestep;
  557. m_angularDeflectionEfficiency = 0;
  558. m_angularDeflectionTimescale = 5;
  559. m_verticalAttractionEfficiency = 1f;
  560. m_verticalAttractionTimescale = 1000f;
  561. m_bankingEfficiency = 0;
  562. m_bankingMix = 0.7f;
  563. m_bankingTimescale = 5;
  564. m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
  565. VehicleFlag.HOVER_TERRAIN_ONLY |
  566. VehicleFlag.HOVER_UP_ONLY |
  567. VehicleFlag.NO_DEFLECTION_UP |
  568. VehicleFlag.LIMIT_MOTOR_UP | //);
  569. VehicleFlag.LIMIT_ROLL_ONLY | // new sl
  570. VehicleFlag.HOVER_GLOBAL_HEIGHT); // new sl
  571. // m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
  572. // VehicleFlag.HOVER_GLOBAL_HEIGHT);
  573. break;
  574. }
  575. // disable mouse steering
  576. m_flags &= ~(VehicleFlag.MOUSELOOK_STEER |
  577. VehicleFlag.MOUSELOOK_BANK |
  578. VehicleFlag.CAMERA_DECOUPLED);
  579. m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
  580. m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
  581. }//end SetDefaultsForType
  582. internal void Stop()
  583. {
  584. m_lmEfect = 0;
  585. m_lmDecay = 0f;
  586. m_amEfect = 0;
  587. m_amDecay = 0;
  588. m_ffactor = 1f;
  589. }
  590. public static Vector3 Xrot(Quaternion rot)
  591. {
  592. rot.Normalize(); // just in case
  593. return Vector3.UnitXRotated(rot);
  594. }
  595. private const float pi = MathF.PI;
  596. private const float halfpi = 0.5f * MathF.PI;
  597. public static Vector3 ubRot2Euler(Quaternion rot)
  598. {
  599. // returns roll in X
  600. // pitch in Y
  601. // yaw in Z
  602. Vector3 vec;
  603. // assuming rot is normalised
  604. // rot.Normalize();
  605. float zX = rot.X * rot.Z + rot.Y * rot.W;
  606. if (zX < -0.49999f)
  607. {
  608. vec.X = 0;
  609. vec.Y = -halfpi;
  610. vec.Z = -2f * MathF.Atan(rot.X / rot.W);
  611. }
  612. else if (zX > 0.49999f)
  613. {
  614. vec.X = 0;
  615. vec.Y = halfpi;
  616. vec.Z = 2f * MathF.Atan(rot.X / rot.W);
  617. }
  618. else
  619. {
  620. vec.Y = MathF.Asin(2 * zX);
  621. float sqw = rot.W * rot.W;
  622. float minuszY = rot.X * rot.W - rot.Y * rot.Z;
  623. float zZ = rot.Z * rot.Z + sqw - 0.5f;
  624. vec.X = MathF.Atan2(minuszY, zZ);
  625. float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
  626. float yY = rot.X * rot.X + sqw - 0.5f;
  627. vec.Z = MathF.Atan2(yX, yY);
  628. }
  629. return vec;
  630. }
  631. public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
  632. {
  633. // assuming rot is normalised
  634. // rot.Normalize();
  635. float zX = rot.X * rot.Z + rot.Y * rot.W;
  636. if (zX < -0.49999f)
  637. {
  638. roll = 0;
  639. pitch = -halfpi;
  640. }
  641. else if (zX > 0.49999f)
  642. {
  643. roll = 0;
  644. pitch = halfpi;
  645. }
  646. else
  647. {
  648. pitch = MathF.Asin(2 * zX);
  649. float minuszY = rot.X * rot.W - rot.Y * rot.Z;
  650. float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
  651. roll = MathF.Atan2(minuszY, zZ);
  652. }
  653. }
  654. internal void Step()
  655. {
  656. IntPtr Body = rootPrim.Body;
  657. UBOdeNative.BodyGetMass(Body, out UBOdeNative.Mass dmass);
  658. Quaternion objrotq = UBOdeNative.BodyGetQuaternionOMV(Body);
  659. Quaternion rotq = objrotq; // rotq = rotation of object
  660. rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
  661. Quaternion irotq = Quaternion.Inverse(rotq);
  662. Vector3 tmpV;
  663. Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
  664. Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
  665. UBOdeNative.Vector3 dtorque = new();
  666. Vector3 curVel = UBOdeNative.BodyGetLinearVelOMV(Body); // velocity in world
  667. Vector3 curLocalVel = curVel * irotq; // current velocity in local
  668. Vector3 curAngVel = UBOdeNative.BodyGetAngularVelOMV(Body); // angular velocity in world
  669. Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
  670. float ldampZ = 0;
  671. bool mousemode = false;
  672. bool mousemodebank = false;
  673. float bankingEfficiency;
  674. float verticalAttractionTimescale = m_verticalAttractionTimescale;
  675. if((m_flags & (VehicleFlag.MOUSELOOK_STEER | VehicleFlag.MOUSELOOK_BANK)) != 0 )
  676. {
  677. mousemode = true;
  678. mousemodebank = (m_flags & VehicleFlag.MOUSELOOK_BANK) != 0;
  679. if(mousemodebank)
  680. {
  681. bankingEfficiency = m_bankingEfficiency;
  682. if(verticalAttractionTimescale < 149.9)
  683. verticalAttractionTimescale *= 2.0f; // reduce current instability
  684. }
  685. else
  686. bankingEfficiency = 0;
  687. }
  688. else
  689. bankingEfficiency = m_bankingEfficiency;
  690. // linear motor
  691. if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
  692. {
  693. tmpV = m_linearMotorDirection - curLocalVel; // velocity error
  694. tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
  695. tmpV *= rotq; // to world
  696. if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
  697. tmpV.Z = 0;
  698. if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
  699. {
  700. // have offset, do it now
  701. tmpV *= dmass.mass;
  702. UBOdeNative.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
  703. }
  704. else
  705. {
  706. force.X += tmpV.X;
  707. force.Y += tmpV.Y;
  708. force.Z += tmpV.Z;
  709. }
  710. m_lmEfect *= m_lmDecay;
  711. // m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
  712. m_ffactor = 0.0f;
  713. }
  714. else
  715. {
  716. m_lmEfect = 0;
  717. m_ffactor = 1f;
  718. }
  719. // hover
  720. if (m_VhoverTimescale < 300 && rootPrim.m_prim_geom != IntPtr.Zero)
  721. {
  722. UBOdeNative.Vector3 pos = UBOdeNative.GeomGetPosition(rootPrim.m_prim_geom);
  723. pos.Z -= 0.21f; // minor offset that seems to be always there in sl
  724. float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
  725. float perr;
  726. // default to global but don't go underground
  727. perr = m_VhoverHeight - pos.Z;
  728. if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
  729. {
  730. if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
  731. {
  732. perr += _pParentScene.WaterLevel;
  733. }
  734. else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
  735. {
  736. perr += t;
  737. }
  738. else
  739. {
  740. if (t > _pParentScene.WaterLevel)
  741. perr += t;
  742. else
  743. perr += _pParentScene.WaterLevel;
  744. }
  745. }
  746. else if (t > m_VhoverHeight)
  747. perr = t - pos.Z;
  748. if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
  749. {
  750. ldampZ = m_VhoverEfficiency * m_invtimestep;
  751. perr *= (1.0f + ldampZ) / m_VhoverTimescale;
  752. //force.Z += perr - curVel.Z * tmp;
  753. force.Z += perr;
  754. ldampZ *= -curVel.Z;
  755. force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
  756. }
  757. else // no buoyancy
  758. force.Z += _pParentScene.gravityz;
  759. }
  760. else
  761. {
  762. // default gravity and Buoyancy
  763. force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
  764. }
  765. // linear deflection
  766. if (m_linearDeflectionEfficiency > 0)
  767. {
  768. float len = curVel.Length();
  769. if (len > 0.01f) // if moving
  770. {
  771. Vector3 atAxis = Xrot(rotq); // where are we pointing to
  772. atAxis *= len; // make it same size as world velocity vector
  773. tmpV = -atAxis; // oposite direction
  774. atAxis -= curVel; // error to one direction
  775. len = atAxis.LengthSquared();
  776. tmpV -= curVel; // error to oposite
  777. float lens = tmpV.LengthSquared();
  778. if (len > 0.01f || lens > 0.01f) // do nothing if close enougth
  779. {
  780. if (len < lens)
  781. tmpV = atAxis;
  782. tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
  783. force.X += tmpV.X;
  784. force.Y += tmpV.Y;
  785. if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
  786. force.Z += tmpV.Z;
  787. }
  788. }
  789. }
  790. // linear friction/damping
  791. if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
  792. {
  793. tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
  794. tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
  795. tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
  796. tmpV *= rotq; // to world
  797. if(ldampZ != 0 && MathF.Abs(ldampZ) > MathF.Abs(tmpV.Z))
  798. tmpV.Z = ldampZ;
  799. force.X += tmpV.X;
  800. force.Y += tmpV.Y;
  801. force.Z += tmpV.Z;
  802. }
  803. // vertical atractor
  804. if (verticalAttractionTimescale < 300)
  805. {
  806. float ftmp = m_invtimestep / verticalAttractionTimescale / verticalAttractionTimescale;
  807. float ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
  808. m_amdampX = ftmp2;
  809. m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
  810. GetRollPitch(irotq, out float roll, out float pitch);
  811. if (roll > halfpi)
  812. roll = pi - roll;
  813. else if (roll < -halfpi)
  814. roll = -pi - roll;
  815. float effroll = pitch / halfpi;
  816. effroll *= effroll;
  817. effroll = 1 - effroll;
  818. effroll *= roll;
  819. torque.X += effroll * ftmp;
  820. if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
  821. {
  822. float effpitch = roll / halfpi;
  823. effpitch *= effpitch;
  824. effpitch = 1 - effpitch;
  825. effpitch *= pitch;
  826. torque.Y += effpitch * ftmp;
  827. }
  828. if (bankingEfficiency != 0 && MathF.Abs(effroll) > 0.01f)
  829. {
  830. float broll = effroll;
  831. /*
  832. if (broll > halfpi)
  833. broll = pi - broll;
  834. else if (broll < -halfpi)
  835. broll = -pi - broll;
  836. */
  837. broll *= m_bankingEfficiency;
  838. if (m_bankingMix != 0)
  839. {
  840. float vfact = MathF.Abs(curLocalVel.X) / 10.0f;
  841. if (vfact > 1.0f) vfact = 1.0f;
  842. if (curLocalVel.X >= 0)
  843. broll *= (1f + (vfact - 1f) * m_bankingMix);
  844. else
  845. broll *= -(1f + (vfact - 1f) * m_bankingMix);
  846. }
  847. // make z rot be in world Z not local as seems to be in sl
  848. broll /= m_bankingTimescale;
  849. tmpV = Vector3.UnitZRotated(irotq);
  850. tmpV *= broll;
  851. torque.X += tmpV.X;
  852. torque.Y += tmpV.Y;
  853. torque.Z += tmpV.Z;
  854. m_amdampZ = MathF.Abs(m_bankingEfficiency) / m_bankingTimescale;
  855. m_amdampY = m_amdampZ;
  856. }
  857. else
  858. {
  859. m_amdampZ = 1f / m_angularFrictionTimescale.Z;
  860. m_amdampY = m_amdampX;
  861. }
  862. }
  863. else
  864. {
  865. m_ampwr = 1.0f;
  866. m_amdampX = 1f / m_angularFrictionTimescale.X;
  867. m_amdampY = 1f / m_angularFrictionTimescale.Y;
  868. m_amdampZ = 1f / m_angularFrictionTimescale.Z;
  869. }
  870. if(mousemode)
  871. {
  872. CameraData cam = rootPrim.TryGetCameraData();
  873. if(cam != null && cam.MouseLook)
  874. {
  875. Vector3 dirv = cam.CameraAtAxis * irotq;
  876. float invamts = 1.0f/m_angularMotorTimescale;
  877. float tmp;
  878. // get out of x == 0 plane
  879. if(MathF.Abs(dirv.X) < 0.001f)
  880. dirv.X = 0.001f;
  881. if (MathF.Abs(dirv.Z) > 0.01f)
  882. {
  883. tmp = -MathF.Atan2(dirv.Z, dirv.X) * m_angularMotorDirection.Y;
  884. if(tmp < -4f)
  885. tmp = -4f;
  886. else if(tmp > 4f)
  887. tmp = 4f;
  888. torque.Y += (tmp - curLocalAngVel.Y) * invamts;
  889. torque.Y -= curLocalAngVel.Y * m_amdampY;
  890. }
  891. else
  892. torque.Y -= curLocalAngVel.Y * m_invtimestep;
  893. if (MathF.Abs(dirv.Y) > 0.01f)
  894. {
  895. if(mousemodebank)
  896. {
  897. tmp = -MathF.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.X;
  898. if(tmp < -4f)
  899. tmp = -4f;
  900. else if(tmp > 4f)
  901. tmp = 4f;
  902. torque.X += (tmp - curLocalAngVel.X) * invamts;
  903. }
  904. else
  905. {
  906. tmp = MathF.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.Z;
  907. tmp *= invamts;
  908. if(tmp < -4f)
  909. tmp = -4f;
  910. else if(tmp > 4f)
  911. tmp = 4f;
  912. torque.Z += (tmp - curLocalAngVel.Z) * invamts;
  913. }
  914. torque.X -= curLocalAngVel.X * m_amdampX;
  915. torque.Z -= curLocalAngVel.Z * m_amdampZ;
  916. }
  917. else
  918. {
  919. if(mousemodebank)
  920. torque.X -= curLocalAngVel.X * m_invtimestep;
  921. else
  922. torque.Z -= curLocalAngVel.Z * m_invtimestep;
  923. }
  924. }
  925. else
  926. {
  927. if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
  928. {
  929. torque.X -= curLocalAngVel.X * 10f;
  930. torque.Y -= curLocalAngVel.Y * 10f;
  931. torque.Z -= curLocalAngVel.Z * 10f;
  932. }
  933. }
  934. }
  935. else
  936. {
  937. // angular motor
  938. if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000f)
  939. {
  940. tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
  941. tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
  942. torque.X += tmpV.X * m_ampwr;
  943. torque.Y += tmpV.Y * m_ampwr;
  944. torque.Z += tmpV.Z;
  945. m_amEfect *= m_amDecay;
  946. }
  947. else
  948. m_amEfect = 0;
  949. // angular deflection
  950. if (m_angularDeflectionEfficiency > 0)
  951. {
  952. Vector3 dirv;
  953. if (curLocalVel.X > 0.01f)
  954. dirv = curLocalVel;
  955. else if (curLocalVel.X < -0.01f)
  956. // use oposite
  957. dirv = -curLocalVel;
  958. else
  959. {
  960. // make it fall into small positive x case
  961. dirv.X = 0.01f;
  962. dirv.Y = curLocalVel.Y;
  963. dirv.Z = curLocalVel.Z;
  964. }
  965. float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
  966. if (MathF.Abs(dirv.Z) > 0.01f)
  967. {
  968. torque.Y -= MathF.Atan2(dirv.Z, dirv.X) * ftmp;
  969. }
  970. if (MathF.Abs(dirv.Y) > 0.01f)
  971. {
  972. torque.Z += MathF.Atan2(dirv.Y, dirv.X) * ftmp;
  973. }
  974. }
  975. if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
  976. {
  977. torque.X -= curLocalAngVel.X * m_amdampX;
  978. torque.Y -= curLocalAngVel.Y * m_amdampY;
  979. torque.Z -= curLocalAngVel.Z * m_amdampZ;
  980. }
  981. }
  982. force *= dmass.mass;
  983. force += rootPrim.m_force;
  984. force += rootPrim.m_forceacc;
  985. rootPrim.m_forceacc = Vector3.Zero;
  986. if (force.X != 0f || force.Y != 0f || force.Z != 0f)
  987. {
  988. UBOdeNative.BodyAddForce(Body, force.X, force.Y, force.Z);
  989. }
  990. if (torque.X != 0f || torque.Y != 0f || torque.Z != 0f)
  991. {
  992. torque *= m_referenceFrame; // to object frame
  993. dtorque.X = torque.X;
  994. dtorque.Y = torque.Y;
  995. dtorque.Z = torque.Z;
  996. UBOdeNative.MultiplyM3V3(out UBOdeNative.Vector3 dvtmp, ref dmass.I, ref dtorque);
  997. UBOdeNative.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
  998. }
  999. torque = rootPrim.m_torque;
  1000. torque += rootPrim.m_angularForceacc;
  1001. rootPrim.m_angularForceacc = Vector3.Zero;
  1002. if (torque.X != 0f || torque.Y != 0f || torque.Z != 0f)
  1003. UBOdeNative.BodyAddTorque(Body,torque.X, torque.Y, torque.Z);
  1004. }
  1005. }
  1006. }