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