ODEDynamics.cs 50 KB

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