ODEPrim.cs 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425
  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. */
  28. using System;
  29. using System.Collections.Generic;
  30. using System.Runtime.InteropServices;
  31. using Axiom.Math;
  32. using Ode.NET;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Physics.Manager;
  35. namespace OpenSim.Region.Physics.OdePlugin
  36. {
  37. public class OdePrim : PhysicsActor
  38. {
  39. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  40. public PhysicsVector _position;
  41. private PhysicsVector _velocity;
  42. private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
  43. private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
  44. private PhysicsVector m_rotationalVelocity;
  45. private PhysicsVector _size;
  46. private PhysicsVector _acceleration;
  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 bool m_taintshape = false;
  53. private bool m_taintPhysics = false;
  54. public bool m_taintremove = false;
  55. public bool m_taintdisable = false;
  56. public bool m_disabled = false;
  57. public bool m_taintadd = false;
  58. public GCHandle gc;
  59. private CollisionLocker ode;
  60. private bool m_taintforce = false;
  61. private List<PhysicsVector> m_forcelist = new List<PhysicsVector>();
  62. private IMesh _mesh;
  63. private PrimitiveBaseShape _pbs;
  64. private OdeScene _parent_scene;
  65. public IntPtr m_targetSpace = (IntPtr) 0;
  66. public IntPtr prim_geom;
  67. public IntPtr prev_geom;
  68. public IntPtr _triMeshData;
  69. private bool iscolliding = false;
  70. private bool m_isphysical = false;
  71. private bool m_throttleUpdates = false;
  72. private int throttleCounter = 0;
  73. public int m_interpenetrationcount = 0;
  74. public int m_collisionscore = 0;
  75. public int m_roundsUnderMotionThreshold = 0;
  76. private int m_crossingfailures = 0;
  77. public bool outofBounds = false;
  78. private float m_density = 10.000006836f; // Aluminum g/cm3;
  79. public bool _zeroFlag = false;
  80. private bool m_lastUpdateSent = false;
  81. public IntPtr Body = (IntPtr) 0;
  82. private String m_primName;
  83. private PhysicsVector _target_velocity;
  84. public d.Mass pMass;
  85. private int debugcounter = 0;
  86. public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
  87. Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
  88. {
  89. gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
  90. ode = dode;
  91. _velocity = new PhysicsVector();
  92. _position = pos;
  93. m_taintposition = pos;
  94. if (_position.X > 257)
  95. {
  96. _position.X = 257;
  97. }
  98. if (_position.X < 0)
  99. {
  100. _position.X = 0;
  101. }
  102. if (_position.Y > 257)
  103. {
  104. _position.Y = 257;
  105. }
  106. if (_position.Y < 0)
  107. {
  108. _position.Y = 0;
  109. }
  110. prim_geom = (IntPtr)0;
  111. prev_geom = (IntPtr)0;
  112. _size = size;
  113. m_taintsize = _size;
  114. _acceleration = new PhysicsVector();
  115. m_rotationalVelocity = PhysicsVector.Zero;
  116. _orientation = rotation;
  117. m_taintrot = _orientation;
  118. _mesh = mesh;
  119. _pbs = pbs;
  120. _parent_scene = parent_scene;
  121. m_targetSpace = (IntPtr)0;
  122. if (pos.Z < 0)
  123. m_isphysical = false;
  124. else
  125. {
  126. m_isphysical = pisPhysical;
  127. // If we're physical, we need to be in the master space for now.
  128. // linksets *should* be in a space together.. but are not currently
  129. if (m_isphysical)
  130. m_targetSpace = _parent_scene.space;
  131. }
  132. m_primName = primName;
  133. m_taintadd = true;
  134. _parent_scene.AddPhysicsActorTaint(this);
  135. // don't do .add() here; old geoms get recycled with the same hash
  136. }
  137. /// <summary>
  138. /// Nasty, however without this you get
  139. /// 'invalid operation for locked space' when things are really loaded down
  140. /// </summary>
  141. /// <param name="space"></param>
  142. public override int PhysicsActorType
  143. {
  144. get { return (int) ActorTypes.Prim; }
  145. set { return; }
  146. }
  147. public override bool SetAlwaysRun
  148. {
  149. get { return false; }
  150. set { return; }
  151. }
  152. public override bool Grabbed
  153. {
  154. set { return; }
  155. }
  156. public override bool Selected
  157. {
  158. set { return; }
  159. }
  160. public void SetGeom(IntPtr geom)
  161. {
  162. prev_geom = prim_geom;
  163. prim_geom = geom;
  164. //m_log.Warn("Setting Geom to: " + prim_geom);
  165. }
  166. public void enableBody()
  167. {
  168. // Sets the geom to a body
  169. Body = d.BodyCreate(_parent_scene.world);
  170. setMass();
  171. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  172. d.Quaternion myrot = new d.Quaternion();
  173. myrot.W = _orientation.w;
  174. myrot.X = _orientation.x;
  175. myrot.Y = _orientation.y;
  176. myrot.Z = _orientation.z;
  177. d.BodySetQuaternion(Body, ref myrot);
  178. d.GeomSetBody(prim_geom, Body);
  179. d.BodySetAutoDisableFlag(Body, true);
  180. d.BodySetAutoDisableSteps(Body, 20);
  181. m_interpenetrationcount = 0;
  182. m_collisionscore = 0;
  183. m_disabled = false;
  184. _parent_scene.addActivePrim(this);
  185. }
  186. private float CalculateMass()
  187. {
  188. float volume = 0;
  189. // No material is passed to the physics engines yet.. soo..
  190. // we're using the m_density constant in the class definition
  191. float returnMass = 0;
  192. switch (_pbs.ProfileShape)
  193. {
  194. case ProfileShape.Square:
  195. // Profile Volume
  196. volume = _size.X*_size.Y*_size.Z;
  197. // If the user has 'hollowed out'
  198. // ProfileHollow is one of those 0 to 50000 values :P
  199. // we like percentages better.. so turning into a percentage
  200. if (((float) _pbs.ProfileHollow/50000f) > 0.0)
  201. {
  202. float hollowAmount = (float) _pbs.ProfileHollow/50000f;
  203. // calculate the hollow volume by it's shape compared to the prim shape
  204. float hollowVolume = 0;
  205. switch (_pbs.HollowShape)
  206. {
  207. case HollowShape.Square:
  208. case HollowShape.Same:
  209. // Cube Hollow volume calculation
  210. float hollowsizex = _size.X*hollowAmount;
  211. float hollowsizey = _size.Y*hollowAmount;
  212. float hollowsizez = _size.Z*hollowAmount;
  213. hollowVolume = hollowsizex*hollowsizey*hollowsizez;
  214. break;
  215. case HollowShape.Circle:
  216. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  217. // Cyllinder hollow volume calculation
  218. float hRadius = _size.X/2;
  219. float hLength = _size.Z;
  220. // pi * r2 * h
  221. hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount);
  222. break;
  223. case HollowShape.Triangle:
  224. // Equilateral Triangular Prism volume hollow calculation
  225. // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
  226. float aLength = _size.Y;
  227. // 1/2 abh
  228. hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount);
  229. break;
  230. default:
  231. hollowVolume = 0;
  232. break;
  233. }
  234. volume = volume - hollowVolume;
  235. }
  236. break;
  237. default:
  238. // we don't have all of the volume formulas yet so
  239. // use the common volume formula for all
  240. volume = _size.X*_size.Y*_size.Z;
  241. break;
  242. }
  243. // Calculate Path cut effect on volume
  244. // Not exact, in the triangle hollow example
  245. // They should never be zero or less then zero..
  246. // we'll ignore it if it's less then zero
  247. // ProfileEnd and ProfileBegin are values
  248. // from 0 to 50000
  249. // Turning them back into percentages so that I can cut that percentage off the volume
  250. float PathCutEndAmount = _pbs.ProfileEnd;
  251. float PathCutStartAmount = _pbs.ProfileBegin;
  252. if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f)
  253. {
  254. float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f);
  255. // Check the return amount for sanity
  256. if (pathCutAmount >= 0.99f)
  257. pathCutAmount = 0.99f;
  258. volume = volume - (volume*pathCutAmount);
  259. }
  260. // Mass = density * volume
  261. returnMass = m_density*volume;
  262. return returnMass;
  263. }
  264. public void setMass()
  265. {
  266. if (Body != (IntPtr) 0)
  267. {
  268. d.MassSetBoxTotal(out pMass, CalculateMass(), _size.X, _size.Y, _size.Z);
  269. d.BodySetMass(Body, ref pMass);
  270. }
  271. }
  272. public void disableBody()
  273. {
  274. //this kills the body so things like 'mesh' can re-create it.
  275. if (Body != (IntPtr) 0)
  276. {
  277. _parent_scene.remActivePrim(this);
  278. d.BodyDestroy(Body);
  279. Body = (IntPtr) 0;
  280. }
  281. m_disabled = true;
  282. m_collisionscore = 0;
  283. }
  284. public void setMesh(OdeScene parent_scene, IMesh mesh)
  285. {
  286. // This sleeper is there to moderate how long it takes between
  287. // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
  288. System.Threading.Thread.Sleep(10);
  289. //Kill Body so that mesh can re-make the geom
  290. if (IsPhysical && Body != (IntPtr) 0)
  291. {
  292. disableBody();
  293. }
  294. float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
  295. int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
  296. int VertexCount = vertexList.GetLength(0)/3;
  297. int IndexCount = indexList.GetLength(0);
  298. _triMeshData = d.GeomTriMeshDataCreate();
  299. d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
  300. 3*sizeof (int));
  301. d.GeomTriMeshDataPreprocess(_triMeshData);
  302. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  303. try
  304. {
  305. if (prim_geom == (IntPtr)0)
  306. {
  307. SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
  308. }
  309. }
  310. catch (System.AccessViolationException)
  311. {
  312. m_log.Error("[PHYSICS]: MESH LOCKED");
  313. return;
  314. }
  315. if (IsPhysical && Body == (IntPtr) 0)
  316. {
  317. // Recreate the body
  318. m_interpenetrationcount = 0;
  319. m_collisionscore = 0;
  320. enableBody();
  321. }
  322. }
  323. public void ProcessTaints(float timestep)
  324. {
  325. if (m_taintadd)
  326. {
  327. changeadd(timestep);
  328. }
  329. if (m_taintposition != _position)
  330. Move(timestep);
  331. if (m_taintrot != _orientation)
  332. rotate(timestep);
  333. //
  334. if (m_taintPhysics != m_isphysical)
  335. changePhysicsStatus(timestep);
  336. //
  337. if (m_taintsize != _size)
  338. changesize(timestep);
  339. //
  340. if (m_taintshape)
  341. changeshape(timestep);
  342. //
  343. if (m_taintforce)
  344. changeAddForce(timestep);
  345. if (m_taintdisable)
  346. changedisable(timestep);
  347. if (m_taintVelocity != PhysicsVector.Zero)
  348. changevelocity(timestep);
  349. }
  350. public void ResetTaints()
  351. {
  352. m_taintposition = _position;
  353. m_taintrot = _orientation;
  354. m_taintPhysics = m_isphysical;
  355. m_taintsize = _size;
  356. m_taintshape = false;
  357. m_taintforce = false;
  358. m_taintdisable = false;
  359. m_taintVelocity = PhysicsVector.Zero;
  360. }
  361. public void changeadd(float timestep)
  362. {
  363. while (ode.lockquery())
  364. {
  365. }
  366. ode.dlock(_parent_scene.world);
  367. int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  368. IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
  369. if (targetspace == IntPtr.Zero)
  370. targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
  371. m_targetSpace = targetspace;
  372. if (_mesh != null)
  373. {
  374. }
  375. else
  376. {
  377. if (_parent_scene.needsMeshing(_pbs))
  378. {
  379. // Don't need to re-enable body.. it's done in SetMesh
  380. _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size);
  381. // createmesh returns null when it's a shape that isn't a cube.
  382. }
  383. }
  384. lock (OdeScene.OdeLock)
  385. {
  386. if (_mesh != null)
  387. {
  388. setMesh(_parent_scene, _mesh);
  389. }
  390. else
  391. {
  392. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  393. {
  394. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  395. {
  396. if (((_size.X / 2f) > 0f))
  397. {
  398. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  399. try
  400. {
  401. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  402. }
  403. catch (System.AccessViolationException)
  404. {
  405. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  406. ode.dunlock(_parent_scene.world);
  407. return;
  408. }
  409. }
  410. else
  411. {
  412. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  413. try
  414. {
  415. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  416. }
  417. catch (System.AccessViolationException)
  418. {
  419. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  420. ode.dunlock(_parent_scene.world);
  421. return;
  422. }
  423. }
  424. }
  425. else
  426. {
  427. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  428. try
  429. {
  430. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  431. }
  432. catch (System.AccessViolationException)
  433. {
  434. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  435. ode.dunlock(_parent_scene.world);
  436. return;
  437. }
  438. }
  439. }
  440. //else if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  441. //{
  442. //Cyllinder
  443. //if (_size.X == _size.Y)
  444. //{
  445. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  446. //}
  447. //else
  448. //{
  449. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  450. //}
  451. //}
  452. else
  453. {
  454. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  455. try
  456. {
  457. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  458. }
  459. catch (System.AccessViolationException)
  460. {
  461. m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
  462. ode.dunlock(_parent_scene.world);
  463. return;
  464. }
  465. }
  466. }
  467. if (prim_geom != (IntPtr) 0)
  468. {
  469. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  470. d.Quaternion myrot = new d.Quaternion();
  471. myrot.W = _orientation.w;
  472. myrot.X = _orientation.x;
  473. myrot.Y = _orientation.y;
  474. myrot.Z = _orientation.z;
  475. d.GeomSetQuaternion(prim_geom, ref myrot);
  476. }
  477. if (m_isphysical && Body == (IntPtr)0)
  478. {
  479. enableBody();
  480. }
  481. }
  482. ode.dunlock(_parent_scene.world);
  483. _parent_scene.geom_name_map[prim_geom] = this.m_primName;
  484. _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
  485. m_taintadd = false;
  486. }
  487. public void Move(float timestep)
  488. {
  489. while (ode.lockquery())
  490. {
  491. }
  492. ode.dlock(_parent_scene.world);
  493. if (m_isphysical)
  494. {
  495. // This is a fallback.. May no longer be necessary.
  496. if (Body == (IntPtr) 0)
  497. enableBody();
  498. //Prim auto disable after 20 frames,
  499. //if you move it, re-enable the prim manually.
  500. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  501. d.BodyEnable(Body);
  502. }
  503. else
  504. {
  505. string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
  506. int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  507. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  508. IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
  509. m_targetSpace = tempspace;
  510. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  511. if (prim_geom != (IntPtr) 0)
  512. {
  513. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  514. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  515. d.SpaceAdd(m_targetSpace, prim_geom);
  516. }
  517. }
  518. ode.dunlock(_parent_scene.world);
  519. resetCollisionAccounting();
  520. m_taintposition = _position;
  521. }
  522. public void rotate(float timestep)
  523. {
  524. while (ode.lockquery())
  525. {
  526. }
  527. ode.dlock(_parent_scene.world);
  528. d.Quaternion myrot = new d.Quaternion();
  529. myrot.W = _orientation.w;
  530. myrot.X = _orientation.x;
  531. myrot.Y = _orientation.y;
  532. myrot.Z = _orientation.z;
  533. d.GeomSetQuaternion(prim_geom, ref myrot);
  534. if (m_isphysical && Body != (IntPtr) 0)
  535. {
  536. d.BodySetQuaternion(Body, ref myrot);
  537. }
  538. ode.dunlock(_parent_scene.world);
  539. resetCollisionAccounting();
  540. m_taintrot = _orientation;
  541. }
  542. private void resetCollisionAccounting()
  543. {
  544. m_collisionscore = 0;
  545. m_interpenetrationcount = 0;
  546. m_disabled = false;
  547. }
  548. public void changedisable(float timestep)
  549. {
  550. while (ode.lockquery())
  551. {
  552. }
  553. ode.dlock(_parent_scene.world);
  554. m_disabled = true;
  555. if (Body != (IntPtr)0)
  556. {
  557. d.BodyDisable(Body);
  558. Body = (IntPtr)0;
  559. }
  560. ode.dunlock(_parent_scene.world);
  561. m_taintdisable = false;
  562. }
  563. public void changePhysicsStatus(float timestap)
  564. {
  565. lock (ode)
  566. {
  567. while (ode.lockquery())
  568. {
  569. }
  570. ode.dlock(_parent_scene.world);
  571. if (m_isphysical == true)
  572. {
  573. if (Body == (IntPtr)0)
  574. {
  575. enableBody();
  576. }
  577. }
  578. else
  579. {
  580. if (Body != (IntPtr)0)
  581. {
  582. disableBody();
  583. }
  584. }
  585. ode.dunlock(_parent_scene.world);
  586. }
  587. resetCollisionAccounting();
  588. m_taintPhysics = m_isphysical;
  589. }
  590. public void changesize(float timestamp)
  591. {
  592. while (ode.lockquery())
  593. {
  594. }
  595. ode.dlock(_parent_scene.world);
  596. //if (!_parent_scene.geom_name_map.ContainsKey(prim_geom))
  597. //{
  598. // m_taintsize = _size;
  599. //return;
  600. //}
  601. string oldname = _parent_scene.geom_name_map[prim_geom];
  602. // Cleanup of old prim geometry
  603. if (_mesh != null)
  604. {
  605. // Cleanup meshing here
  606. }
  607. //kill body to rebuild
  608. if (IsPhysical && Body != (IntPtr) 0)
  609. {
  610. disableBody();
  611. }
  612. if (d.SpaceQuery(m_targetSpace, prim_geom))
  613. {
  614. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  615. d.SpaceRemove(m_targetSpace, prim_geom);
  616. }
  617. d.GeomDestroy(prim_geom);
  618. prim_geom = (IntPtr)0;
  619. // we don't need to do space calculation because the client sends a position update also.
  620. // Construction of new prim
  621. if (_parent_scene.needsMeshing(_pbs))
  622. {
  623. // Don't need to re-enable body.. it's done in SetMesh
  624. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  625. // createmesh returns null when it's a shape that isn't a cube.
  626. if (mesh != null)
  627. {
  628. setMesh(_parent_scene, mesh);
  629. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  630. d.Quaternion myrot = new d.Quaternion();
  631. myrot.W = _orientation.w;
  632. myrot.X = _orientation.x;
  633. myrot.Y = _orientation.y;
  634. myrot.Z = _orientation.z;
  635. d.GeomSetQuaternion(prim_geom, ref myrot);
  636. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  637. if (IsPhysical && Body == (IntPtr)0)
  638. {
  639. // Re creates body on size.
  640. // EnableBody also does setMass()
  641. enableBody();
  642. d.BodyEnable(Body);
  643. }
  644. }
  645. else
  646. {
  647. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  648. {
  649. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  650. {
  651. if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
  652. {
  653. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  654. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  655. }
  656. else
  657. {
  658. m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
  659. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  660. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  661. }
  662. }
  663. else
  664. {
  665. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  666. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  667. }
  668. }
  669. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  670. //{
  671. //Cyllinder
  672. //if (_size.X == _size.Y)
  673. //{
  674. // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  675. //}
  676. //else
  677. //{
  678. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  679. //}
  680. //}
  681. else
  682. {
  683. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  684. SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  685. }
  686. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  687. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  688. d.Quaternion myrot = new d.Quaternion();
  689. myrot.W = _orientation.w;
  690. myrot.X = _orientation.x;
  691. myrot.Y = _orientation.y;
  692. myrot.Z = _orientation.z;
  693. d.GeomSetQuaternion(prim_geom, ref myrot);
  694. }
  695. }
  696. else
  697. {
  698. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  699. {
  700. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  701. {
  702. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  703. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  704. }
  705. else
  706. {
  707. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  708. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  709. }
  710. }
  711. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  712. //{
  713. //Cyllinder
  714. //if (_size.X == _size.Y)
  715. //{
  716. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  717. //}
  718. //else
  719. //{
  720. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  721. //}
  722. //}
  723. else
  724. {
  725. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  726. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  727. }
  728. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  729. d.Quaternion myrot = new d.Quaternion();
  730. myrot.W = _orientation.w;
  731. myrot.X = _orientation.x;
  732. myrot.Y = _orientation.y;
  733. myrot.Z = _orientation.z;
  734. d.GeomSetQuaternion(prim_geom, ref myrot);
  735. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  736. if (IsPhysical && Body == (IntPtr) 0)
  737. {
  738. // Re creates body on size.
  739. // EnableBody also does setMass()
  740. enableBody();
  741. d.BodyEnable(Body);
  742. }
  743. }
  744. _parent_scene.geom_name_map[prim_geom] = oldname;
  745. ode.dunlock(_parent_scene.world);
  746. resetCollisionAccounting();
  747. m_taintsize = _size;
  748. }
  749. public void changeshape(float timestamp)
  750. {
  751. while (ode.lockquery())
  752. {
  753. }
  754. ode.dlock(_parent_scene.world);
  755. string oldname = _parent_scene.geom_name_map[prim_geom];
  756. // Cleanup of old prim geometry and Bodies
  757. if (IsPhysical && Body != (IntPtr) 0)
  758. {
  759. disableBody();
  760. }
  761. d.GeomDestroy(prim_geom);
  762. prim_geom = (IntPtr) 0;
  763. // we don't need to do space calculation because the client sends a position update also.
  764. // Construction of new prim
  765. if (_parent_scene.needsMeshing(_pbs))
  766. {
  767. // Don't need to re-enable body.. it's done in SetMesh
  768. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  769. // createmesh returns null when it's a shape that isn't a cube.
  770. if (mesh != null)
  771. {
  772. setMesh(_parent_scene, mesh);
  773. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  774. d.Quaternion myrot = new d.Quaternion();
  775. myrot.W = _orientation.w;
  776. myrot.X = _orientation.x;
  777. myrot.Y = _orientation.y;
  778. myrot.Z = _orientation.z;
  779. d.GeomSetQuaternion(prim_geom, ref myrot);
  780. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  781. if (IsPhysical && Body == (IntPtr)0)
  782. {
  783. // Re creates body on size.
  784. // EnableBody also does setMass()
  785. enableBody();
  786. d.BodyEnable(Body);
  787. }
  788. }
  789. else
  790. {
  791. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  792. {
  793. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  794. {
  795. if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
  796. {
  797. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  798. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  799. }
  800. else
  801. {
  802. m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
  803. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  804. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  805. }
  806. }
  807. else
  808. {
  809. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  810. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  811. }
  812. }
  813. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  814. //{
  815. //Cyllinder
  816. //if (_size.X == _size.Y)
  817. //{
  818. // prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  819. //}
  820. //else
  821. //{
  822. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  823. //}
  824. //}
  825. else
  826. {
  827. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  828. SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  829. }
  830. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  831. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  832. d.Quaternion myrot = new d.Quaternion();
  833. myrot.W = _orientation.w;
  834. myrot.X = _orientation.x;
  835. myrot.Y = _orientation.y;
  836. myrot.Z = _orientation.z;
  837. d.GeomSetQuaternion(prim_geom, ref myrot);
  838. }
  839. }
  840. else
  841. {
  842. if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
  843. {
  844. if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
  845. {
  846. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  847. SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
  848. }
  849. else
  850. {
  851. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  852. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  853. }
  854. }
  855. //else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
  856. //{
  857. //Cyllinder
  858. //if (_size.X == _size.Y)
  859. //{
  860. //prim_geom = d.CreateCylinder(m_targetSpace, _size.X / 2, _size.Z);
  861. //}
  862. //else
  863. //{
  864. //prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  865. //}
  866. //}
  867. else
  868. {
  869. _parent_scene.waitForSpaceUnlock(m_targetSpace);
  870. SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
  871. }
  872. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  873. d.Quaternion myrot = new d.Quaternion();
  874. myrot.W = _orientation.w;
  875. myrot.X = _orientation.x;
  876. myrot.Y = _orientation.y;
  877. myrot.Z = _orientation.z;
  878. d.GeomSetQuaternion(prim_geom, ref myrot);
  879. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  880. if (IsPhysical && Body == (IntPtr)0)
  881. {
  882. // Re creates body on size.
  883. // EnableBody also does setMass()
  884. enableBody();
  885. d.BodyEnable(Body);
  886. }
  887. }
  888. _parent_scene.geom_name_map[prim_geom] = oldname;
  889. ode.dunlock(_parent_scene.world);
  890. resetCollisionAccounting();
  891. m_taintshape = false;
  892. }
  893. public void changeAddForce(float timestamp)
  894. {
  895. while (ode.lockquery())
  896. {
  897. }
  898. ode.dlock(_parent_scene.world);
  899. lock (m_forcelist)
  900. {
  901. //m_log.Info("[PHYSICS]: dequeing forcelist");
  902. if (IsPhysical)
  903. {
  904. PhysicsVector iforce = new PhysicsVector();
  905. for (int i = 0; i < m_forcelist.Count; i++)
  906. {
  907. iforce = iforce + (m_forcelist[i]*100);
  908. }
  909. d.BodyEnable(Body);
  910. d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
  911. }
  912. m_forcelist.Clear();
  913. }
  914. ode.dunlock(_parent_scene.world);
  915. m_collisionscore = 0;
  916. m_interpenetrationcount = 0;
  917. m_taintforce = false;
  918. }
  919. private void changevelocity(float timestep)
  920. {
  921. lock (ode)
  922. {
  923. while (ode.lockquery())
  924. {
  925. }
  926. ode.dlock(_parent_scene.world);
  927. System.Threading.Thread.Sleep(20);
  928. if (IsPhysical)
  929. {
  930. if (Body != (IntPtr)0)
  931. {
  932. d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
  933. }
  934. }
  935. ode.dunlock(_parent_scene.world);
  936. }
  937. //resetCollisionAccounting();
  938. m_taintVelocity = PhysicsVector.Zero;
  939. }
  940. public override bool IsPhysical
  941. {
  942. get { return m_isphysical; }
  943. set { m_isphysical = value; }
  944. }
  945. public void setPrimForRemoval()
  946. {
  947. m_taintremove = true;
  948. }
  949. public override bool Flying
  950. {
  951. get { return false; //no flying prims for you
  952. }
  953. set { }
  954. }
  955. public override bool IsColliding
  956. {
  957. get { return iscolliding; }
  958. set { iscolliding = value; }
  959. }
  960. public override bool CollidingGround
  961. {
  962. get { return false; }
  963. set { return; }
  964. }
  965. public override bool CollidingObj
  966. {
  967. get { return false; }
  968. set { return; }
  969. }
  970. public override bool ThrottleUpdates
  971. {
  972. get { return m_throttleUpdates; }
  973. set { m_throttleUpdates = value; }
  974. }
  975. public override bool Stopped
  976. {
  977. get { return _zeroFlag; }
  978. }
  979. public override PhysicsVector Position
  980. {
  981. get { return _position; }
  982. set { _position = value;
  983. //m_log.Info("[PHYSICS]: " + _position.ToString());
  984. }
  985. }
  986. public override PhysicsVector Size
  987. {
  988. get { return _size; }
  989. set { _size = value; }
  990. }
  991. public override float Mass
  992. {
  993. get { return CalculateMass(); }
  994. }
  995. public override PhysicsVector Force
  996. {
  997. get { return PhysicsVector.Zero; }
  998. }
  999. public override PhysicsVector CenterOfMass
  1000. {
  1001. get { return PhysicsVector.Zero; }
  1002. }
  1003. public override PhysicsVector GeometricCenter
  1004. {
  1005. get { return PhysicsVector.Zero; }
  1006. }
  1007. public override PrimitiveBaseShape Shape
  1008. {
  1009. set {
  1010. _pbs = value;
  1011. m_taintshape = true;
  1012. }
  1013. }
  1014. public override PhysicsVector Velocity
  1015. {
  1016. get
  1017. {
  1018. // Averate previous velocity with the new one so
  1019. // client object interpolation works a 'little' better
  1020. PhysicsVector returnVelocity = new PhysicsVector();
  1021. returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
  1022. returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
  1023. returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
  1024. return returnVelocity;
  1025. }
  1026. set {
  1027. _velocity = value;
  1028. m_taintVelocity = value;
  1029. _parent_scene.AddPhysicsActorTaint(this);
  1030. }
  1031. }
  1032. public override float CollisionScore
  1033. {
  1034. get { return m_collisionscore; }
  1035. }
  1036. public override bool Kinematic
  1037. {
  1038. get { return false; }
  1039. set { }
  1040. }
  1041. public override Quaternion Orientation
  1042. {
  1043. get { return _orientation; }
  1044. set { _orientation = value; }
  1045. }
  1046. public override PhysicsVector Acceleration
  1047. {
  1048. get { return _acceleration; }
  1049. }
  1050. public void SetAcceleration(PhysicsVector accel)
  1051. {
  1052. _acceleration = accel;
  1053. }
  1054. public override void AddForce(PhysicsVector force)
  1055. {
  1056. m_forcelist.Add(force);
  1057. m_taintforce = true;
  1058. //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
  1059. }
  1060. public override PhysicsVector RotationalVelocity
  1061. {
  1062. get {
  1063. PhysicsVector pv = new PhysicsVector(0, 0, 0);
  1064. if (_zeroFlag)
  1065. return pv;
  1066. m_lastUpdateSent = false;
  1067. if (m_rotationalVelocity.IsIdentical(pv, 0.2f))
  1068. return pv;
  1069. return m_rotationalVelocity;
  1070. }
  1071. set { m_rotationalVelocity = value; }
  1072. }
  1073. public override void CrossingFailure()
  1074. {
  1075. m_crossingfailures++;
  1076. if (m_crossingfailures > 5)
  1077. {
  1078. base.RaiseOutOfBounds(_position);
  1079. return;
  1080. }
  1081. else if (m_crossingfailures == 5)
  1082. {
  1083. m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName);
  1084. }
  1085. }
  1086. public void UpdatePositionAndVelocity()
  1087. {
  1088. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  1089. PhysicsVector pv = new PhysicsVector(0, 0, 0);
  1090. if (Body != (IntPtr) 0)
  1091. {
  1092. d.Vector3 vec = d.BodyGetPosition(Body);
  1093. d.Quaternion ori = d.BodyGetQuaternion(Body);
  1094. d.Vector3 vel = d.BodyGetLinearVel(Body);
  1095. d.Vector3 rotvel = d.BodyGetAngularVel(Body);
  1096. PhysicsVector l_position = new PhysicsVector();
  1097. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  1098. //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1099. //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1100. //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1101. //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
  1102. m_lastposition = _position;
  1103. l_position.X = vec.X;
  1104. l_position.Y = vec.Y;
  1105. l_position.Z = vec.Z;
  1106. if (l_position.X > 255.95f || l_position.X < 0f || l_position.Y > 255.95f || l_position.Y < 0f)
  1107. {
  1108. base.RaiseOutOfBounds(_position);
  1109. }
  1110. //if (m_crossingfailures < 5)
  1111. //{
  1112. //base.RequestPhysicsterseUpdate();
  1113. //}
  1114. //}
  1115. if (l_position.Z < 0)
  1116. {
  1117. // This is so prim that get lost underground don't fall forever and suck up
  1118. //
  1119. // Sim resources and memory.
  1120. // Disables the prim's movement physics....
  1121. // It's a hack and will generate a console message if it fails.
  1122. //IsPhysical = false;
  1123. base.RaiseOutOfBounds(_position);
  1124. _velocity.X = 0;
  1125. _velocity.Y = 0;
  1126. _velocity.Z = 0;
  1127. m_rotationalVelocity.X = 0;
  1128. m_rotationalVelocity.Y = 0;
  1129. m_rotationalVelocity.Z = 0;
  1130. base.RequestPhysicsterseUpdate();
  1131. m_throttleUpdates = false;
  1132. throttleCounter = 0;
  1133. _zeroFlag = true;
  1134. //outofBounds = true;
  1135. }
  1136. if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
  1137. && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
  1138. && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02))
  1139. {
  1140. _zeroFlag = true;
  1141. m_throttleUpdates = false;
  1142. }
  1143. else
  1144. {
  1145. //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
  1146. _zeroFlag = false;
  1147. }
  1148. if (_zeroFlag)
  1149. {
  1150. // Supposedly this is supposed to tell SceneObjectGroup that
  1151. // no more updates need to be sent..
  1152. // but it seems broken.
  1153. _velocity.X = 0.0f;
  1154. _velocity.Y = 0.0f;
  1155. _velocity.Z = 0.0f;
  1156. //_orientation.w = 0f;
  1157. //_orientation.x = 0f;
  1158. //_orientation.y = 0f;
  1159. //_orientation.z = 0f;
  1160. m_rotationalVelocity.X = 0;
  1161. m_rotationalVelocity.Y = 0;
  1162. m_rotationalVelocity.Z = 0;
  1163. if (!m_lastUpdateSent)
  1164. {
  1165. m_throttleUpdates = false;
  1166. throttleCounter = 0;
  1167. m_rotationalVelocity = pv;
  1168. base.RequestPhysicsterseUpdate();
  1169. m_lastUpdateSent = true;
  1170. }
  1171. }
  1172. else
  1173. {
  1174. m_lastVelocity = _velocity;
  1175. _position = l_position;
  1176. _velocity.X = vel.X;
  1177. _velocity.Y = vel.Y;
  1178. _velocity.Z = vel.Z;
  1179. if (_velocity.IsIdentical(pv, 0.5f))
  1180. {
  1181. m_rotationalVelocity = pv;
  1182. }
  1183. else
  1184. {
  1185. m_rotationalVelocity.setValues(rotvel.X, rotvel.Y, rotvel.Z);
  1186. }
  1187. //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
  1188. _orientation.w = ori.W;
  1189. _orientation.x = ori.X;
  1190. _orientation.y = ori.Y;
  1191. _orientation.z = ori.Z;
  1192. m_lastUpdateSent = false;
  1193. if (!m_throttleUpdates || throttleCounter > 15)
  1194. {
  1195. base.RequestPhysicsterseUpdate();
  1196. }
  1197. else
  1198. {
  1199. throttleCounter++;
  1200. }
  1201. }
  1202. m_lastposition = l_position;
  1203. }
  1204. else
  1205. {
  1206. // Not a body.. so Make sure the client isn't interpolating
  1207. _velocity.X = 0;
  1208. _velocity.Y = 0;
  1209. _velocity.Z = 0;
  1210. m_rotationalVelocity.X = 0;
  1211. m_rotationalVelocity.Y = 0;
  1212. m_rotationalVelocity.Z = 0;
  1213. _zeroFlag = true;
  1214. }
  1215. }
  1216. public override void SetMomentum(PhysicsVector momentum)
  1217. {
  1218. }
  1219. }
  1220. }