ODEPrim.cs 82 KB

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