ODEDynamics.cs 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  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 OdePrim rootPrim;
  52. private 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 Vector3(1000, 1000, 1000);
  71. private float m_linearMotorDecayTimescale = 120;
  72. private float m_linearMotorTimescale = 1000;
  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 = 1000; // motor angular velocity ramp up rate
  77. private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
  78. private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
  79. //Deflection properties
  80. private float m_angularDeflectionEfficiency = 0;
  81. private float m_angularDeflectionTimescale = 1000;
  82. private float m_linearDeflectionEfficiency = 0;
  83. private float m_linearDeflectionTimescale = 1000;
  84. //Banking properties
  85. private float m_bankingEfficiency = 0;
  86. private float m_bankingMix = 0;
  87. private float m_bankingTimescale = 1000;
  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 float m_timestep = 0.02f;
  106. private 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._parent_scene;
  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 && !SafeNativeMethods.BodyIsEnabled(rootPrim.Body)
  290. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  291. SafeNativeMethods.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 && !SafeNativeMethods.BodyIsEnabled(rootPrim.Body)
  306. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  307. SafeNativeMethods.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 && !SafeNativeMethods.BodyIsEnabled(rootPrim.Body)
  339. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  340. SafeNativeMethods.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 && !SafeNativeMethods.BodyIsEnabled(rootPrim.Body)
  357. && !rootPrim.m_isSelected && !rootPrim.m_disabled)
  358. SafeNativeMethods.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. Vector3 vec;
  593. rot.Normalize(); // just in case
  594. vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
  595. vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
  596. vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
  597. return vec;
  598. }
  599. public static Vector3 Zrot(Quaternion rot)
  600. {
  601. Vector3 vec;
  602. rot.Normalize(); // just in case
  603. vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
  604. vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
  605. vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
  606. return vec;
  607. }
  608. private const float pi = (float)Math.PI;
  609. private const float halfpi = 0.5f * (float)Math.PI;
  610. private const float twopi = 2.0f * pi;
  611. public static Vector3 ubRot2Euler(Quaternion rot)
  612. {
  613. // returns roll in X
  614. // pitch in Y
  615. // yaw in Z
  616. Vector3 vec;
  617. // assuming rot is normalised
  618. // rot.Normalize();
  619. float zX = rot.X * rot.Z + rot.Y * rot.W;
  620. if (zX < -0.49999f)
  621. {
  622. vec.X = 0;
  623. vec.Y = -halfpi;
  624. vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
  625. }
  626. else 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
  633. {
  634. vec.Y = (float)Math.Asin(2 * zX);
  635. float sqw = rot.W * rot.W;
  636. float minuszY = rot.X * rot.W - rot.Y * rot.Z;
  637. float zZ = rot.Z * rot.Z + sqw - 0.5f;
  638. vec.X = (float)Math.Atan2(minuszY, zZ);
  639. float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
  640. float yY = rot.X * rot.X + sqw - 0.5f;
  641. vec.Z = (float)Math.Atan2(yX, yY);
  642. }
  643. return vec;
  644. }
  645. public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
  646. {
  647. // assuming rot is normalised
  648. // rot.Normalize();
  649. float zX = rot.X * rot.Z + rot.Y * rot.W;
  650. if (zX < -0.49999f)
  651. {
  652. roll = 0;
  653. pitch = -halfpi;
  654. }
  655. else if (zX > 0.49999f)
  656. {
  657. roll = 0;
  658. pitch = halfpi;
  659. }
  660. else
  661. {
  662. pitch = (float)Math.Asin(2 * zX);
  663. float minuszY = rot.X * rot.W - rot.Y * rot.Z;
  664. float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
  665. roll = (float)Math.Atan2(minuszY, zZ);
  666. }
  667. return ;
  668. }
  669. internal void Step()
  670. {
  671. IntPtr Body = rootPrim.Body;
  672. SafeNativeMethods.Mass dmass;
  673. SafeNativeMethods.BodyGetMass(Body, out dmass);
  674. SafeNativeMethods.Quaternion rot = SafeNativeMethods.BodyGetQuaternion(Body);
  675. Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
  676. Quaternion rotq = objrotq; // rotq = rotation of object
  677. rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
  678. Quaternion irotq = Quaternion.Inverse(rotq);
  679. SafeNativeMethods.Vector3 dvtmp;
  680. Vector3 tmpV;
  681. Vector3 curVel; // velocity in world
  682. Vector3 curAngVel; // angular velocity in world
  683. Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
  684. Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
  685. SafeNativeMethods.Vector3 dtorque = new SafeNativeMethods.Vector3();
  686. dvtmp = SafeNativeMethods.BodyGetLinearVel(Body);
  687. curVel.X = dvtmp.X;
  688. curVel.Y = dvtmp.Y;
  689. curVel.Z = dvtmp.Z;
  690. Vector3 curLocalVel = curVel * irotq; // current velocity in local
  691. dvtmp = SafeNativeMethods.BodyGetAngularVel(Body);
  692. curAngVel.X = dvtmp.X;
  693. curAngVel.Y = dvtmp.Y;
  694. curAngVel.Z = dvtmp.Z;
  695. Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
  696. float ldampZ = 0;
  697. bool mousemode = false;
  698. bool mousemodebank = false;
  699. float bankingEfficiency;
  700. float verticalAttractionTimescale = m_verticalAttractionTimescale;
  701. if((m_flags & (VehicleFlag.MOUSELOOK_STEER | VehicleFlag.MOUSELOOK_BANK)) != 0 )
  702. {
  703. mousemode = true;
  704. mousemodebank = (m_flags & VehicleFlag.MOUSELOOK_BANK) != 0;
  705. if(mousemodebank)
  706. {
  707. bankingEfficiency = m_bankingEfficiency;
  708. if(verticalAttractionTimescale < 149.9)
  709. verticalAttractionTimescale *= 2.0f; // reduce current instability
  710. }
  711. else
  712. bankingEfficiency = 0;
  713. }
  714. else
  715. bankingEfficiency = m_bankingEfficiency;
  716. // linear motor
  717. if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
  718. {
  719. tmpV = m_linearMotorDirection - curLocalVel; // velocity error
  720. tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
  721. tmpV *= rotq; // to world
  722. if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
  723. tmpV.Z = 0;
  724. if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
  725. {
  726. // have offset, do it now
  727. tmpV *= dmass.mass;
  728. SafeNativeMethods.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
  729. }
  730. else
  731. {
  732. force.X += tmpV.X;
  733. force.Y += tmpV.Y;
  734. force.Z += tmpV.Z;
  735. }
  736. m_lmEfect *= m_lmDecay;
  737. // m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
  738. m_ffactor = 0.0f;
  739. }
  740. else
  741. {
  742. m_lmEfect = 0;
  743. m_ffactor = 1f;
  744. }
  745. // hover
  746. if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
  747. {
  748. // d.Vector3 pos = d.BodyGetPosition(Body);
  749. SafeNativeMethods.Vector3 pos = SafeNativeMethods.GeomGetPosition(rootPrim.prim_geom);
  750. pos.Z -= 0.21f; // minor offset that seems to be always there in sl
  751. float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
  752. float perr;
  753. // default to global but don't go underground
  754. perr = m_VhoverHeight - pos.Z;
  755. if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
  756. {
  757. if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
  758. {
  759. perr += _pParentScene.GetWaterLevel();
  760. }
  761. else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
  762. {
  763. perr += t;
  764. }
  765. else
  766. {
  767. float w = _pParentScene.GetWaterLevel();
  768. if (t > w)
  769. perr += t;
  770. else
  771. perr += w;
  772. }
  773. }
  774. else if (t > m_VhoverHeight)
  775. perr = t - pos.Z; ;
  776. if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
  777. {
  778. ldampZ = m_VhoverEfficiency * m_invtimestep;
  779. perr *= (1.0f + ldampZ) / m_VhoverTimescale;
  780. // force.Z += perr - curVel.Z * tmp;
  781. force.Z += perr;
  782. ldampZ *= -curVel.Z;
  783. force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
  784. }
  785. else // no buoyancy
  786. force.Z += _pParentScene.gravityz;
  787. }
  788. else
  789. {
  790. // default gravity and Buoyancy
  791. force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
  792. }
  793. // linear deflection
  794. if (m_linearDeflectionEfficiency > 0)
  795. {
  796. float len = curVel.Length();
  797. if (len > 0.01) // if moving
  798. {
  799. Vector3 atAxis;
  800. atAxis = Xrot(rotq); // where are we pointing to
  801. atAxis *= len; // make it same size as world velocity vector
  802. tmpV = -atAxis; // oposite direction
  803. atAxis -= curVel; // error to one direction
  804. len = atAxis.LengthSquared();
  805. tmpV -= curVel; // error to oposite
  806. float lens = tmpV.LengthSquared();
  807. if (len > 0.01 || lens > 0.01) // do nothing if close enougth
  808. {
  809. if (len < lens)
  810. tmpV = atAxis;
  811. tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
  812. force.X += tmpV.X;
  813. force.Y += tmpV.Y;
  814. if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
  815. force.Z += tmpV.Z;
  816. }
  817. }
  818. }
  819. // linear friction/damping
  820. if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
  821. {
  822. tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
  823. tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
  824. tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
  825. tmpV *= rotq; // to world
  826. if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
  827. tmpV.Z = ldampZ;
  828. force.X += tmpV.X;
  829. force.Y += tmpV.Y;
  830. force.Z += tmpV.Z;
  831. }
  832. // vertical atractor
  833. if (verticalAttractionTimescale < 300)
  834. {
  835. float roll;
  836. float pitch;
  837. float ftmp = m_invtimestep / verticalAttractionTimescale / verticalAttractionTimescale;
  838. float ftmp2;
  839. ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
  840. m_amdampX = ftmp2;
  841. m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
  842. GetRollPitch(irotq, out roll, out pitch);
  843. if (roll > halfpi)
  844. roll = pi - roll;
  845. else if (roll < -halfpi)
  846. roll = -pi - roll;
  847. float effroll = pitch / halfpi;
  848. effroll *= effroll;
  849. effroll = 1 - effroll;
  850. effroll *= roll;
  851. torque.X += effroll * ftmp;
  852. if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
  853. {
  854. float effpitch = roll / halfpi;
  855. effpitch *= effpitch;
  856. effpitch = 1 - effpitch;
  857. effpitch *= pitch;
  858. torque.Y += effpitch * ftmp;
  859. }
  860. if (bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
  861. {
  862. float broll = effroll;
  863. /*
  864. if (broll > halfpi)
  865. broll = pi - broll;
  866. else if (broll < -halfpi)
  867. broll = -pi - broll;
  868. */
  869. broll *= m_bankingEfficiency;
  870. if (m_bankingMix != 0)
  871. {
  872. float vfact = Math.Abs(curLocalVel.X) / 10.0f;
  873. if (vfact > 1.0f) vfact = 1.0f;
  874. if (curLocalVel.X >= 0)
  875. broll *= (1 + (vfact - 1) * m_bankingMix);
  876. else
  877. broll *= -(1 + (vfact - 1) * m_bankingMix);
  878. }
  879. // make z rot be in world Z not local as seems to be in sl
  880. broll = broll / m_bankingTimescale;
  881. tmpV = Zrot(irotq);
  882. tmpV *= broll;
  883. torque.X += tmpV.X;
  884. torque.Y += tmpV.Y;
  885. torque.Z += tmpV.Z;
  886. m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
  887. m_amdampY = m_amdampZ;
  888. }
  889. else
  890. {
  891. m_amdampZ = 1 / m_angularFrictionTimescale.Z;
  892. m_amdampY = m_amdampX;
  893. }
  894. }
  895. else
  896. {
  897. m_ampwr = 1.0f;
  898. m_amdampX = 1 / m_angularFrictionTimescale.X;
  899. m_amdampY = 1 / m_angularFrictionTimescale.Y;
  900. m_amdampZ = 1 / m_angularFrictionTimescale.Z;
  901. }
  902. if(mousemode)
  903. {
  904. CameraData cam = rootPrim.TryGetCameraData();
  905. if(cam.Valid && cam.MouseLook)
  906. {
  907. Vector3 dirv = cam.CameraAtAxis * irotq;
  908. float invamts = 1.0f/m_angularMotorTimescale;
  909. float tmp;
  910. // get out of x == 0 plane
  911. if(Math.Abs(dirv.X) < 0.001f)
  912. dirv.X = 0.001f;
  913. if (Math.Abs(dirv.Z) > 0.01)
  914. {
  915. tmp = -(float)Math.Atan2(dirv.Z, dirv.X) * m_angularMotorDirection.Y;
  916. if(tmp < -4f)
  917. tmp = -4f;
  918. else if(tmp > 4f)
  919. tmp = 4f;
  920. torque.Y += (tmp - curLocalAngVel.Y) * invamts;
  921. torque.Y -= curLocalAngVel.Y * m_amdampY;
  922. }
  923. else
  924. torque.Y -= curLocalAngVel.Y * m_invtimestep;
  925. if (Math.Abs(dirv.Y) > 0.01)
  926. {
  927. if(mousemodebank)
  928. {
  929. tmp = -(float)Math.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.X;
  930. if(tmp < -4f)
  931. tmp = -4f;
  932. else if(tmp > 4f)
  933. tmp = 4f;
  934. torque.X += (tmp - curLocalAngVel.X) * invamts;
  935. }
  936. else
  937. {
  938. tmp = (float)Math.Atan2(dirv.Y, dirv.X) * m_angularMotorDirection.Z;
  939. tmp *= invamts;
  940. if(tmp < -4f)
  941. tmp = -4f;
  942. else if(tmp > 4f)
  943. tmp = 4f;
  944. torque.Z += (tmp - curLocalAngVel.Z) * invamts;
  945. }
  946. torque.X -= curLocalAngVel.X * m_amdampX;
  947. torque.Z -= curLocalAngVel.Z * m_amdampZ;
  948. }
  949. else
  950. {
  951. if(mousemodebank)
  952. torque.X -= curLocalAngVel.X * m_invtimestep;
  953. else
  954. torque.Z -= curLocalAngVel.Z * m_invtimestep;
  955. }
  956. }
  957. else
  958. {
  959. if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
  960. {
  961. torque.X -= curLocalAngVel.X * 10f;
  962. torque.Y -= curLocalAngVel.Y * 10f;
  963. torque.Z -= curLocalAngVel.Z * 10f;
  964. }
  965. }
  966. }
  967. else
  968. {
  969. // angular motor
  970. if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
  971. {
  972. tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
  973. tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
  974. torque.X += tmpV.X * m_ampwr;
  975. torque.Y += tmpV.Y * m_ampwr;
  976. torque.Z += tmpV.Z;
  977. m_amEfect *= m_amDecay;
  978. }
  979. else
  980. m_amEfect = 0;
  981. // angular deflection
  982. if (m_angularDeflectionEfficiency > 0)
  983. {
  984. Vector3 dirv;
  985. if (curLocalVel.X > 0.01f)
  986. dirv = curLocalVel;
  987. else if (curLocalVel.X < -0.01f)
  988. // use oposite
  989. dirv = -curLocalVel;
  990. else
  991. {
  992. // make it fall into small positive x case
  993. dirv.X = 0.01f;
  994. dirv.Y = curLocalVel.Y;
  995. dirv.Z = curLocalVel.Z;
  996. }
  997. float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
  998. if (Math.Abs(dirv.Z) > 0.01)
  999. {
  1000. torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
  1001. }
  1002. if (Math.Abs(dirv.Y) > 0.01)
  1003. {
  1004. torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
  1005. }
  1006. }
  1007. if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
  1008. {
  1009. torque.X -= curLocalAngVel.X * m_amdampX;
  1010. torque.Y -= curLocalAngVel.Y * m_amdampY;
  1011. torque.Z -= curLocalAngVel.Z * m_amdampZ;
  1012. }
  1013. }
  1014. force *= dmass.mass;
  1015. force += rootPrim.m_force;
  1016. force += rootPrim.m_forceacc;
  1017. rootPrim.m_forceacc = Vector3.Zero;
  1018. if (force.X != 0 || force.Y != 0 || force.Z != 0)
  1019. {
  1020. SafeNativeMethods.BodyAddForce(Body, force.X, force.Y, force.Z);
  1021. }
  1022. if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
  1023. {
  1024. torque *= m_referenceFrame; // to object frame
  1025. dtorque.X = torque.X ;
  1026. dtorque.Y = torque.Y;
  1027. dtorque.Z = torque.Z;
  1028. SafeNativeMethods.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
  1029. SafeNativeMethods.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
  1030. }
  1031. torque = rootPrim.m_torque;
  1032. torque += rootPrim.m_angularForceacc;
  1033. rootPrim.m_angularForceacc = Vector3.Zero;
  1034. if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
  1035. SafeNativeMethods.BodyAddTorque(Body,torque.X, torque.Y, torque.Z);
  1036. }
  1037. }
  1038. }