ODEDynamics.cs 50 KB

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