ODEPrim.cs 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072
  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 OpenSim 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. using System;
  28. using System.Collections.Generic;
  29. using System.Runtime.InteropServices;
  30. using Axiom.Math;
  31. using Ode.NET;
  32. using OpenSim.Framework;
  33. using OpenSim.Region.Physics.Manager;
  34. namespace OpenSim.Region.Physics.OdePlugin
  35. {
  36. public class OdePrim : PhysicsActor
  37. {
  38. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  39. public PhysicsVector _position;
  40. private PhysicsVector _velocity;
  41. private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
  42. private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
  43. private PhysicsVector m_rotationalVelocity;
  44. private PhysicsVector _size;
  45. private PhysicsVector _acceleration;
  46. private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
  47. private Quaternion _orientation;
  48. private PhysicsVector m_taintposition;
  49. private PhysicsVector m_taintsize;
  50. private PhysicsVector m_taintVelocity = PhysicsVector.Zero;
  51. private Quaternion m_taintrot;
  52. private PhysicsVector m_PIDTarget = new PhysicsVector(0, 0, 0);
  53. private float m_PIDTau = 0f;
  54. private bool m_usePID = false;
  55. private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
  56. | CollisionCategories.Space
  57. | CollisionCategories.Body
  58. | CollisionCategories.Character
  59. );
  60. private bool m_taintshape = false;
  61. private bool m_taintPhysics = false;
  62. private bool m_collidesLand = true;
  63. private bool m_collidesWater = false;
  64. public bool m_returnCollisions = false;
  65. // Default we're a Geometry
  66. private CollisionCategories m_collisionCategories = (CollisionCategories.Geom );
  67. // Default, Collide with Other Geometries, spaces and Bodies
  68. private CollisionCategories m_collisionFlags = m_default_collisionFlags;
  69. public bool m_taintremove = false;
  70. public bool m_taintdisable = false;
  71. public bool m_disabled = false;
  72. public bool m_taintadd = false;
  73. public bool m_taintselected = false;
  74. public bool m_taintCollidesWater = false;
  75. public uint m_localID = 0;
  76. public GCHandle gc;
  77. private CollisionLocker ode;
  78. private bool m_taintforce = false;
  79. private List<PhysicsVector> m_forcelist = new List<PhysicsVector>();
  80. private IMesh _mesh;
  81. private PrimitiveBaseShape _pbs;
  82. private OdeScene _parent_scene;
  83. public IntPtr m_targetSpace = (IntPtr) 0;
  84. public IntPtr prim_geom;
  85. public IntPtr prev_geom;
  86. public IntPtr _triMeshData;
  87. private IntPtr _linkJointGroup = (IntPtr)0;
  88. private PhysicsActor _parent = null;
  89. private PhysicsActor m_taintparent = null;
  90. private bool iscolliding = false;
  91. private bool m_isphysical = false;
  92. private bool m_isSelected = false;
  93. private bool m_throttleUpdates = false;
  94. private int throttleCounter = 0;
  95. public int m_interpenetrationcount = 0;
  96. public int m_collisionscore = 0;
  97. public int m_roundsUnderMotionThreshold = 0;
  98. private int m_crossingfailures = 0;
  99. public float m_buoyancy = 0f;
  100. public bool outofBounds = false;
  101. private float m_density = 10.000006836f; // Aluminum g/cm3;
  102. public bool _zeroFlag = false;
  103. private bool m_lastUpdateSent = false;
  104. public IntPtr Body = (IntPtr) 0;
  105. private String m_primName;
  106. private PhysicsVector _target_velocity;
  107. public d.Mass pMass;
  108. private IntPtr m_linkJoint = (IntPtr)0;
  109. public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
  110. Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
  111. {
  112. _target_velocity = new PhysicsVector(0, 0, 0);
  113. gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
  114. ode = dode;
  115. _velocity = new PhysicsVector();
  116. _position = pos;
  117. m_taintposition = pos;
  118. if (_position.X > 257)
  119. {
  120. _position.X = 257;
  121. }
  122. if (_position.X < 0)
  123. {
  124. _position.X = 0;
  125. }
  126. if (_position.Y > 257)
  127. {
  128. _position.Y = 257;
  129. }
  130. if (_position.Y < 0)
  131. {
  132. _position.Y = 0;
  133. }
  134. prim_geom = (IntPtr)0;
  135. prev_geom = (IntPtr)0;
  136. _size = size;
  137. m_taintsize = _size;
  138. _acceleration = new PhysicsVector();
  139. m_rotationalVelocity = PhysicsVector.Zero;
  140. _orientation = rotation;
  141. m_taintrot = _orientation;
  142. _mesh = mesh;
  143. _pbs = pbs;
  144. _parent_scene = parent_scene;
  145. m_targetSpace = (IntPtr)0;
  146. if (pos.Z < 0)
  147. m_isphysical = false;
  148. else
  149. {
  150. m_isphysical = pisPhysical;
  151. // If we're physical, we need to be in the master space for now.
  152. // linksets *should* be in a space together.. but are not currently
  153. if (m_isphysical)
  154. m_targetSpace = _parent_scene.space;
  155. }
  156. m_primName = primName;
  157. m_taintadd = true;
  158. _parent_scene.AddPhysicsActorTaint(this);
  159. // don't do .add() here; old geoms get recycled with the same hash
  160. }
  161. /// <summary>
  162. /// Nasty, however without this you get
  163. /// 'invalid operation for locked space' when things are really loaded down
  164. /// </summary>
  165. /// <param name="space"></param>
  166. public override int PhysicsActorType
  167. {
  168. get { return (int) ActorTypes.Prim; }
  169. set { return; }
  170. }
  171. public override bool SetAlwaysRun
  172. {
  173. get { return false; }
  174. set { return; }
  175. }
  176. public override uint LocalID
  177. {
  178. set {
  179. //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
  180. m_localID = value; }
  181. }
  182. public override bool Grabbed
  183. {
  184. set { return; }
  185. }
  186. public override bool Selected
  187. {
  188. set {
  189. // This only makes the object not collidable if the object
  190. // is physical or the object is modified somehow *IN THE FUTURE*
  191. // without this, if an avatar selects prim, they can walk right
  192. // through it while it's selected
  193. if ((m_isphysical && !_zeroFlag) || !value)
  194. {
  195. m_taintselected = value;
  196. _parent_scene.AddPhysicsActorTaint(this);
  197. }
  198. else
  199. {
  200. m_taintselected = value;
  201. m_isSelected = value;
  202. }
  203. }
  204. }
  205. public void SetGeom(IntPtr geom)
  206. {
  207. prev_geom = prim_geom;
  208. prim_geom = geom;
  209. if (prim_geom != (IntPtr)0)
  210. {
  211. d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
  212. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  213. }
  214. //m_log.Warn("Setting Geom to: " + prim_geom);
  215. }
  216. public void enableBodySoft()
  217. {
  218. if (m_isphysical)
  219. if (Body != (IntPtr)0)
  220. d.BodyEnable(Body);
  221. m_disabled = false;
  222. }
  223. public void disableBodySoft()
  224. {
  225. m_disabled = true;
  226. if (m_isphysical)
  227. if (Body != (IntPtr)0)
  228. d.BodyDisable(Body);
  229. }
  230. public void enableBody()
  231. {
  232. // Sets the geom to a body
  233. Body = d.BodyCreate(_parent_scene.world);
  234. setMass();
  235. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  236. d.Quaternion myrot = new d.Quaternion();
  237. myrot.W = _orientation.w;
  238. myrot.X = _orientation.x;
  239. myrot.Y = _orientation.y;
  240. myrot.Z = _orientation.z;
  241. d.BodySetQuaternion(Body, ref myrot);
  242. d.GeomSetBody(prim_geom, Body);
  243. m_collisionCategories |= CollisionCategories.Body;
  244. m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
  245. d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
  246. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  247. d.BodySetAutoDisableFlag(Body, true);
  248. d.BodySetAutoDisableSteps(Body, 20);
  249. m_interpenetrationcount = 0;
  250. m_collisionscore = 0;
  251. m_disabled = false;
  252. _parent_scene.addActivePrim(this);
  253. }
  254. #region Mass Calculation
  255. private float CalculateMass()
  256. {
  257. float volume = 0;
  258. // No material is passed to the physics engines yet.. soo..
  259. // we're using the m_density constant in the class definition
  260. float returnMass = 0;
  261. switch (_pbs.ProfileShape)
  262. {
  263. case ProfileShape.Square:
  264. // Profile Volume
  265. volume = _size.X*_size.Y*_size.Z;
  266. // If the user has 'hollowed out'
  267. // ProfileHollow is one of those 0 to 50000 values :P
  268. // we like percentages better.. so turning into a percentage
  269. if (((float) _pbs.ProfileHollow/50000f) > 0.0)
  270. {
  271. float hollowAmount = (float) _pbs.ProfileHollow/50000f;
  272. // calculate the hollow volume by it's shape compared to the prim shape
  273. float hollowVolume = 0;
  274. switch (_pbs.HollowShape)
  275. {
  276. case HollowShape.Square:
  277. case HollowShape.Same:
  278. // Cube Hollow volume calculation
  279. float hollowsizex = _size.X*hollowAmount;
  280. float hollowsizey = _size.Y*hollowAmount;
  281. float hollowsizez = _size.Z*hollowAmount;
  282. hollowVolume = hollowsizex*hollowsizey*hollowsizez;
  283. break;
  284. case HollowShape.Circle:
  285. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  286. // Cyllinder hollow volume calculation
  287. float hRadius = _size.X/2;
  288. float hLength = _size.Z;
  289. // pi * r2 * h
  290. hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount);
  291. break;
  292. case HollowShape.Triangle:
  293. // Equilateral Triangular Prism volume hollow calculation
  294. // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
  295. float aLength = _size.Y;
  296. // 1/2 abh
  297. hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount);
  298. break;
  299. default:
  300. hollowVolume = 0;
  301. break;
  302. }
  303. volume = volume - hollowVolume;
  304. }
  305. break;
  306. case ProfileShape.Circle:
  307. if (_pbs.PathCurve == (byte)Extrusion.Straight)
  308. {
  309. // Cylinder
  310. float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z);
  311. float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z);
  312. // Approximating the cylinder's irregularity.
  313. if (volume1 > volume2)
  314. {
  315. volume = (float)volume1 - (volume1 - volume2);
  316. }
  317. else if (volume2 > volume1)
  318. {
  319. volume = (float)volume2 - (volume2 - volume1);
  320. }
  321. else
  322. {
  323. // Regular cylinder
  324. volume = volume1;
  325. }
  326. }
  327. else
  328. {
  329. // We don't know what the shape is yet, so use default
  330. volume = _size.X * _size.Y * _size.Z;
  331. }
  332. // If the user has 'hollowed out'
  333. // ProfileHollow is one of those 0 to 50000 values :P
  334. // we like percentages better.. so turning into a percentage
  335. if (((float)_pbs.ProfileHollow / 50000f) > 0.0)
  336. {
  337. float hollowAmount = (float)_pbs.ProfileHollow / 50000f;
  338. // calculate the hollow volume by it's shape compared to the prim shape
  339. float hollowVolume = 0;
  340. switch (_pbs.HollowShape)
  341. {
  342. case HollowShape.Same:
  343. case HollowShape.Circle:
  344. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  345. // Cyllinder hollow volume calculation
  346. float hRadius = _size.X / 2;
  347. float hLength = _size.Z;
  348. // pi * r2 * h
  349. hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount);
  350. break;
  351. case HollowShape.Square:
  352. // Cube Hollow volume calculation
  353. float hollowsizex = _size.X * hollowAmount;
  354. float hollowsizey = _size.Y * hollowAmount;
  355. float hollowsizez = _size.Z * hollowAmount;
  356. hollowVolume = hollowsizex * hollowsizey * hollowsizez;
  357. break;
  358. case HollowShape.Triangle:
  359. // Equilateral Triangular Prism volume hollow calculation
  360. // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
  361. float aLength = _size.Y;
  362. // 1/2 abh
  363. hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
  364. break;
  365. default:
  366. hollowVolume = 0;
  367. break;
  368. }
  369. volume = volume - hollowVolume;
  370. }
  371. break;
  372. case ProfileShape.HalfCircle:
  373. if (_pbs.PathCurve == (byte)Extrusion.Curve1)
  374. {
  375. if (_size.X == _size.Z && _size.Z == _size.X)
  376. {
  377. // regular sphere
  378. // v = 4/3 * pi * r^3
  379. float sradius3 = (float)Math.Pow((_size.X / 2), 3);
  380. volume = (float)((4 / 3) * Math.PI * sradius3);
  381. }
  382. else
  383. {
  384. // we treat this as a box currently
  385. volume = _size.X * _size.Y * _size.Z;
  386. }
  387. }
  388. else
  389. {
  390. // We don't know what the shape is yet, so use default
  391. volume = _size.X * _size.Y * _size.Z;
  392. }
  393. break;
  394. case ProfileShape.EquilateralTriangle:
  395. /*
  396. v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h
  397. // seed mesh
  398. Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f);
  399. Vertex PM = new Vertex(+0.5f, 0f, 0.0f);
  400. Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f);
  401. */
  402. float xA = -0.25f * _size.X;
  403. float yA = -0.45f * _size.Y;
  404. float xB = 0.5f * _size.X;
  405. float yB = 0;
  406. float xC = -0.25f * _size.X;
  407. float yC = 0.45f * _size.Y;
  408. volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z);
  409. // If the user has 'hollowed out'
  410. // ProfileHollow is one of those 0 to 50000 values :P
  411. // we like percentages better.. so turning into a percentage
  412. float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f);
  413. if (((float)fhollowFactor / 50000f) > 0.0)
  414. {
  415. float hollowAmount = (float)fhollowFactor / 50000f;
  416. // calculate the hollow volume by it's shape compared to the prim shape
  417. float hollowVolume = 0;
  418. switch (_pbs.HollowShape)
  419. {
  420. case HollowShape.Same:
  421. case HollowShape.Triangle:
  422. // Equilateral Triangular Prism volume hollow calculation
  423. // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
  424. float aLength = _size.Y;
  425. // 1/2 abh
  426. hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount);
  427. break;
  428. case HollowShape.Square:
  429. // Cube Hollow volume calculation
  430. float hollowsizex = _size.X * hollowAmount;
  431. float hollowsizey = _size.Y * hollowAmount;
  432. float hollowsizez = _size.Z * hollowAmount;
  433. hollowVolume = hollowsizex * hollowsizey * hollowsizez;
  434. break;
  435. case HollowShape.Circle:
  436. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  437. // Cyllinder hollow volume calculation
  438. float hRadius = _size.X / 2;
  439. float hLength = _size.Z;
  440. // pi * r2 * h
  441. hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount);
  442. break;
  443. default:
  444. hollowVolume = 0;
  445. break;
  446. }
  447. volume = volume - hollowVolume;
  448. }
  449. break;
  450. default:
  451. // we don't have all of the volume formulas yet so
  452. // use the common volume formula for all
  453. volume = _size.X*_size.Y*_size.Z;
  454. break;
  455. }
  456. // Calculate Path cut effect on volume
  457. // Not exact, in the triangle hollow example
  458. // They should never be zero or less then zero..
  459. // we'll ignore it if it's less then zero
  460. // ProfileEnd and ProfileBegin are values
  461. // from 0 to 50000
  462. // Turning them back into percentages so that I can cut that percentage off the volume
  463. float PathCutEndAmount = _pbs.ProfileEnd;
  464. float PathCutStartAmount = _pbs.ProfileBegin;
  465. if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f)
  466. {
  467. float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f);
  468. // Check the return amount for sanity
  469. if (pathCutAmount >= 0.99f)
  470. pathCutAmount = 0.99f;
  471. volume = volume - (volume*pathCutAmount);
  472. }
  473. UInt16 taperX = _pbs.PathScaleX;
  474. UInt16 taperY = _pbs.PathScaleY;
  475. float taperFactorX = 0;
  476. float taperFactorY = 0;
  477. // Mass = density * volume
  478. if (taperX != 100)
  479. {
  480. if (taperX > 100)
  481. {
  482. taperFactorX = 1.0f - ((float)taperX / 200);
  483. //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString());
  484. }
  485. else
  486. {
  487. taperFactorX = 1.0f - ((100 - (float)taperX) / 100);
  488. //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString());
  489. }
  490. volume = (float)volume * ((taperFactorX / 3f) + 0.001f);
  491. }
  492. if (taperY != 100)
  493. {
  494. if (taperY > 100)
  495. {
  496. taperFactorY = 1.0f - ((float)taperY / 200);
  497. //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString());
  498. }
  499. else
  500. {
  501. taperFactorY = 1.0f - ((100 - (float)taperY) / 100);
  502. //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString());
  503. }
  504. volume = (float)volume * ((taperFactorY / 3f) + 0.001f);
  505. }
  506. returnMass = m_density*volume;
  507. return returnMass;
  508. }
  509. #endregion
  510. public void setMass()
  511. {
  512. if (Body != (IntPtr) 0)
  513. {
  514. float newmass = CalculateMass();
  515. //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
  516. if (newmass <= 0) newmass = 0.0001f;
  517. d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
  518. d.BodySetMass(Body, ref pMass);
  519. }
  520. }
  521. public void disableBody()
  522. {
  523. //this kills the body so things like 'mesh' can re-create it.
  524. lock (this)
  525. {
  526. if (Body != (IntPtr)0)
  527. {
  528. m_collisionCategories &= ~CollisionCategories.Body;
  529. m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
  530. if (prim_geom != (IntPtr)0)
  531. {
  532. d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
  533. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  534. }
  535. _parent_scene.remActivePrim(this);
  536. d.BodyDestroy(Body);
  537. Body = (IntPtr)0;
  538. }
  539. }
  540. m_disabled = true;
  541. m_collisionscore = 0;
  542. }
  543. public void setMesh(OdeScene parent_scene, IMesh mesh)
  544. {
  545. // This sleeper is there to moderate how long it takes between
  546. // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
  547. System.Threading.Thread.Sleep(10);
  548. //Kill Body so that mesh can re-make the geom
  549. if (IsPhysical && Body != (IntPtr) 0)
  550. {
  551. disableBody();
  552. }
  553. float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
  554. int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
  555. int VertexCount = vertexList.GetLength(0)/3;
  556. int IndexCount = indexList.GetLength(0);
  557. _triMeshData = d.GeomTriMeshDataCreate();
  558. d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
  559. 3*sizeof (int));
  560. d.GeomTriMeshDataPreprocess(_triMeshData);
  561. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  562. try
  563. {
  564. if (prim_geom == (IntPtr)0)
  565. {
  566. SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
  567. }
  568. }
  569. catch (System.AccessViolationException)
  570. {
  571. m_log.Error("[PHYSICS]: MESH LOCKED");
  572. return;
  573. }
  574. if (IsPhysical && Body == (IntPtr) 0)
  575. {
  576. // Recreate the body
  577. m_interpenetrationcount = 0;
  578. m_collisionscore = 0;
  579. enableBody();
  580. }
  581. }
  582. public void ProcessTaints(float timestep)
  583. {
  584. if (m_taintadd)
  585. {
  586. changeadd(timestep);
  587. }
  588. if (prim_geom != (IntPtr)0)
  589. {
  590. if (m_taintposition != _position)
  591. changemove(timestep);
  592. if (m_taintrot != _orientation)
  593. rotate(timestep);
  594. //
  595. if (m_taintPhysics != m_isphysical)
  596. changePhysicsStatus(timestep);
  597. //
  598. if (m_taintsize != _size)
  599. changesize(timestep);
  600. //
  601. if (m_taintshape)
  602. changeshape(timestep);
  603. //
  604. if (m_taintforce)
  605. changeAddForce(timestep);
  606. if (m_taintdisable)
  607. changedisable(timestep);
  608. if (m_taintselected != m_isSelected)
  609. changeSelectedStatus(timestep);
  610. if (m_taintVelocity != PhysicsVector.Zero)
  611. changevelocity(timestep);
  612. if (m_taintparent != _parent)
  613. changelink(timestep);
  614. if (m_taintCollidesWater != m_collidesWater)
  615. changefloatonwater(timestep);
  616. }
  617. else
  618. {
  619. m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil.");
  620. }
  621. }
  622. private void changelink(float timestep)
  623. {
  624. if (_parent == null && m_taintparent != null)
  625. {
  626. if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
  627. {
  628. OdePrim obj = (OdePrim)m_taintparent;
  629. if (obj.Body != (IntPtr)0 && Body != (IntPtr)0)
  630. {
  631. _linkJointGroup = d.JointGroupCreate(0);
  632. m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
  633. d.JointAttach(m_linkJoint, obj.Body, Body);
  634. d.JointSetFixed(m_linkJoint);
  635. }
  636. }
  637. }
  638. else if (_parent != null && m_taintparent == null)
  639. {
  640. if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
  641. d.JointGroupDestroy(_linkJointGroup);
  642. _linkJointGroup = (IntPtr)0;
  643. m_linkJoint = (IntPtr)0;
  644. }
  645. _parent = m_taintparent;
  646. }
  647. private void changeSelectedStatus(float timestep)
  648. {
  649. if (m_taintselected)
  650. {
  651. m_collisionCategories = CollisionCategories.Selected;
  652. m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
  653. // We do the body disable soft twice because 'in theory' a collision could have happened
  654. // in between the disabling and the collision properties setting
  655. // which would wake the physical body up from a soft disabling and potentially cause it to fall
  656. // through the ground.
  657. if (m_isphysical)
  658. {
  659. disableBodySoft();
  660. }
  661. if (prim_geom != (IntPtr)0)
  662. {
  663. d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
  664. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  665. }
  666. if (m_isphysical)
  667. {
  668. disableBodySoft();
  669. }
  670. }
  671. else
  672. {
  673. m_collisionCategories = CollisionCategories.Geom;
  674. if (m_isphysical)
  675. m_collisionCategories |= CollisionCategories.Body;
  676. m_collisionFlags = m_default_collisionFlags;
  677. if (m_collidesLand)
  678. m_collisionFlags |= CollisionCategories.Land;
  679. if (m_collidesWater)
  680. m_collisionFlags |= CollisionCategories.Water;
  681. if (prim_geom != (IntPtr)0)
  682. {
  683. d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
  684. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  685. }
  686. if (m_isphysical)
  687. {
  688. d.BodySetLinearVel(Body, 0f, 0f, 0f);
  689. enableBodySoft();
  690. }
  691. }
  692. resetCollisionAccounting();
  693. m_isSelected = m_taintselected;
  694. }
  695. public void ResetTaints()
  696. {
  697. m_taintposition = _position;
  698. m_taintrot = _orientation;
  699. m_taintPhysics = m_isphysical;
  700. m_taintselected = m_isSelected;
  701. m_taintsize = _size;
  702. m_taintshape = false;
  703. m_taintforce = false;
  704. m_taintdisable = false;
  705. m_taintVelocity = PhysicsVector.Zero;
  706. }
  707. public void changeadd(float timestep)
  708. {
  709. int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  710. IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
  711. if (targetspace == IntPtr.Zero)
  712. targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
  713. m_targetSpace = targetspace;
  714. if (_mesh != null)
  715. {
  716. }
  717. else
  718. {
  719. if (_parent_scene.needsMeshing(_pbs))
  720. {
  721. // Don't need to re-enable body.. it's done in SetMesh
  722. _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size);
  723. // createmesh returns null when it's a shape that isn't a cube.
  724. }
  725. }
  726. lock (OdeScene.OdeLock)
  727. {
  728. if (_mesh != null)
  729. {
  730. setMesh(_parent_scene, _mesh);
  731. }
  732. else
  733. {
  734. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  735. {
  736. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  737. {
  738. if (((_size.X / 2f) > 0f))
  739. {
  740. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  741. try
  742. {
  743. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  744. }
  745. catch (System.AccessViolationException)
  746. {
  747. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  748. ode.dunlock(_parent_scene.world);
  749. return;
  750. }
  751. }
  752. else
  753. {
  754. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  755. try
  756. {
  757. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  758. }
  759. catch (System.AccessViolationException)
  760. {
  761. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  762. ode.dunlock(_parent_scene.world);
  763. return;
  764. }
  765. }
  766. }
  767. else
  768. {
  769. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  770. try
  771. {
  772. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  773. }
  774. catch (System.AccessViolationException)
  775. {
  776. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  777. ode.dunlock(_parent_scene.world);
  778. return;
  779. }
  780. }
  781. }
  782. //else if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  783. //{
  784. //Cyllinder
  785. //if (_size.X == _size.Y)
  786. //{
  787. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  788. //}
  789. //else
  790. //{
  791. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  792. //}
  793. //}
  794. else
  795. {
  796. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  797. try
  798. {
  799. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  800. }
  801. catch (System.AccessViolationException)
  802. {
  803. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  804. ode.dunlock(_parent_scene.world);
  805. return;
  806. }
  807. }
  808. }
  809. if (prim_geom != (IntPtr) 0)
  810. {
  811. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  812. d.Quaternion myrot = new d.Quaternion();
  813. myrot.W = _orientation.w;
  814. myrot.X = _orientation.x;
  815. myrot.Y = _orientation.y;
  816. myrot.Z = _orientation.z;
  817. d.GeomSetQuaternion(prim_geom, ref myrot);
  818. }
  819. if (m_isphysical && Body == (IntPtr)0)
  820. {
  821. enableBody();
  822. }
  823. }
  824. _parent_scene.geom_name_map[prim_geom] = this.m_primName;
  825. _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
  826. changeSelectedStatus(timestep);
  827. m_taintadd = false;
  828. }
  829. public void changemove(float timestep)
  830. {
  831. if (m_isphysical)
  832. {
  833. // This is a fallback.. May no longer be necessary.
  834. if (Body == (IntPtr) 0)
  835. enableBody();
  836. //Prim auto disable after 20 frames,
  837. //if you move it, re-enable the prim manually.
  838. if (_parent != null)
  839. {
  840. if (m_linkJoint != (IntPtr)0)
  841. {
  842. d.JointDestroy(m_linkJoint);
  843. m_linkJoint = (IntPtr)0;
  844. }
  845. }
  846. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  847. if (_parent != null)
  848. {
  849. OdePrim odParent = (OdePrim)_parent;
  850. if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0)
  851. {
  852. m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
  853. d.JointAttach(m_linkJoint, Body, odParent.Body);
  854. d.JointSetFixed(m_linkJoint);
  855. }
  856. }
  857. d.BodyEnable(Body);
  858. }
  859. else
  860. {
  861. string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
  862. int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  863. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  864. IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
  865. m_targetSpace = tempspace;
  866. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  867. if (prim_geom != (IntPtr) 0)
  868. {
  869. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  870. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  871. d.SpaceAdd(m_targetSpace, prim_geom);
  872. }
  873. }
  874. changeSelectedStatus(timestep);
  875. resetCollisionAccounting();
  876. m_taintposition = _position;
  877. }
  878. public void Move(float timestep)
  879. {
  880. float fx = 0;
  881. float fy = 0;
  882. float fz = 0;
  883. if (IsPhysical && Body != (IntPtr)0 && !m_isSelected)
  884. {
  885. float PID_D = 2200.0f;
  886. //float PID_P = 900.0f;
  887. float m_mass = CalculateMass();
  888. fz = 0f;
  889. //m_log.Info(m_collisionFlags.ToString());
  890. if (m_buoyancy != 0)
  891. {
  892. if (m_buoyancy > 0)
  893. {
  894. fz = ((9.8f * m_buoyancy) * m_mass);
  895. //d.Vector3 l_velocity = d.BodyGetLinearVel(Body);
  896. //m_log.Info("Using Buoyancy: " + buoyancy + " G: " + (9.8f * m_buoyancy) + "mass:" + m_mass + " Pos: " + Position.ToString());
  897. }
  898. else
  899. {
  900. fz = (-1 * ((9.8f * (-1 * m_buoyancy)) * m_mass));
  901. }
  902. }
  903. if (m_usePID)
  904. {
  905. // If we're using the PID controller, then we have no gravity
  906. fz = ((9.8f) * this.Mass );
  907. // no lock; for now it's only called from within Simulate()
  908. // If the PID Controller isn't active then we set our force
  909. // calculating base velocity to the current position
  910. if (System.Environment.OSVersion.Platform == PlatformID.Unix)
  911. {
  912. PID_D = 3200.0f;
  913. //PID_P = 1400.0f;
  914. }
  915. else
  916. {
  917. PID_D = 2200.0f;
  918. //PID_P = 900.0f;
  919. }
  920. PID_D = 1.0f;
  921. //PID_P = 1.0f;
  922. //PidStatus = true;
  923. PhysicsVector vec = new PhysicsVector();
  924. d.Vector3 vel = d.BodyGetLinearVel(Body);
  925. d.Vector3 pos = d.BodyGetPosition(Body);
  926. _target_velocity =
  927. new PhysicsVector(
  928. (m_PIDTarget.X - pos.X) / m_PIDTau,
  929. (m_PIDTarget.Y - pos.Y) / m_PIDTau,
  930. (m_PIDTarget.Z - pos.Z) / m_PIDTau
  931. );
  932. // if velocity is zero, use position control; otherwise, velocity control
  933. if (_target_velocity.IsIdentical(PhysicsVector.Zero,0.1f))
  934. {
  935. // keep track of where we stopped. No more slippin' & slidin'
  936. // We only want to deactivate the PID Controller if we think we want to have our surrogate
  937. // react to the physics scene by moving it's position.
  938. // Avatar to Avatar collisions
  939. // Prim to avatar collisions
  940. //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
  941. //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
  942. //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
  943. d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
  944. d.BodySetLinearVel(Body, 0, 0, 0);
  945. d.BodyAddForce(Body, 0, 0, fz);
  946. return;
  947. }
  948. else
  949. {
  950. _zeroFlag = false;
  951. // We're flying and colliding with something
  952. fx = ((_target_velocity.X / m_PIDTau) - vel.X) * (PID_D / 6);
  953. fy = ((_target_velocity.Y / m_PIDTau) - vel.Y) * (PID_D / 6);
  954. // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
  955. fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
  956. }
  957. }
  958. fx *= m_mass;
  959. fy *= m_mass;
  960. //fz *= m_mass;
  961. //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
  962. if (fx != 0 || fy != 0 || fz != 0)
  963. {
  964. //m_taintdisable = true;
  965. //base.RaiseOutOfBounds(Position);
  966. //d.BodySetLinearVel(Body, fx, fy, 0f);
  967. d.BodyAddForce(Body, fx, fy, fz);
  968. }
  969. }
  970. else
  971. {
  972. _zeroPosition = d.BodyGetPosition(Body);
  973. return;
  974. }
  975. }
  976. public void rotate(float timestep)
  977. {
  978. d.Quaternion myrot = new d.Quaternion();
  979. myrot.W = _orientation.w;
  980. myrot.X = _orientation.x;
  981. myrot.Y = _orientation.y;
  982. myrot.Z = _orientation.z;
  983. d.GeomSetQuaternion(prim_geom, ref myrot);
  984. if (m_isphysical && Body != (IntPtr) 0)
  985. {
  986. d.BodySetQuaternion(Body, ref myrot);
  987. }
  988. resetCollisionAccounting();
  989. m_taintrot = _orientation;
  990. }
  991. private void resetCollisionAccounting()
  992. {
  993. m_collisionscore = 0;
  994. m_interpenetrationcount = 0;
  995. m_disabled = false;
  996. }
  997. public void changedisable(float timestep)
  998. {
  999. m_disabled = true;
  1000. if (Body != (IntPtr)0)
  1001. {
  1002. d.BodyDisable(Body);
  1003. Body = (IntPtr)0;
  1004. }
  1005. m_taintdisable = false;
  1006. }
  1007. public void changePhysicsStatus(float timestep)
  1008. {
  1009. if (m_isphysical == true)
  1010. {
  1011. if (Body == (IntPtr)0)
  1012. {
  1013. enableBody();
  1014. }
  1015. }
  1016. else
  1017. {
  1018. if (Body != (IntPtr)0)
  1019. {
  1020. disableBody();
  1021. }
  1022. }
  1023. changeSelectedStatus(timestep);
  1024. resetCollisionAccounting();
  1025. m_taintPhysics = m_isphysical;
  1026. }
  1027. public void changesize(float timestamp)
  1028. {
  1029. //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom))
  1030. //{
  1031. // m_taintsize = _size;
  1032. //return;
  1033. //}
  1034. string oldname = _parent_scene.geom_name_map[prim_geom];
  1035. // Cleanup of old prim geometry
  1036. if (_mesh != null)
  1037. {
  1038. // Cleanup meshing here
  1039. }
  1040. //kill body to rebuild
  1041. if (IsPhysical && Body != (IntPtr) 0)
  1042. {
  1043. disableBody();
  1044. }
  1045. if (d.SpaceQuery(m_targetSpace, prim_geom))
  1046. {
  1047. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1048. d.SpaceRemove(m_targetSpace, prim_geom);
  1049. }
  1050. d.GeomDestroy(prim_geom);
  1051. prim_geom = (IntPtr)0;
  1052. // we don't need to do space calculation because the client sends a position update also.
  1053. // Construction of new prim
  1054. if (_parent_scene.needsMeshing(_pbs))
  1055. {
  1056. // Don't need to re-enable body.. it's done in SetMesh
  1057. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  1058. // createmesh returns null when it's a shape that isn't a cube.
  1059. if (mesh != null)
  1060. {
  1061. setMesh(_parent_scene, mesh);
  1062. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1063. d.Quaternion myrot = new d.Quaternion();
  1064. myrot.W = _orientation.w;
  1065. myrot.X = _orientation.x;
  1066. myrot.Y = _orientation.y;
  1067. myrot.Z = _orientation.z;
  1068. d.GeomSetQuaternion(prim_geom, ref myrot);
  1069. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  1070. if (IsPhysical && Body == (IntPtr)0)
  1071. {
  1072. // Re creates body on size.
  1073. // EnableBody also does setMass()
  1074. enableBody();
  1075. d.BodyEnable(Body);
  1076. }
  1077. }
  1078. else
  1079. {
  1080. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  1081. {
  1082. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  1083. {
  1084. if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
  1085. {
  1086. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1087. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  1088. }
  1089. else
  1090. {
  1091. m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
  1092. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1093. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1094. }
  1095. }
  1096. else
  1097. {
  1098. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1099. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1100. }
  1101. }
  1102. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  1103. //{
  1104. //Cyllinder
  1105. //if (_size.X == _size.Y)
  1106. //{
  1107. // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  1108. //}
  1109. //else
  1110. //{
  1111. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1112. //}
  1113. //}
  1114. else
  1115. {
  1116. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1117. SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1118. }
  1119. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1120. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1121. d.Quaternion myrot = new d.Quaternion();
  1122. myrot.W = _orientation.w;
  1123. myrot.X = _orientation.x;
  1124. myrot.Y = _orientation.y;
  1125. myrot.Z = _orientation.z;
  1126. d.GeomSetQuaternion(prim_geom, ref myrot);
  1127. }
  1128. }
  1129. else
  1130. {
  1131. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  1132. {
  1133. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  1134. {
  1135. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1136. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  1137. }
  1138. else
  1139. {
  1140. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1141. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1142. }
  1143. }
  1144. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  1145. //{
  1146. //Cyllinder
  1147. //if (_size.X == _size.Y)
  1148. //{
  1149. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  1150. //}
  1151. //else
  1152. //{
  1153. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1154. //}
  1155. //}
  1156. else
  1157. {
  1158. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1159. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1160. }
  1161. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1162. d.Quaternion myrot = new d.Quaternion();
  1163. myrot.W = _orientation.w;
  1164. myrot.X = _orientation.x;
  1165. myrot.Y = _orientation.y;
  1166. myrot.Z = _orientation.z;
  1167. d.GeomSetQuaternion(prim_geom, ref myrot);
  1168. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  1169. if (IsPhysical && Body == (IntPtr) 0)
  1170. {
  1171. // Re creates body on size.
  1172. // EnableBody also does setMass()
  1173. enableBody();
  1174. d.BodyEnable(Body);
  1175. }
  1176. }
  1177. _parent_scene.geom_name_map[prim_geom] = oldname;
  1178. changeSelectedStatus(timestamp);
  1179. resetCollisionAccounting();
  1180. m_taintsize = _size;
  1181. }
  1182. public void changefloatonwater(float timestep)
  1183. {
  1184. m_collidesWater = m_taintCollidesWater;
  1185. if (prim_geom != (IntPtr)0)
  1186. {
  1187. if (m_collidesWater)
  1188. {
  1189. m_collisionFlags |= CollisionCategories.Water;
  1190. }
  1191. else
  1192. {
  1193. m_collisionFlags &= ~CollisionCategories.Water;
  1194. }
  1195. d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
  1196. }
  1197. }
  1198. public void changeshape(float timestamp)
  1199. {
  1200. string oldname = _parent_scene.geom_name_map[prim_geom];
  1201. // Cleanup of old prim geometry and Bodies
  1202. if (IsPhysical && Body != (IntPtr) 0)
  1203. {
  1204. disableBody();
  1205. }
  1206. d.GeomDestroy(prim_geom);
  1207. prim_geom = (IntPtr) 0;
  1208. // we don't need to do space calculation because the client sends a position update also.
  1209. // Construction of new prim
  1210. if (_parent_scene.needsMeshing(_pbs))
  1211. {
  1212. // Don't need to re-enable body.. it's done in SetMesh
  1213. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  1214. // createmesh returns null when it's a shape that isn't a cube.
  1215. if (mesh != null)
  1216. {
  1217. setMesh(_parent_scene, mesh);
  1218. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1219. d.Quaternion myrot = new d.Quaternion();
  1220. myrot.W = _orientation.w;
  1221. myrot.X = _orientation.x;
  1222. myrot.Y = _orientation.y;
  1223. myrot.Z = _orientation.z;
  1224. d.GeomSetQuaternion(prim_geom, ref myrot);
  1225. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  1226. if (IsPhysical && Body == (IntPtr)0)
  1227. {
  1228. // Re creates body on size.
  1229. // EnableBody also does setMass()
  1230. enableBody();
  1231. }
  1232. }
  1233. else
  1234. {
  1235. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  1236. {
  1237. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  1238. {
  1239. if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
  1240. {
  1241. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1242. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  1243. }
  1244. else
  1245. {
  1246. m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
  1247. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1248. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1249. }
  1250. }
  1251. else
  1252. {
  1253. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1254. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1255. }
  1256. }
  1257. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  1258. //{
  1259. //Cyllinder
  1260. //if (_size.X == _size.Y)
  1261. //{
  1262. // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  1263. //}
  1264. //else
  1265. //{
  1266. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1267. //}
  1268. //}
  1269. else
  1270. {
  1271. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1272. SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1273. }
  1274. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1275. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1276. d.Quaternion myrot = new d.Quaternion();
  1277. myrot.W = _orientation.w;
  1278. myrot.X = _orientation.x;
  1279. myrot.Y = _orientation.y;
  1280. myrot.Z = _orientation.z;
  1281. d.GeomSetQuaternion(prim_geom, ref myrot);
  1282. }
  1283. }
  1284. else
  1285. {
  1286. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  1287. {
  1288. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  1289. {
  1290. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1291. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  1292. }
  1293. else
  1294. {
  1295. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1296. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1297. }
  1298. }
  1299. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  1300. //{
  1301. //Cyllinder
  1302. //if (_size.X == _size.Y)
  1303. //{
  1304. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  1305. //}
  1306. //else
  1307. //{
  1308. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  1309. //}
  1310. //}
  1311. else
  1312. {
  1313. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  1314. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  1315. }
  1316. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  1317. d.Quaternion myrot = new d.Quaternion();
  1318. myrot.W = _orientation.w;
  1319. myrot.X = _orientation.x;
  1320. myrot.Y = _orientation.y;
  1321. myrot.Z = _orientation.z;
  1322. d.GeomSetQuaternion(prim_geom, ref myrot);
  1323. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  1324. if (IsPhysical && Body == (IntPtr)0)
  1325. {
  1326. // Re creates body on size.
  1327. // EnableBody also does setMass()
  1328. enableBody();
  1329. d.BodyEnable(Body);
  1330. }
  1331. }
  1332. _parent_scene.geom_name_map[prim_geom] = oldname;
  1333. changeSelectedStatus(timestamp);
  1334. resetCollisionAccounting();
  1335. m_taintshape = false;
  1336. }
  1337. public void changeAddForce(float timestamp)
  1338. {
  1339. if (!m_isSelected)
  1340. {
  1341. lock (m_forcelist)
  1342. {
  1343. //m_log.Info("[PHYSICS]: dequeing forcelist");
  1344. if (IsPhysical)
  1345. {
  1346. PhysicsVector iforce = new PhysicsVector();
  1347. for (int i = 0; i < m_forcelist.Count; i++)
  1348. {
  1349. iforce = iforce + (m_forcelist[i] * 100);
  1350. }
  1351. d.BodyEnable(Body);
  1352. d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
  1353. }
  1354. m_forcelist.Clear();
  1355. }
  1356. m_collisionscore = 0;
  1357. m_interpenetrationcount = 0;
  1358. }
  1359. m_taintforce = false;
  1360. }
  1361. private void changevelocity(float timestep)
  1362. {
  1363. if (!m_isSelected)
  1364. {
  1365. System.Threading.Thread.Sleep(20);
  1366. if (IsPhysical)
  1367. {
  1368. if (Body != (IntPtr)0)
  1369. {
  1370. d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
  1371. }
  1372. }
  1373. //resetCollisionAccounting();
  1374. }
  1375. m_taintVelocity = PhysicsVector.Zero;
  1376. }
  1377. public override bool IsPhysical
  1378. {
  1379. get { return m_isphysical; }
  1380. set { m_isphysical = value; }
  1381. }
  1382. public void setPrimForRemoval()
  1383. {
  1384. m_taintremove = true;
  1385. }
  1386. public override bool Flying
  1387. {
  1388. get { return false; //no flying prims for you
  1389. }
  1390. set { }
  1391. }
  1392. public override bool IsColliding
  1393. {
  1394. get { return iscolliding; }
  1395. set { iscolliding = value; }
  1396. }
  1397. public override bool CollidingGround
  1398. {
  1399. get { return false; }
  1400. set { return; }
  1401. }
  1402. public override bool CollidingObj
  1403. {
  1404. get { return false; }
  1405. set { return; }
  1406. }
  1407. public override bool ThrottleUpdates
  1408. {
  1409. get { return m_throttleUpdates; }
  1410. set { m_throttleUpdates = value; }
  1411. }
  1412. public override bool Stopped
  1413. {
  1414. get { return _zeroFlag; }
  1415. }
  1416. public override PhysicsVector Position
  1417. {
  1418. get { return _position; }
  1419. set { _position = value;
  1420. //m_log.Info("[PHYSICS]: " + _position.ToString());
  1421. }
  1422. }
  1423. public override PhysicsVector Size
  1424. {
  1425. get { return _size; }
  1426. set { _size = value; }
  1427. }
  1428. public override float Mass
  1429. {
  1430. get { return CalculateMass(); }
  1431. }
  1432. public override PhysicsVector Force
  1433. {
  1434. get { return PhysicsVector.Zero; }
  1435. }
  1436. public override PhysicsVector CenterOfMass
  1437. {
  1438. get { return PhysicsVector.Zero; }
  1439. }
  1440. public override PhysicsVector GeometricCenter
  1441. {
  1442. get { return PhysicsVector.Zero; }
  1443. }
  1444. public override PrimitiveBaseShape Shape
  1445. {
  1446. set {
  1447. _pbs = value;
  1448. m_taintshape = true;
  1449. }
  1450. }
  1451. public override PhysicsVector Velocity
  1452. {
  1453. get
  1454. {
  1455. // Averate previous velocity with the new one so
  1456. // client object interpolation works a 'little' better
  1457. PhysicsVector returnVelocity = new PhysicsVector();
  1458. returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
  1459. returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
  1460. returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
  1461. return returnVelocity;
  1462. }
  1463. set {
  1464. _velocity = value;
  1465. m_taintVelocity = value;
  1466. _parent_scene.AddPhysicsActorTaint(this);
  1467. }
  1468. }
  1469. public override float CollisionScore
  1470. {
  1471. get { return m_collisionscore; }
  1472. }
  1473. public override bool Kinematic
  1474. {
  1475. get { return false; }
  1476. set { }
  1477. }
  1478. public override Quaternion Orientation
  1479. {
  1480. get { return _orientation; }
  1481. set { _orientation = value; }
  1482. }
  1483. public override PhysicsVector Acceleration
  1484. {
  1485. get { return _acceleration; }
  1486. }
  1487. public void SetAcceleration(PhysicsVector accel)
  1488. {
  1489. _acceleration = accel;
  1490. }
  1491. public override void AddForce(PhysicsVector force)
  1492. {
  1493. m_forcelist.Add(force);
  1494. m_taintforce = true;
  1495. //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
  1496. }
  1497. public override PhysicsVector RotationalVelocity
  1498. {
  1499. get {
  1500. PhysicsVector pv = new PhysicsVector(0, 0, 0);
  1501. if (_zeroFlag)
  1502. return pv;
  1503. m_lastUpdateSent = false;
  1504. if (m_rotationalVelocity.IsIdentical(pv, 0.2f))
  1505. return pv;
  1506. return m_rotationalVelocity;
  1507. }
  1508. set { m_rotationalVelocity = value; }
  1509. }
  1510. public override void CrossingFailure()
  1511. {
  1512. m_crossingfailures++;
  1513. if (m_crossingfailures > 5)
  1514. {
  1515. base.RaiseOutOfBounds(_position);
  1516. return;
  1517. }
  1518. else if (m_crossingfailures == 5)
  1519. {
  1520. m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
  1521. }
  1522. }
  1523. public override float Buoyancy
  1524. {
  1525. get { return m_buoyancy; }
  1526. set { m_buoyancy = value; }
  1527. }
  1528. public override void link(PhysicsActor obj)
  1529. {
  1530. m_taintparent = obj;
  1531. }
  1532. public override void delink()
  1533. {
  1534. m_taintparent = null;
  1535. }
  1536. public void UpdatePositionAndVelocity()
  1537. {
  1538. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  1539. if (_parent != null)
  1540. {
  1541. }
  1542. else
  1543. {
  1544. PhysicsVector pv = new PhysicsVector(0, 0, 0);
  1545. bool lastZeroFlag = _zeroFlag;
  1546. if (Body != (IntPtr)0)
  1547. {
  1548. d.Vector3 vec = d.BodyGetPosition(Body);
  1549. d.Quaternion ori = d.BodyGetQuaternion(Body);
  1550. d.Vector3 vel = d.BodyGetLinearVel(Body);
  1551. d.Vector3 rotvel = d.BodyGetAngularVel(Body);
  1552. PhysicsVector l_position = new PhysicsVector();
  1553. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  1554. //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1555. //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1556. //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1557. //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1558. m_lastposition = _position;
  1559. l_position.X = vec.X;
  1560. l_position.Y = vec.Y;
  1561. l_position.Z = vec.Z;
  1562. if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f)
  1563. {
  1564. //base.RaiseOutOfBounds(l_position);
  1565. if (m_crossingfailures < 5)
  1566. {
  1567. _position = l_position;
  1568. //_parent_scene.remActivePrim(this);
  1569. base.RequestPhysicsterseUpdate();
  1570. return;
  1571. }
  1572. else
  1573. {
  1574. base.RaiseOutOfBounds(l_position);
  1575. return;
  1576. }
  1577. }
  1578. if (l_position.Z < 0)
  1579. {
  1580. // This is so prim that get lost underground don't fall forever and suck up
  1581. //
  1582. // Sim resources and memory.
  1583. // Disables the prim's movement physics....
  1584. // It's a hack and will generate a console message if it fails.
  1585. //IsPhysical = false;
  1586. base.RaiseOutOfBounds(_position);
  1587. _acceleration.X = 0;
  1588. _acceleration.Y = 0;
  1589. _acceleration.Z = 0;
  1590. _velocity.X = 0;
  1591. _velocity.Y = 0;
  1592. _velocity.Z = 0;
  1593. m_rotationalVelocity.X = 0;
  1594. m_rotationalVelocity.Y = 0;
  1595. m_rotationalVelocity.Z = 0;
  1596. base.RequestPhysicsterseUpdate();
  1597. m_throttleUpdates = false;
  1598. throttleCounter = 0;
  1599. _zeroFlag = true;
  1600. //outofBounds = true;
  1601. }
  1602. if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
  1603. && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
  1604. && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02))
  1605. {
  1606. _zeroFlag = true;
  1607. m_throttleUpdates = false;
  1608. }
  1609. else
  1610. {
  1611. //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
  1612. _zeroFlag = false;
  1613. }
  1614. if (_zeroFlag)
  1615. {
  1616. // Supposedly this is supposed to tell SceneObjectGroup that
  1617. // no more updates need to be sent..
  1618. // but it seems broken.
  1619. _velocity.X = 0.0f;
  1620. _velocity.Y = 0.0f;
  1621. _velocity.Z = 0.0f;
  1622. _acceleration.X = 0;
  1623. _acceleration.Y = 0;
  1624. _acceleration.Z = 0;
  1625. //_orientation.w = 0f;
  1626. //_orientation.x = 0f;
  1627. //_orientation.y = 0f;
  1628. //_orientation.z = 0f;
  1629. m_rotationalVelocity.X = 0;
  1630. m_rotationalVelocity.Y = 0;
  1631. m_rotationalVelocity.Z = 0;
  1632. if (!m_lastUpdateSent)
  1633. {
  1634. m_throttleUpdates = false;
  1635. throttleCounter = 0;
  1636. m_rotationalVelocity = pv;
  1637. base.RequestPhysicsterseUpdate();
  1638. m_lastUpdateSent = true;
  1639. }
  1640. }
  1641. else
  1642. {
  1643. if (lastZeroFlag != _zeroFlag)
  1644. base.RequestPhysicsterseUpdate();
  1645. m_lastVelocity = _velocity;
  1646. _position = l_position;
  1647. _velocity.X = vel.X;
  1648. _velocity.Y = vel.Y;
  1649. _velocity.Z = vel.Z;
  1650. _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
  1651. _acceleration = new PhysicsVector(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
  1652. //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
  1653. if (_velocity.IsIdentical(pv, 0.5f))
  1654. {
  1655. m_rotationalVelocity = pv;
  1656. }
  1657. else
  1658. {
  1659. m_rotationalVelocity.setValues(rotvel.X, rotvel.Y, rotvel.Z);
  1660. }
  1661. //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
  1662. _orientation.w = ori.W;
  1663. _orientation.x = ori.X;
  1664. _orientation.y = ori.Y;
  1665. _orientation.z = ori.Z;
  1666. m_lastUpdateSent = false;
  1667. if (!m_throttleUpdates || throttleCounter > 15)
  1668. {
  1669. base.RequestPhysicsterseUpdate();
  1670. }
  1671. else
  1672. {
  1673. throttleCounter++;
  1674. }
  1675. }
  1676. m_lastposition = l_position;
  1677. }
  1678. else
  1679. {
  1680. // Not a body.. so Make sure the client isn't interpolating
  1681. _velocity.X = 0;
  1682. _velocity.Y = 0;
  1683. _velocity.Z = 0;
  1684. _acceleration.X = 0;
  1685. _acceleration.Y = 0;
  1686. _acceleration.Z = 0;
  1687. m_rotationalVelocity.X = 0;
  1688. m_rotationalVelocity.Y = 0;
  1689. m_rotationalVelocity.Z = 0;
  1690. _zeroFlag = true;
  1691. }
  1692. }
  1693. }
  1694. public override bool FloatOnWater
  1695. {
  1696. set {
  1697. m_taintCollidesWater = value;
  1698. _parent_scene.AddPhysicsActorTaint(this);
  1699. }
  1700. }
  1701. public override void SetMomentum(PhysicsVector momentum)
  1702. {
  1703. }
  1704. public override PhysicsVector PIDTarget { set { m_PIDTarget = value; ; } }
  1705. public override bool PIDActive { set { m_usePID = value; } }
  1706. public override float PIDTau { set { m_PIDTau = (value * 0.6f); } }
  1707. }
  1708. }