OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ODEPrim.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
30  * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
31  * ODEPrim.cs contains methods dealing with Prim editing, Prim
32  * characteristics and Kinetic motion.
33  * ODEDynamics.cs contains methods dealing with Prim Physical motion
34  * (dynamics) and the associated settings. Old Linear and angular
35  * motors for dynamic motion have been replace with MoveLinear()
36  * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
37  * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
38  * switch between 'VEHICLE' parameter use and general dynamics
39  * settings use.
40  */
41 
42 //#define SPAM
43 
44 using System;
45 using System.Collections.Generic;
46 using System.Reflection;
47 using System.Runtime.InteropServices;
48 using System.Threading;
49 using log4net;
50 using OpenMetaverse;
51 using OpenSim.Framework;
52 using OpenSim.Region.PhysicsModules.SharedBase;
53 
54 namespace OpenSim.Region.PhysicsModule.ODE
55 {
59  public class OdePrim : PhysicsActor
60  {
61  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 
63  private bool m_isphysical;
64 
65  public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } }
66  private int m_expectedCollisionContacts = 0;
67 
71  private int BadMeshAssetCollideBits
72  {
73  get { return m_isphysical ? (int)CollisionCategories.Land : 0; }
74  }
75 
79  public override bool IsPhysical
80  {
81  get { return m_isphysical; }
82  set
83  {
84  m_isphysical = value;
85  if (!m_isphysical)
86  {
87  _zeroFlag = true; // Zero the remembered last velocity
88  m_lastVelocity = Vector3.Zero;
89  _acceleration = Vector3.Zero;
90  _velocity = Vector3.Zero;
91  m_taintVelocity = Vector3.Zero;
92  m_rotationalVelocity = Vector3.Zero;
93  }
94  }
95  }
96 
97  private Vector3 _position;
98  private Vector3 _velocity;
99  private Vector3 _torque;
100  private Vector3 m_lastVelocity;
101  private Vector3 m_lastposition;
102  private Quaternion m_lastorientation = new Quaternion();
103  private Vector3 m_rotationalVelocity;
104  private Vector3 _size;
105  private Vector3 _acceleration;
106  // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f);
107  private Quaternion _orientation;
108  private Vector3 m_taintposition;
109  private Vector3 m_taintsize;
110  private Vector3 m_taintVelocity;
111  private Vector3 m_taintTorque;
112  private Quaternion m_taintrot;
113 
114  private IntPtr Amotor = IntPtr.Zero;
115 
116  private byte m_taintAngularLock = 0;
117  private byte m_angularlock = 0;
118 
119  private bool m_assetFailed = false;
120 
121  private Vector3 m_PIDTarget;
122  private float m_PIDTau;
123  private float PID_D = 35f;
124  private float PID_G = 25f;
125 
126  // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
127  // and are for non-VEHICLES only.
128 
129  private float m_PIDHoverHeight;
130  private float m_PIDHoverTau;
131  private bool m_useHoverPID;
132  private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
133  private float m_targetHoverHeight;
134  private float m_groundHeight;
135  private float m_waterHeight;
136  private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
137 
138  // private float m_tensor = 5f;
139  private int body_autodisable_frames = 20;
140 
141 
142  private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
143  | CollisionCategories.Space
144  | CollisionCategories.Body
145  | CollisionCategories.Character
146  );
147  private bool m_taintshape;
148  private bool m_taintPhysics;
149  private bool m_collidesLand = true;
150  private bool m_collidesWater;
151 
152  // Default we're a Geometry
153  private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
154 
155  // Default, Collide with Other Geometries, spaces and Bodies
156  private CollisionCategories m_collisionFlags = m_default_collisionFlags;
157 
158  public bool m_taintremove { get; private set; }
159  public bool m_taintdisable { get; private set; }
160  internal bool m_disabled;
161  public bool m_taintadd { get; private set; }
162  public bool m_taintselected { get; private set; }
163  public bool m_taintCollidesWater { get; private set; }
164 
165  private bool m_taintforce = false;
166  private bool m_taintaddangularforce = false;
167  private Vector3 m_force;
168  private List<Vector3> m_forcelist = new List<Vector3>();
169  private List<Vector3> m_angularforcelist = new List<Vector3>();
170 
171  private PrimitiveBaseShape _pbs;
172  private OdeScene _parent_scene;
173 
177  public IntPtr m_targetSpace = IntPtr.Zero;
178 
186  public IntPtr prim_geom { get; private set; }
187 
188  public IntPtr _triMeshData { get; private set; }
189 
190  private IntPtr _linkJointGroup = IntPtr.Zero;
191  private PhysicsActor _parent;
192  private PhysicsActor m_taintparent;
193 
194  private List<OdePrim> childrenPrim = new List<OdePrim>();
195 
196  private bool iscolliding;
197  private bool m_isSelected;
198 
199  internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
200 
201  private bool m_throttleUpdates;
202  private int throttleCounter;
203  public int m_interpenetrationcount { get; private set; }
204  internal float m_collisionscore;
205  public int m_roundsUnderMotionThreshold { get; private set; }
206 
207  public bool outofBounds { get; private set; }
208  private float m_density = 10.000006836f; // Aluminum g/cm3;
209 
210  public bool _zeroFlag { get; private set; }
211  private bool m_lastUpdateSent;
212 
213  public IntPtr Body = IntPtr.Zero;
214  private Vector3 _target_velocity;
215  private d.Mass pMass;
216 
217  private int m_eventsubscription;
218  private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
219 
227  private bool m_collisionsOnPreviousFrame;
228 
229  private IntPtr m_linkJoint = IntPtr.Zero;
230 
231  internal volatile bool childPrim;
232 
233  private ODEDynamics m_vehicle;
234 
235  internal int m_material = (int)Material.Wood;
236 
237  public OdePrim(
238  String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
239  Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
240  {
241  Name = primName;
242  m_vehicle = new ODEDynamics();
243  //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
244 
245  if (!pos.IsFinite())
246  {
247  pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
248  parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
249  m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
250  }
251  _position = pos;
252  m_taintposition = pos;
253  PID_D = parent_scene.bodyPIDD;
254  PID_G = parent_scene.bodyPIDG;
255  m_density = parent_scene.geomDefaultDensity;
256  // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
257  body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
258 
259  prim_geom = IntPtr.Zero;
260 
261  if (!pos.IsFinite())
262  {
263  size = new Vector3(0.5f, 0.5f, 0.5f);
264  m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
265  }
266 
267  if (size.X <= 0) size.X = 0.01f;
268  if (size.Y <= 0) size.Y = 0.01f;
269  if (size.Z <= 0) size.Z = 0.01f;
270 
271  _size = size;
272  m_taintsize = _size;
273 
274  if (!QuaternionIsFinite(rotation))
275  {
276  rotation = Quaternion.Identity;
277  m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
278  }
279 
280  _orientation = rotation;
281  m_taintrot = _orientation;
282  _pbs = pbs;
283 
284  _parent_scene = parent_scene;
285  m_targetSpace = (IntPtr)0;
286 
287  if (pos.Z < 0)
288  {
289  IsPhysical = false;
290  }
291  else
292  {
293  IsPhysical = pisPhysical;
294  // If we're physical, we need to be in the master space for now.
295  // linksets *should* be in a space together.. but are not currently
296  if (IsPhysical)
297  m_targetSpace = _parent_scene.space;
298  }
299 
300  m_taintadd = true;
301  m_assetFailed = false;
302  _parent_scene.AddPhysicsActorTaint(this);
303  }
304 
305  public override int PhysicsActorType
306  {
307  get { return (int) ActorTypes.Prim; }
308  set { return; }
309  }
310 
311  public override bool SetAlwaysRun
312  {
313  get { return false; }
314  set { return; }
315  }
316 
317  public override bool Grabbed
318  {
319  set { return; }
320  }
321 
322  public override bool Selected
323  {
324  set
325  {
326  // This only makes the object not collidable if the object
327  // is physical or the object is modified somehow *IN THE FUTURE*
328  // without this, if an avatar selects prim, they can walk right
329  // through it while it's selected
330  m_collisionscore = 0;
331 
332  if ((IsPhysical && !_zeroFlag) || !value)
333  {
334  m_taintselected = value;
335  _parent_scene.AddPhysicsActorTaint(this);
336  }
337  else
338  {
339  m_taintselected = value;
340  m_isSelected = value;
341  }
342 
343  if (m_isSelected)
344  disableBodySoft();
345  }
346  }
347 
352  private void SetGeom(IntPtr geom)
353  {
354  prim_geom = geom;
355 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
356 
357  if (m_assetFailed)
358  {
359  d.GeomSetCategoryBits(prim_geom, 0);
360  d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
361  }
362  else
363  {
364  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
365  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
366  }
367 
368  _parent_scene.geom_name_map[prim_geom] = Name;
369  _parent_scene.actor_name_map[prim_geom] = this;
370 
371  if (childPrim)
372  {
373  if (_parent != null && _parent is OdePrim)
374  {
375  OdePrim parent = (OdePrim)_parent;
376 //Console.WriteLine("SetGeom calls ChildSetGeom");
377  parent.ChildSetGeom(this);
378  }
379  }
380  //m_log.Warn("Setting Geom to: " + prim_geom);
381  }
382 
383  private void enableBodySoft()
384  {
385  if (!childPrim)
386  {
387  if (IsPhysical && Body != IntPtr.Zero)
388  {
389  d.BodyEnable(Body);
390  if (m_vehicle.Type != Vehicle.TYPE_NONE)
391  m_vehicle.Enable(Body, _parent_scene);
392  }
393 
394  m_disabled = false;
395  }
396  }
397 
398  private void disableBodySoft()
399  {
400  m_disabled = true;
401 
402  if (IsPhysical && Body != IntPtr.Zero)
403  {
404  d.BodyDisable(Body);
405  }
406  }
407 
411  private void enableBody()
412  {
413  // Don't enable this body if we're a child prim
414  // this should be taken care of in the parent function not here
415  if (!childPrim)
416  {
417  // Sets the geom to a body
418  Body = d.BodyCreate(_parent_scene.world);
419 
420  setMass();
421  d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
422  d.Quaternion myrot = new d.Quaternion();
423  myrot.X = _orientation.X;
424  myrot.Y = _orientation.Y;
425  myrot.Z = _orientation.Z;
426  myrot.W = _orientation.W;
427  d.BodySetQuaternion(Body, ref myrot);
428  d.GeomSetBody(prim_geom, Body);
429 
430  if (m_assetFailed)
431  {
432  d.GeomSetCategoryBits(prim_geom, 0);
433  d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
434  }
435  else
436  {
437  m_collisionCategories |= CollisionCategories.Body;
438  m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
439  }
440 
441  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
442  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
443 
444  d.BodySetAutoDisableFlag(Body, true);
445  d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
446 
447  // disconnect from world gravity so we can apply buoyancy
448  d.BodySetGravityMode (Body, false);
449 
450  m_interpenetrationcount = 0;
451  m_collisionscore = 0;
452  m_disabled = false;
453 
454  // The body doesn't already have a finite rotation mode set here
455  if (m_angularlock != 0 && _parent == null)
456  {
457  createAMotor(m_angularlock);
458  }
459  if (m_vehicle.Type != Vehicle.TYPE_NONE)
460  {
461  m_vehicle.Enable(Body, _parent_scene);
462  }
463 
464  _parent_scene.ActivatePrim(this);
465  }
466  }
467 
468  #region Mass Calculation
469 
470  private float CalculateMass()
471  {
472  float volume = _size.X * _size.Y * _size.Z; // default
473  float tmp;
474 
475  float returnMass = 0;
476  float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
477  float hollowVolume = hollowAmount * hollowAmount;
478 
479  switch (_pbs.ProfileShape)
480  {
481  case ProfileShape.Square:
482  // default box
483 
484  if (_pbs.PathCurve == (byte)Extrusion.Straight)
485  {
486  if (hollowAmount > 0.0)
487  {
488  switch (_pbs.HollowShape)
489  {
490  case HollowShape.Square:
491  case HollowShape.Same:
492  break;
493 
494  case HollowShape.Circle:
495 
496  hollowVolume *= 0.78539816339f;
497  break;
498 
499  case HollowShape.Triangle:
500 
501  hollowVolume *= (0.5f * .5f);
502  break;
503 
504  default:
505  hollowVolume = 0;
506  break;
507  }
508  volume *= (1.0f - hollowVolume);
509  }
510  }
511 
512  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
513  {
514  //a tube
515 
516  volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
517  tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
518  volume -= volume*tmp*tmp;
519 
520  if (hollowAmount > 0.0)
521  {
522  hollowVolume *= hollowAmount;
523 
524  switch (_pbs.HollowShape)
525  {
526  case HollowShape.Square:
527  case HollowShape.Same:
528  break;
529 
530  case HollowShape.Circle:
531  hollowVolume *= 0.78539816339f;;
532  break;
533 
534  case HollowShape.Triangle:
535  hollowVolume *= 0.5f * 0.5f;
536  break;
537  default:
538  hollowVolume = 0;
539  break;
540  }
541  volume *= (1.0f - hollowVolume);
542  }
543  }
544 
545  break;
546 
547  case ProfileShape.Circle:
548 
549  if (_pbs.PathCurve == (byte)Extrusion.Straight)
550  {
551  volume *= 0.78539816339f; // elipse base
552 
553  if (hollowAmount > 0.0)
554  {
555  switch (_pbs.HollowShape)
556  {
557  case HollowShape.Same:
558  case HollowShape.Circle:
559  break;
560 
561  case HollowShape.Square:
562  hollowVolume *= 0.5f * 2.5984480504799f;
563  break;
564 
565  case HollowShape.Triangle:
566  hollowVolume *= .5f * 1.27323954473516f;
567  break;
568 
569  default:
570  hollowVolume = 0;
571  break;
572  }
573  volume *= (1.0f - hollowVolume);
574  }
575  }
576 
577  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
578  {
579  volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
580  tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
581  volume *= (1.0f - tmp * tmp);
582 
583  if (hollowAmount > 0.0)
584  {
585 
586  // calculate the hollow volume by it's shape compared to the prim shape
587  hollowVolume *= hollowAmount;
588 
589  switch (_pbs.HollowShape)
590  {
591  case HollowShape.Same:
592  case HollowShape.Circle:
593  break;
594 
595  case HollowShape.Square:
596  hollowVolume *= 0.5f * 2.5984480504799f;
597  break;
598 
599  case HollowShape.Triangle:
600  hollowVolume *= .5f * 1.27323954473516f;
601  break;
602 
603  default:
604  hollowVolume = 0;
605  break;
606  }
607  volume *= (1.0f - hollowVolume);
608  }
609  }
610  break;
611 
612  case ProfileShape.HalfCircle:
613  if (_pbs.PathCurve == (byte)Extrusion.Curve1)
614  {
615  volume *= 0.52359877559829887307710723054658f;
616  }
617  break;
618 
619  case ProfileShape.EquilateralTriangle:
620 
621  if (_pbs.PathCurve == (byte)Extrusion.Straight)
622  {
623  volume *= 0.32475953f;
624 
625  if (hollowAmount > 0.0)
626  {
627 
628  // calculate the hollow volume by it's shape compared to the prim shape
629  switch (_pbs.HollowShape)
630  {
631  case HollowShape.Same:
632  case HollowShape.Triangle:
633  hollowVolume *= .25f;
634  break;
635 
636  case HollowShape.Square:
637  hollowVolume *= 0.499849f * 3.07920140172638f;
638  break;
639 
640  case HollowShape.Circle:
641  // Hollow shape is a perfect cyllinder in respect to the cube's scale
642  // Cyllinder hollow volume calculation
643 
644  hollowVolume *= 0.1963495f * 3.07920140172638f;
645  break;
646 
647  default:
648  hollowVolume = 0;
649  break;
650  }
651  volume *= (1.0f - hollowVolume);
652  }
653  }
654  else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
655  {
656  volume *= 0.32475953f;
657  volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
658  tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
659  volume *= (1.0f - tmp * tmp);
660 
661  if (hollowAmount > 0.0)
662  {
663 
664  hollowVolume *= hollowAmount;
665 
666  switch (_pbs.HollowShape)
667  {
668  case HollowShape.Same:
669  case HollowShape.Triangle:
670  hollowVolume *= .25f;
671  break;
672 
673  case HollowShape.Square:
674  hollowVolume *= 0.499849f * 3.07920140172638f;
675  break;
676 
677  case HollowShape.Circle:
678 
679  hollowVolume *= 0.1963495f * 3.07920140172638f;
680  break;
681 
682  default:
683  hollowVolume = 0;
684  break;
685  }
686  volume *= (1.0f - hollowVolume);
687  }
688  }
689  break;
690 
691  default:
692  break;
693  }
694 
695  float taperX1;
696  float taperY1;
697  float taperX;
698  float taperY;
699  float pathBegin;
700  float pathEnd;
701  float profileBegin;
702  float profileEnd;
703 
704  if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
705  {
706  taperX1 = _pbs.PathScaleX * 0.01f;
707  if (taperX1 > 1.0f)
708  taperX1 = 2.0f - taperX1;
709  taperX = 1.0f - taperX1;
710 
711  taperY1 = _pbs.PathScaleY * 0.01f;
712  if (taperY1 > 1.0f)
713  taperY1 = 2.0f - taperY1;
714  taperY = 1.0f - taperY1;
715  }
716  else
717  {
718  taperX = _pbs.PathTaperX * 0.01f;
719  if (taperX < 0.0f)
720  taperX = -taperX;
721  taperX1 = 1.0f - taperX;
722 
723  taperY = _pbs.PathTaperY * 0.01f;
724  if (taperY < 0.0f)
725  taperY = -taperY;
726  taperY1 = 1.0f - taperY;
727  }
728 
729  volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
730 
731  pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
732  pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
733  volume *= (pathEnd - pathBegin);
734 
735 // this is crude aproximation
736  profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
737  profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
738  volume *= (profileEnd - profileBegin);
739 
740  returnMass = m_density * volume;
741 
742  if (returnMass <= 0)
743  returnMass = 0.0001f;//ckrinke: Mass must be greater then zero.
744 // else if (returnMass > _parent_scene.maximumMassObject)
745 // returnMass = _parent_scene.maximumMassObject;
746 
747  // Recursively calculate mass
748  bool HasChildPrim = false;
749  lock (childrenPrim)
750  {
751  if (childrenPrim.Count > 0)
752  {
753  HasChildPrim = true;
754  }
755  }
756 
757  if (HasChildPrim)
758  {
759  OdePrim[] childPrimArr = new OdePrim[0];
760 
761  lock (childrenPrim)
762  childPrimArr = childrenPrim.ToArray();
763 
764  for (int i = 0; i < childPrimArr.Length; i++)
765  {
766  if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove)
767  returnMass += childPrimArr[i].CalculateMass();
768  // failsafe, this shouldn't happen but with OpenSim, you never know :)
769  if (i > 256)
770  break;
771  }
772  }
773 
774  if (returnMass > _parent_scene.maximumMassObject)
775  returnMass = _parent_scene.maximumMassObject;
776 
777  return returnMass;
778  }
779 
780  #endregion
781 
782  private void setMass()
783  {
784  if (Body != (IntPtr) 0)
785  {
786  float newmass = CalculateMass();
787 
788  //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString());
789 
790  d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z);
791  d.BodySetMass(Body, ref pMass);
792  }
793  }
794 
795  private void setAngularVelocity(float x, float y, float z)
796  {
797  if (Body != (IntPtr)0)
798  {
799  d.BodySetAngularVel(Body, x, y, z);
800  }
801  }
802 
806  internal void disableBody()
807  {
808  //this kills the body so things like 'mesh' can re-create it.
809  lock (this)
810  {
811  if (!childPrim)
812  {
813  if (Body != IntPtr.Zero)
814  {
815  _parent_scene.DeactivatePrim(this);
816  m_collisionCategories &= ~CollisionCategories.Body;
817  m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
818 
819  if (m_assetFailed)
820  {
821  d.GeomSetCategoryBits(prim_geom, 0);
822  d.GeomSetCollideBits(prim_geom, 0);
823  }
824  else
825  {
826  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
827  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
828  }
829 
830  d.BodyDestroy(Body);
831  lock (childrenPrim)
832  {
833  if (childrenPrim.Count > 0)
834  {
835  foreach (OdePrim prm in childrenPrim)
836  {
837  _parent_scene.DeactivatePrim(prm);
838  prm.Body = IntPtr.Zero;
839  }
840  }
841  }
842  Body = IntPtr.Zero;
843  }
844  }
845  else
846  {
847  _parent_scene.DeactivatePrim(this);
848 
849  m_collisionCategories &= ~CollisionCategories.Body;
850  m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
851 
852  if (m_assetFailed)
853  {
854  d.GeomSetCategoryBits(prim_geom, 0);
855  d.GeomSetCollideBits(prim_geom, 0);
856  }
857  else
858  {
859 
860  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
861  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
862  }
863 
864  Body = IntPtr.Zero;
865  }
866  }
867 
868  m_disabled = true;
869  m_collisionscore = 0;
870  }
871 
872  private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>();
873 
874  private void setMesh(OdeScene parent_scene, IMesh mesh)
875  {
876 // m_log.DebugFormat("[ODE PRIM]: Setting mesh on {0} to {1}", Name, mesh);
877 
878  // This sleeper is there to moderate how long it takes between
879  // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object
880 
881  //Thread.Sleep(10);
882 
883  //Kill Body so that mesh can re-make the geom
884  if (IsPhysical && Body != IntPtr.Zero)
885  {
886  if (childPrim)
887  {
888  if (_parent != null)
889  {
890  OdePrim parent = (OdePrim)_parent;
891  parent.ChildDelink(this);
892  }
893  }
894  else
895  {
896  disableBody();
897  }
898  }
899 
900  IntPtr vertices, indices;
901  int vertexCount, indexCount;
902  int vertexStride, triStride;
903  mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
904  mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
905  m_expectedCollisionContacts = indexCount;
906  mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
907 
908  // We must lock here since m_MeshToTriMeshMap is static and multiple scene threads may call this method at
909  // the same time.
910  lock (m_MeshToTriMeshMap)
911  {
912  if (m_MeshToTriMeshMap.ContainsKey(mesh))
913  {
914  _triMeshData = m_MeshToTriMeshMap[mesh];
915  }
916  else
917  {
918  _triMeshData = d.GeomTriMeshDataCreate();
919 
920  d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
921  d.GeomTriMeshDataPreprocess(_triMeshData);
922  m_MeshToTriMeshMap[mesh] = _triMeshData;
923  }
924  }
925 
926 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
927  try
928  {
929  SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
930  }
931  catch (AccessViolationException)
932  {
933  m_log.ErrorFormat("[PHYSICS]: MESH LOCKED FOR {0}", Name);
934  return;
935  }
936 
937  // if (IsPhysical && Body == (IntPtr) 0)
938  // {
939  // Recreate the body
940  // m_interpenetrationcount = 0;
941  // m_collisionscore = 0;
942 
943  // enableBody();
944  // }
945  }
946 
947  internal void ProcessTaints()
948  {
949 #if SPAM
950 Console.WriteLine("ZProcessTaints for " + Name);
951 #endif
952 
953  // This must be processed as the very first taint so that later operations have a prim_geom to work with
954  // if this is a new prim.
955  if (m_taintadd)
956  changeadd();
957 
958  if (!_position.ApproxEquals(m_taintposition, 0f))
959  changemove();
960 
961  if (m_taintrot != _orientation)
962  {
963  if (childPrim && IsPhysical) // For physical child prim...
964  {
965  rotate();
966  // KF: ODE will also rotate the parent prim!
967  // so rotate the root back to where it was
968  OdePrim parent = (OdePrim)_parent;
969  parent.rotate();
970  }
971  else
972  {
973  //Just rotate the prim
974  rotate();
975  }
976  }
977 
978  if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
979  changePhysicsStatus();
980 
981  if (!_size.ApproxEquals(m_taintsize, 0f))
982  changesize();
983 
984  if (m_taintshape)
985  changeshape();
986 
987  if (m_taintforce)
988  changeAddForce();
989 
990  if (m_taintaddangularforce)
991  changeAddAngularForce();
992 
993  if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f))
994  changeSetTorque();
995 
996  if (m_taintdisable)
997  changedisable();
998 
999  if (m_taintselected != m_isSelected)
1000  changeSelectedStatus();
1001 
1002  if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f))
1003  changevelocity();
1004 
1005  if (m_taintparent != _parent)
1006  changelink();
1007 
1008  if (m_taintCollidesWater != m_collidesWater)
1009  changefloatonwater();
1010 
1011  if (m_taintAngularLock != m_angularlock)
1012  changeAngularLock();
1013  }
1014 
1018  private void changeAngularLock()
1019  {
1020  // do we have a Physical object?
1021  if (Body != IntPtr.Zero)
1022  {
1023  //Check that we have a Parent
1024  //If we have a parent then we're not authorative here
1025  if (_parent == null)
1026  {
1027  if (m_taintAngularLock != 0)
1028  {
1029  createAMotor(m_taintAngularLock);
1030  }
1031  else
1032  {
1033  if (Amotor != IntPtr.Zero)
1034  {
1035  d.JointDestroy(Amotor);
1036  Amotor = IntPtr.Zero;
1037  }
1038  }
1039  }
1040  }
1041 
1042  m_angularlock = m_taintAngularLock;
1043  }
1044 
1048  private void changelink()
1049  {
1050  // If the newly set parent is not null
1051  // create link
1052  if (_parent == null && m_taintparent != null)
1053  {
1054  if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim)
1055  {
1056  OdePrim obj = (OdePrim)m_taintparent;
1057  //obj.disableBody();
1058 //Console.WriteLine("changelink calls ParentPrim");
1059  obj.AddChildPrim(this);
1060 
1061  /*
1062  if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
1063  {
1064  _linkJointGroup = d.JointGroupCreate(0);
1065  m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1066  d.JointAttach(m_linkJoint, obj.Body, Body);
1067  d.JointSetFixed(m_linkJoint);
1068  }
1069  */
1070  }
1071  }
1072  // If the newly set parent is null
1073  // destroy link
1074  else if (_parent != null && m_taintparent == null)
1075  {
1076 //Console.WriteLine(" changelink B");
1077 
1078  if (_parent is OdePrim)
1079  {
1080  OdePrim obj = (OdePrim)_parent;
1081  obj.ChildDelink(this);
1082  childPrim = false;
1083  //_parent = null;
1084  }
1085 
1086  /*
1087  if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0)
1088  d.JointGroupDestroy(_linkJointGroup);
1089 
1090  _linkJointGroup = (IntPtr)0;
1091  m_linkJoint = (IntPtr)0;
1092  */
1093  }
1094 
1095  _parent = m_taintparent;
1096  m_taintPhysics = IsPhysical;
1097  }
1098 
1103  private void AddChildPrim(OdePrim prim)
1104  {
1105  if (LocalID == prim.LocalID)
1106  return;
1107 
1108  if (Body == IntPtr.Zero)
1109  {
1110  Body = d.BodyCreate(_parent_scene.world);
1111  setMass();
1112  }
1113 
1114  lock (childrenPrim)
1115  {
1116  if (childrenPrim.Contains(prim))
1117  return;
1118 
1119 // m_log.DebugFormat(
1120 // "[ODE PRIM]: Linking prim {0} {1} to {2} {3}", prim.Name, prim.LocalID, Name, LocalID);
1121 
1122  childrenPrim.Add(prim);
1123 
1124  foreach (OdePrim prm in childrenPrim)
1125  {
1126  d.Mass m2;
1127  d.MassSetZero(out m2);
1128  d.MassSetBoxTotal(out m2, prm.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1129 
1130  d.Quaternion quat = new d.Quaternion();
1131  quat.W = prm._orientation.W;
1132  quat.X = prm._orientation.X;
1133  quat.Y = prm._orientation.Y;
1134  quat.Z = prm._orientation.Z;
1135 
1136  d.Matrix3 mat = new d.Matrix3();
1137  d.RfromQ(out mat, ref quat);
1138  d.MassRotate(ref m2, ref mat);
1139  d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z);
1140  d.MassAdd(ref pMass, ref m2);
1141  }
1142 
1143  foreach (OdePrim prm in childrenPrim)
1144  {
1145  prm.m_collisionCategories |= CollisionCategories.Body;
1146  prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1147 
1148 //Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + Name);
1149  if (prm.m_assetFailed)
1150  {
1151  d.GeomSetCategoryBits(prm.prim_geom, 0);
1152  d.GeomSetCollideBits(prm.prim_geom, (uint)prm.BadMeshAssetCollideBits);
1153  }
1154  else
1155  {
1156  d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1157  d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1158  }
1159 
1160  d.Quaternion quat = new d.Quaternion();
1161  quat.W = prm._orientation.W;
1162  quat.X = prm._orientation.X;
1163  quat.Y = prm._orientation.Y;
1164  quat.Z = prm._orientation.Z;
1165 
1166  d.Matrix3 mat = new d.Matrix3();
1167  d.RfromQ(out mat, ref quat);
1168  if (Body != IntPtr.Zero)
1169  {
1170  d.GeomSetBody(prm.prim_geom, Body);
1171  prm.childPrim = true;
1172  d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z);
1173  //d.GeomSetOffsetPosition(prim.prim_geom,
1174  // (Position.X - prm.Position.X) - pMass.c.X,
1175  // (Position.Y - prm.Position.Y) - pMass.c.Y,
1176  // (Position.Z - prm.Position.Z) - pMass.c.Z);
1177  d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat);
1178  //d.GeomSetOffsetRotation(prm.prim_geom, ref mat);
1179  d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1180  d.BodySetMass(Body, ref pMass);
1181  }
1182  else
1183  {
1184  m_log.DebugFormat("[PHYSICS]: {0} ain't got no boooooooooddy, no body", Name);
1185  }
1186 
1187  prm.m_interpenetrationcount = 0;
1188  prm.m_collisionscore = 0;
1189  prm.m_disabled = false;
1190 
1191  prm.Body = Body;
1192  _parent_scene.ActivatePrim(prm);
1193  }
1194 
1195  m_collisionCategories |= CollisionCategories.Body;
1196  m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1197 
1198  if (m_assetFailed)
1199  {
1200  d.GeomSetCategoryBits(prim_geom, 0);
1201  d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
1202  }
1203  else
1204  {
1205  //Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + Name);
1206  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1207  //Console.WriteLine(" Post GeomSetCategoryBits 2");
1208  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1209  }
1210 
1211  d.Quaternion quat2 = new d.Quaternion();
1212  quat2.W = _orientation.W;
1213  quat2.X = _orientation.X;
1214  quat2.Y = _orientation.Y;
1215  quat2.Z = _orientation.Z;
1216 
1217  d.Matrix3 mat2 = new d.Matrix3();
1218  d.RfromQ(out mat2, ref quat2);
1219  d.GeomSetBody(prim_geom, Body);
1220  d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z);
1221  //d.GeomSetOffsetPosition(prim.prim_geom,
1222  // (Position.X - prm.Position.X) - pMass.c.X,
1223  // (Position.Y - prm.Position.Y) - pMass.c.Y,
1224  // (Position.Z - prm.Position.Z) - pMass.c.Z);
1225  //d.GeomSetOffsetRotation(prim_geom, ref mat2);
1226  d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z);
1227  d.BodySetMass(Body, ref pMass);
1228 
1229  d.BodySetAutoDisableFlag(Body, true);
1230  d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1231 
1232  m_interpenetrationcount = 0;
1233  m_collisionscore = 0;
1234  m_disabled = false;
1235 
1236  // The body doesn't already have a finite rotation mode set here
1237  // or remove
1238  if (_parent == null)
1239  {
1240  createAMotor(m_angularlock);
1241  }
1242 
1243  d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1244 
1245  if (m_vehicle.Type != Vehicle.TYPE_NONE)
1246  m_vehicle.Enable(Body, _parent_scene);
1247 
1248  _parent_scene.ActivatePrim(this);
1249  }
1250  }
1251 
1252  private void ChildSetGeom(OdePrim odePrim)
1253  {
1254 // m_log.DebugFormat(
1255 // "[ODE PRIM]: ChildSetGeom {0} {1} for {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1256 
1257  //if (IsPhysical && Body != IntPtr.Zero)
1258  lock (childrenPrim)
1259  {
1260  foreach (OdePrim prm in childrenPrim)
1261  {
1262  //prm.childPrim = true;
1263  prm.disableBody();
1264  //prm.m_taintparent = null;
1265  //prm._parent = null;
1266  //prm.m_taintPhysics = false;
1267  //prm.m_disabled = true;
1268  //prm.childPrim = false;
1269  }
1270  }
1271 
1272  disableBody();
1273 
1274  // Spurious - Body == IntPtr.Zero after disableBody()
1275 // if (Body != IntPtr.Zero)
1276 // {
1277 // _parent_scene.DeactivatePrim(this);
1278 // }
1279 
1280  lock (childrenPrim)
1281  {
1282  foreach (OdePrim prm in childrenPrim)
1283  {
1284 //Console.WriteLine("ChildSetGeom calls ParentPrim");
1285  AddChildPrim(prm);
1286  }
1287  }
1288  }
1289 
1290  private void ChildDelink(OdePrim odePrim)
1291  {
1292 // m_log.DebugFormat(
1293 // "[ODE PRIM]: Delinking prim {0} {1} from {2} {3}", odePrim.Name, odePrim.LocalID, Name, LocalID);
1294 
1295  // Okay, we have a delinked child.. need to rebuild the body.
1296  lock (childrenPrim)
1297  {
1298  foreach (OdePrim prm in childrenPrim)
1299  {
1300  prm.childPrim = true;
1301  prm.disableBody();
1302  //prm.m_taintparent = null;
1303  //prm._parent = null;
1304  //prm.m_taintPhysics = false;
1305  //prm.m_disabled = true;
1306  //prm.childPrim = false;
1307  }
1308  }
1309 
1310  disableBody();
1311 
1312  lock (childrenPrim)
1313  {
1314  //Console.WriteLine("childrenPrim.Remove " + odePrim);
1315  childrenPrim.Remove(odePrim);
1316  }
1317 
1318  // Spurious - Body == IntPtr.Zero after disableBody()
1319 // if (Body != IntPtr.Zero)
1320 // {
1321 // _parent_scene.DeactivatePrim(this);
1322 // }
1323 
1324  lock (childrenPrim)
1325  {
1326  foreach (OdePrim prm in childrenPrim)
1327  {
1328 //Console.WriteLine("ChildDelink calls ParentPrim");
1329  AddChildPrim(prm);
1330  }
1331  }
1332  }
1333 
1337  private void changeSelectedStatus()
1338  {
1339  if (m_taintselected)
1340  {
1341  m_collisionCategories = CollisionCategories.Selected;
1342  m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
1343 
1344  // We do the body disable soft twice because 'in theory' a collision could have happened
1345  // in between the disabling and the collision properties setting
1346  // which would wake the physical body up from a soft disabling and potentially cause it to fall
1347  // through the ground.
1348 
1349  // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select
1350  // just one part of the assembly, the rest of the assembly is non-selected and still simulating,
1351  // so that causes the selected part to wake up and continue moving.
1352 
1353  // even if you select all parts of a jointed assembly, it is not guaranteed that the entire
1354  // assembly will stop simulating during the selection, because of the lack of atomicity
1355  // of select operations (their processing could be interrupted by a thread switch, causing
1356  // simulation to continue before all of the selected object notifications trickle down to
1357  // the physics engine).
1358 
1359  // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are
1360  // selected and disabled. then, due to a thread switch, the selection processing is
1361  // interrupted and the physics engine continues to simulate, so the last 50 items, whose
1362  // selection was not yet processed, continues to simulate. this wakes up ALL of the
1363  // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1364  // up, start simulating again, which in turn wakes up the last 50.
1365 
1366  if (IsPhysical)
1367  {
1368  disableBodySoft();
1369  }
1370 
1371  if (m_assetFailed)
1372  {
1373  d.GeomSetCategoryBits(prim_geom, 0);
1374  d.GeomSetCollideBits(prim_geom, 0);
1375  }
1376  else
1377  {
1378  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1379  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1380  }
1381 
1382  if (IsPhysical)
1383  {
1384  disableBodySoft();
1385  }
1386  }
1387  else
1388  {
1389  m_collisionCategories = CollisionCategories.Geom;
1390 
1391  if (IsPhysical)
1392  m_collisionCategories |= CollisionCategories.Body;
1393 
1394  m_collisionFlags = m_default_collisionFlags;
1395 
1396  if (m_collidesLand)
1397  m_collisionFlags |= CollisionCategories.Land;
1398  if (m_collidesWater)
1399  m_collisionFlags |= CollisionCategories.Water;
1400 
1401  if (m_assetFailed)
1402  {
1403  d.GeomSetCategoryBits(prim_geom, 0);
1404  d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
1405  }
1406  else
1407  {
1408  d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1409  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1410  }
1411 
1412  if (IsPhysical)
1413  {
1414  if (Body != IntPtr.Zero)
1415  {
1416  d.BodySetLinearVel(Body, 0f, 0f, 0f);
1417  d.BodySetForce(Body, 0, 0, 0);
1418  enableBodySoft();
1419  }
1420  }
1421  }
1422 
1423  resetCollisionAccounting();
1424  m_isSelected = m_taintselected;
1425  }//end changeSelectedStatus
1426 
1427  internal void ResetTaints()
1428  {
1429  m_taintposition = _position;
1430  m_taintrot = _orientation;
1431  m_taintPhysics = IsPhysical;
1432  m_taintselected = m_isSelected;
1433  m_taintsize = _size;
1434  m_taintshape = false;
1435  m_taintforce = false;
1436  m_taintdisable = false;
1437  m_taintVelocity = Vector3.Zero;
1438  }
1439 
1445  private void CreateGeom(IntPtr m_targetSpace, IMesh mesh)
1446  {
1447 #if SPAM
1448 Console.WriteLine("CreateGeom:");
1449 #endif
1450  if (mesh != null)
1451  {
1452  setMesh(_parent_scene, mesh);
1453  }
1454  else
1455  {
1456  if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1457  {
1458  if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1459  {
1460  if (((_size.X / 2f) > 0f))
1461  {
1462 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1463  try
1464  {
1465 //Console.WriteLine(" CreateGeom 1");
1466  SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
1467  m_expectedCollisionContacts = 3;
1468  }
1469  catch (AccessViolationException)
1470  {
1471  m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1472  return;
1473  }
1474  }
1475  else
1476  {
1477 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1478  try
1479  {
1480 //Console.WriteLine(" CreateGeom 2");
1481  SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1482  m_expectedCollisionContacts = 4;
1483  }
1484  catch (AccessViolationException)
1485  {
1486  m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1487  return;
1488  }
1489  }
1490  }
1491  else
1492  {
1493 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1494  try
1495  {
1496 //Console.WriteLine(" CreateGeom 3");
1497  SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1498  m_expectedCollisionContacts = 4;
1499  }
1500  catch (AccessViolationException)
1501  {
1502  m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1503  return;
1504  }
1505  }
1506  }
1507  else
1508  {
1509 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1510  try
1511  {
1512 //Console.WriteLine(" CreateGeom 4");
1513  SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1514  m_expectedCollisionContacts = 4;
1515  }
1516  catch (AccessViolationException)
1517  {
1518  m_log.WarnFormat("[PHYSICS]: Unable to create physics proxy for object {0}", Name);
1519  return;
1520  }
1521  }
1522  }
1523  }
1524 
1531  internal bool RemoveGeom()
1532  {
1533  if (prim_geom != IntPtr.Zero)
1534  {
1535  try
1536  {
1537  _parent_scene.geom_name_map.Remove(prim_geom);
1538  _parent_scene.actor_name_map.Remove(prim_geom);
1539  d.GeomDestroy(prim_geom);
1540  m_expectedCollisionContacts = 0;
1541  prim_geom = IntPtr.Zero;
1542  }
1543  catch (System.AccessViolationException)
1544  {
1545  prim_geom = IntPtr.Zero;
1546  m_expectedCollisionContacts = 0;
1547  m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1548 
1549  return false;
1550  }
1551 
1552  return true;
1553  }
1554  else
1555  {
1556  m_log.WarnFormat(
1557  "[ODE PRIM]: Called RemoveGeom() on {0} {1} where geometry was already null.", Name, LocalID);
1558 
1559  return false;
1560  }
1561  }
1565  private void changeadd()
1566  {
1567 // m_log.DebugFormat("[ODE PRIM]: Adding prim {0}", Name);
1568 
1569  int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1570  IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
1571 
1572  if (targetspace == IntPtr.Zero)
1573  targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
1574 
1575  m_targetSpace = targetspace;
1576 
1577  IMesh mesh = null;
1578 
1579  if (_parent_scene.needsMeshing(_pbs))
1580  {
1581  // Don't need to re-enable body.. it's done in SetMesh
1582  mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1583  // createmesh returns null when it's a shape that isn't a cube.
1584  // m_log.Debug(m_localID);
1585  if (mesh == null)
1586  CheckMeshAsset();
1587  else
1588  m_assetFailed = false;
1589  }
1590 
1591 #if SPAM
1592 Console.WriteLine("changeadd 1");
1593 #endif
1594  CreateGeom(m_targetSpace, mesh);
1595 
1596  d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1597  d.Quaternion myrot = new d.Quaternion();
1598  myrot.X = _orientation.X;
1599  myrot.Y = _orientation.Y;
1600  myrot.Z = _orientation.Z;
1601  myrot.W = _orientation.W;
1602  d.GeomSetQuaternion(prim_geom, ref myrot);
1603 
1604  if (IsPhysical && Body == IntPtr.Zero)
1605  enableBody();
1606 
1607  changeSelectedStatus();
1608 
1609  m_taintadd = false;
1610  }
1611 
1615  private void changemove()
1616  {
1617  if (IsPhysical)
1618  {
1619  if (!m_disabled && !m_taintremove && !childPrim)
1620  {
1621  if (Body == IntPtr.Zero)
1622  enableBody();
1623 
1624  //Prim auto disable after 20 frames,
1625  //if you move it, re-enable the prim manually.
1626  if (_parent != null)
1627  {
1628  if (m_linkJoint != IntPtr.Zero)
1629  {
1630  d.JointDestroy(m_linkJoint);
1631  m_linkJoint = IntPtr.Zero;
1632  }
1633  }
1634 
1635  if (Body != IntPtr.Zero)
1636  {
1637  d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1638 
1639  if (_parent != null)
1640  {
1641  OdePrim odParent = (OdePrim)_parent;
1642  if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body)
1643  {
1644 // KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used??
1645 Console.WriteLine(" JointCreateFixed");
1646  m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup);
1647  d.JointAttach(m_linkJoint, Body, odParent.Body);
1648  d.JointSetFixed(m_linkJoint);
1649  }
1650  }
1651  d.BodyEnable(Body);
1652  if (m_vehicle.Type != Vehicle.TYPE_NONE)
1653  {
1654  m_vehicle.Enable(Body, _parent_scene);
1655  }
1656  }
1657  else
1658  {
1659  m_log.WarnFormat("[PHYSICS]: Body for {0} still null after enableBody(). This is a crash scenario.", Name);
1660  }
1661  }
1662  //else
1663  // {
1664  //m_log.Debug("[BUG]: race!");
1665  //}
1666  }
1667 
1668  // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1669  // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1670 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1671 
1672  IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1673  m_targetSpace = tempspace;
1674 
1675 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1676 
1677  d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1678 
1679 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
1680  d.SpaceAdd(m_targetSpace, prim_geom);
1681 
1682  changeSelectedStatus();
1683 
1684  resetCollisionAccounting();
1685  m_taintposition = _position;
1686  }
1687 
1688  internal void Move(float timestep)
1689  {
1690  float fx = 0;
1691  float fy = 0;
1692  float fz = 0;
1693 
1694  if (outofBounds)
1695  return;
1696 
1697  if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1698  {
1699  if (m_vehicle.Type != Vehicle.TYPE_NONE)
1700  {
1701  // 'VEHICLES' are dealt with in ODEDynamics.cs
1702  m_vehicle.Step(timestep, _parent_scene);
1703  }
1704  else
1705  {
1706 //Console.WriteLine("Move " + Name);
1707  if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
1708 
1709  float m_mass = CalculateMass();
1710 
1711 // fz = 0f;
1712  //m_log.Info(m_collisionFlags.ToString());
1713 
1714 
1715  //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
1716  // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ??
1717  // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up
1718  // gravityz multiplier = 1 - m_buoyancy
1719  fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass;
1720 
1721  if (PIDActive)
1722  {
1723 //Console.WriteLine("PID " + Name);
1724  // KF - this is for object move? eg. llSetPos() ?
1725  //if (!d.BodyIsEnabled(Body))
1726  //d.BodySetForce(Body, 0f, 0f, 0f);
1727  // If we're using the PID controller, then we have no gravity
1728  //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply...
1729  fz = 0f;
1730 
1731  // no lock; for now it's only called from within Simulate()
1732 
1733  // If the PID Controller isn't active then we set our force
1734  // calculating base velocity to the current position
1735 
1736  if ((m_PIDTau < 1) && (m_PIDTau != 0))
1737  {
1738  //PID_G = PID_G / m_PIDTau;
1739  m_PIDTau = 1;
1740  }
1741 
1742  if ((PID_G - m_PIDTau) <= 0)
1743  {
1744  PID_G = m_PIDTau + 1;
1745  }
1746  //PidStatus = true;
1747 
1748  // PhysicsVector vec = new PhysicsVector();
1749  d.Vector3 vel = d.BodyGetLinearVel(Body);
1750 
1751  d.Vector3 pos = d.BodyGetPosition(Body);
1752  _target_velocity =
1753  new Vector3(
1754  (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
1755  (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
1756  (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
1757  );
1758 
1759  // if velocity is zero, use position control; otherwise, velocity control
1760 
1761  if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f))
1762  {
1763  // keep track of where we stopped. No more slippin' & slidin'
1764 
1765  // We only want to deactivate the PID Controller if we think we want to have our surrogate
1766  // react to the physics scene by moving it's position.
1767  // Avatar to Avatar collisions
1768  // Prim to avatar collisions
1769 
1770  //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
1771  //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
1772  //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
1773  d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
1774  d.BodySetLinearVel(Body, 0, 0, 0);
1775  d.BodyAddForce(Body, 0, 0, fz);
1776  return;
1777  }
1778  else
1779  {
1780  _zeroFlag = false;
1781 
1782  // We're flying and colliding with something
1783  fx = ((_target_velocity.X) - vel.X) * (PID_D);
1784  fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
1785 
1786  // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
1787 
1788  fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1789  }
1790  } // end if (PIDActive)
1791 
1792  // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
1793  if (m_useHoverPID && !PIDActive)
1794  {
1795 //Console.WriteLine("Hover " + Name);
1796 
1797  // If we're using the PID controller, then we have no gravity
1798  fz = (-1 * _parent_scene.gravityz) * m_mass;
1799 
1800  // no lock; for now it's only called from within Simulate()
1801 
1802  // If the PID Controller isn't active then we set our force
1803  // calculating base velocity to the current position
1804 
1805  if ((m_PIDTau < 1))
1806  {
1807  PID_G = PID_G / m_PIDTau;
1808  }
1809 
1810  if ((PID_G - m_PIDTau) <= 0)
1811  {
1812  PID_G = m_PIDTau + 1;
1813  }
1814 
1815  // Where are we, and where are we headed?
1816  d.Vector3 pos = d.BodyGetPosition(Body);
1817  d.Vector3 vel = d.BodyGetLinearVel(Body);
1818 
1819  // Non-Vehicles have a limited set of Hover options.
1820  // determine what our target height really is based on HoverType
1821  switch (m_PIDHoverType)
1822  {
1823  case PIDHoverType.Ground:
1824  m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1825  m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1826  break;
1827  case PIDHoverType.GroundAndWater:
1828  m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
1829  m_waterHeight = _parent_scene.GetWaterLevel();
1830  if (m_groundHeight > m_waterHeight)
1831  {
1832  m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
1833  }
1834  else
1835  {
1836  m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
1837  }
1838  break;
1839 
1840  } // end switch (m_PIDHoverType)
1841 
1842 
1843  _target_velocity =
1844  new Vector3(0.0f, 0.0f,
1845  (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
1846  );
1847 
1848  // if velocity is zero, use position control; otherwise, velocity control
1849 
1850  if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
1851  {
1852  // keep track of where we stopped. No more slippin' & slidin'
1853 
1854  // We only want to deactivate the PID Controller if we think we want to have our surrogate
1855  // react to the physics scene by moving it's position.
1856  // Avatar to Avatar collisions
1857  // Prim to avatar collisions
1858 
1859  d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
1860  d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
1861  d.BodyAddForce(Body, 0, 0, fz);
1862  return;
1863  }
1864  else
1865  {
1866  _zeroFlag = false;
1867 
1868  // We're flying and colliding with something
1869  fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
1870  }
1871  }
1872 
1873  fx *= m_mass;
1874  fy *= m_mass;
1875  //fz *= m_mass;
1876 
1877  fx += m_force.X;
1878  fy += m_force.Y;
1879  fz += m_force.Z;
1880 
1881  //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
1882  if (fx != 0 || fy != 0 || fz != 0)
1883  {
1884  //m_taintdisable = true;
1885  //base.RaiseOutOfBounds(Position);
1886  //d.BodySetLinearVel(Body, fx, fy, 0f);
1887  if (!d.BodyIsEnabled(Body))
1888  {
1889  // A physical body at rest on a surface will auto-disable after a while,
1890  // this appears to re-enable it incase the surface it is upon vanishes,
1891  // and the body should fall again.
1892  d.BodySetLinearVel(Body, 0f, 0f, 0f);
1893  d.BodySetForce(Body, 0, 0, 0);
1894  enableBodySoft();
1895  }
1896 
1897  // 35x10 = 350n times the mass per second applied maximum.
1898  float nmax = 35f * m_mass;
1899  float nmin = -35f * m_mass;
1900 
1901  if (fx > nmax)
1902  fx = nmax;
1903  if (fx < nmin)
1904  fx = nmin;
1905  if (fy > nmax)
1906  fy = nmax;
1907  if (fy < nmin)
1908  fy = nmin;
1909  d.BodyAddForce(Body, fx, fy, fz);
1910 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
1911  }
1912  }
1913  }
1914  else
1915  { // is not physical, or is not a body or is selected
1916  // _zeroPosition = d.BodyGetPosition(Body);
1917  return;
1918 //Console.WriteLine("Nothing " + Name);
1919 
1920  }
1921  }
1922 
1923  private void rotate()
1924  {
1925  d.Quaternion myrot = new d.Quaternion();
1926  myrot.X = _orientation.X;
1927  myrot.Y = _orientation.Y;
1928  myrot.Z = _orientation.Z;
1929  myrot.W = _orientation.W;
1930  if (Body != IntPtr.Zero)
1931  {
1932  // KF: If this is a root prim do BodySet
1933  d.BodySetQuaternion(Body, ref myrot);
1934  if (IsPhysical)
1935  {
1936  // create or remove locks
1937  createAMotor(m_angularlock);
1938  }
1939  }
1940  else
1941  {
1942  // daughter prim, do Geom set
1943  d.GeomSetQuaternion(prim_geom, ref myrot);
1944  }
1945 
1946  resetCollisionAccounting();
1947  m_taintrot = _orientation;
1948  }
1949 
1950  private void resetCollisionAccounting()
1951  {
1952  m_collisionscore = 0;
1953  m_interpenetrationcount = 0;
1954  m_disabled = false;
1955  }
1956 
1960  private void changedisable()
1961  {
1962  m_disabled = true;
1963  if (Body != IntPtr.Zero)
1964  {
1965  d.BodyDisable(Body);
1966  Body = IntPtr.Zero;
1967  }
1968 
1969  m_taintdisable = false;
1970  }
1971 
1975  private void changePhysicsStatus()
1976  {
1977  if (IsPhysical)
1978  {
1979  if (Body == IntPtr.Zero)
1980  {
1981  if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1982  {
1983  changeshape();
1984  }
1985  else
1986  {
1987  enableBody();
1988  }
1989  }
1990  }
1991  else
1992  {
1993  if (Body != IntPtr.Zero)
1994  {
1995  if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1996  {
1997  RemoveGeom();
1998 
1999 //Console.WriteLine("changePhysicsStatus for " + Name);
2000  changeadd();
2001  }
2002 
2003  if (childPrim)
2004  {
2005  if (_parent != null)
2006  {
2007  OdePrim parent = (OdePrim)_parent;
2008  parent.ChildDelink(this);
2009  }
2010  }
2011  else
2012  {
2013  disableBody();
2014  }
2015  }
2016  }
2017 
2018  changeSelectedStatus();
2019 
2020  resetCollisionAccounting();
2021  m_taintPhysics = IsPhysical;
2022  }
2023 
2027  private void changesize()
2028  {
2029 #if SPAM
2030  m_log.DebugFormat("[ODE PRIM]: Called changesize");
2031 #endif
2032 
2033  if (_size.X <= 0) _size.X = 0.01f;
2034  if (_size.Y <= 0) _size.Y = 0.01f;
2035  if (_size.Z <= 0) _size.Z = 0.01f;
2036 
2037  //kill body to rebuild
2038  if (IsPhysical && Body != IntPtr.Zero)
2039  {
2040  if (childPrim)
2041  {
2042  if (_parent != null)
2043  {
2044  OdePrim parent = (OdePrim)_parent;
2045  parent.ChildDelink(this);
2046  }
2047  }
2048  else
2049  {
2050  disableBody();
2051  }
2052  }
2053 
2054  if (d.SpaceQuery(m_targetSpace, prim_geom))
2055  {
2056 // _parent_scene.waitForSpaceUnlock(m_targetSpace);
2057  d.SpaceRemove(m_targetSpace, prim_geom);
2058  }
2059 
2060  RemoveGeom();
2061 
2062  // we don't need to do space calculation because the client sends a position update also.
2063 
2064  IMesh mesh = null;
2065 
2066  // Construction of new prim
2067  if (_parent_scene.needsMeshing(_pbs))
2068  {
2069  float meshlod = _parent_scene.meshSculptLOD;
2070 
2071  if (IsPhysical)
2072  meshlod = _parent_scene.MeshSculptphysicalLOD;
2073  // Don't need to re-enable body.. it's done in SetMesh
2074 
2075  if (_parent_scene.needsMeshing(_pbs))
2076  {
2077  mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2078  if (mesh == null)
2079  CheckMeshAsset();
2080  else
2081  m_assetFailed = false;
2082  }
2083 
2084  }
2085 
2086  CreateGeom(m_targetSpace, mesh);
2087  d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2088  d.Quaternion myrot = new d.Quaternion();
2089  myrot.X = _orientation.X;
2090  myrot.Y = _orientation.Y;
2091  myrot.Z = _orientation.Z;
2092  myrot.W = _orientation.W;
2093  d.GeomSetQuaternion(prim_geom, ref myrot);
2094 
2095  //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2096  if (IsPhysical && Body == IntPtr.Zero && !childPrim)
2097  {
2098  // Re creates body on size.
2099  // EnableBody also does setMass()
2100  enableBody();
2101  d.BodyEnable(Body);
2102  }
2103 
2104  changeSelectedStatus();
2105 
2106  if (childPrim)
2107  {
2108  if (_parent is OdePrim)
2109  {
2110  OdePrim parent = (OdePrim)_parent;
2111  parent.ChildSetGeom(this);
2112  }
2113  }
2114  resetCollisionAccounting();
2115  m_taintsize = _size;
2116  }
2117 
2122  private void changefloatonwater()
2123  {
2124  m_collidesWater = m_taintCollidesWater;
2125 
2126  if (m_collidesWater)
2127  {
2128  m_collisionFlags |= CollisionCategories.Water;
2129  }
2130  else
2131  {
2132  m_collisionFlags &= ~CollisionCategories.Water;
2133  }
2134 
2135  if (m_assetFailed)
2136  d.GeomSetCollideBits(prim_geom, (uint)BadMeshAssetCollideBits);
2137  else
2138 
2139  d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2140  }
2144  private void changeshape()
2145  {
2146  m_taintshape = false;
2147 
2148  // Cleanup of old prim geometry and Bodies
2149  if (IsPhysical && Body != IntPtr.Zero)
2150  {
2151  if (childPrim)
2152  {
2153  if (_parent != null)
2154  {
2155  OdePrim parent = (OdePrim)_parent;
2156  parent.ChildDelink(this);
2157  }
2158  }
2159  else
2160  {
2161  disableBody();
2162  }
2163  }
2164 
2165  RemoveGeom();
2166 
2167  // we don't need to do space calculation because the client sends a position update also.
2168  if (_size.X <= 0) _size.X = 0.01f;
2169  if (_size.Y <= 0) _size.Y = 0.01f;
2170  if (_size.Z <= 0) _size.Z = 0.01f;
2171  // Construction of new prim
2172 
2173  IMesh mesh = null;
2174 
2175 
2176  if (_parent_scene.needsMeshing(_pbs))
2177  {
2178  // Don't need to re-enable body.. it's done in CreateMesh
2179  float meshlod = _parent_scene.meshSculptLOD;
2180 
2181  if (IsPhysical)
2182  meshlod = _parent_scene.MeshSculptphysicalLOD;
2183 
2184  // createmesh returns null when it doesn't mesh.
2185  mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2186  if (mesh == null)
2187  CheckMeshAsset();
2188  else
2189  m_assetFailed = false;
2190  }
2191 
2192  CreateGeom(m_targetSpace, mesh);
2193  d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2194  d.Quaternion myrot = new d.Quaternion();
2195  //myrot.W = _orientation.w;
2196  myrot.W = _orientation.W;
2197  myrot.X = _orientation.X;
2198  myrot.Y = _orientation.Y;
2199  myrot.Z = _orientation.Z;
2200  d.GeomSetQuaternion(prim_geom, ref myrot);
2201 
2202  //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
2203  if (IsPhysical && Body == IntPtr.Zero)
2204  {
2205  // Re creates body on size.
2206  // EnableBody also does setMass()
2207  enableBody();
2208  if (Body != IntPtr.Zero)
2209  {
2210  d.BodyEnable(Body);
2211  }
2212  }
2213 
2214  changeSelectedStatus();
2215 
2216  if (childPrim)
2217  {
2218  if (_parent is OdePrim)
2219  {
2220  OdePrim parent = (OdePrim)_parent;
2221  parent.ChildSetGeom(this);
2222  }
2223  }
2224 
2225  resetCollisionAccounting();
2226 // m_taintshape = false;
2227  }
2228 
2232  private void changeAddForce()
2233  {
2234  if (!m_isSelected)
2235  {
2236  lock (m_forcelist)
2237  {
2238  //m_log.Info("[PHYSICS]: dequeing forcelist");
2239  if (IsPhysical)
2240  {
2241  Vector3 iforce = Vector3.Zero;
2242  int i = 0;
2243  try
2244  {
2245  for (i = 0; i < m_forcelist.Count; i++)
2246  {
2247 
2248  iforce = iforce + (m_forcelist[i] * 100);
2249  }
2250  }
2251  catch (IndexOutOfRangeException)
2252  {
2253  m_forcelist = new List<Vector3>();
2254  m_collisionscore = 0;
2255  m_interpenetrationcount = 0;
2256  m_taintforce = false;
2257  return;
2258  }
2259  catch (ArgumentOutOfRangeException)
2260  {
2261  m_forcelist = new List<Vector3>();
2262  m_collisionscore = 0;
2263  m_interpenetrationcount = 0;
2264  m_taintforce = false;
2265  return;
2266  }
2267  d.BodyEnable(Body);
2268  d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z);
2269  }
2270  m_forcelist.Clear();
2271  }
2272 
2273  m_collisionscore = 0;
2274  m_interpenetrationcount = 0;
2275  }
2276 
2277  m_taintforce = false;
2278  }
2279 
2283  private void changeSetTorque()
2284  {
2285  if (!m_isSelected)
2286  {
2287  if (IsPhysical && Body != IntPtr.Zero)
2288  {
2289  d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z);
2290  }
2291  }
2292 
2293  m_taintTorque = Vector3.Zero;
2294  }
2295 
2299  private void changeAddAngularForce()
2300  {
2301  if (!m_isSelected)
2302  {
2303  lock (m_angularforcelist)
2304  {
2305  //m_log.Info("[PHYSICS]: dequeing forcelist");
2306  if (IsPhysical)
2307  {
2308  Vector3 iforce = Vector3.Zero;
2309  for (int i = 0; i < m_angularforcelist.Count; i++)
2310  {
2311  iforce = iforce + (m_angularforcelist[i] * 100);
2312  }
2313  d.BodyEnable(Body);
2314  d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z);
2315 
2316  }
2317  m_angularforcelist.Clear();
2318  }
2319 
2320  m_collisionscore = 0;
2321  m_interpenetrationcount = 0;
2322  }
2323 
2324  m_taintaddangularforce = false;
2325  }
2326 
2330  private void changevelocity()
2331  {
2332  if (!m_isSelected)
2333  {
2334  // Not sure exactly why this sleep is here, but from experimentation it appears to stop an avatar
2335  // walking through a default rez size prim if it keeps kicking it around - justincc.
2336  Thread.Sleep(20);
2337 
2338  if (IsPhysical)
2339  {
2340  if (Body != IntPtr.Zero)
2341  {
2342  d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
2343  }
2344  }
2345 
2346  //resetCollisionAccounting();
2347  }
2348 
2349  m_taintVelocity = Vector3.Zero;
2350  }
2351 
2352  internal void setPrimForRemoval()
2353  {
2354  m_taintremove = true;
2355  }
2356 
2357  public override bool Flying
2358  {
2359  // no flying prims for you
2360  get { return false; }
2361  set { }
2362  }
2363 
2364  public override bool IsColliding
2365  {
2366  get { return iscolliding; }
2367  set { iscolliding = value; }
2368  }
2369 
2370  public override bool CollidingGround
2371  {
2372  get { return false; }
2373  set { return; }
2374  }
2375 
2376  public override bool CollidingObj
2377  {
2378  get { return false; }
2379  set { return; }
2380  }
2381 
2382  public override bool ThrottleUpdates
2383  {
2384  get { return m_throttleUpdates; }
2385  set { m_throttleUpdates = value; }
2386  }
2387 
2388  public override bool Stopped
2389  {
2390  get { return _zeroFlag; }
2391  }
2392 
2393  public override Vector3 Position
2394  {
2395  get { return _position; }
2396 
2397  set { _position = value;
2398  //m_log.Info("[PHYSICS]: " + _position.ToString());
2399  }
2400  }
2401 
2402  public override Vector3 Size
2403  {
2404  get { return _size; }
2405  set
2406  {
2407  if (value.IsFinite())
2408  {
2409  _size = value;
2410 // m_log.DebugFormat("[PHYSICS]: Set size on {0} to {1}", Name, value);
2411  }
2412  else
2413  {
2414  m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
2415  }
2416  }
2417  }
2418 
2419  public override float Mass
2420  {
2421  get { return CalculateMass(); }
2422  }
2423 
2424  public override Vector3 Force
2425  {
2426  //get { return Vector3.Zero; }
2427  get { return m_force; }
2428  set
2429  {
2430  if (value.IsFinite())
2431  {
2432  m_force = value;
2433  }
2434  else
2435  {
2436  m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
2437  }
2438  }
2439  }
2440 
2441  public override int VehicleType
2442  {
2443  get { return (int)m_vehicle.Type; }
2444  set { m_vehicle.ProcessTypeChange((Vehicle)value); }
2445  }
2446 
2447  public override void VehicleFloatParam(int param, float value)
2448  {
2449  m_vehicle.ProcessFloatVehicleParam((Vehicle) param, value);
2450  }
2451 
2452  public override void VehicleVectorParam(int param, Vector3 value)
2453  {
2454  m_vehicle.ProcessVectorVehicleParam((Vehicle) param, value);
2455  }
2456 
2457  public override void VehicleRotationParam(int param, Quaternion rotation)
2458  {
2459  m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation);
2460  }
2461 
2462  public override void VehicleFlags(int param, bool remove)
2463  {
2464  m_vehicle.ProcessVehicleFlags(param, remove);
2465  }
2466 
2467  public override void SetVolumeDetect(int param)
2468  {
2469  // We have to lock the scene here so that an entire simulate loop either uses volume detect for all
2470  // possible collisions with this prim or for none of them.
2471  lock (_parent_scene.OdeLock)
2472  {
2473  m_isVolumeDetect = (param != 0);
2474  }
2475  }
2476 
2477  public override Vector3 CenterOfMass
2478  {
2479  get { return Vector3.Zero; }
2480  }
2481 
2482  public override Vector3 GeometricCenter
2483  {
2484  get { return Vector3.Zero; }
2485  }
2486 
2487  public override PrimitiveBaseShape Shape
2488  {
2489  set
2490  {
2491  _pbs = value;
2492  m_assetFailed = false;
2493  m_taintshape = true;
2494  }
2495  }
2496 
2497  public override Vector3 Velocity
2498  {
2499  get
2500  {
2501  // Average previous velocity with the new one so
2502  // client object interpolation works a 'little' better
2503  if (_zeroFlag)
2504  return Vector3.Zero;
2505 
2506  Vector3 returnVelocity = Vector3.Zero;
2507  returnVelocity.X = (m_lastVelocity.X + _velocity.X) * 0.5f; // 0.5f is mathematically equiv to '/ 2'
2508  returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) * 0.5f;
2509  returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) * 0.5f;
2510  return returnVelocity;
2511  }
2512  set
2513  {
2514  if (value.IsFinite())
2515  {
2516  _velocity = value;
2517 
2518  m_taintVelocity = value;
2519  _parent_scene.AddPhysicsActorTaint(this);
2520  }
2521  else
2522  {
2523  m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
2524  }
2525 
2526  }
2527  }
2528 
2529  public override Vector3 Torque
2530  {
2531  get
2532  {
2533  if (!IsPhysical || Body == IntPtr.Zero)
2534  return Vector3.Zero;
2535 
2536  return _torque;
2537  }
2538 
2539  set
2540  {
2541  if (value.IsFinite())
2542  {
2543  m_taintTorque = value;
2544  _parent_scene.AddPhysicsActorTaint(this);
2545  }
2546  else
2547  {
2548  m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
2549  }
2550  }
2551  }
2552 
2553  public override float CollisionScore
2554  {
2555  get { return m_collisionscore; }
2556  set { m_collisionscore = value; }
2557  }
2558 
2559  public override bool Kinematic
2560  {
2561  get { return false; }
2562  set { }
2563  }
2564 
2565  public override Quaternion Orientation
2566  {
2567  get { return _orientation; }
2568  set
2569  {
2570  if (QuaternionIsFinite(value))
2571  _orientation = value;
2572  else
2573  m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
2574  }
2575  }
2576 
2577  private static bool QuaternionIsFinite(Quaternion q)
2578  {
2579  if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
2580  return false;
2581  if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
2582  return false;
2583  if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
2584  return false;
2585  if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
2586  return false;
2587  return true;
2588  }
2589 
2590  public override Vector3 Acceleration
2591  {
2592  get { return _acceleration; }
2593  set { _acceleration = value; }
2594  }
2595 
2596  public override void AddForce(Vector3 force, bool pushforce)
2597  {
2598  if (force.IsFinite())
2599  {
2600  lock (m_forcelist)
2601  m_forcelist.Add(force);
2602 
2603  m_taintforce = true;
2604  }
2605  else
2606  {
2607  m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
2608  }
2609  //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
2610  }
2611 
2612  public override void AddAngularForce(Vector3 force, bool pushforce)
2613  {
2614  if (force.IsFinite())
2615  {
2616  m_angularforcelist.Add(force);
2617  m_taintaddangularforce = true;
2618  }
2619  else
2620  {
2621  m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
2622  }
2623  }
2624 
2625  public override Vector3 RotationalVelocity
2626  {
2627  get
2628  {
2629  Vector3 pv = Vector3.Zero;
2630  if (_zeroFlag)
2631  return pv;
2632  m_lastUpdateSent = false;
2633 
2634  if (m_rotationalVelocity.ApproxEquals(pv, 0.2f))
2635  return pv;
2636 
2637  return m_rotationalVelocity;
2638  }
2639  set
2640  {
2641  if (value.IsFinite())
2642  {
2643  m_rotationalVelocity = value;
2644  setAngularVelocity(value.X, value.Y, value.Z);
2645  }
2646  else
2647  {
2648  m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
2649  }
2650  }
2651  }
2652 
2653  public override void CrossingFailure()
2654  {
2655  /*
2656  m_crossingfailures++;
2657  if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2658  {
2659  base.RaiseOutOfBounds(_position);
2660  return;
2661  }
2662  else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2663  {
2664  m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name);
2665  }
2666  */
2667 
2668  d.AllocateODEDataForThread(0U);
2669 
2670  _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
2671  _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
2672  _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2673 
2674  m_lastposition = _position;
2675  _velocity.X = 0;
2676  _velocity.Y = 0;
2677  _velocity.Z = 0;
2678 
2679  m_lastVelocity = _velocity;
2680 
2681  if (Body != IntPtr.Zero)
2682  {
2683  d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2684  d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
2685  }
2686 
2687  if(m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2688  m_vehicle.Stop(); // this also updates vehicle last position from the body position
2689 
2690  enableBodySoft();
2691 
2692  outofBounds = false;
2693  base.RequestPhysicsterseUpdate();
2694 
2695  }
2696 
2697  public override float Buoyancy
2698  {
2699  get { return m_buoyancy; }
2700  set { m_buoyancy = value; }
2701  }
2702 
2703  public override void link(PhysicsActor obj)
2704  {
2705  m_taintparent = obj;
2706  }
2707 
2708  public override void delink()
2709  {
2710  m_taintparent = null;
2711  }
2712 
2713  public override void LockAngularMotion(byte axislocks)
2714  {
2715  // m_log.DebugFormat("[axislocks]: {0}", axislocks);
2716  m_taintAngularLock = axislocks;
2717  }
2718 
2719  internal void UpdatePositionAndVelocity()
2720  {
2721  // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2722  if (outofBounds)
2723  return;
2724  if (_parent == null)
2725  {
2726  Vector3 pv = Vector3.Zero;
2727  bool lastZeroFlag = _zeroFlag;
2728  float m_minvelocity = 0;
2729  if (Body != IntPtr.Zero) // FIXME -> or if it is a joint
2730  {
2731  d.Vector3 vec = d.BodyGetPosition(Body);
2732  d.Quaternion ori = d.BodyGetQuaternion(Body);
2733  d.Vector3 vel = d.BodyGetLinearVel(Body);
2734  d.Vector3 rotvel = d.BodyGetAngularVel(Body);
2735  d.Vector3 torque = d.BodyGetTorque(Body);
2736  _torque = new Vector3(torque.X, torque.Y, torque.Z);
2737  Vector3 l_position = Vector3.Zero;
2738  Quaternion l_orientation = Quaternion.Identity;
2739 
2740  m_lastposition = _position;
2741  m_lastorientation = _orientation;
2742 
2743  l_position.X = vec.X;
2744  l_position.Y = vec.Y;
2745  l_position.Z = vec.Z;
2746  l_orientation.X = ori.X;
2747  l_orientation.Y = ori.Y;
2748  l_orientation.Z = ori.Z;
2749  l_orientation.W = ori.W;
2750 
2751  if (l_position.Z < 0)
2752  {
2753  // This is so prim that get lost underground don't fall forever and suck up
2754  //
2755  // Sim resources and memory.
2756  // Disables the prim's movement physics....
2757  // It's a hack and will generate a console message if it fails.
2758 
2759  //IsPhysical = false;
2760 
2761  _acceleration.X = 0;
2762  _acceleration.Y = 0;
2763  _acceleration.Z = 0;
2764 
2765  _velocity.X = 0;
2766  _velocity.Y = 0;
2767  _velocity.Z = 0;
2768  m_rotationalVelocity.X = 0;
2769  m_rotationalVelocity.Y = 0;
2770  m_rotationalVelocity.Z = 0;
2771 
2772  if (_parent == null)
2773  base.RaiseOutOfBounds(_position);
2774 
2775  if (_parent == null)
2776  base.RequestPhysicsterseUpdate();
2777 
2778  m_throttleUpdates = false;
2779  throttleCounter = 0;
2780  _zeroFlag = true;
2781  //outofBounds = true;
2782  return;
2783  }
2784 
2785  if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2786  {
2787  //base.RaiseOutOfBounds(l_position);
2788  /*
2789  if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2790  {
2791  _position = l_position;
2792  //_parent_scene.remActivePrim(this);
2793  if (_parent == null)
2794  base.RequestPhysicsterseUpdate();
2795  return;
2796  }
2797  else
2798  {
2799  if (_parent == null)
2800  base.RaiseOutOfBounds(l_position);
2801  return;
2802  }
2803  */
2804  outofBounds = true;
2805  // part near the border on outside
2806  if (l_position.X < 0)
2807  Util.Clamp(l_position.X, -0.1f, -2f);
2808  else
2809  Util.Clamp(l_position.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
2810  if (l_position.Y < 0)
2811  Util.Clamp(l_position.Y, -0.1f, -2f);
2812  else
2813  Util.Clamp(l_position.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
2814 
2815  d.BodySetPosition(Body, l_position.X, l_position.Y, l_position.Z);
2816 
2817  // stop it
2818  d.BodySetAngularVel(Body, 0, 0, 0);
2819  d.BodySetLinearVel(Body, 0, 0, 0);
2820  disableBodySoft();
2821 
2822  _position = l_position;
2823  // tell framework to fix it
2824  if (_parent == null)
2825  base.RequestPhysicsterseUpdate();
2826  return;
2827  }
2828 
2829 
2830  //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation));
2831  //Console.WriteLine("Adiff " + Name + " = " + Adiff);
2832  if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2833  && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2834  && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
2835 // && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01))
2836  && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large
2837  {
2838  _zeroFlag = true;
2839 //Console.WriteLine("ZFT 2");
2840  m_throttleUpdates = false;
2841  }
2842  else
2843  {
2844  //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2845  _zeroFlag = false;
2846  m_lastUpdateSent = false;
2847  //m_throttleUpdates = false;
2848  }
2849 
2850  if (_zeroFlag)
2851  {
2852  _velocity.X = 0.0f;
2853  _velocity.Y = 0.0f;
2854  _velocity.Z = 0.0f;
2855 
2856  _acceleration.X = 0;
2857  _acceleration.Y = 0;
2858  _acceleration.Z = 0;
2859 
2860  //_orientation.w = 0f;
2861  //_orientation.X = 0f;
2862  //_orientation.Y = 0f;
2863  //_orientation.Z = 0f;
2864  m_rotationalVelocity.X = 0;
2865  m_rotationalVelocity.Y = 0;
2866  m_rotationalVelocity.Z = 0;
2867  if (!m_lastUpdateSent)
2868  {
2869  m_throttleUpdates = false;
2870  throttleCounter = 0;
2871  m_rotationalVelocity = pv;
2872 
2873  if (_parent == null)
2874  {
2875  base.RequestPhysicsterseUpdate();
2876  }
2877 
2878  m_lastUpdateSent = true;
2879  }
2880  }
2881  else
2882  {
2883  if (lastZeroFlag != _zeroFlag)
2884  {
2885  if (_parent == null)
2886  {
2887  base.RequestPhysicsterseUpdate();
2888  }
2889  }
2890 
2891  m_lastVelocity = _velocity;
2892 
2893  _position = l_position;
2894 
2895  _velocity.X = vel.X;
2896  _velocity.Y = vel.Y;
2897  _velocity.Z = vel.Z;
2898 
2899  _acceleration = ((_velocity - m_lastVelocity) / 0.1f);
2900  _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f);
2901  //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString());
2902 
2903  // Note here that linearvelocity is affecting angular velocity... so I'm guessing this is a vehicle specific thing...
2904  // it does make sense to do this for tiny little instabilities with physical prim, however 0.5m/frame is fairly large.
2905  // reducing this to 0.02m/frame seems to help the angular rubberbanding quite a bit, however, to make sure it doesn't affect elevators and vehicles
2906  // adding these logical exclusion situations to maintain this where I think it was intended to be.
2907  if (m_throttleUpdates || PIDActive || (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) || (Amotor != IntPtr.Zero))
2908  {
2909  m_minvelocity = 0.5f;
2910  }
2911  else
2912  {
2913  m_minvelocity = 0.02f;
2914  }
2915 
2916  if (_velocity.ApproxEquals(pv, m_minvelocity))
2917  {
2918  m_rotationalVelocity = pv;
2919  }
2920  else
2921  {
2922  m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z);
2923  }
2924 
2925  //m_log.Debug("ODE: " + m_rotationalVelocity.ToString());
2926  _orientation.X = ori.X;
2927  _orientation.Y = ori.Y;
2928  _orientation.Z = ori.Z;
2929  _orientation.W = ori.W;
2930  m_lastUpdateSent = false;
2931  if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
2932  {
2933  if (_parent == null)
2934  {
2935  base.RequestPhysicsterseUpdate();
2936  }
2937  }
2938  else
2939  {
2940  throttleCounter++;
2941  }
2942  }
2943  m_lastposition = l_position;
2944  }
2945  else
2946  {
2947  // Not a body.. so Make sure the client isn't interpolating
2948  _velocity.X = 0;
2949  _velocity.Y = 0;
2950  _velocity.Z = 0;
2951 
2952  _acceleration.X = 0;
2953  _acceleration.Y = 0;
2954  _acceleration.Z = 0;
2955 
2956  m_rotationalVelocity.X = 0;
2957  m_rotationalVelocity.Y = 0;
2958  m_rotationalVelocity.Z = 0;
2959  _zeroFlag = true;
2960  }
2961  }
2962  }
2963 
2964  public override bool FloatOnWater
2965  {
2966  set {
2967  m_taintCollidesWater = value;
2968  _parent_scene.AddPhysicsActorTaint(this);
2969  }
2970  }
2971 
2972  public override void SetMomentum(Vector3 momentum)
2973  {
2974  }
2975 
2976  public override Vector3 PIDTarget
2977  {
2978  set
2979  {
2980  if (value.IsFinite())
2981  {
2982  m_PIDTarget = value;
2983  }
2984  else
2985  m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
2986  }
2987  }
2988 
2989  public override bool PIDActive { get; set; }
2990  public override float PIDTau { set { m_PIDTau = value; } }
2991 
2992  public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2993  public override bool PIDHoverActive { get { return m_useHoverPID;} set { m_useHoverPID = value; } }
2994  public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
2995  public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
2996 
2997  public override Quaternion APIDTarget{ set { return; } }
2998 
2999  public override bool APIDActive{ set { return; } }
3000 
3001  public override float APIDStrength{ set { return; } }
3002 
3003  public override float APIDDamping{ set { return; } }
3004 
3005  private void createAMotor(byte axislock)
3006  {
3007  if (Body == IntPtr.Zero)
3008  return;
3009 
3010  if (Amotor != IntPtr.Zero)
3011  {
3012  d.JointDestroy(Amotor);
3013  Amotor = IntPtr.Zero;
3014  }
3015 
3016  if(axislock == 0)
3017  return;
3018 
3019  int axisnum = 0;
3020  bool axisX = false;
3021  bool axisY = false;
3022  bool axisZ = false;
3023  if((axislock & 0x02) != 0)
3024  {
3025  axisnum++;
3026  axisX = true;
3027  }
3028  if((axislock & 0x04) != 0)
3029  {
3030  axisnum++;
3031  axisY = true;
3032  }
3033  if((axislock & 0x08) != 0)
3034  {
3035  axisnum++;
3036  axisZ = true;
3037  }
3038 
3039  if(axisnum == 0)
3040  return;
3041  // stop it
3042  d.BodySetTorque(Body, 0, 0, 0);
3043  d.BodySetAngularVel(Body, 0, 0, 0);
3044 
3045  Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3046  d.JointAttach(Amotor, Body, IntPtr.Zero);
3047 
3048  d.JointSetAMotorMode(Amotor, 0);
3049 
3050  d.JointSetAMotorNumAxes(Amotor, axisnum);
3051 
3052  // get current orientation to lock
3053 
3054  d.Quaternion dcur = d.BodyGetQuaternion(Body);
3055  Quaternion curr; // crap convertion between identical things
3056  curr.X = dcur.X;
3057  curr.Y = dcur.Y;
3058  curr.Z = dcur.Z;
3059  curr.W = dcur.W;
3060  Vector3 ax;
3061 
3062  int i = 0;
3063  int j = 0;
3064  if (axisX)
3065  {
3066  ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
3067  d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
3068  d.JointSetAMotorAngle(Amotor, 0, 0);
3069  d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
3070  d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
3071  d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
3072  d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
3073  d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
3074  d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
3075  d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
3076  d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
3077  d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
3078  i++;
3079  j = 256; // move to next axis set
3080  }
3081 
3082  if (axisY)
3083  {
3084  ax = (new Vector3(0, 1, 0)) * curr;
3085  d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3086  d.JointSetAMotorAngle(Amotor, i, 0);
3087  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3088  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3089  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3090  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3091  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3092  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3093  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3094  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3095  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3096  i++;
3097  j += 256;
3098  }
3099 
3100  if (axisZ)
3101  {
3102  ax = (new Vector3(0, 0, 1)) * curr;
3103  d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3104  d.JointSetAMotorAngle(Amotor, i, 0);
3105  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3106  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3107  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3108  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3109  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3110  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3111  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3112  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3113  d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3114  }
3115  }
3116 
3117  public override void SubscribeEvents(int ms)
3118  {
3119  m_eventsubscription = ms;
3120  _parent_scene.AddCollisionEventReporting(this);
3121  }
3122 
3123  public override void UnSubscribeEvents()
3124  {
3125  _parent_scene.RemoveCollisionEventReporting(this);
3126  m_eventsubscription = 0;
3127  }
3128 
3129  public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
3130  {
3131  CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
3132  }
3133 
3134  public void SendCollisions()
3135  {
3136  if (m_collisionsOnPreviousFrame || CollisionEventsThisFrame.Count > 0)
3137  {
3138  base.SendCollisionUpdate(CollisionEventsThisFrame);
3139 
3140  if (CollisionEventsThisFrame.Count > 0)
3141  {
3142  m_collisionsOnPreviousFrame = true;
3143  CollisionEventsThisFrame.Clear();
3144  }
3145  else
3146  {
3147  m_collisionsOnPreviousFrame = false;
3148  }
3149  }
3150  }
3151 
3152  public override bool SubscribedEvents()
3153  {
3154  if (m_eventsubscription > 0)
3155  return true;
3156  return false;
3157  }
3158 
3159  public override void SetMaterial(int pMaterial)
3160  {
3161  m_material = pMaterial;
3162  }
3163 
3164  private void CheckMeshAsset()
3165  {
3166  if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
3167  {
3168  m_assetFailed = true;
3169  Util.FireAndForget(delegate
3170  {
3171  RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3172  if (assetProvider != null)
3173  assetProvider(_pbs.SculptTexture, MeshAssetReceived);
3174  }, null, "ODEPrim.CheckMeshAsset");
3175  }
3176  }
3177 
3178  private void MeshAssetReceived(AssetBase asset)
3179  {
3180  if (asset != null && asset.Data != null && asset.Data.Length > 0)
3181  {
3182  if (!_pbs.SculptEntry)
3183  return;
3184  if (_pbs.SculptTexture.ToString() != asset.ID)
3185  return;
3186 
3187  _pbs.SculptData = new byte[asset.Data.Length];
3188  asset.Data.CopyTo(_pbs.SculptData, 0);
3189 // m_assetFailed = false;
3190 
3191 // m_log.DebugFormat(
3192 // "[ODE PRIM]: Received mesh/sculpt data asset {0} with {1} bytes for {2} at {3} in {4}",
3193 // _pbs.SculptTexture, _pbs.SculptData.Length, Name, _position, _parent_scene.Name);
3194 
3195  m_taintshape = true;
3196  _parent_scene.AddPhysicsActorTaint(this);
3197  }
3198  else
3199  {
3200  m_log.WarnFormat(
3201  "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}",
3202  _pbs.SculptTexture, Name, _position, _parent_scene.PhysicsSceneName);
3203  }
3204  }
3205  }
3206 }
override void SetMomentum(Vector3 momentum)
Definition: ODEPrim.cs:2972
override void VehicleVectorParam(int param, Vector3 value)
Definition: ODEPrim.cs:2452
override void SetVolumeDetect(int param)
Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more ...
Definition: ODEPrim.cs:2467
override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
Definition: ODEPrim.cs:3129
delegate void SetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun)
override void AddAngularForce(Vector3 force, bool pushforce)
Definition: ODEPrim.cs:2612
override void LockAngularMotion(byte axislocks)
Definition: ODEPrim.cs:2713
Asset class. All Assets are reference by this class or a class derived from this class ...
Definition: AssetBase.cs:49
Used to pass collision information to OnCollisionUpdate listeners.
Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ours...
Definition: ODEPrim.cs:59
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
Definition: ICM_Api.cs:32
delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback)
override void VehicleFloatParam(int param, float value)
Definition: ODEPrim.cs:2447
override void link(PhysicsActor obj)
Definition: ODEPrim.cs:2703
override void SubscribeEvents(int ms)
Definition: ODEPrim.cs:3117
override void SetMaterial(int pMaterial)
Definition: ODEPrim.cs:3159
override void VehicleRotationParam(int param, Quaternion rotation)
Definition: ODEPrim.cs:2457
Material
Material type for a primitive
Definition: OdeScene.cs:79
override void VehicleFlags(int param, bool remove)
Definition: ODEPrim.cs:2462
override void AddForce(Vector3 force, bool pushforce)
Definition: ODEPrim.cs:2596