aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs3256
1 files changed, 3256 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
new file mode 100644
index 0000000..7718a29
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -0,0 +1,3256 @@
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/* Revision 2011 by Ubit Umarov
29 *
30 *
31 */
32
33/*
34 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
35 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
36 * ODEPrim.cs contains methods dealing with Prim editing, Prim
37 * characteristics and Kinetic motion.
38 * ODEDynamics.cs contains methods dealing with Prim Physical motion
39 * (dynamics) and the associated settings. Old Linear and angular
40 * motors for dynamic motion have been replace with MoveLinear()
41 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
42 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
43 * switch between 'VEHICLE' parameter use and general dynamics
44 * settings use.
45 */
46
47//#define SPAM
48
49using System;
50using System.Collections.Generic;
51using System.Reflection;
52using System.Runtime.InteropServices;
53using System.Threading;
54using log4net;
55using OpenMetaverse;
56using OdeAPI;
57using OpenSim.Framework;
58using OpenSim.Region.Physics.Manager;
59
60
61namespace OpenSim.Region.Physics.OdePlugin
62{
63 public class OdePrim : PhysicsActor
64 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66
67 private bool m_isphysical;
68 private bool m_fakeisphysical;
69
70 protected bool m_building;
71 private Quaternion m_lastorientation = new Quaternion();
72 private Quaternion _orientation;
73
74 private Vector3 _position;
75 private Vector3 _velocity;
76 private Vector3 _torque;
77 private Vector3 m_lastVelocity;
78 private Vector3 m_lastposition;
79 private Vector3 m_rotationalVelocity;
80 private Vector3 _size;
81 private Vector3 _acceleration;
82 private Vector3 m_angularlock = Vector3.One;
83 private IntPtr Amotor = IntPtr.Zero;
84
85 private Vector3 m_force;
86 private Vector3 m_forceacc;
87 private Vector3 m_angularForceacc;
88
89 private Vector3 m_PIDTarget;
90 private float m_PIDTau;
91 private float PID_D = 35f;
92 private float PID_G = 25f;
93 private bool m_usePID;
94
95 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
96 // and are for non-VEHICLES only.
97
98 private float m_PIDHoverHeight;
99 private float m_PIDHoverTau;
100 private bool m_useHoverPID;
101 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
102 private float m_targetHoverHeight;
103 private float m_groundHeight;
104 private float m_waterHeight;
105 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
106
107 private int body_autodisable_frames = 20;
108
109 private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
110 | CollisionCategories.Space
111 | CollisionCategories.Body
112 | CollisionCategories.Character
113 );
114 private bool m_collidesLand = true;
115 private bool m_collidesWater;
116 public bool m_returnCollisions;
117
118 // Default we're a Geometry
119 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
120
121 // Default, Collide with Other Geometries, spaces and Bodies
122 private CollisionCategories m_collisionFlags = m_default_collisionFlags;
123
124 public bool m_disabled;
125 public bool m_taintselected;
126
127 public uint m_localID;
128
129 private PrimitiveBaseShape _pbs;
130 public OdeScene _parent_scene;
131
132 /// <summary>
133 /// The physics space which contains prim geometry
134 /// </summary>
135 public IntPtr m_targetSpace = IntPtr.Zero;
136
137 public IntPtr prim_geom;
138 public IntPtr _triMeshData;
139
140 private PhysicsActor _parent;
141
142 private List<OdePrim> childrenPrim = new List<OdePrim>();
143
144 private bool m_iscolliding;
145 private bool m_wascolliding;
146 private bool m_isSelected;
147
148 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
149
150 private bool m_throttleUpdates;
151 private int throttleCounter;
152 public int m_interpenetrationcount;
153 public float m_collisionscore;
154 int m_colliderfilter = 0;
155 public int m_roundsUnderMotionThreshold;
156 private int m_crossingfailures;
157
158 public bool outofBounds;
159 private float m_density = 10.000006836f; // Aluminum g/cm3;
160
161 public bool _zeroFlag;
162 private bool m_lastUpdateSent;
163
164 public IntPtr Body = IntPtr.Zero;
165 public String Name { get; private set; }
166 private Vector3 _target_velocity;
167
168 public Vector3 primOOBsize; // prim real dimensions from mesh
169 public Vector3 primOOBoffset; // is centroid out of mesh or rest aabb
170 public float primOOBradiusSQ;
171 public d.Mass primdMass; // prim inertia information on it's own referencial
172 float primMass; // prim own mass
173 float _mass; // object mass acording to case
174 public d.Mass objectpMass; // object last computed inertia
175 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
176
177 public int givefakepos = 0;
178 private Vector3 fakepos;
179 public int givefakeori = 0;
180 private Quaternion fakeori;
181
182 public int m_eventsubscription;
183 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
184
185 private IntPtr m_linkJoint = IntPtr.Zero;
186 private IntPtr _linkJointGroup = IntPtr.Zero;
187
188 public volatile bool childPrim;
189
190 public ODEDynamics m_vehicle;
191
192 internal int m_material = (int)Material.Wood;
193 protected ContactData primContactData = new ContactData { mu = 0f, bounce = 0.1f};
194
195 /// <summary>
196 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
197 /// </summary>
198 public override bool IsPhysical // this is not reliable for internal use
199 {
200 get { return m_fakeisphysical; }
201 set
202 {
203 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
204 // and also to stop imediatly some updates
205 // but real change will only happen in taintprocessing
206
207 if (!value) // Zero the remembered last velocity
208 m_lastVelocity = Vector3.Zero;
209 AddChange(changes.Physical, value);
210 }
211 }
212
213 public override bool Building // this is not reliable for internal use
214 {
215 get { return m_building; }
216 set
217 {
218 if (value)
219 m_building = true;
220 AddChange(changes.building, value);
221 }
222 }
223
224 public override ContactData ContactData
225 {
226 get
227 {
228/*
229 ODEDynamics v;
230 if(childPrim && _parent !=null)
231 {
232 v =((OdePrim)_parent).m_vehicle;
233 if(v != null && v.Type != Vehicle.TYPE_NONE)
234 return v.VehiculeContactData;
235 return primContactData;
236 }
237
238 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
239 return m_vehicle.VehiculeContactData;
240*/
241 return primContactData;
242 }
243 }
244
245 public override int PhysicsActorType
246 {
247 get { return (int)ActorTypes.Prim; }
248 set { return; }
249 }
250
251 public override bool SetAlwaysRun
252 {
253 get { return false; }
254 set { return; }
255 }
256
257 public override uint LocalID
258 {
259 get
260 {
261 return m_localID;
262 }
263 set
264 {
265 //m_log.Info("[PHYSICS]: Setting TrackerID: " + value);
266 m_localID = value;
267 }
268 }
269
270 public override bool Grabbed
271 {
272 set { return; }
273 }
274
275 public override bool Selected
276 {
277 set
278 {
279 if(value)
280 m_isSelected = value;
281 AddChange(changes.Selected, value);
282 }
283 }
284
285 public override bool Flying
286 {
287 // no flying prims for you
288 get { return false; }
289 set { }
290 }
291
292 public override bool IsColliding
293 {
294 get { return m_iscolliding; }
295 set
296 {
297 if (value)
298 {
299 m_colliderfilter += 2;
300 if (m_colliderfilter > 2)
301 m_colliderfilter = 2;
302 }
303 else
304 {
305 m_colliderfilter--;
306 if (m_colliderfilter < 0)
307 m_colliderfilter = 0;
308 }
309
310 if (m_colliderfilter == 0)
311 m_iscolliding = false;
312 else
313 m_iscolliding = true;
314
315 if (m_wascolliding != m_iscolliding)
316 {
317 if (m_wascolliding && !m_isSelected && Body != IntPtr.Zero)
318 d.BodyEnable(Body);
319 m_wascolliding = m_iscolliding;
320 }
321 }
322 }
323
324 public override bool CollidingGround
325 {
326 get { return false; }
327 set { return; }
328 }
329
330 public override bool CollidingObj
331 {
332 get { return false; }
333 set { return; }
334 }
335
336 public override bool ThrottleUpdates
337 {
338 get { return m_throttleUpdates; }
339 set { m_throttleUpdates = value; }
340 }
341
342 public override bool Stopped
343 {
344 get { return _zeroFlag; }
345 }
346
347 public override Vector3 Position
348 {
349 get
350 {
351 if (givefakepos > 0)
352 return fakepos;
353 else
354 return _position;
355 }
356
357 set
358 {
359 fakepos = value;
360 givefakepos++;
361 AddChange(changes.Position, value);
362 }
363 }
364
365 public override Vector3 Size
366 {
367 get { return _size; }
368 set
369 {
370 if (value.IsFinite())
371 {
372 AddChange(changes.Size, value);
373 }
374 else
375 {
376 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
377 }
378 }
379 }
380
381 public override float Mass
382 {
383 get { return _mass; }
384 }
385
386 public override Vector3 Force
387 {
388 //get { return Vector3.Zero; }
389 get { return m_force; }
390 set
391 {
392 if (value.IsFinite())
393 {
394 AddChange(changes.Force, value);
395 }
396 else
397 {
398 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
399 }
400 }
401 }
402
403
404 public override void SetVolumeDetect(int param)
405 {
406 AddChange(changes.VolumeDtc,(param != 0));
407 }
408
409 public override Vector3 GeometricCenter
410 {
411 get
412 {
413 return Vector3.Zero;
414 }
415 }
416
417 public override Vector3 CenterOfMass
418 {
419 get
420 {
421 d.Vector3 dtmp;
422 if (IsPhysical && !childPrim && Body != IntPtr.Zero)
423 {
424 dtmp = d.BodyGetPosition(Body);
425 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
426 }
427 else if (prim_geom != IntPtr.Zero)
428 {
429 d.Quaternion dq;
430 d.GeomCopyQuaternion(prim_geom, out dq);
431 Quaternion q;
432 q.X = dq.X;
433 q.Y = dq.Y;
434 q.Z = dq.Z;
435 q.W = dq.W;
436
437 Vector3 vtmp = primOOBoffset * q;
438 dtmp = d.GeomGetPosition(prim_geom);
439 return new Vector3(dtmp.X + vtmp.X, dtmp.Y + vtmp.Y, dtmp.Z + vtmp.Z);
440 }
441 else
442 return Vector3.Zero;
443 }
444 }
445 /*
446 public override Vector3 PrimOOBsize
447 {
448 get
449 {
450 return primOOBsize;
451 }
452 }
453
454 public override Vector3 PrimOOBoffset
455 {
456 get
457 {
458 return primOOBoffset;
459 }
460 }
461
462 public override float PrimOOBRadiusSQ
463 {
464 get
465 {
466 return primOOBradiusSQ;
467 }
468 }
469 */
470 public override PrimitiveBaseShape Shape
471 {
472 set
473 {
474 AddChange(changes.Shape, value);
475 }
476 }
477
478 public override Vector3 Velocity
479 {
480 get
481 {
482 // Averate previous velocity with the new one so
483 // client object interpolation works a 'little' better
484 if (_zeroFlag)
485 return Vector3.Zero;
486/*
487 Vector3 returnVelocity = Vector3.Zero;
488 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
489 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
490 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
491
492 return returnVelocity;
493 */
494 return _velocity;
495 }
496 set
497 {
498 if (value.IsFinite())
499 {
500 AddChange(changes.Velocity, value);
501// _velocity = value;
502
503 }
504 else
505 {
506 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
507 }
508
509 }
510 }
511
512 public override Vector3 Torque
513 {
514 get
515 {
516 if (!IsPhysical || Body == IntPtr.Zero)
517 return Vector3.Zero;
518
519 return _torque;
520 }
521
522 set
523 {
524 if (value.IsFinite())
525 {
526 AddChange(changes.Torque, value);
527 }
528 else
529 {
530 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
531 }
532 }
533 }
534
535 public override float CollisionScore
536 {
537 get { return m_collisionscore; }
538 set { m_collisionscore = value; }
539 }
540
541 public override bool Kinematic
542 {
543 get { return false; }
544 set { }
545 }
546
547 public override Quaternion Orientation
548 {
549 get
550 {
551 if (givefakeori>0)
552 return fakeori;
553 else
554
555 return _orientation;
556 }
557 set
558 {
559 if (QuaternionIsFinite(value))
560 {
561 fakeori = value;
562 givefakeori++;
563 AddChange(changes.Orientation, value);
564 }
565 else
566 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
567
568 }
569 }
570
571 public override Vector3 Acceleration
572 {
573 get { return _acceleration; }
574 set { }
575 }
576
577 public override Vector3 RotationalVelocity
578 {
579 get
580 {
581 Vector3 pv = Vector3.Zero;
582 if (_zeroFlag)
583 return pv;
584 m_lastUpdateSent = false;
585
586 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
587 return pv;
588
589 return m_rotationalVelocity;
590 }
591 set
592 {
593 if (value.IsFinite())
594 {
595 m_rotationalVelocity = value;
596 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
597 d.BodyEnable(Body);
598 }
599 else
600 {
601 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
602 }
603 }
604 }
605
606
607 public override float Buoyancy
608 {
609 get { return m_buoyancy; }
610 set
611 {
612 m_buoyancy = value;
613 }
614 }
615
616 public override bool FloatOnWater
617 {
618 set
619 {
620 AddChange(changes.CollidesWater, value);
621 }
622 }
623
624 public override Vector3 PIDTarget
625 {
626 set
627 {
628 if (value.IsFinite())
629 {
630 m_PIDTarget = value;
631 }
632 else
633 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
634 }
635 }
636
637 public override bool PIDActive { set { m_usePID = value; } }
638 public override float PIDTau { set { m_PIDTau = value; } }
639
640 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
641 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
642 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
643 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
644
645 public override Quaternion APIDTarget { set { return; } }
646
647 public override bool APIDActive { set { return; } }
648
649 public override float APIDStrength { set { return; } }
650
651 public override float APIDDamping { set { return; } }
652
653 public override int VehicleType
654 {
655 get
656 {
657 if (m_vehicle == null)
658 return (int)Vehicle.TYPE_NONE;
659 else
660 return (int)m_vehicle.Type;
661 }
662 set
663 {
664 if (m_vehicle == null)
665 {
666 if (value != (int)Vehicle.TYPE_NONE)
667 {
668 m_vehicle = new ODEDynamics(this);
669 m_vehicle.ProcessTypeChange((Vehicle)value);
670 }
671 }
672 else
673 m_vehicle.ProcessTypeChange((Vehicle)value);
674 }
675 }
676
677 public override void VehicleFloatParam(int param, float value)
678 {
679 if (m_vehicle == null)
680 return;
681 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
682 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
683 d.BodyEnable(Body);
684 }
685
686 public override void VehicleVectorParam(int param, Vector3 value)
687 {
688 if (m_vehicle == null)
689 return;
690 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
691 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
692 d.BodyEnable(Body);
693 }
694
695 public override void VehicleRotationParam(int param, Quaternion rotation)
696 {
697 if (m_vehicle == null)
698 return;
699 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
700 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
701 d.BodyEnable(Body);
702 }
703
704 public override void VehicleFlags(int param, bool remove)
705 {
706 if (m_vehicle == null)
707 return;
708 m_vehicle.ProcessVehicleFlags(param, remove);
709 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
710 d.BodyEnable(Body);
711 }
712
713 public void SetAcceleration(Vector3 accel)
714 {
715 _acceleration = accel;
716 }
717
718 public override void AddForce(Vector3 force, bool pushforce)
719 {
720 if (force.IsFinite())
721 {
722 AddChange(changes.AddForce, force / _parent_scene.ODE_STEPSIZE);
723 }
724 else
725 {
726 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
727 }
728 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
729 }
730
731 public override void AddAngularForce(Vector3 force, bool pushforce)
732 {
733 if (force.IsFinite())
734 {
735 AddChange(changes.AddAngForce, force / _parent_scene.ODE_STEPSIZE);
736 }
737 else
738 {
739 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
740 }
741 }
742
743 public override void CrossingFailure()
744 {
745 m_crossingfailures++;
746 changeDisable(false);
747 }
748
749 public override void SetMomentum(Vector3 momentum)
750 {
751 }
752
753 public override void SetMaterial(int pMaterial)
754 {
755 m_material = pMaterial;
756 primContactData.mu = _parent_scene.m_materialContactsData[pMaterial].mu;
757 primContactData.bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
758 }
759
760 public void setPrimForRemoval()
761 {
762 AddChange(changes.Remove, null);
763 }
764
765 public override void link(PhysicsActor obj)
766 {
767 AddChange(changes.Link, obj);
768 }
769
770 public override void delink()
771 {
772 AddChange(changes.DeLink, null);
773 }
774
775 public override void LockAngularMotion(Vector3 axis)
776 {
777 // reverse the zero/non zero values for ODE.
778 if (axis.IsFinite())
779 {
780 axis.X = (axis.X > 0) ? 1f : 0f;
781 axis.Y = (axis.Y > 0) ? 1f : 0f;
782 axis.Z = (axis.Z > 0) ? 1f : 0f;
783 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
784 AddChange(changes.AngLock, axis);
785 }
786 else
787 {
788 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
789 }
790 }
791
792 public override void SubscribeEvents(int ms)
793 {
794 m_eventsubscription = ms;
795 _parent_scene.AddCollisionEventReporting(this);
796 }
797
798 public override void UnSubscribeEvents()
799 {
800 _parent_scene.RemoveCollisionEventReporting(this);
801 m_eventsubscription = 0;
802 }
803
804 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
805 {
806 if (CollisionEventsThisFrame == null)
807 CollisionEventsThisFrame = new CollisionEventUpdate();
808
809 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
810 }
811
812 public void SendCollisions()
813 {
814 if (CollisionEventsThisFrame == null)
815 return;
816
817 base.SendCollisionUpdate(CollisionEventsThisFrame);
818
819 if (CollisionEventsThisFrame.m_objCollisionList.Count == 0)
820 CollisionEventsThisFrame = null;
821 else
822 CollisionEventsThisFrame = new CollisionEventUpdate();
823 }
824
825 public override bool SubscribedEvents()
826 {
827 if (m_eventsubscription > 0)
828 return true;
829 return false;
830 }
831
832
833 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
834 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
835 {
836 Name = primName;
837
838 m_vehicle = null;
839
840 if (!pos.IsFinite())
841 {
842 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
843 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
844 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
845 }
846 _position = pos;
847 givefakepos = 0;
848
849 PID_D = parent_scene.bodyPIDD;
850 PID_G = parent_scene.bodyPIDG;
851 m_density = parent_scene.geomDefaultDensity;
852 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
853 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
854
855 prim_geom = IntPtr.Zero;
856 Body = IntPtr.Zero;
857
858 if (!size.IsFinite())
859 {
860 size = new Vector3(0.5f, 0.5f, 0.5f);
861 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
862 }
863
864 if (size.X <= 0) size.X = 0.01f;
865 if (size.Y <= 0) size.Y = 0.01f;
866 if (size.Z <= 0) size.Z = 0.01f;
867
868 _size = size;
869
870
871 if (!QuaternionIsFinite(rotation))
872 {
873 rotation = Quaternion.Identity;
874 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
875 }
876
877 _orientation = rotation;
878 givefakeori = 0;
879
880 _pbs = pbs;
881
882 _parent_scene = parent_scene;
883 m_targetSpace = IntPtr.Zero;
884
885 if (pos.Z < 0)
886 {
887 m_isphysical = false;
888 }
889 else
890 {
891 m_isphysical = pisPhysical;
892 }
893 m_fakeisphysical = m_isphysical;
894
895 m_isVolumeDetect = false;
896
897 m_force = Vector3.Zero;
898
899 m_iscolliding = false;
900 m_wascolliding = false;
901 m_colliderfilter = 0;
902
903 hasOOBoffsetFromMesh = false;
904 _triMeshData = IntPtr.Zero;
905
906
907 primContactData.mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
908 primContactData.bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
909
910 CalcPrimBodyData();
911
912 m_building = true; // control must set this to false when done
913
914 AddChange(changes.Add, null);
915 }
916
917 private void resetCollisionAccounting()
918 {
919 m_collisionscore = 0;
920 m_interpenetrationcount = 0;
921 m_disabled = false;
922 }
923
924 private void createAMotor(Vector3 axis)
925 {
926 if (Body == IntPtr.Zero)
927 return;
928
929 if (Amotor != IntPtr.Zero)
930 {
931 d.JointDestroy(Amotor);
932 Amotor = IntPtr.Zero;
933 }
934
935 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z);
936
937 if (axisnum <= 0)
938 return;
939
940 // stop it
941 d.BodySetTorque(Body, 0, 0, 0);
942 d.BodySetAngularVel(Body, 0, 0, 0);
943
944 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
945 d.JointAttach(Amotor, Body, IntPtr.Zero);
946
947 d.JointSetAMotorMode(Amotor, 0);
948
949 d.JointSetAMotorNumAxes(Amotor, axisnum);
950
951 // get current orientation to lock
952
953 d.Quaternion dcur = d.BodyGetQuaternion(Body);
954 Quaternion curr; // crap convertion between identical things
955 curr.X = dcur.X;
956 curr.Y = dcur.Y;
957 curr.Z = dcur.Z;
958 curr.W = dcur.W;
959 Vector3 ax;
960
961 const int StopERP = 7;
962 const int StopCFM = 8;
963
964 int i = 0;
965 int j = 0;
966 if (axis.X == 0)
967 {
968 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
969 // ODE should do this with axis relative to body 1 but seems to fail
970 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
971 d.JointSetAMotorAngle(Amotor, 0, 0);
972 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f);
973 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f);
974 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
975 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
976 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
977 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
978 d.JointSetAMotorParam(Amotor, (int)StopCFM, 0f);
979 d.JointSetAMotorParam(Amotor, (int)StopERP, 0.8f);
980 i++;
981 j = 256; // odeplugin.cs doesn't have all parameters so this moves to next axis set
982 }
983
984 if (axis.Y == 0)
985 {
986 ax = (new Vector3(0, 1, 0)) * curr;
987 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
988 d.JointSetAMotorAngle(Amotor, i, 0);
989 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
990 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
991 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
992 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
993 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
994 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
995 d.JointSetAMotorParam(Amotor, j + (int)StopCFM, 0f);
996 d.JointSetAMotorParam(Amotor, j + (int)StopERP, 0.8f);
997 i++;
998 j += 256;
999 }
1000
1001 if (axis.Z == 0)
1002 {
1003 ax = (new Vector3(0, 0, 1)) * curr;
1004 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1005 d.JointSetAMotorAngle(Amotor, i, 0);
1006 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1007 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1008 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1009 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1010 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1011 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1012 d.JointSetAMotorParam(Amotor, j + (int)StopCFM, 0f);
1013 d.JointSetAMotorParam(Amotor, j + (int)StopERP, 0.8f);
1014 }
1015 }
1016
1017 private bool setMesh(OdeScene parent_scene)
1018 {
1019 if (Body != IntPtr.Zero)
1020 {
1021 if (childPrim)
1022 {
1023 if (_parent != null)
1024 {
1025 OdePrim parent = (OdePrim)_parent;
1026 parent.ChildDelink(this,false);
1027 }
1028 }
1029 else
1030 {
1031 DestroyBody();
1032 }
1033 }
1034
1035 IMesh mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true);
1036 if (mesh == null)
1037 {
1038 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1039 return false;
1040 }
1041
1042 IntPtr vertices, indices;
1043 int vertexCount, indexCount;
1044 int vertexStride, triStride;
1045
1046 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1047 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1048
1049 if (vertexCount == 0 || indexCount == 0)
1050 {
1051 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. It can be a sculp with alpha channel in map. Replacing it by a small box.", Name, _position.X, _position.Y, _position.Z);
1052 _size.X = 0.01f;
1053 _size.Y = 0.01f;
1054 _size.Z = 0.01f;
1055 return false;
1056 }
1057
1058// primOOBoffset = mesh.GetCentroid();
1059// hasOOBoffsetFromMesh = true;
1060 hasOOBoffsetFromMesh = false;
1061
1062 _triMeshData = d.GeomTriMeshDataCreate();
1063
1064 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1065 d.GeomTriMeshDataPreprocess(_triMeshData);
1066
1067 mesh.releaseSourceMeshData();
1068
1069 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1070 try
1071 {
1072 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
1073 }
1074
1075 catch (Exception e)
1076 {
1077 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1078 return false;
1079 }
1080 return true;
1081 }
1082
1083 private void SetGeom(IntPtr geom)
1084 {
1085 prim_geom = geom;
1086 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1087 if (prim_geom != IntPtr.Zero)
1088 {
1089 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1090 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1091
1092 CalcPrimBodyData();
1093
1094 _parent_scene.geom_name_map[prim_geom] = Name;
1095 _parent_scene.actor_name_map[prim_geom] = this;
1096
1097/*
1098 if (childPrim)
1099 {
1100 if (_parent != null && _parent is OdePrim)
1101 {
1102 OdePrim parent = (OdePrim)_parent;
1103 //Console.WriteLine("SetGeom calls ChildSetGeom");
1104 parent.ChildSetGeom(this);
1105 }
1106 }
1107 */
1108 }
1109 else
1110 m_log.Warn("Setting bad Geom");
1111 }
1112
1113
1114 /// <summary>
1115 /// Create a geometry for the given mesh in the given target space.
1116 /// </summary>
1117 /// <param name="m_targetSpace"></param>
1118 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1119 private void CreateGeom()
1120 {
1121 if (_triMeshData != IntPtr.Zero)
1122 {
1123 d.GeomTriMeshDataDestroy(_triMeshData);
1124 _triMeshData = IntPtr.Zero;
1125 }
1126
1127 bool haveMesh = false;
1128 hasOOBoffsetFromMesh = false;
1129
1130 if (_parent_scene.needsMeshing(_pbs))
1131 {
1132 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1133 }
1134
1135 if(!haveMesh)
1136 {
1137 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1138 && _size.X == _size.Y && _size.Y == _size.Z)
1139 { // it's a sphere
1140 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1141 try
1142 {
1143 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
1144 }
1145 catch (Exception e)
1146 {
1147 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1148 return;
1149 }
1150 }
1151 else
1152 {// do it as a box
1153 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1154 try
1155 {
1156 //Console.WriteLine(" CreateGeom 4");
1157 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1158 }
1159 catch (Exception e)
1160 {
1161 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1162 return;
1163 }
1164 }
1165 }
1166 }
1167
1168 /// <summary>
1169 /// Set a new geometry for this prim.
1170 /// </summary>
1171 /// <param name="geom"></param>
1172 private void RemoveGeom()
1173 {
1174 if (prim_geom != IntPtr.Zero)
1175 {
1176 _parent_scene.geom_name_map.Remove(prim_geom);
1177 _parent_scene.actor_name_map.Remove(prim_geom);
1178 try
1179 {
1180 d.GeomDestroy(prim_geom);
1181 if (_triMeshData != IntPtr.Zero)
1182 {
1183 d.GeomTriMeshDataDestroy(_triMeshData);
1184 _triMeshData = IntPtr.Zero;
1185 }
1186 }
1187 // catch (System.AccessViolationException)
1188 catch (Exception e)
1189 {
1190 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name,e);
1191 }
1192
1193 prim_geom = IntPtr.Zero;
1194 }
1195 else
1196 {
1197 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1198 }
1199 Body = IntPtr.Zero;
1200 hasOOBoffsetFromMesh = false;
1201 CalcPrimBodyData();
1202 }
1203
1204 private void ChildSetGeom(OdePrim odePrim)
1205 {
1206 // well..
1207 DestroyBody();
1208 MakeBody();
1209 }
1210
1211 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1212 // should only be called for non physical prims unless they are becoming non physical
1213 private void SetInStaticSpace(OdePrim prim)
1214 {
1215 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1216 prim.m_targetSpace = targetSpace;
1217 d.GeomEnable(prim_geom);
1218 }
1219
1220 public void enableBodySoft()
1221 {
1222 if (!childPrim)
1223 {
1224 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
1225 {
1226 if (m_targetSpace != _parent_scene.ActiveSpace)
1227 {
1228 m_targetSpace = _parent_scene.ActiveSpace;
1229
1230 foreach (OdePrim prm in childrenPrim)
1231 {
1232 if (prm.prim_geom != IntPtr.Zero)
1233 {
1234 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1235 prm.m_targetSpace = m_targetSpace;
1236 }
1237 }
1238 d.SpaceAdd(m_targetSpace, prim_geom);
1239 }
1240 d.GeomEnable(prim_geom);
1241 foreach (OdePrim prm in childrenPrim)
1242 d.GeomEnable(prm.prim_geom);
1243
1244 d.BodyEnable(Body);
1245 }
1246 }
1247 resetCollisionAccounting(); // this sets m_disable to false
1248 }
1249
1250 private void disableBodySoft()
1251 {
1252 m_disabled = true;
1253 if (!childPrim)
1254 {
1255 if (m_isphysical && Body != IntPtr.Zero && prim_geom != IntPtr.Zero)
1256 {
1257 if (m_targetSpace == _parent_scene.ActiveSpace)
1258 {
1259 foreach (OdePrim prm in childrenPrim)
1260 {
1261 if (prm.m_targetSpace != IntPtr.Zero && prm.prim_geom != IntPtr.Zero)
1262 {
1263 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1264 prm.m_targetSpace = IntPtr.Zero;
1265 }
1266 }
1267 d.SpaceRemove(m_targetSpace, prim_geom);
1268 m_targetSpace = IntPtr.Zero;
1269 }
1270 d.GeomDisable(prim_geom);
1271 foreach (OdePrim prm in childrenPrim)
1272 d.GeomDisable(prm.prim_geom);
1273 d.BodyDisable(Body);
1274 }
1275 }
1276 }
1277
1278 private void MakeBody()
1279 {
1280 if (!m_isphysical) // only physical get bodies
1281 return;
1282
1283 if (childPrim) // child prims don't get bodies;
1284 return;
1285
1286 if (m_building)
1287 return;
1288
1289 if (prim_geom == IntPtr.Zero)
1290 {
1291 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1292 return;
1293 }
1294
1295 if (Body != IntPtr.Zero)
1296 {
1297 d.BodyDestroy(Body);
1298 Body = IntPtr.Zero;
1299 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1300 }
1301
1302
1303 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1304 {
1305 d.GeomSetBody(prim_geom, IntPtr.Zero);
1306 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1307 }
1308
1309 d.Matrix3 mymat = new d.Matrix3();
1310 d.Quaternion myrot = new d.Quaternion();
1311 d.Mass objdmass = new d.Mass { };
1312
1313 Body = d.BodyCreate(_parent_scene.world);
1314
1315 DMassDup(ref primdMass, out objdmass);
1316
1317 // rotate inertia
1318 myrot.X = _orientation.X;
1319 myrot.Y = _orientation.Y;
1320 myrot.Z = _orientation.Z;
1321 myrot.W = _orientation.W;
1322
1323 d.RfromQ(out mymat, ref myrot);
1324 d.MassRotate(ref objdmass, ref mymat);
1325
1326 // set the body rotation and position
1327 d.BodySetRotation(Body, ref mymat);
1328
1329 // recompute full object inertia if needed
1330 if (childrenPrim.Count > 0)
1331 {
1332 d.Matrix3 mat = new d.Matrix3();
1333 d.Quaternion quat = new d.Quaternion();
1334 d.Mass tmpdmass = new d.Mass { };
1335 Vector3 rcm;
1336
1337 rcm.X = _position.X + objdmass.c.X;
1338 rcm.Y = _position.Y + objdmass.c.Y;
1339 rcm.Z = _position.Z + objdmass.c.Z;
1340
1341 lock (childrenPrim)
1342 {
1343 foreach (OdePrim prm in childrenPrim)
1344 {
1345 if (prm.prim_geom == IntPtr.Zero)
1346 {
1347 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1348 continue;
1349 }
1350
1351
1352
1353 DMassCopy(ref prm.primdMass, ref tmpdmass);
1354
1355 // apply prim current rotation to inertia
1356 quat.X = prm._orientation.X;
1357 quat.Y = prm._orientation.Y;
1358 quat.Z = prm._orientation.Z;
1359 quat.W = prm._orientation.W;
1360 d.RfromQ(out mat, ref quat);
1361 d.MassRotate(ref tmpdmass, ref mat);
1362
1363 Vector3 ppos = prm._position;
1364 ppos.X += tmpdmass.c.X - rcm.X;
1365 ppos.Y += tmpdmass.c.Y - rcm.Y;
1366 ppos.Z += tmpdmass.c.Z - rcm.Z;
1367
1368 // refer inertia to root prim center of mass position
1369 d.MassTranslate(ref tmpdmass,
1370 ppos.X,
1371 ppos.Y,
1372 ppos.Z);
1373
1374 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1375 // fix prim colision cats
1376
1377 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1378 {
1379 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1380 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1381 }
1382
1383 d.GeomClearOffset(prm.prim_geom);
1384 d.GeomSetBody(prm.prim_geom, Body);
1385 prm.Body = Body;
1386 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1387 }
1388 }
1389 }
1390
1391 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1392 // associate root geom with body
1393 d.GeomSetBody(prim_geom, Body);
1394
1395 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1396 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1397
1398 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1399 myrot.W = -myrot.W;
1400 d.RfromQ(out mymat, ref myrot);
1401 d.MassRotate(ref objdmass, ref mymat);
1402 d.BodySetMass(Body, ref objdmass);
1403 _mass = objdmass.mass;
1404
1405 m_collisionCategories |= CollisionCategories.Body;
1406 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1407
1408 // disconnect from world gravity so we can apply buoyancy
1409 d.BodySetGravityMode(Body, false);
1410
1411 d.BodySetAutoDisableFlag(Body, true);
1412 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1413 // d.BodySetLinearDampingThreshold(Body, 0.01f);
1414 // d.BodySetAngularDampingThreshold(Body, 0.001f);
1415 d.BodySetDamping(Body, .001f, .0002f);
1416
1417 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1418 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1419
1420 m_interpenetrationcount = 0;
1421 m_collisionscore = 0;
1422
1423 m_disabled = false;
1424
1425 if (m_targetSpace != _parent_scene.ActiveSpace)
1426 {
1427 if (m_targetSpace != IntPtr.Zero)
1428 {
1429 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1430 if (d.SpaceQuery(m_targetSpace, prim_geom))
1431 d.SpaceRemove(m_targetSpace, prim_geom);
1432 }
1433
1434 m_targetSpace = _parent_scene.ActiveSpace;
1435 d.SpaceAdd(m_targetSpace, prim_geom);
1436 }
1437
1438 lock (childrenPrim)
1439 {
1440 foreach (OdePrim prm in childrenPrim)
1441 {
1442 if (prm.prim_geom == IntPtr.Zero)
1443 continue;
1444
1445 Vector3 ppos = prm._position;
1446 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1447
1448 prm.m_collisionCategories |= CollisionCategories.Body;
1449 prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1450 d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories);
1451 d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags);
1452
1453 if (prm.m_targetSpace != _parent_scene.ActiveSpace)
1454 {
1455 if (prm.m_targetSpace != IntPtr.Zero)
1456 {
1457 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1458 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1459 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1460 }
1461 prm.m_targetSpace = _parent_scene.ActiveSpace;
1462 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1463 }
1464 d.GeomEnable(prm.prim_geom);
1465 prm.m_disabled = false;
1466 prm.m_interpenetrationcount = 0;
1467 prm.m_collisionscore = 0;
1468 _parent_scene.addActivePrim(prm);
1469 }
1470 }
1471
1472 // The body doesn't already have a finite rotation mode set here
1473 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
1474 {
1475 createAMotor(m_angularlock);
1476 }
1477
1478 d.GeomEnable(prim_geom);
1479 m_disabled = false;
1480 _parent_scene.addActivePrim(this);
1481 }
1482
1483 private void DestroyBody()
1484 {
1485 if (Body != IntPtr.Zero)
1486 {
1487 _parent_scene.remActivePrim(this);
1488 m_collisionCategories &= ~CollisionCategories.Body;
1489 m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1490 if (prim_geom != IntPtr.Zero)
1491 {
1492 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1493 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1494 UpdateDataFromGeom();
1495 d.GeomSetBody(prim_geom, IntPtr.Zero);
1496 SetInStaticSpace(this);
1497 }
1498
1499 if (!childPrim)
1500 {
1501 lock (childrenPrim)
1502 {
1503 foreach (OdePrim prm in childrenPrim)
1504 {
1505 _parent_scene.remActivePrim(prm);
1506 prm.m_collisionCategories &= ~CollisionCategories.Body;
1507 prm.m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land);
1508 if (prm.prim_geom != IntPtr.Zero)
1509 {
1510 d.GeomSetCategoryBits(prm.prim_geom, (int)m_collisionCategories);
1511 d.GeomSetCollideBits(prm.prim_geom, (int)m_collisionFlags);
1512 prm.UpdateDataFromGeom();
1513 SetInStaticSpace(prm);
1514 }
1515 prm.Body = IntPtr.Zero;
1516 prm._mass = prm.primMass;
1517 prm.m_collisionscore = 0;
1518 }
1519 }
1520 d.BodyDestroy(Body);
1521 }
1522 Body = IntPtr.Zero;
1523 }
1524 _mass = primMass;
1525 m_disabled = true;
1526 m_collisionscore = 0;
1527 }
1528
1529 #region Mass Calculation
1530
1531 private float CalculatePrimVolume()
1532 {
1533 float volume = _size.X * _size.Y * _size.Z; // default
1534 float tmp;
1535
1536 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
1537 float hollowVolume = hollowAmount * hollowAmount;
1538
1539 switch (_pbs.ProfileShape)
1540 {
1541 case ProfileShape.Square:
1542 // default box
1543
1544 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1545 {
1546 if (hollowAmount > 0.0)
1547 {
1548 switch (_pbs.HollowShape)
1549 {
1550 case HollowShape.Square:
1551 case HollowShape.Same:
1552 break;
1553
1554 case HollowShape.Circle:
1555
1556 hollowVolume *= 0.78539816339f;
1557 break;
1558
1559 case HollowShape.Triangle:
1560
1561 hollowVolume *= (0.5f * .5f);
1562 break;
1563
1564 default:
1565 hollowVolume = 0;
1566 break;
1567 }
1568 volume *= (1.0f - hollowVolume);
1569 }
1570 }
1571
1572 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1573 {
1574 //a tube
1575
1576 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
1577 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
1578 volume -= volume * tmp * tmp;
1579
1580 if (hollowAmount > 0.0)
1581 {
1582 hollowVolume *= hollowAmount;
1583
1584 switch (_pbs.HollowShape)
1585 {
1586 case HollowShape.Square:
1587 case HollowShape.Same:
1588 break;
1589
1590 case HollowShape.Circle:
1591 hollowVolume *= 0.78539816339f;
1592 break;
1593
1594 case HollowShape.Triangle:
1595 hollowVolume *= 0.5f * 0.5f;
1596 break;
1597 default:
1598 hollowVolume = 0;
1599 break;
1600 }
1601 volume *= (1.0f - hollowVolume);
1602 }
1603 }
1604
1605 break;
1606
1607 case ProfileShape.Circle:
1608
1609 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1610 {
1611 volume *= 0.78539816339f; // elipse base
1612
1613 if (hollowAmount > 0.0)
1614 {
1615 switch (_pbs.HollowShape)
1616 {
1617 case HollowShape.Same:
1618 case HollowShape.Circle:
1619 break;
1620
1621 case HollowShape.Square:
1622 hollowVolume *= 0.5f * 2.5984480504799f;
1623 break;
1624
1625 case HollowShape.Triangle:
1626 hollowVolume *= .5f * 1.27323954473516f;
1627 break;
1628
1629 default:
1630 hollowVolume = 0;
1631 break;
1632 }
1633 volume *= (1.0f - hollowVolume);
1634 }
1635 }
1636
1637 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1638 {
1639 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
1640 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1641 volume *= (1.0f - tmp * tmp);
1642
1643 if (hollowAmount > 0.0)
1644 {
1645
1646 // calculate the hollow volume by it's shape compared to the prim shape
1647 hollowVolume *= hollowAmount;
1648
1649 switch (_pbs.HollowShape)
1650 {
1651 case HollowShape.Same:
1652 case HollowShape.Circle:
1653 break;
1654
1655 case HollowShape.Square:
1656 hollowVolume *= 0.5f * 2.5984480504799f;
1657 break;
1658
1659 case HollowShape.Triangle:
1660 hollowVolume *= .5f * 1.27323954473516f;
1661 break;
1662
1663 default:
1664 hollowVolume = 0;
1665 break;
1666 }
1667 volume *= (1.0f - hollowVolume);
1668 }
1669 }
1670 break;
1671
1672 case ProfileShape.HalfCircle:
1673 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1674 {
1675 volume *= 0.52359877559829887307710723054658f;
1676 }
1677 break;
1678
1679 case ProfileShape.EquilateralTriangle:
1680
1681 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1682 {
1683 volume *= 0.32475953f;
1684
1685 if (hollowAmount > 0.0)
1686 {
1687
1688 // calculate the hollow volume by it's shape compared to the prim shape
1689 switch (_pbs.HollowShape)
1690 {
1691 case HollowShape.Same:
1692 case HollowShape.Triangle:
1693 hollowVolume *= .25f;
1694 break;
1695
1696 case HollowShape.Square:
1697 hollowVolume *= 0.499849f * 3.07920140172638f;
1698 break;
1699
1700 case HollowShape.Circle:
1701 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1702 // Cyllinder hollow volume calculation
1703
1704 hollowVolume *= 0.1963495f * 3.07920140172638f;
1705 break;
1706
1707 default:
1708 hollowVolume = 0;
1709 break;
1710 }
1711 volume *= (1.0f - hollowVolume);
1712 }
1713 }
1714 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1715 {
1716 volume *= 0.32475953f;
1717 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1718 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1719 volume *= (1.0f - tmp * tmp);
1720
1721 if (hollowAmount > 0.0)
1722 {
1723
1724 hollowVolume *= hollowAmount;
1725
1726 switch (_pbs.HollowShape)
1727 {
1728 case HollowShape.Same:
1729 case HollowShape.Triangle:
1730 hollowVolume *= .25f;
1731 break;
1732
1733 case HollowShape.Square:
1734 hollowVolume *= 0.499849f * 3.07920140172638f;
1735 break;
1736
1737 case HollowShape.Circle:
1738
1739 hollowVolume *= 0.1963495f * 3.07920140172638f;
1740 break;
1741
1742 default:
1743 hollowVolume = 0;
1744 break;
1745 }
1746 volume *= (1.0f - hollowVolume);
1747 }
1748 }
1749 break;
1750
1751 default:
1752 break;
1753 }
1754
1755 float taperX1;
1756 float taperY1;
1757 float taperX;
1758 float taperY;
1759 float pathBegin;
1760 float pathEnd;
1761 float profileBegin;
1762 float profileEnd;
1763
1764 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1765 {
1766 taperX1 = _pbs.PathScaleX * 0.01f;
1767 if (taperX1 > 1.0f)
1768 taperX1 = 2.0f - taperX1;
1769 taperX = 1.0f - taperX1;
1770
1771 taperY1 = _pbs.PathScaleY * 0.01f;
1772 if (taperY1 > 1.0f)
1773 taperY1 = 2.0f - taperY1;
1774 taperY = 1.0f - taperY1;
1775 }
1776 else
1777 {
1778 taperX = _pbs.PathTaperX * 0.01f;
1779 if (taperX < 0.0f)
1780 taperX = -taperX;
1781 taperX1 = 1.0f - taperX;
1782
1783 taperY = _pbs.PathTaperY * 0.01f;
1784 if (taperY < 0.0f)
1785 taperY = -taperY;
1786 taperY1 = 1.0f - taperY;
1787 }
1788
1789 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1790
1791 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1792 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1793 volume *= (pathEnd - pathBegin);
1794
1795 // this is crude aproximation
1796 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1797 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1798 volume *= (profileEnd - profileBegin);
1799
1800 return volume;
1801 }
1802
1803
1804 private void CalcPrimBodyData()
1805 {
1806 float volume;
1807
1808 if (prim_geom == IntPtr.Zero)
1809 {
1810 // Ubit let's have a initial basic OOB
1811 primOOBsize.X = _size.X;
1812 primOOBsize.Y = _size.Y;
1813 primOOBsize.Z = _size.Z;
1814 primOOBoffset = Vector3.Zero;
1815 }
1816 else
1817 {
1818 d.AABB AABB;
1819 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
1820
1821 primOOBsize.X = (AABB.MaxX - AABB.MinX);
1822 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
1823 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
1824 if (!hasOOBoffsetFromMesh)
1825 {
1826 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
1827 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
1828 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
1829 }
1830 }
1831
1832 // also its own inertia and mass
1833 // keep using basic shape mass for now
1834 volume = CalculatePrimVolume();
1835
1836 primMass = m_density * volume;
1837
1838 if (primMass <= 0)
1839 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
1840 if (primMass > _parent_scene.maximumMassObject)
1841 primMass = _parent_scene.maximumMassObject;
1842
1843 _mass = primMass; // just in case
1844
1845 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
1846
1847 d.MassTranslate(ref primdMass,
1848 primOOBoffset.X,
1849 primOOBoffset.Y,
1850 primOOBoffset.Z);
1851
1852 primOOBsize *= 0.5f; // let obb size be a corner coords
1853 primOOBradiusSQ = primOOBsize.LengthSquared();
1854 }
1855
1856
1857 #endregion
1858
1859
1860 /// <summary>
1861 /// Add a child prim to this parent prim.
1862 /// </summary>
1863 /// <param name="prim">Child prim</param>
1864 // I'm the parent
1865 // prim is the child
1866 public void ParentPrim(OdePrim prim)
1867 {
1868 //Console.WriteLine("ParentPrim " + m_primName);
1869 if (this.m_localID != prim.m_localID)
1870 {
1871 DestroyBody(); // for now we need to rebuil entire object on link change
1872
1873 lock (childrenPrim)
1874 {
1875 // adopt the prim
1876 if (!childrenPrim.Contains(prim))
1877 childrenPrim.Add(prim);
1878
1879 // see if this prim has kids and adopt them also
1880 // should not happen for now
1881 foreach (OdePrim prm in prim.childrenPrim)
1882 {
1883 if (!childrenPrim.Contains(prm))
1884 {
1885 if (prm.Body != IntPtr.Zero)
1886 {
1887 if (prm.prim_geom != IntPtr.Zero)
1888 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1889 if(prm.Body != prim.Body)
1890 prm.DestroyBody(); // don't loose bodies around
1891 prm.Body = IntPtr.Zero;
1892 }
1893
1894 childrenPrim.Add(prm);
1895 prm._parent = this;
1896 }
1897 }
1898 }
1899 //Remove old children from the prim
1900 prim.childrenPrim.Clear();
1901
1902 if (prim.Body != IntPtr.Zero)
1903 {
1904 if (prim.prim_geom != IntPtr.Zero)
1905 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
1906 prim.DestroyBody(); // don't loose bodies around
1907 prim.Body = IntPtr.Zero;
1908 }
1909
1910 prim.childPrim = true;
1911 prim._parent = this;
1912
1913 MakeBody(); // full nasty reconstruction
1914 }
1915 }
1916
1917 private void UpdateChildsfromgeom()
1918 {
1919 if (childrenPrim.Count > 0)
1920 {
1921 foreach (OdePrim prm in childrenPrim)
1922 prm.UpdateDataFromGeom();
1923 }
1924 }
1925
1926 private void UpdateDataFromGeom()
1927 {
1928 if (prim_geom != IntPtr.Zero)
1929 {
1930 d.Vector3 lpos;
1931 d.GeomCopyPosition(prim_geom, out lpos);
1932 _position.X = lpos.X;
1933 _position.Y = lpos.Y;
1934 _position.Z = lpos.Z;
1935 d.Quaternion qtmp = new d.Quaternion { };
1936 d.GeomCopyQuaternion(prim_geom, out qtmp);
1937 _orientation.W = qtmp.W;
1938 _orientation.X = qtmp.X;
1939 _orientation.Y = qtmp.Y;
1940 _orientation.Z = qtmp.Z;
1941 }
1942 }
1943
1944 private void ChildDelink(OdePrim odePrim, bool remakebodies)
1945 {
1946 // Okay, we have a delinked child.. destroy all body and remake
1947 if (odePrim != this && !childrenPrim.Contains(odePrim))
1948 return;
1949
1950 DestroyBody();
1951
1952 if (odePrim == this) // delinking the root prim
1953 {
1954 OdePrim newroot = null;
1955 lock (childrenPrim)
1956 {
1957 if (childrenPrim.Count > 0)
1958 {
1959 newroot = childrenPrim[0];
1960 childrenPrim.RemoveAt(0);
1961 foreach (OdePrim prm in childrenPrim)
1962 {
1963 newroot.childrenPrim.Add(prm);
1964 }
1965 childrenPrim.Clear();
1966 }
1967 if (newroot != null)
1968 {
1969 newroot.childPrim = false;
1970 newroot._parent = null;
1971 if (remakebodies)
1972 newroot.MakeBody();
1973 }
1974 }
1975 }
1976
1977 else
1978 {
1979 lock (childrenPrim)
1980 {
1981 childrenPrim.Remove(odePrim);
1982 odePrim.childPrim = false;
1983 odePrim._parent = null;
1984 // odePrim.UpdateDataFromGeom();
1985 if (remakebodies)
1986 odePrim.MakeBody();
1987 }
1988 }
1989 if (remakebodies)
1990 MakeBody();
1991 }
1992
1993 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
1994 {
1995 // Okay, we have a delinked child.. destroy all body and remake
1996 if (odePrim != this && !childrenPrim.Contains(odePrim))
1997 return;
1998
1999 DestroyBody();
2000
2001 if (odePrim == this)
2002 {
2003 OdePrim newroot = null;
2004 lock (childrenPrim)
2005 {
2006 if (childrenPrim.Count > 0)
2007 {
2008 newroot = childrenPrim[0];
2009 childrenPrim.RemoveAt(0);
2010 foreach (OdePrim prm in childrenPrim)
2011 {
2012 newroot.childrenPrim.Add(prm);
2013 }
2014 childrenPrim.Clear();
2015 }
2016 if (newroot != null)
2017 {
2018 newroot.childPrim = false;
2019 newroot._parent = null;
2020 newroot.MakeBody();
2021 }
2022 }
2023 if (reMakeBody)
2024 MakeBody();
2025 return;
2026 }
2027 else
2028 {
2029 lock (childrenPrim)
2030 {
2031 childrenPrim.Remove(odePrim);
2032 odePrim.childPrim = false;
2033 odePrim._parent = null;
2034 if (reMakeBody)
2035 odePrim.MakeBody();
2036 }
2037 }
2038 MakeBody();
2039 }
2040
2041 #region changes
2042
2043 private void changeadd()
2044 {
2045 CreateGeom();
2046
2047 if (prim_geom != IntPtr.Zero)
2048 {
2049 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2050 d.Quaternion myrot = new d.Quaternion();
2051 myrot.X = _orientation.X;
2052 myrot.Y = _orientation.Y;
2053 myrot.Z = _orientation.Z;
2054 myrot.W = _orientation.W;
2055 d.GeomSetQuaternion(prim_geom, ref myrot);
2056 // _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
2057 if (!m_isphysical)
2058 SetInStaticSpace(this);
2059 }
2060
2061// m_building = false; // REMOVE THIS LATER
2062
2063
2064 if (m_isphysical && Body == IntPtr.Zero)
2065 {
2066/*
2067 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2068 {
2069 changeShape(_pbs);
2070 }
2071 else
2072 {
2073 */
2074 MakeBody();
2075// }
2076 }
2077 }
2078
2079 private void changeAngularLock(Vector3 newLock)
2080 {
2081 // do we have a Physical object?
2082 if (Body != IntPtr.Zero)
2083 {
2084 //Check that we have a Parent
2085 //If we have a parent then we're not authorative here
2086 if (_parent == null)
2087 {
2088 if (!newLock.ApproxEquals(Vector3.One, 0f))
2089 {
2090 createAMotor(newLock);
2091 }
2092 else
2093 {
2094 if (Amotor != IntPtr.Zero)
2095 {
2096 d.JointDestroy(Amotor);
2097 Amotor = IntPtr.Zero;
2098 }
2099 }
2100 }
2101 }
2102 // Store this for later in case we get turned into a separate body
2103 m_angularlock = newLock;
2104 }
2105
2106 private void changeLink(OdePrim NewParent)
2107 {
2108 if (_parent == null && NewParent != null)
2109 {
2110 NewParent.ParentPrim(this);
2111 }
2112 else if (_parent != null)
2113 {
2114 if (_parent is OdePrim)
2115 {
2116 if (NewParent != _parent)
2117 {
2118 (_parent as OdePrim).ChildDelink(this,false); // for now...
2119 childPrim = false;
2120
2121 if (NewParent != null)
2122 {
2123 NewParent.ParentPrim(this);
2124 }
2125 }
2126 }
2127 }
2128 _parent = NewParent;
2129 }
2130
2131
2132 private void Stop()
2133 {
2134 if(!childPrim)
2135 {
2136 m_force = Vector3.Zero;
2137 m_forceacc = Vector3.Zero;
2138 m_angularForceacc = Vector3.Zero;
2139 _torque = Vector3.Zero;
2140 _velocity = Vector3.Zero;
2141 _acceleration = Vector3.Zero;
2142 m_rotationalVelocity = Vector3.Zero;
2143 _target_velocity = Vector3.Zero;
2144 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2145 m_vehicle.Stop();
2146 }
2147
2148 if (Body != IntPtr.Zero)
2149 {
2150 d.BodySetForce(Body, 0f, 0f, 0f);
2151 d.BodySetTorque(Body, 0f, 0f, 0f);
2152 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2153 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2154
2155 }
2156 }
2157
2158 private void changeSelectedStatus(bool newval)
2159 {
2160 m_isSelected = newval;
2161 Stop();
2162
2163 if (newval)
2164 {
2165 m_collisionCategories = CollisionCategories.Selected;
2166 m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space);
2167
2168 if (prim_geom != IntPtr.Zero)
2169 {
2170 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2171 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2172 }
2173
2174 disableBodySoft();
2175 }
2176 else
2177 {
2178 m_collisionCategories = CollisionCategories.Geom;
2179
2180 if (m_isphysical)
2181 m_collisionCategories |= CollisionCategories.Body;
2182
2183 m_collisionFlags = m_default_collisionFlags;
2184
2185 if (m_collidesLand)
2186 m_collisionFlags |= CollisionCategories.Land;
2187 if (m_collidesWater)
2188 m_collisionFlags |= CollisionCategories.Water;
2189
2190 if (prim_geom != IntPtr.Zero)
2191 {
2192 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
2193 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2194 }
2195
2196 enableBodySoft();
2197 }
2198
2199 resetCollisionAccounting();
2200 }
2201
2202 private void changePosition(Vector3 newPos)
2203 {
2204 if (m_isphysical)
2205 {
2206 if (childPrim) // inertia is messed, must rebuild
2207 {
2208 if (m_building)
2209 {
2210 _position = newPos;
2211 }
2212 }
2213 else
2214 {
2215 if (_position != newPos)
2216 {
2217 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2218 _position = newPos;
2219 }
2220 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2221 d.BodyEnable(Body);
2222 }
2223 }
2224 else
2225 {
2226 if (prim_geom != IntPtr.Zero)
2227 {
2228 if (newPos != _position)
2229 {
2230 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2231 _position = newPos;
2232
2233 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2234 }
2235 }
2236 }
2237 givefakepos--;
2238 if (givefakepos < 0)
2239 givefakepos = 0;
2240// changeSelectedStatus();
2241 resetCollisionAccounting();
2242 }
2243
2244 private void changeOrientation(Quaternion newOri)
2245 {
2246 if (m_isphysical)
2247 {
2248 if (childPrim) // inertia is messed, must rebuild
2249 {
2250 if (m_building)
2251 {
2252 _orientation = newOri;
2253 }
2254 }
2255 else
2256 {
2257 if (newOri != _orientation)
2258 {
2259 d.Quaternion myrot = new d.Quaternion();
2260 myrot.X = newOri.X;
2261 myrot.Y = newOri.Y;
2262 myrot.Z = newOri.Z;
2263 myrot.W = newOri.W;
2264 d.GeomSetQuaternion(prim_geom, ref myrot);
2265 _orientation = newOri;
2266 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2267 createAMotor(m_angularlock);
2268 }
2269 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2270 d.BodyEnable(Body);
2271 }
2272 }
2273 else
2274 {
2275 if (prim_geom != IntPtr.Zero)
2276 {
2277 if (newOri != _orientation)
2278 {
2279 d.Quaternion myrot = new d.Quaternion();
2280 myrot.X = newOri.X;
2281 myrot.Y = newOri.Y;
2282 myrot.Z = newOri.Z;
2283 myrot.W = newOri.W;
2284 d.GeomSetQuaternion(prim_geom, ref myrot);
2285 _orientation = newOri;
2286 }
2287 }
2288 }
2289 givefakeori--;
2290 if (givefakeori < 0)
2291 givefakeori = 0;
2292 resetCollisionAccounting();
2293 }
2294
2295 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2296 {
2297 if (m_isphysical)
2298 {
2299 if (childPrim && m_building) // inertia is messed, must rebuild
2300 {
2301 _position = newPos;
2302 _orientation = newOri;
2303 }
2304 else
2305 {
2306 if (newOri != _orientation)
2307 {
2308 d.Quaternion myrot = new d.Quaternion();
2309 myrot.X = newOri.X;
2310 myrot.Y = newOri.Y;
2311 myrot.Z = newOri.Z;
2312 myrot.W = newOri.W;
2313 d.GeomSetQuaternion(prim_geom, ref myrot);
2314 _orientation = newOri;
2315 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
2316 createAMotor(m_angularlock);
2317 }
2318 if (_position != newPos)
2319 {
2320 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2321 _position = newPos;
2322 }
2323 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2324 d.BodyEnable(Body);
2325 }
2326 }
2327 else
2328 {
2329 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2330 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2331
2332 if (prim_geom != IntPtr.Zero)
2333 {
2334 if (newOri != _orientation)
2335 {
2336 d.Quaternion myrot = new d.Quaternion();
2337 myrot.X = newOri.X;
2338 myrot.Y = newOri.Y;
2339 myrot.Z = newOri.Z;
2340 myrot.W = newOri.W;
2341 d.GeomSetQuaternion(prim_geom, ref myrot);
2342 _orientation = newOri;
2343 }
2344
2345 if (newPos != _position)
2346 {
2347 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2348 _position = newPos;
2349
2350 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2351 }
2352 }
2353 }
2354 givefakepos--;
2355 if (givefakepos < 0)
2356 givefakepos = 0;
2357 givefakeori--;
2358 if (givefakeori < 0)
2359 givefakeori = 0;
2360
2361 resetCollisionAccounting();
2362 }
2363
2364
2365 private void changeDisable(bool disable)
2366 {
2367 if (disable)
2368 {
2369 if (!m_disabled)
2370 disableBodySoft();
2371 }
2372 else
2373 {
2374 if (m_disabled)
2375 enableBodySoft();
2376 }
2377 }
2378
2379 private void changePhysicsStatus(bool NewStatus)
2380 {
2381 m_isphysical = NewStatus;
2382
2383 if (!childPrim)
2384 {
2385 if (NewStatus)
2386 {
2387 if (Body == IntPtr.Zero)
2388 {
2389/*
2390 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2391 {
2392 changeShape(_pbs);
2393 }
2394 else
2395 */
2396 {
2397 MakeBody();
2398 }
2399 }
2400 }
2401 else
2402 {
2403 if (Body != IntPtr.Zero)
2404 {
2405 // UpdateChildsfromgeom();
2406/* if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
2407 {
2408 changeShape(_pbs);
2409 }
2410 else
2411 */
2412 DestroyBody();
2413 }
2414 }
2415 }
2416
2417 resetCollisionAccounting();
2418 }
2419
2420 private void changeprimsizeshape()
2421 {
2422 OdePrim parent = (OdePrim)_parent;
2423
2424 bool chp = childPrim;
2425
2426 if (chp)
2427 {
2428 if (parent != null)
2429 {
2430 parent.DestroyBody();
2431 }
2432 }
2433 else
2434 {
2435 DestroyBody();
2436 }
2437
2438 RemoveGeom();
2439
2440 // we don't need to do space calculation because the client sends a position update also.
2441 if (_size.X <= 0)
2442 _size.X = 0.01f;
2443 if (_size.Y <= 0)
2444 _size.Y = 0.01f;
2445 if (_size.Z <= 0)
2446 _size.Z = 0.01f;
2447 // Construction of new prim
2448
2449 CreateGeom();
2450
2451 if (prim_geom != IntPtr.Zero)
2452 {
2453 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2454 d.Quaternion myrot = new d.Quaternion();
2455 myrot.X = _orientation.X;
2456 myrot.Y = _orientation.Y;
2457 myrot.Z = _orientation.Z;
2458 myrot.W = _orientation.W;
2459 d.GeomSetQuaternion(prim_geom, ref myrot);
2460 }
2461
2462 if (chp)
2463 {
2464 if (parent != null)
2465 {
2466 parent.MakeBody();
2467 }
2468 }
2469 else
2470 MakeBody();
2471
2472 resetCollisionAccounting();
2473 }
2474
2475 private void changeSize(Vector3 newSize)
2476 {
2477 _size = newSize;
2478 changeprimsizeshape();
2479 }
2480
2481 private void changeShape(PrimitiveBaseShape newShape)
2482 {
2483 _pbs = newShape;
2484 changeprimsizeshape();
2485 }
2486
2487 private void changeFloatOnWater(bool newval)
2488 {
2489 m_collidesWater = newval;
2490
2491 if (prim_geom != IntPtr.Zero)
2492 {
2493 if (m_collidesWater)
2494 {
2495 m_collisionFlags |= CollisionCategories.Water;
2496 }
2497 else
2498 {
2499 m_collisionFlags &= ~CollisionCategories.Water;
2500 }
2501 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
2502 }
2503 }
2504
2505 private void changeSetTorque(Vector3 newtorque)
2506 {
2507 if (!m_isSelected)
2508 {
2509 if (m_isphysical && Body != IntPtr.Zero)
2510 {
2511 if (m_disabled)
2512 enableBodySoft();
2513 else if (!d.BodyIsEnabled(Body))
2514 d.BodyEnable(Body);
2515
2516 }
2517 _torque = newtorque;
2518 }
2519 }
2520
2521 private void changeForce(Vector3 force)
2522 {
2523 m_force = force;
2524 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2525 d.BodyEnable(Body);
2526 }
2527
2528 private void changeAddForce(Vector3 force)
2529 {
2530 m_forceacc += force;
2531 if (!m_isSelected)
2532 {
2533 lock (this)
2534 {
2535 //m_log.Info("[PHYSICS]: dequeing forcelist");
2536 if (m_isphysical && Body != IntPtr.Zero)
2537 {
2538 if (m_disabled)
2539 enableBodySoft();
2540 else if (!d.BodyIsEnabled(Body))
2541 d.BodyEnable(Body);
2542 }
2543 }
2544
2545 m_collisionscore = 0;
2546 m_interpenetrationcount = 0;
2547 }
2548 }
2549
2550 private void changeAddAngularForce(Vector3 aforce)
2551 {
2552 m_angularForceacc += aforce;
2553 if (!m_isSelected)
2554 {
2555 lock (this)
2556 {
2557 if (m_isphysical && Body != IntPtr.Zero)
2558 {
2559 if (m_disabled)
2560 enableBodySoft();
2561 else if (!d.BodyIsEnabled(Body))
2562 d.BodyEnable(Body);
2563 }
2564 }
2565 m_collisionscore = 0;
2566 m_interpenetrationcount = 0;
2567 }
2568 }
2569
2570 private void changevelocity(Vector3 newVel)
2571 {
2572 if (!m_isSelected)
2573 {
2574 if (Body != IntPtr.Zero)
2575 {
2576 if (m_disabled)
2577 enableBodySoft();
2578 else if (!d.BodyIsEnabled(Body))
2579 d.BodyEnable(Body);
2580
2581 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
2582 }
2583 //resetCollisionAccounting();
2584 }
2585 _velocity = newVel;
2586 }
2587
2588 private void changeVolumedetetion(bool newVolDtc)
2589 {
2590 m_isVolumeDetect = newVolDtc;
2591 }
2592
2593 protected void changeBuilding(bool newbuilding)
2594 {
2595 if ((bool)newbuilding)
2596 {
2597 m_building = true;
2598 DestroyBody();
2599 }
2600 else
2601 {
2602 m_building = false;
2603 if (!childPrim)
2604 MakeBody();
2605 }
2606 if (!childPrim && childrenPrim.Count > 0)
2607 {
2608 foreach (OdePrim prm in childrenPrim)
2609 prm.changeBuilding(m_building); // call directly
2610 }
2611 }
2612
2613 #endregion
2614
2615 public void Move()
2616 {
2617 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
2618 !m_disabled && !m_isSelected && d.BodyIsEnabled(Body) && !m_building) // KF: Only move root prims.
2619 {
2620// if (!d.BodyIsEnabled(Body)) d.BodyEnable(Body); // KF add 161009
2621
2622 float timestep = _parent_scene.ODE_STEPSIZE;
2623
2624 float fx = 0;
2625 float fy = 0;
2626 float fz = 0;
2627
2628 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2629 {
2630 // 'VEHICLES' are dealt with in ODEDynamics.cs
2631 m_vehicle.Step();
2632 }
2633 else
2634 {
2635 float m_mass = _mass;
2636
2637 // fz = 0f;
2638 //m_log.Info(m_collisionFlags.ToString());
2639 if (m_usePID)
2640 {
2641
2642 // If the PID Controller isn't active then we set our force
2643 // calculating base velocity to the current position
2644
2645 if ((m_PIDTau < 1) && (m_PIDTau != 0))
2646 {
2647 //PID_G = PID_G / m_PIDTau;
2648 m_PIDTau = 1;
2649 }
2650
2651 if ((PID_G - m_PIDTau) <= 0)
2652 {
2653 PID_G = m_PIDTau + 1;
2654 }
2655
2656 d.Vector3 vel = d.BodyGetLinearVel(Body);
2657 d.Vector3 pos = d.BodyGetPosition(Body);
2658 _target_velocity =
2659 new Vector3(
2660 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
2661 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
2662 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
2663 );
2664
2665 // if velocity is zero, use position control; otherwise, velocity control
2666
2667 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
2668 {
2669 // keep track of where we stopped. No more slippin' & slidin'
2670
2671 // We only want to deactivate the PID Controller if we think we want to have our surrogate
2672 // react to the physics scene by moving it's position.
2673 // Avatar to Avatar collisions
2674 // Prim to avatar collisions
2675
2676 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
2677 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
2678 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
2679 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
2680 d.BodySetLinearVel(Body, 0, 0, 0);
2681 d.BodyAddForce(Body, 0, 0, fz);
2682 return;
2683 }
2684 else
2685 {
2686 _zeroFlag = false;
2687
2688 // We're flying and colliding with something
2689 fx = ((_target_velocity.X) - vel.X) * (PID_D);
2690 fy = ((_target_velocity.Y) - vel.Y) * (PID_D);
2691
2692 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
2693
2694 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
2695 }
2696 } // end if (m_usePID)
2697
2698 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
2699 else if (m_useHoverPID)
2700 {
2701 //Console.WriteLine("Hover " + Name);
2702
2703 // If we're using the PID controller, then we have no gravity
2704
2705 // no lock; for now it's only called from within Simulate()
2706
2707 // If the PID Controller isn't active then we set our force
2708 // calculating base velocity to the current position
2709
2710 if ((m_PIDTau < 1))
2711 {
2712 PID_G = PID_G / m_PIDTau;
2713 }
2714
2715 if ((PID_G - m_PIDTau) <= 0)
2716 {
2717 PID_G = m_PIDTau + 1;
2718 }
2719
2720 // Where are we, and where are we headed?
2721 d.Vector3 pos = d.BodyGetPosition(Body);
2722 d.Vector3 vel = d.BodyGetLinearVel(Body);
2723
2724 // Non-Vehicles have a limited set of Hover options.
2725 // determine what our target height really is based on HoverType
2726 switch (m_PIDHoverType)
2727 {
2728 case PIDHoverType.Ground:
2729 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
2730 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
2731 break;
2732 case PIDHoverType.GroundAndWater:
2733 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
2734 m_waterHeight = _parent_scene.GetWaterLevel();
2735 if (m_groundHeight > m_waterHeight)
2736 {
2737 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
2738 }
2739 else
2740 {
2741 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
2742 }
2743 break;
2744
2745 } // end switch (m_PIDHoverType)
2746
2747
2748 _target_velocity =
2749 new Vector3(0.0f, 0.0f,
2750 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
2751 );
2752
2753 // if velocity is zero, use position control; otherwise, velocity control
2754
2755 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f))
2756 {
2757 // keep track of where we stopped. No more slippin' & slidin'
2758
2759 // We only want to deactivate the PID Controller if we think we want to have our surrogate
2760 // react to the physics scene by moving it's position.
2761 // Avatar to Avatar collisions
2762 // Prim to avatar collisions
2763
2764 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
2765 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
2766 // ? d.BodyAddForce(Body, 0, 0, fz);
2767 return;
2768 }
2769 else
2770 {
2771 _zeroFlag = false;
2772
2773 // We're flying and colliding with something
2774 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
2775 }
2776 }
2777 else
2778 {
2779 float b = (1.0f - m_buoyancy);
2780 fx = _parent_scene.gravityx * b;
2781 fy = _parent_scene.gravityy * b;
2782 fz = _parent_scene.gravityz * b;
2783 }
2784
2785 fx *= m_mass;
2786 fy *= m_mass;
2787 fz *= m_mass;
2788
2789 // constant force
2790 fx += m_force.X;
2791 fy += m_force.Y;
2792 fz += m_force.Z;
2793
2794 fx += m_forceacc.X;
2795 fy += m_forceacc.Y;
2796 fz += m_forceacc.Z;
2797
2798 m_forceacc = Vector3.Zero;
2799
2800 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
2801 if (fx != 0 || fy != 0 || fz != 0)
2802 {
2803 d.BodyAddForce(Body, fx, fy, fz);
2804 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
2805 }
2806
2807 Vector3 trq;
2808
2809 trq = _torque;
2810 trq += m_angularForceacc;
2811 m_angularForceacc = Vector3.Zero;
2812 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
2813 {
2814 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
2815 }
2816
2817 }
2818 }
2819 else
2820 { // is not physical, or is not a body or is selected
2821 // _zeroPosition = d.BodyGetPosition(Body);
2822 return;
2823 //Console.WriteLine("Nothing " + Name);
2824
2825 }
2826 }
2827
2828
2829 public void UpdatePositionAndVelocity(float simulatedtime)
2830 {
2831 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2832 if (_parent == null && !m_disabled && !m_building)
2833 {
2834 if (Body != IntPtr.Zero)
2835 {
2836 if (m_crossingfailures != 0 && m_crossingfailures < 5)
2837 {
2838 _position.X = Util.Clip(_position.X, 0.4f, _parent_scene.WorldExtents.X - 0.4f);
2839 _position.Y = Util.Clip(_position.Y, 0.4f, _parent_scene.WorldExtents.Y - 0.4f);
2840 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2841
2842 float tmp = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y);
2843 if (_position.Z < tmp)
2844 _position.Z = tmp + 0.2f;
2845
2846 m_lastposition = _position;
2847 m_lastorientation = _orientation;
2848 _velocity.X = 0;
2849 _velocity.Y = 0;
2850 _velocity.Z = 0;
2851
2852 m_lastVelocity = _velocity;
2853 m_rotationalVelocity = _velocity;
2854 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2855 m_vehicle.Stop();
2856
2857 m_crossingfailures = 0; // do this only once
2858 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2859 d.BodySetAngularVel(Body, 0, 0, 0);
2860 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2861 enableBodySoft();
2862 base.RequestPhysicsterseUpdate();
2863 return;
2864 }
2865
2866 else if (m_crossingfailures != 0)
2867 {
2868 return;
2869 }
2870
2871 Vector3 pv = Vector3.Zero;
2872 bool lastZeroFlag = _zeroFlag;
2873
2874 d.Vector3 lpos;
2875 d.GeomCopyPosition(prim_geom,out lpos); // root position that is seem by rest of simulator
2876
2877 // we need to use root position since that's all the rest of scene uses
2878 if ( lpos.X < 0f || lpos.X > _parent_scene.WorldExtents.X
2879 || lpos.Y < 0f || lpos.Y > _parent_scene.WorldExtents.Y
2880 )
2881 {
2882 // we are outside current region
2883 // we can't let it keeping moving and having colisions
2884 // since it can be stucked between something like terrain and edge
2885 // so lets stop and disable it until something else kicks it
2886 if (m_crossingfailures == 0)
2887 {
2888
2889 _position.X = Util.Clip(lpos.X, -0.5f, _parent_scene.WorldExtents.X + 0.5f);
2890 _position.Y = Util.Clip(lpos.Y, -0.5f, _parent_scene.WorldExtents.Y + 0.5f);
2891 _position.Z = Util.Clip(lpos.Z, -100f, 50000f);
2892
2893 m_lastposition = _position;
2894 m_lastorientation = _orientation;
2895
2896 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2897 d.BodySetAngularVel(Body, 0, 0, 0);
2898 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2899 disableBodySoft(); // stop collisions
2900 m_crossingfailures++; // do this only once
2901 base.RequestPhysicsterseUpdate();
2902 return;
2903 }
2904 }
2905
2906 if (lpos.Z < -100 || lpos.Z > 100000f)
2907 {
2908 lpos.Z = Util.Clip(lpos.Z, -100f, 50000f);
2909
2910 _acceleration.X = 0;
2911 _acceleration.Y = 0;
2912 _acceleration.Z = 0;
2913
2914 _velocity.X = 0;
2915 _velocity.Y = 0;
2916 _velocity.Z = 0;
2917 m_rotationalVelocity.X = 0;
2918 m_rotationalVelocity.Y = 0;
2919 m_rotationalVelocity.Z = 0;
2920
2921 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2922 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
2923 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
2924 m_lastposition = _position;
2925 m_lastorientation = _orientation;
2926
2927 base.RequestPhysicsterseUpdate();
2928
2929 m_throttleUpdates = false;
2930 throttleCounter = 0;
2931 _zeroFlag = true;
2932
2933 disableBodySoft(); // disable it and colisions
2934 base.RaiseOutOfBounds(_position);
2935
2936 return;
2937 }
2938
2939 d.Quaternion ori;
2940 d.GeomCopyQuaternion(prim_geom, out ori);
2941 d.Vector3 vel = d.BodyGetLinearVel(Body);
2942 d.Vector3 rotvel = d.BodyGetAngularVel(Body);
2943
2944 if ((Math.Abs(m_lastposition.X - lpos.X) < 0.01)
2945 && (Math.Abs(m_lastposition.Y - lpos.Y) < 0.01)
2946 && (Math.Abs(m_lastposition.Z - lpos.Z) < 0.01)
2947 && (Math.Abs(m_lastorientation.X - ori.X) < 0.0001)
2948 && (Math.Abs(m_lastorientation.Y - ori.Y) < 0.0001)
2949 && (Math.Abs(m_lastorientation.Z - ori.Z) < 0.0001)
2950 )
2951 {
2952 _zeroFlag = true;
2953 //Console.WriteLine("ZFT 2");
2954 m_throttleUpdates = false;
2955 }
2956 else
2957 {
2958 //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString());
2959 _zeroFlag = false;
2960 m_lastUpdateSent = false;
2961 //m_throttleUpdates = false;
2962 }
2963
2964 if (_zeroFlag)
2965 {
2966 m_lastposition = _position;
2967 m_lastorientation = _orientation;
2968
2969 _velocity.X = 0.0f;
2970 _velocity.Y = 0.0f;
2971 _velocity.Z = 0.0f;
2972
2973 _acceleration.X = 0;
2974 _acceleration.Y = 0;
2975 _acceleration.Z = 0;
2976
2977 m_rotationalVelocity.X = 0;
2978 m_rotationalVelocity.Y = 0;
2979 m_rotationalVelocity.Z = 0;
2980 if (!m_lastUpdateSent)
2981 {
2982 m_throttleUpdates = false;
2983 throttleCounter = 0;
2984 m_rotationalVelocity = pv;
2985
2986 base.RequestPhysicsterseUpdate();
2987
2988 m_lastUpdateSent = true;
2989 }
2990 }
2991 else
2992 {
2993 if (lastZeroFlag != _zeroFlag)
2994 {
2995 base.RequestPhysicsterseUpdate();
2996 }
2997
2998 m_lastVelocity = _velocity;
2999
3000 _position.X = lpos.X;
3001 _position.Y = lpos.Y;
3002 _position.Z = lpos.Z;
3003
3004 _velocity.X = vel.X;
3005 _velocity.Y = vel.Y;
3006 _velocity.Z = vel.Z;
3007
3008 _orientation.X = ori.X;
3009 _orientation.Y = ori.Y;
3010 _orientation.Z = ori.Z;
3011 _orientation.W = ori.W;
3012
3013 _acceleration = ((_velocity - m_lastVelocity) / simulatedtime);
3014
3015 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
3016 {
3017 m_rotationalVelocity = pv;
3018 }
3019 else
3020 {
3021 m_rotationalVelocity.X = rotvel.X;
3022 m_rotationalVelocity.Y = rotvel.Y;
3023 m_rotationalVelocity.Z = rotvel.Z;
3024 }
3025
3026 m_lastUpdateSent = false;
3027 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate)
3028 {
3029 m_lastposition = _position;
3030 m_lastorientation = _orientation;
3031 base.RequestPhysicsterseUpdate();
3032 }
3033 else
3034 {
3035 throttleCounter++;
3036 }
3037 }
3038 }
3039 else if (!m_lastUpdateSent || !_zeroFlag)
3040 {
3041 // Not a body.. so Make sure the client isn't interpolating
3042 _velocity.X = 0;
3043 _velocity.Y = 0;
3044 _velocity.Z = 0;
3045
3046 _acceleration.X = 0;
3047 _acceleration.Y = 0;
3048 _acceleration.Z = 0;
3049
3050 m_rotationalVelocity.X = 0;
3051 m_rotationalVelocity.Y = 0;
3052 m_rotationalVelocity.Z = 0;
3053 _zeroFlag = true;
3054
3055 if (!m_lastUpdateSent)
3056 {
3057 m_throttleUpdates = false;
3058 throttleCounter = 0;
3059
3060 base.RequestPhysicsterseUpdate();
3061
3062 m_lastUpdateSent = true;
3063 }
3064 }
3065 }
3066 }
3067
3068 internal static bool QuaternionIsFinite(Quaternion q)
3069 {
3070 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3071 return false;
3072 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3073 return false;
3074 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3075 return false;
3076 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3077 return false;
3078 return true;
3079 }
3080
3081 internal static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3082 {
3083 dst.c.W = src.c.W;
3084 dst.c.X = src.c.X;
3085 dst.c.Y = src.c.Y;
3086 dst.c.Z = src.c.Z;
3087 dst.mass = src.mass;
3088 dst.I.M00 = src.I.M00;
3089 dst.I.M01 = src.I.M01;
3090 dst.I.M02 = src.I.M02;
3091 dst.I.M10 = src.I.M10;
3092 dst.I.M11 = src.I.M11;
3093 dst.I.M12 = src.I.M12;
3094 dst.I.M20 = src.I.M20;
3095 dst.I.M21 = src.I.M21;
3096 dst.I.M22 = src.I.M22;
3097 }
3098
3099 private static void DMassDup(ref d.Mass src, out d.Mass dst)
3100 {
3101 dst = new d.Mass { };
3102
3103 dst.c.W = src.c.W;
3104 dst.c.X = src.c.X;
3105 dst.c.Y = src.c.Y;
3106 dst.c.Z = src.c.Z;
3107 dst.mass = src.mass;
3108 dst.I.M00 = src.I.M00;
3109 dst.I.M01 = src.I.M01;
3110 dst.I.M02 = src.I.M02;
3111 dst.I.M10 = src.I.M10;
3112 dst.I.M11 = src.I.M11;
3113 dst.I.M12 = src.I.M12;
3114 dst.I.M20 = src.I.M20;
3115 dst.I.M21 = src.I.M21;
3116 dst.I.M22 = src.I.M22;
3117 }
3118 private void donullchange()
3119 {
3120 }
3121
3122 public bool DoAChange(changes what, object arg)
3123 {
3124 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
3125 {
3126 return false;
3127 }
3128
3129 // nasty switch
3130 switch (what)
3131 {
3132 case changes.Add:
3133 changeadd();
3134 break;
3135 case changes.Remove:
3136 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3137 //When we return true, it destroys all of the prims in the linkset anyway
3138 if (_parent != null)
3139 {
3140 OdePrim parent = (OdePrim)_parent;
3141 parent.ChildRemove(this,false);
3142 }
3143 else
3144 ChildRemove(this,false);
3145
3146 RemoveGeom();
3147 m_targetSpace = IntPtr.Zero;
3148 if (m_eventsubscription > 0)
3149 UnSubscribeEvents();
3150 return true;
3151
3152 case changes.Link:
3153 OdePrim tmp = (OdePrim)arg;
3154 changeLink(tmp);
3155 break;
3156
3157 case changes.DeLink:
3158 changeLink(null);
3159 break;
3160
3161 case changes.Position:
3162 changePosition((Vector3)arg);
3163 break;
3164
3165 case changes.Orientation:
3166 changeOrientation((Quaternion)arg);
3167 break;
3168
3169 case changes.PosOffset:
3170 donullchange();
3171 break;
3172
3173 case changes.OriOffset:
3174 donullchange();
3175 break;
3176
3177 case changes.Velocity:
3178 changevelocity((Vector3)arg);
3179 break;
3180
3181// case changes.Acceleration:
3182// changeacceleration((Vector3)arg);
3183// break;
3184// case changes.AngVelocity:
3185// changeangvelocity((Vector3)arg);
3186// break;
3187
3188 case changes.Force:
3189 changeForce((Vector3)arg);
3190 break;
3191
3192 case changes.Torque:
3193 changeSetTorque((Vector3)arg);
3194 break;
3195
3196 case changes.AddForce:
3197 changeAddForce((Vector3)arg);
3198 break;
3199
3200 case changes.AddAngForce:
3201 changeAddAngularForce((Vector3)arg);
3202 break;
3203
3204 case changes.AngLock:
3205 changeAngularLock((Vector3)arg);
3206 break;
3207
3208 case changes.Size:
3209 changeSize((Vector3)arg);
3210 break;
3211
3212 case changes.Shape:
3213 changeShape((PrimitiveBaseShape) arg);
3214 break;
3215
3216 case changes.CollidesWater:
3217 changeFloatOnWater((bool)arg);
3218 break;
3219
3220 case changes.VolumeDtc:
3221 changeVolumedetetion((bool)arg);
3222 break;
3223
3224 case changes.Physical:
3225 changePhysicsStatus((bool)arg);
3226 break;
3227
3228 case changes.Selected:
3229 changeSelectedStatus((bool)arg);
3230 break;
3231
3232 case changes.disabled:
3233 changeDisable((bool) arg);
3234 break;
3235
3236 case changes.building:
3237 changeBuilding((bool)arg);
3238 break;
3239
3240 case changes.Null:
3241 donullchange();
3242 break;
3243
3244 default:
3245 donullchange();
3246 break;
3247 }
3248 return false;
3249 }
3250
3251 public void AddChange(changes what, object arg)
3252 {
3253 _parent_scene.AddChange(this, what, arg);
3254 }
3255 }
3256}