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.cs4032
1 files changed, 4032 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..6bf5be1
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -0,0 +1,4032 @@
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 private bool m_isphantom;
70 private bool m_fakeisphantom;
71 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
72 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
73
74 protected bool m_building;
75 protected bool m_forcePosOrRotation;
76 private bool m_iscolliding;
77
78 internal bool m_isSelected;
79 private bool m_delaySelect;
80 private bool m_lastdoneSelected;
81 internal bool m_outbounds;
82
83 private Quaternion m_lastorientation = new Quaternion();
84 private Quaternion _orientation;
85
86 private Vector3 _position;
87 private Vector3 _velocity;
88 private Vector3 _torque;
89 private Vector3 m_lastVelocity;
90 private Vector3 m_lastposition;
91 private Vector3 m_rotationalVelocity;
92 private Vector3 _size;
93 private Vector3 _acceleration;
94 private Vector3 m_angularlock = Vector3.One;
95 private IntPtr Amotor = IntPtr.Zero;
96
97 private Vector3 m_force;
98 private Vector3 m_forceacc;
99 private Vector3 m_angularForceacc;
100
101 private float m_invTimeStep = 50.0f;
102 private float m_timeStep = .02f;
103
104 private Vector3 m_PIDTarget;
105 private float m_PIDTau;
106 private bool m_usePID;
107
108 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
109 // and are for non-VEHICLES only.
110
111 private float m_PIDHoverHeight;
112 private float m_PIDHoverTau;
113 private bool m_useHoverPID;
114 private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
115 private float m_targetHoverHeight;
116 private float m_groundHeight;
117 private float m_waterHeight;
118 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
119
120 private int body_autodisable_frames = 5;
121 public int bodydisablecontrol = 0;
122
123
124 // Default we're a Geometry
125 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
126 // Default colide nonphysical don't try to colide with anything
127 private const CollisionCategories m_default_collisionFlagsNotPhysical = 0;
128
129 private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom |
130 CollisionCategories.Character |
131 CollisionCategories.Land |
132 CollisionCategories.VolumeDtc);
133
134// private bool m_collidesLand = true;
135 private bool m_collidesWater;
136// public bool m_returnCollisions;
137
138 private bool m_NoColide; // for now only for internal use for bad meshs
139
140
141 // Default, Collide with Other Geometries, spaces and Bodies
142 private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical;
143
144 public bool m_disabled;
145
146 private uint m_localID;
147
148 private IMesh m_mesh;
149 private object m_meshlock = new object();
150 private PrimitiveBaseShape _pbs;
151 public OdeScene _parent_scene;
152
153 /// <summary>
154 /// The physics space which contains prim geometry
155 /// </summary>
156 public IntPtr m_targetSpace = IntPtr.Zero;
157
158 public IntPtr prim_geom;
159 public IntPtr _triMeshData;
160
161 private PhysicsActor _parent;
162
163 private List<OdePrim> childrenPrim = new List<OdePrim>();
164
165
166// private bool m_throttleUpdates;
167// private int throttleCounter;
168 public float m_collisionscore;
169 private int m_colliderfilter = 0;
170
171 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
172
173 private float m_density = 10.000006836f; // Aluminum g/cm3;
174 private byte m_shapetype;
175 public bool _zeroFlag;
176 private bool m_lastUpdateSent;
177
178 public IntPtr Body = IntPtr.Zero;
179// public String Name { get; private set; }
180 private Vector3 _target_velocity;
181
182 public Vector3 primOOBsize; // prim real dimensions from mesh
183 public Vector3 primOOBoffset; // its centroid out of mesh or rest aabb
184 public float primOOBradiusSQ;
185 public d.Mass primdMass; // prim inertia information on it's own referencial
186 float primMass; // prim own mass
187 float primVolume; // prim own volume;
188 float _mass; // object mass acording to case
189 private bool hasOOBoffsetFromMesh = false; // if true we did compute it form mesh centroid, else from aabb
190
191 public int givefakepos = 0;
192 private Vector3 fakepos;
193 public int givefakeori = 0;
194 private Quaternion fakeori;
195
196 private int m_eventsubscription;
197 private int m_cureventsubscription;
198 private CollisionEventUpdate CollisionEventsThisFrame = null;
199 private bool SentEmptyCollisionsEvent;
200
201 public volatile bool childPrim;
202
203 public ODEDynamics m_vehicle;
204
205 internal int m_material = (int)Material.Wood;
206 private float mu;
207 private float bounce;
208
209 /// <summary>
210 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
211 /// </summary>
212 public override bool IsPhysical // this is not reliable for internal use
213 {
214 get { return m_fakeisphysical; }
215 set
216 {
217 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
218 // and also to stop imediatly some updates
219 // but real change will only happen in taintprocessing
220
221 if (!value) // Zero the remembered last velocity
222 m_lastVelocity = Vector3.Zero;
223 AddChange(changes.Physical, value);
224 }
225 }
226
227 public override bool IsVolumeDtc
228 {
229 get { return m_fakeisVolumeDetect; }
230 set
231 {
232 m_fakeisVolumeDetect = value;
233 AddChange(changes.VolumeDtc, value);
234 }
235 }
236
237 public override bool Phantom // this is not reliable for internal use
238 {
239 get { return m_fakeisphantom; }
240 set
241 {
242 m_fakeisphantom = value;
243 AddChange(changes.Phantom, value);
244 }
245 }
246
247 public override bool Building // this is not reliable for internal use
248 {
249 get { return m_building; }
250 set
251 {
252 if (value)
253 m_building = true;
254 AddChange(changes.building, value);
255 }
256 }
257
258 public override void getContactData(ref ContactData cdata)
259 {
260 cdata.mu = mu;
261 cdata.bounce = bounce;
262
263 // cdata.softcolide = m_softcolide;
264 cdata.softcolide = false;
265
266 if (m_isphysical)
267 {
268 ODEDynamics veh;
269 if (_parent != null)
270 veh = ((OdePrim)_parent).m_vehicle;
271 else
272 veh = m_vehicle;
273
274 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
275 cdata.mu *= veh.FrictionFactor;
276// cdata.mu *= 0;
277 }
278 }
279
280 public override int PhysicsActorType
281 {
282 get { return (int)ActorTypes.Prim; }
283 set { return; }
284 }
285
286 public override bool SetAlwaysRun
287 {
288 get { return false; }
289 set { return; }
290 }
291
292 public override uint LocalID
293 {
294 get { return m_localID; }
295 set { m_localID = value; }
296 }
297
298 public override PhysicsActor ParentActor
299 {
300 get
301 {
302 if (childPrim)
303 return _parent;
304 else
305 return (PhysicsActor)this;
306 }
307 }
308
309 public override bool Grabbed
310 {
311 set { return; }
312 }
313
314 public override bool Selected
315 {
316 set
317 {
318 if (value)
319 m_isSelected = value; // if true set imediatly to stop moves etc
320 AddChange(changes.Selected, value);
321 }
322 }
323
324 public override bool Flying
325 {
326 // no flying prims for you
327 get { return false; }
328 set { }
329 }
330
331 public override bool IsColliding
332 {
333 get { return m_iscolliding; }
334 set
335 {
336 if (value)
337 {
338 m_colliderfilter += 2;
339 if (m_colliderfilter > 2)
340 m_colliderfilter = 2;
341 }
342 else
343 {
344 m_colliderfilter--;
345 if (m_colliderfilter < 0)
346 m_colliderfilter = 0;
347 }
348
349 if (m_colliderfilter == 0)
350 m_iscolliding = false;
351 else
352 m_iscolliding = true;
353 }
354 }
355
356 public override bool CollidingGround
357 {
358 get { return false; }
359 set { return; }
360 }
361
362 public override bool CollidingObj
363 {
364 get { return false; }
365 set { return; }
366 }
367
368
369 public override bool ThrottleUpdates {get;set;}
370/*
371 {
372 get { return m_throttleUpdates; }
373 set { m_throttleUpdates = value; }
374 }
375*/
376 public override bool Stopped
377 {
378 get { return _zeroFlag; }
379 }
380
381 public override Vector3 Position
382 {
383 get
384 {
385 if (givefakepos > 0)
386 return fakepos;
387 else
388 return _position;
389 }
390
391 set
392 {
393 fakepos = value;
394 givefakepos++;
395 AddChange(changes.Position, value);
396 }
397 }
398
399 public override Vector3 Size
400 {
401 get { return _size; }
402 set
403 {
404 if (value.IsFinite())
405 {
406 AddChange(changes.Size, value);
407 }
408 else
409 {
410 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
411 }
412 }
413 }
414
415 public override float Mass
416 {
417 get { return primMass; }
418 }
419
420 public override Vector3 Force
421 {
422 //get { return Vector3.Zero; }
423 get { return m_force; }
424 set
425 {
426 if (value.IsFinite())
427 {
428 AddChange(changes.Force, value);
429 }
430 else
431 {
432 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
433 }
434 }
435 }
436
437 public override void SetVolumeDetect(int param)
438 {
439 m_fakeisVolumeDetect = (param != 0);
440 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
441 }
442
443 public override Vector3 GeometricCenter
444 {
445 // this is not real geometric center but a average of positions relative to root prim acording to
446 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
447 // ignoring tortured prims details since sl also seems to ignore
448 // so no real use in doing it on physics
449 get
450 {
451 return Vector3.Zero;
452 }
453 }
454
455 public override Vector3 CenterOfMass
456 {
457 get
458 {
459 lock (_parent_scene.OdeLock)
460 {
461 d.Vector3 dtmp;
462 if (!childPrim && Body != IntPtr.Zero)
463 {
464 dtmp = d.BodyGetPosition(Body);
465 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
466 }
467 else if (prim_geom != IntPtr.Zero)
468 {
469 d.Quaternion dq;
470 d.GeomCopyQuaternion(prim_geom, out dq);
471 Quaternion q;
472 q.X = dq.X;
473 q.Y = dq.Y;
474 q.Z = dq.Z;
475 q.W = dq.W;
476
477 Vector3 Ptot = primOOBoffset * q;
478 dtmp = d.GeomGetPosition(prim_geom);
479 Ptot.X += dtmp.X;
480 Ptot.Y += dtmp.Y;
481 Ptot.Z += dtmp.Z;
482
483 // if(childPrim) we only know about physical linksets
484 return Ptot;
485/*
486 float tmass = _mass;
487 Ptot *= tmass;
488
489 float m;
490
491 foreach (OdePrim prm in childrenPrim)
492 {
493 m = prm._mass;
494 Ptot += prm.CenterOfMass * m;
495 tmass += m;
496 }
497
498 if (tmass == 0)
499 tmass = 0;
500 else
501 tmass = 1.0f / tmass;
502
503 Ptot *= tmass;
504 return Ptot;
505*/
506 }
507 else
508 return _position;
509 }
510 }
511 }
512
513 public override Vector3 OOBsize
514 {
515 get
516 {
517 return primOOBsize;
518 }
519 }
520
521 public override Vector3 OOBoffset
522 {
523 get
524 {
525 return primOOBoffset;
526 }
527 }
528
529 public override float OOBRadiusSQ
530 {
531 get
532 {
533 return primOOBradiusSQ;
534 }
535 }
536
537 public override PrimitiveBaseShape Shape
538 {
539 set
540 {
541/*
542 IMesh mesh = null;
543 if (_parent_scene.needsMeshing(value))
544 {
545 bool convex;
546 if (m_shapetype == 0)
547 convex = false;
548 else
549 convex = true;
550 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
551 }
552
553 if (mesh != null)
554 {
555 lock (m_meshlock)
556 m_mesh = mesh;
557 }
558*/
559 AddChange(changes.Shape, value);
560 }
561 }
562
563 public override byte PhysicsShapeType
564 {
565 get
566 {
567 return m_shapetype;
568 }
569 set
570 {
571 m_shapetype = value;
572 AddChange(changes.Shape, null);
573 }
574 }
575
576
577 public override Vector3 Velocity
578 {
579 get
580 {
581 if (_zeroFlag)
582 return Vector3.Zero;
583 return _velocity;
584 }
585 set
586 {
587 if (value.IsFinite())
588 {
589 AddChange(changes.Velocity, value);
590 }
591 else
592 {
593 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
594 }
595
596 }
597 }
598
599 public override Vector3 Torque
600 {
601 get
602 {
603 if (!IsPhysical || Body == IntPtr.Zero)
604 return Vector3.Zero;
605
606 return _torque;
607 }
608
609 set
610 {
611 if (value.IsFinite())
612 {
613 AddChange(changes.Torque, value);
614 }
615 else
616 {
617 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
618 }
619 }
620 }
621
622 public override float CollisionScore
623 {
624 get { return m_collisionscore; }
625 set { m_collisionscore = value; }
626 }
627
628 public override bool Kinematic
629 {
630 get { return false; }
631 set { }
632 }
633
634 public override Quaternion Orientation
635 {
636 get
637 {
638 if (givefakeori > 0)
639 return fakeori;
640 else
641
642 return _orientation;
643 }
644 set
645 {
646 if (QuaternionIsFinite(value))
647 {
648 fakeori = value;
649 givefakeori++;
650 AddChange(changes.Orientation, value);
651 }
652 else
653 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
654
655 }
656 }
657
658 public override Vector3 Acceleration
659 {
660 get { return _acceleration; }
661 set { }
662 }
663
664 public override Vector3 RotationalVelocity
665 {
666 get
667 {
668 Vector3 pv = Vector3.Zero;
669 if (_zeroFlag)
670 return pv;
671
672 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
673 return pv;
674
675 return m_rotationalVelocity;
676 }
677 set
678 {
679 if (value.IsFinite())
680 {
681 AddChange(changes.AngVelocity, value);
682 }
683 else
684 {
685 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
686 }
687 }
688 }
689
690 public override float Buoyancy
691 {
692 get { return m_buoyancy; }
693 set
694 {
695 m_buoyancy = value;
696 }
697 }
698
699 public override bool FloatOnWater
700 {
701 set
702 {
703 AddChange(changes.CollidesWater, value);
704 }
705 }
706
707 public override Vector3 PIDTarget
708 {
709 set
710 {
711 if (value.IsFinite())
712 {
713 m_PIDTarget = value;
714 }
715 else
716 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
717 }
718 }
719
720 public override bool PIDActive { set { m_usePID = value; } }
721 public override float PIDTau
722 {
723 set
724 {
725 if (value <= 0)
726 m_PIDTau = 0;
727 else
728 {
729 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
730 if (value < mint)
731 m_PIDTau = mint;
732 else
733 m_PIDTau = value;
734 }
735 }
736 }
737
738 public override float PIDHoverHeight
739 {
740 set
741 {
742 m_PIDHoverHeight = value;
743 if (value == 0)
744 m_useHoverPID = false;
745 }
746 }
747 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
748 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
749 public override float PIDHoverTau
750 {
751 set
752 {
753 if (value <= 0)
754 m_PIDHoverTau = 0;
755 else
756 {
757 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
758 if (value < mint)
759 m_PIDHoverTau = mint;
760 else
761 m_PIDHoverTau = value;
762 }
763 }
764 }
765
766 public override Quaternion APIDTarget { set { return; } }
767
768 public override bool APIDActive { set { return; } }
769
770 public override float APIDStrength { set { return; } }
771
772 public override float APIDDamping { set { return; } }
773
774 public override int VehicleType
775 {
776 // we may need to put a fake on this
777 get
778 {
779 if (m_vehicle == null)
780 return (int)Vehicle.TYPE_NONE;
781 else
782 return (int)m_vehicle.Type;
783 }
784 set
785 {
786 AddChange(changes.VehicleType, value);
787 }
788 }
789
790 public override void VehicleFloatParam(int param, float value)
791 {
792 strVehicleFloatParam fp = new strVehicleFloatParam();
793 fp.param = param;
794 fp.value = value;
795 AddChange(changes.VehicleFloatParam, fp);
796 }
797
798 public override void VehicleVectorParam(int param, Vector3 value)
799 {
800 strVehicleVectorParam fp = new strVehicleVectorParam();
801 fp.param = param;
802 fp.value = value;
803 AddChange(changes.VehicleVectorParam, fp);
804 }
805
806 public override void VehicleRotationParam(int param, Quaternion value)
807 {
808 strVehicleQuatParam fp = new strVehicleQuatParam();
809 fp.param = param;
810 fp.value = value;
811 AddChange(changes.VehicleRotationParam, fp);
812 }
813
814 public override void VehicleFlags(int param, bool value)
815 {
816 strVehicleBoolParam bp = new strVehicleBoolParam();
817 bp.param = param;
818 bp.value = value;
819 AddChange(changes.VehicleFlags, bp);
820 }
821
822 public override void SetVehicle(object vdata)
823 {
824 AddChange(changes.SetVehicle, vdata);
825 }
826 public void SetAcceleration(Vector3 accel)
827 {
828 _acceleration = accel;
829 }
830
831 public override void AddForce(Vector3 force, bool pushforce)
832 {
833 if (force.IsFinite())
834 {
835 if(pushforce)
836 AddChange(changes.AddForce, force);
837 else // a impulse
838 AddChange(changes.AddForce, force * m_invTimeStep);
839 }
840 else
841 {
842 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
843 }
844 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
845 }
846
847 public override void AddAngularForce(Vector3 force, bool pushforce)
848 {
849 if (force.IsFinite())
850 {
851// if(pushforce) for now applyrotationimpulse seems more happy applied as a force
852 AddChange(changes.AddAngForce, force);
853// else // a impulse
854// AddChange(changes.AddAngForce, force * m_invTimeStep);
855 }
856 else
857 {
858 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
859 }
860 }
861
862 public override void CrossingFailure()
863 {
864 if (m_outbounds)
865 {
866 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
867 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
868 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
869
870 m_lastposition = _position;
871 _velocity.X = 0;
872 _velocity.Y = 0;
873 _velocity.Z = 0;
874
875 m_lastVelocity = _velocity;
876 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
877 m_vehicle.Stop();
878
879 if(Body != IntPtr.Zero)
880 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
881 if (prim_geom != IntPtr.Zero)
882 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
883
884 m_outbounds = false;
885 changeDisable(false);
886 base.RequestPhysicsterseUpdate();
887 }
888 }
889
890 public override void SetMomentum(Vector3 momentum)
891 {
892 }
893
894 public override void SetMaterial(int pMaterial)
895 {
896 m_material = pMaterial;
897 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
898 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
899 }
900
901 public void setPrimForRemoval()
902 {
903 AddChange(changes.Remove, null);
904 }
905
906 public override void link(PhysicsActor obj)
907 {
908 AddChange(changes.Link, obj);
909 }
910
911 public override void delink()
912 {
913 AddChange(changes.DeLink, null);
914 }
915
916 public override void LockAngularMotion(Vector3 axis)
917 {
918 // reverse the zero/non zero values for ODE.
919 if (axis.IsFinite())
920 {
921 axis.X = (axis.X > 0) ? 1f : 0f;
922 axis.Y = (axis.Y > 0) ? 1f : 0f;
923 axis.Z = (axis.Z > 0) ? 1f : 0f;
924 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
925 AddChange(changes.AngLock, axis);
926 }
927 else
928 {
929 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
930 }
931 }
932
933 public override void SubscribeEvents(int ms)
934 {
935 m_eventsubscription = ms;
936 m_cureventsubscription = 0;
937 if (CollisionEventsThisFrame == null)
938 CollisionEventsThisFrame = new CollisionEventUpdate();
939 SentEmptyCollisionsEvent = false;
940 }
941
942 public override void UnSubscribeEvents()
943 {
944 if (CollisionEventsThisFrame != null)
945 {
946 CollisionEventsThisFrame.Clear();
947 CollisionEventsThisFrame = null;
948 }
949 m_eventsubscription = 0;
950 _parent_scene.RemoveCollisionEventReporting(this);
951 }
952
953 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
954 {
955 if (CollisionEventsThisFrame == null)
956 CollisionEventsThisFrame = new CollisionEventUpdate();
957// if(CollisionEventsThisFrame.Count < 32)
958 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
959 }
960
961 public void SendCollisions()
962 {
963 if (CollisionEventsThisFrame == null)
964 return;
965
966 if (m_cureventsubscription < m_eventsubscription)
967 return;
968
969 m_cureventsubscription = 0;
970
971 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
972
973 if (!SentEmptyCollisionsEvent || ncolisions > 0)
974 {
975 base.SendCollisionUpdate(CollisionEventsThisFrame);
976
977 if (ncolisions == 0)
978 {
979 SentEmptyCollisionsEvent = true;
980 _parent_scene.RemoveCollisionEventReporting(this);
981 }
982 else
983 {
984 SentEmptyCollisionsEvent = false;
985 CollisionEventsThisFrame.Clear();
986 }
987 }
988 }
989
990 internal void AddCollisionFrameTime(int t)
991 {
992 if (m_cureventsubscription < 50000)
993 m_cureventsubscription += t;
994 }
995
996 public override bool SubscribedEvents()
997 {
998 if (m_eventsubscription > 0)
999 return true;
1000 return false;
1001 }
1002
1003
1004 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
1005 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
1006 {
1007 Name = primName;
1008 LocalID = plocalID;
1009
1010 m_vehicle = null;
1011
1012 if (!pos.IsFinite())
1013 {
1014 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
1015 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
1016 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
1017 }
1018 _position = pos;
1019 givefakepos = 0;
1020
1021 m_timeStep = parent_scene.ODE_STEPSIZE;
1022 m_invTimeStep = 1f / m_timeStep;
1023
1024 m_density = parent_scene.geomDefaultDensity;
1025 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
1026 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1027
1028 prim_geom = IntPtr.Zero;
1029 collide_geom = IntPtr.Zero;
1030 Body = IntPtr.Zero;
1031
1032 if (!size.IsFinite())
1033 {
1034 size = new Vector3(0.5f, 0.5f, 0.5f);
1035 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
1036 }
1037
1038 if (size.X <= 0) size.X = 0.01f;
1039 if (size.Y <= 0) size.Y = 0.01f;
1040 if (size.Z <= 0) size.Z = 0.01f;
1041
1042 _size = size;
1043
1044 if (!QuaternionIsFinite(rotation))
1045 {
1046 rotation = Quaternion.Identity;
1047 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1048 }
1049
1050 _orientation = rotation;
1051 givefakeori = 0;
1052
1053 _pbs = pbs;
1054
1055 _parent_scene = parent_scene;
1056 m_targetSpace = IntPtr.Zero;
1057
1058 if (pos.Z < 0)
1059 {
1060 m_isphysical = false;
1061 }
1062 else
1063 {
1064 m_isphysical = pisPhysical;
1065 }
1066 m_fakeisphysical = m_isphysical;
1067
1068 m_isVolumeDetect = false;
1069 m_fakeisVolumeDetect = false;
1070
1071 m_force = Vector3.Zero;
1072
1073 m_iscolliding = false;
1074 m_colliderfilter = 0;
1075 m_NoColide = false;
1076
1077 hasOOBoffsetFromMesh = false;
1078 _triMeshData = IntPtr.Zero;
1079
1080 m_shapetype = _shapeType;
1081
1082 m_lastdoneSelected = false;
1083 m_isSelected = false;
1084 m_delaySelect = false;
1085
1086 m_isphantom = pisPhantom;
1087 m_fakeisphantom = pisPhantom;
1088
1089 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1090 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1091
1092 CalcPrimBodyData();
1093
1094 m_mesh = null;
1095 if (_parent_scene.needsMeshing(pbs))
1096 {
1097 bool convex;
1098 if (m_shapetype == 0)
1099 convex = false;
1100 else
1101 convex = true;
1102
1103 m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
1104 }
1105
1106
1107 m_building = true; // control must set this to false when done
1108
1109 AddChange(changes.Add, null);
1110 }
1111
1112 private void resetCollisionAccounting()
1113 {
1114 m_collisionscore = 0;
1115 }
1116
1117 private void UpdateCollisionCatFlags()
1118 {
1119 if(m_isphysical && m_disabled)
1120 {
1121 m_collisionCategories = 0;
1122 m_collisionFlags = 0;
1123 }
1124
1125 else if (m_isSelected)
1126 {
1127 m_collisionCategories = CollisionCategories.Selected;
1128 m_collisionFlags = 0;
1129 }
1130
1131 else if (m_isVolumeDetect)
1132 {
1133 m_collisionCategories = CollisionCategories.VolumeDtc;
1134 if (m_isphysical)
1135 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1136 else
1137 m_collisionFlags = 0;
1138 }
1139 else if (m_isphantom)
1140 {
1141 m_collisionCategories = CollisionCategories.Phantom;
1142 if (m_isphysical)
1143 m_collisionFlags = CollisionCategories.Land;
1144 else
1145 m_collisionFlags = 0;
1146 }
1147 else
1148 {
1149 m_collisionCategories = CollisionCategories.Geom;
1150 if (m_isphysical)
1151 m_collisionFlags = m_default_collisionFlagsPhysical;
1152 else
1153 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1154 }
1155 }
1156
1157 private void ApplyCollisionCatFlags()
1158 {
1159 if (prim_geom != IntPtr.Zero)
1160 {
1161 if (!childPrim && childrenPrim.Count > 0)
1162 {
1163 foreach (OdePrim prm in childrenPrim)
1164 {
1165 if (m_isphysical && m_disabled)
1166 {
1167 prm.m_collisionCategories = 0;
1168 prm.m_collisionFlags = 0;
1169 }
1170 else
1171 {
1172 // preserve some
1173 if (prm.m_isSelected)
1174 {
1175 prm.m_collisionCategories = CollisionCategories.Selected;
1176 prm.m_collisionFlags = 0;
1177 }
1178 else if (prm.m_isVolumeDetect)
1179 {
1180 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1181 if (m_isphysical)
1182 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1183 else
1184 prm.m_collisionFlags = 0;
1185 }
1186 else if (prm.m_isphantom)
1187 {
1188 prm.m_collisionCategories = CollisionCategories.Phantom;
1189 if (m_isphysical)
1190 prm.m_collisionFlags = CollisionCategories.Land;
1191 else
1192 prm.m_collisionFlags = 0;
1193 }
1194 else
1195 {
1196 prm.m_collisionCategories = m_collisionCategories;
1197 prm.m_collisionFlags = m_collisionFlags;
1198 }
1199 }
1200
1201 if (prm.prim_geom != IntPtr.Zero)
1202 {
1203 if (prm.m_NoColide)
1204 {
1205 d.GeomSetCategoryBits(prm.prim_geom, 0);
1206 if (m_isphysical)
1207 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1208 else
1209 d.GeomSetCollideBits(prm.prim_geom, 0);
1210 }
1211 else
1212 {
1213 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1214 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1215 }
1216 }
1217 }
1218 }
1219
1220 if (m_NoColide)
1221 {
1222 d.GeomSetCategoryBits(prim_geom, 0);
1223 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1224 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1225 {
1226 d.GeomSetCategoryBits(collide_geom, 0);
1227 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1228 }
1229 }
1230 else
1231 {
1232 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1233 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1234 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1235 {
1236 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1237 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1238 }
1239 }
1240 }
1241 }
1242
1243 private void createAMotor(Vector3 axis)
1244 {
1245 if (Body == IntPtr.Zero)
1246 return;
1247
1248 if (Amotor != IntPtr.Zero)
1249 {
1250 d.JointDestroy(Amotor);
1251 Amotor = IntPtr.Zero;
1252 }
1253
1254 int axisnum = 3 - (int)(axis.X + axis.Y + axis.Z);
1255
1256 if (axisnum <= 0)
1257 return;
1258
1259 // stop it
1260 d.BodySetTorque(Body, 0, 0, 0);
1261 d.BodySetAngularVel(Body, 0, 0, 0);
1262
1263 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1264 d.JointAttach(Amotor, Body, IntPtr.Zero);
1265
1266 d.JointSetAMotorMode(Amotor, 0);
1267
1268 d.JointSetAMotorNumAxes(Amotor, axisnum);
1269
1270 // get current orientation to lock
1271
1272 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1273 Quaternion curr; // crap convertion between identical things
1274 curr.X = dcur.X;
1275 curr.Y = dcur.Y;
1276 curr.Z = dcur.Z;
1277 curr.W = dcur.W;
1278 Vector3 ax;
1279
1280 int i = 0;
1281 int j = 0;
1282 if (axis.X == 0)
1283 {
1284 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1285 // ODE should do this with axis relative to body 1 but seems to fail
1286 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1287 d.JointSetAMotorAngle(Amotor, 0, 0);
1288 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, -0.000001f);
1289 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0.000001f);
1290 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1291 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1292 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1293 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1294 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1295 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1296 i++;
1297 j = 256; // move to next axis set
1298 }
1299
1300 if (axis.Y == 0)
1301 {
1302 ax = (new Vector3(0, 1, 0)) * curr;
1303 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1304 d.JointSetAMotorAngle(Amotor, i, 0);
1305 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1306 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1307 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1308 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1309 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1310 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1311 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1312 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1313 i++;
1314 j += 256;
1315 }
1316
1317 if (axis.Z == 0)
1318 {
1319 ax = (new Vector3(0, 0, 1)) * curr;
1320 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1321 d.JointSetAMotorAngle(Amotor, i, 0);
1322 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, -0.000001f);
1323 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0.000001f);
1324 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1325 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1326 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1327 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1328 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1329 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1330 }
1331 }
1332
1333 private bool setMesh(OdeScene parent_scene)
1334 {
1335 IntPtr vertices, indices;
1336 int vertexCount, indexCount;
1337 int vertexStride, triStride;
1338
1339 if (Body != IntPtr.Zero)
1340 {
1341 if (childPrim)
1342 {
1343 if (_parent != null)
1344 {
1345 OdePrim parent = (OdePrim)_parent;
1346 parent.ChildDelink(this, false);
1347 }
1348 }
1349 else
1350 {
1351 DestroyBody();
1352 }
1353 }
1354
1355 IMesh mesh = null;
1356
1357
1358 lock (m_meshlock)
1359 {
1360 if (m_mesh == null)
1361 {
1362 bool convex;
1363 if (m_shapetype == 0)
1364 convex = false;
1365 else
1366 convex = true;
1367
1368 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex);
1369 }
1370 else
1371 {
1372 mesh = m_mesh;
1373 }
1374
1375 if (mesh == null)
1376 {
1377 m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z);
1378 return false;
1379 }
1380
1381
1382 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
1383 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
1384
1385 if (vertexCount == 0 || indexCount == 0)
1386 {
1387 m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. mesh UUID {4}",
1388 Name, _position.X, _position.Y, _position.Z, _pbs.SculptTexture.ToString());
1389 mesh.releaseSourceMeshData();
1390 return false;
1391 }
1392
1393 primOOBoffset = mesh.GetCentroid();
1394 hasOOBoffsetFromMesh = true;
1395
1396 mesh.releaseSourceMeshData();
1397 m_mesh = null;
1398 }
1399
1400 IntPtr geo = IntPtr.Zero;
1401
1402 try
1403 {
1404 _triMeshData = d.GeomTriMeshDataCreate();
1405
1406 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1407 d.GeomTriMeshDataPreprocess(_triMeshData);
1408
1409 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1410 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1411 }
1412
1413 catch (Exception e)
1414 {
1415 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1416 if (_triMeshData != IntPtr.Zero)
1417 {
1418 d.GeomTriMeshDataDestroy(_triMeshData);
1419 _triMeshData = IntPtr.Zero;
1420 }
1421 return false;
1422 }
1423
1424 SetGeom(geo);
1425 return true;
1426 }
1427
1428 private void SetGeom(IntPtr geom)
1429 {
1430 prim_geom = geom;
1431 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1432 if (prim_geom != IntPtr.Zero)
1433 {
1434
1435 if (m_NoColide)
1436 {
1437 d.GeomSetCategoryBits(prim_geom, 0);
1438 if (m_isphysical)
1439 {
1440 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1441 }
1442 else
1443 {
1444 d.GeomSetCollideBits(prim_geom, 0);
1445 d.GeomDisable(prim_geom);
1446 }
1447 }
1448 else
1449 {
1450 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1451 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1452 }
1453
1454 CalcPrimBodyData();
1455
1456 _parent_scene.actor_name_map[prim_geom] = this;
1457
1458 }
1459 else
1460 m_log.Warn("Setting bad Geom");
1461 }
1462
1463
1464 /// <summary>
1465 /// Create a geometry for the given mesh in the given target space.
1466 /// </summary>
1467 /// <param name="m_targetSpace"></param>
1468 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1469 private void CreateGeom()
1470 {
1471 if (_triMeshData != IntPtr.Zero)
1472 {
1473 d.GeomTriMeshDataDestroy(_triMeshData);
1474 _triMeshData = IntPtr.Zero;
1475 }
1476
1477 bool haveMesh = false;
1478 hasOOBoffsetFromMesh = false;
1479 m_NoColide = false;
1480
1481 if (_parent_scene.needsMeshing(_pbs))
1482 {
1483 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1484 if (!haveMesh)
1485 m_NoColide = true;
1486 }
1487
1488 if (!haveMesh)
1489 {
1490 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1491 && _size.X == _size.Y && _size.Y == _size.Z)
1492 { // it's a sphere
1493 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1494 try
1495 {
1496 SetGeom(d.CreateSphere(m_targetSpace, _size.X * 0.5f));
1497 }
1498 catch (Exception e)
1499 {
1500 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1501 return;
1502 }
1503 }
1504 else
1505 {// do it as a box
1506 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1507 try
1508 {
1509 //Console.WriteLine(" CreateGeom 4");
1510 SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
1511 }
1512 catch (Exception e)
1513 {
1514 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1515 return;
1516 }
1517 }
1518 }
1519 }
1520
1521 /// <summary>
1522 /// Set a new geometry for this prim.
1523 /// </summary>
1524 /// <param name="geom"></param>
1525 private void RemoveGeom()
1526 {
1527 if (prim_geom != IntPtr.Zero)
1528 {
1529// _parent_scene.geom_name_map.Remove(prim_geom);
1530 _parent_scene.actor_name_map.Remove(prim_geom);
1531 try
1532 {
1533 d.GeomDestroy(prim_geom);
1534 if (_triMeshData != IntPtr.Zero)
1535 {
1536 d.GeomTriMeshDataDestroy(_triMeshData);
1537 _triMeshData = IntPtr.Zero;
1538 }
1539 }
1540 // catch (System.AccessViolationException)
1541 catch (Exception e)
1542 {
1543 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1544 }
1545
1546 prim_geom = IntPtr.Zero;
1547 collide_geom = IntPtr.Zero;
1548 }
1549 else
1550 {
1551 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1552 }
1553 Body = IntPtr.Zero;
1554 hasOOBoffsetFromMesh = false;
1555 }
1556/*
1557 private void ChildSetGeom(OdePrim odePrim)
1558 {
1559 // well..
1560 DestroyBody();
1561 MakeBody();
1562 }
1563*/
1564 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1565 // should only be called for non physical prims unless they are becoming non physical
1566 private void SetInStaticSpace(OdePrim prim)
1567 {
1568 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1569 prim.m_targetSpace = targetSpace;
1570 collide_geom = IntPtr.Zero;
1571 }
1572
1573 public void enableBodySoft()
1574 {
1575 m_disabled = false;
1576 if (!childPrim && !m_isSelected)
1577 {
1578 if (m_isphysical && Body != IntPtr.Zero)
1579 {
1580 UpdateCollisionCatFlags();
1581 ApplyCollisionCatFlags();
1582
1583 d.BodyEnable(Body);
1584 }
1585 }
1586 resetCollisionAccounting();
1587 }
1588
1589 private void disableBodySoft()
1590 {
1591 m_disabled = true;
1592 if (!childPrim)
1593 {
1594 if (m_isphysical && Body != IntPtr.Zero)
1595 {
1596 if (m_isSelected)
1597 m_collisionFlags = CollisionCategories.Selected;
1598 else
1599 m_collisionCategories = 0;
1600 m_collisionFlags = 0;
1601 ApplyCollisionCatFlags();
1602 d.BodyDisable(Body);
1603 }
1604 }
1605 }
1606
1607 private void MakeBody()
1608 {
1609 if (!m_isphysical) // only physical get bodies
1610 return;
1611
1612 if (childPrim) // child prims don't get bodies;
1613 return;
1614
1615 if (m_building)
1616 return;
1617
1618 if (prim_geom == IntPtr.Zero)
1619 {
1620 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1621 return;
1622 }
1623
1624 if (Body != IntPtr.Zero)
1625 {
1626// d.BodyDestroy(Body);
1627// Body = IntPtr.Zero;
1628 // do a more complet destruction
1629 DestroyBody();
1630 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1631 }
1632
1633 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1634 {
1635 d.GeomSetBody(prim_geom, IntPtr.Zero);
1636 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1637 }
1638
1639 d.Matrix3 mymat = new d.Matrix3();
1640 d.Quaternion myrot = new d.Quaternion();
1641 d.Mass objdmass = new d.Mass { };
1642
1643 Body = d.BodyCreate(_parent_scene.world);
1644
1645 objdmass = primdMass;
1646
1647 // rotate inertia
1648 myrot.X = _orientation.X;
1649 myrot.Y = _orientation.Y;
1650 myrot.Z = _orientation.Z;
1651 myrot.W = _orientation.W;
1652
1653 d.RfromQ(out mymat, ref myrot);
1654 d.MassRotate(ref objdmass, ref mymat);
1655
1656 // set the body rotation
1657 d.BodySetRotation(Body, ref mymat);
1658
1659 // recompute full object inertia if needed
1660 if (childrenPrim.Count > 0)
1661 {
1662 d.Matrix3 mat = new d.Matrix3();
1663 d.Quaternion quat = new d.Quaternion();
1664 d.Mass tmpdmass = new d.Mass { };
1665 Vector3 rcm;
1666
1667 rcm.X = _position.X;
1668 rcm.Y = _position.Y;
1669 rcm.Z = _position.Z;
1670
1671 lock (childrenPrim)
1672 {
1673 foreach (OdePrim prm in childrenPrim)
1674 {
1675 if (prm.prim_geom == IntPtr.Zero)
1676 {
1677 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1678 continue;
1679 }
1680
1681 tmpdmass = prm.primdMass;
1682
1683 // apply prim current rotation to inertia
1684 quat.X = prm._orientation.X;
1685 quat.Y = prm._orientation.Y;
1686 quat.Z = prm._orientation.Z;
1687 quat.W = prm._orientation.W;
1688 d.RfromQ(out mat, ref quat);
1689 d.MassRotate(ref tmpdmass, ref mat);
1690
1691 Vector3 ppos = prm._position;
1692 ppos.X -= rcm.X;
1693 ppos.Y -= rcm.Y;
1694 ppos.Z -= rcm.Z;
1695 // refer inertia to root prim center of mass position
1696 d.MassTranslate(ref tmpdmass,
1697 ppos.X,
1698 ppos.Y,
1699 ppos.Z);
1700
1701 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1702 // fix prim colision cats
1703
1704 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1705 {
1706 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1707 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1708 }
1709
1710 d.GeomClearOffset(prm.prim_geom);
1711 d.GeomSetBody(prm.prim_geom, Body);
1712 prm.Body = Body;
1713 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1714 }
1715 }
1716 }
1717
1718 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1719 // associate root geom with body
1720 d.GeomSetBody(prim_geom, Body);
1721
1722 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1723 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1724
1725 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1726 myrot.X = -myrot.X;
1727 myrot.Y = -myrot.Y;
1728 myrot.Z = -myrot.Z;
1729
1730 d.RfromQ(out mymat, ref myrot);
1731 d.MassRotate(ref objdmass, ref mymat);
1732
1733 d.BodySetMass(Body, ref objdmass);
1734 _mass = objdmass.mass;
1735
1736 // disconnect from world gravity so we can apply buoyancy
1737 d.BodySetGravityMode(Body, false);
1738
1739 d.BodySetAutoDisableFlag(Body, true);
1740 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1741 d.BodySetDamping(Body, .005f, .005f);
1742
1743 if (m_targetSpace != IntPtr.Zero)
1744 {
1745 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1746 if (d.SpaceQuery(m_targetSpace, prim_geom))
1747 d.SpaceRemove(m_targetSpace, prim_geom);
1748 }
1749
1750 if (childrenPrim.Count == 0)
1751 {
1752 collide_geom = prim_geom;
1753 m_targetSpace = _parent_scene.ActiveSpace;
1754 }
1755 else
1756 {
1757 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1758 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1759 d.SpaceSetSublevel(m_targetSpace, 3);
1760 d.SpaceSetCleanup(m_targetSpace, false);
1761
1762 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
1763 CollisionCategories.Geom |
1764 CollisionCategories.Phantom |
1765 CollisionCategories.VolumeDtc
1766 ));
1767 d.GeomSetCollideBits(m_targetSpace, 0);
1768 collide_geom = m_targetSpace;
1769 }
1770
1771 d.SpaceAdd(m_targetSpace, prim_geom);
1772
1773 if (m_delaySelect)
1774 {
1775 m_isSelected = true;
1776 m_delaySelect = false;
1777 }
1778
1779 m_collisionscore = 0;
1780
1781 UpdateCollisionCatFlags();
1782 ApplyCollisionCatFlags();
1783
1784 _parent_scene.addActivePrim(this);
1785
1786 lock (childrenPrim)
1787 {
1788 foreach (OdePrim prm in childrenPrim)
1789 {
1790 if (prm.prim_geom == IntPtr.Zero)
1791 continue;
1792
1793 Vector3 ppos = prm._position;
1794 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1795
1796 if (prm.m_targetSpace != m_targetSpace)
1797 {
1798 if (prm.m_targetSpace != IntPtr.Zero)
1799 {
1800 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1801 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1802 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1803 }
1804 prm.m_targetSpace = m_targetSpace;
1805 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1806 }
1807
1808 prm.m_collisionscore = 0;
1809
1810 if(!m_disabled)
1811 prm.m_disabled = false;
1812
1813 _parent_scene.addActivePrim(prm);
1814 }
1815 }
1816
1817 // The body doesn't already have a finite rotation mode set here
1818 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null)
1819 {
1820 createAMotor(m_angularlock);
1821 }
1822
1823
1824 if (m_isSelected || m_disabled)
1825 {
1826 d.BodyDisable(Body);
1827 }
1828 else
1829 {
1830 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1831 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1832 }
1833 _parent_scene.addActiveGroups(this);
1834 }
1835
1836 private void DestroyBody()
1837 {
1838 if (Body != IntPtr.Zero)
1839 {
1840 _parent_scene.remActivePrim(this);
1841
1842 collide_geom = IntPtr.Zero;
1843
1844 if (m_disabled)
1845 m_collisionCategories = 0;
1846 else if (m_isSelected)
1847 m_collisionCategories = CollisionCategories.Selected;
1848 else if (m_isVolumeDetect)
1849 m_collisionCategories = CollisionCategories.VolumeDtc;
1850 else if (m_isphantom)
1851 m_collisionCategories = CollisionCategories.Phantom;
1852 else
1853 m_collisionCategories = CollisionCategories.Geom;
1854
1855 m_collisionFlags = 0;
1856
1857 if (prim_geom != IntPtr.Zero)
1858 {
1859 if (m_NoColide)
1860 {
1861 d.GeomSetCategoryBits(prim_geom, 0);
1862 d.GeomSetCollideBits(prim_geom, 0);
1863 }
1864 else
1865 {
1866 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1867 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1868 }
1869 UpdateDataFromGeom();
1870 d.GeomSetBody(prim_geom, IntPtr.Zero);
1871 SetInStaticSpace(this);
1872 }
1873
1874 if (!childPrim)
1875 {
1876 lock (childrenPrim)
1877 {
1878 foreach (OdePrim prm in childrenPrim)
1879 {
1880 _parent_scene.remActivePrim(prm);
1881
1882 if (prm.m_isSelected)
1883 prm.m_collisionCategories = CollisionCategories.Selected;
1884 else if (prm.m_isVolumeDetect)
1885 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1886 else if (prm.m_isphantom)
1887 prm.m_collisionCategories = CollisionCategories.Phantom;
1888 else
1889 prm.m_collisionCategories = CollisionCategories.Geom;
1890
1891 prm.m_collisionFlags = 0;
1892
1893 if (prm.prim_geom != IntPtr.Zero)
1894 {
1895 if (prm.m_NoColide)
1896 {
1897 d.GeomSetCategoryBits(prm.prim_geom, 0);
1898 d.GeomSetCollideBits(prm.prim_geom, 0);
1899 }
1900 else
1901 {
1902 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1903 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1904 }
1905 prm.UpdateDataFromGeom();
1906 SetInStaticSpace(prm);
1907 }
1908 prm.Body = IntPtr.Zero;
1909 prm._mass = prm.primMass;
1910 prm.m_collisionscore = 0;
1911 }
1912 }
1913 if (Amotor != IntPtr.Zero)
1914 {
1915 d.JointDestroy(Amotor);
1916 Amotor = IntPtr.Zero;
1917 }
1918 _parent_scene.remActiveGroup(this);
1919 d.BodyDestroy(Body);
1920 }
1921 Body = IntPtr.Zero;
1922 }
1923 _mass = primMass;
1924 m_collisionscore = 0;
1925 }
1926
1927 private void FixInertia(Vector3 NewPos,Quaternion newrot)
1928 {
1929 d.Matrix3 mat = new d.Matrix3();
1930 d.Quaternion quat = new d.Quaternion();
1931
1932 d.Mass tmpdmass = new d.Mass { };
1933 d.Mass objdmass = new d.Mass { };
1934
1935 d.BodyGetMass(Body, out tmpdmass);
1936 objdmass = tmpdmass;
1937
1938 d.Vector3 dobjpos;
1939 d.Vector3 thispos;
1940
1941 // get current object position and rotation
1942 dobjpos = d.BodyGetPosition(Body);
1943
1944 // get prim own inertia in its local frame
1945 tmpdmass = primdMass;
1946
1947 // transform to object frame
1948 mat = d.GeomGetOffsetRotation(prim_geom);
1949 d.MassRotate(ref tmpdmass, ref mat);
1950
1951 thispos = d.GeomGetOffsetPosition(prim_geom);
1952 d.MassTranslate(ref tmpdmass,
1953 thispos.X,
1954 thispos.Y,
1955 thispos.Z);
1956
1957 // subtract current prim inertia from object
1958 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
1959
1960 // back prim own inertia
1961 tmpdmass = primdMass;
1962
1963 // update to new position and orientation
1964 _position = NewPos;
1965 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
1966 _orientation = newrot;
1967 quat.X = newrot.X;
1968 quat.Y = newrot.Y;
1969 quat.Z = newrot.Z;
1970 quat.W = newrot.W;
1971 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
1972
1973 mat = d.GeomGetOffsetRotation(prim_geom);
1974 d.MassRotate(ref tmpdmass, ref mat);
1975
1976 thispos = d.GeomGetOffsetPosition(prim_geom);
1977 d.MassTranslate(ref tmpdmass,
1978 thispos.X,
1979 thispos.Y,
1980 thispos.Z);
1981
1982 d.MassAdd(ref objdmass, ref tmpdmass);
1983
1984 // fix all positions
1985 IntPtr g = d.BodyGetFirstGeom(Body);
1986 while (g != IntPtr.Zero)
1987 {
1988 thispos = d.GeomGetOffsetPosition(g);
1989 thispos.X -= objdmass.c.X;
1990 thispos.Y -= objdmass.c.Y;
1991 thispos.Z -= objdmass.c.Z;
1992 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
1993 g = d.dBodyGetNextGeom(g);
1994 }
1995 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
1996
1997 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
1998 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1999 d.BodySetMass(Body, ref objdmass);
2000 _mass = objdmass.mass;
2001 }
2002
2003
2004
2005 private void FixInertia(Vector3 NewPos)
2006 {
2007 d.Matrix3 primmat = new d.Matrix3();
2008 d.Mass tmpdmass = new d.Mass { };
2009 d.Mass objdmass = new d.Mass { };
2010 d.Mass primmass = new d.Mass { };
2011
2012 d.Vector3 dobjpos;
2013 d.Vector3 thispos;
2014
2015 d.BodyGetMass(Body, out objdmass);
2016
2017 // get prim own inertia in its local frame
2018 primmass = primdMass;
2019 // transform to object frame
2020 primmat = d.GeomGetOffsetRotation(prim_geom);
2021 d.MassRotate(ref primmass, ref primmat);
2022
2023 tmpdmass = primmass;
2024
2025 thispos = d.GeomGetOffsetPosition(prim_geom);
2026 d.MassTranslate(ref tmpdmass,
2027 thispos.X,
2028 thispos.Y,
2029 thispos.Z);
2030
2031 // subtract current prim inertia from object
2032 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2033
2034 // update to new position
2035 _position = NewPos;
2036 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2037
2038 thispos = d.GeomGetOffsetPosition(prim_geom);
2039 d.MassTranslate(ref primmass,
2040 thispos.X,
2041 thispos.Y,
2042 thispos.Z);
2043
2044 d.MassAdd(ref objdmass, ref primmass);
2045
2046 // fix all positions
2047 IntPtr g = d.BodyGetFirstGeom(Body);
2048 while (g != IntPtr.Zero)
2049 {
2050 thispos = d.GeomGetOffsetPosition(g);
2051 thispos.X -= objdmass.c.X;
2052 thispos.Y -= objdmass.c.Y;
2053 thispos.Z -= objdmass.c.Z;
2054 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2055 g = d.dBodyGetNextGeom(g);
2056 }
2057
2058 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2059
2060 // get current object position and rotation
2061 dobjpos = d.BodyGetPosition(Body);
2062
2063 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2064 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2065 d.BodySetMass(Body, ref objdmass);
2066 _mass = objdmass.mass;
2067 }
2068
2069 private void FixInertia(Quaternion newrot)
2070 {
2071 d.Matrix3 mat = new d.Matrix3();
2072 d.Quaternion quat = new d.Quaternion();
2073
2074 d.Mass tmpdmass = new d.Mass { };
2075 d.Mass objdmass = new d.Mass { };
2076 d.Vector3 dobjpos;
2077 d.Vector3 thispos;
2078
2079 d.BodyGetMass(Body, out objdmass);
2080
2081 // get prim own inertia in its local frame
2082 tmpdmass = primdMass;
2083 mat = d.GeomGetOffsetRotation(prim_geom);
2084 d.MassRotate(ref tmpdmass, ref mat);
2085 // transform to object frame
2086 thispos = d.GeomGetOffsetPosition(prim_geom);
2087 d.MassTranslate(ref tmpdmass,
2088 thispos.X,
2089 thispos.Y,
2090 thispos.Z);
2091
2092 // subtract current prim inertia from object
2093 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2094
2095 // update to new orientation
2096 _orientation = newrot;
2097 quat.X = newrot.X;
2098 quat.Y = newrot.Y;
2099 quat.Z = newrot.Z;
2100 quat.W = newrot.W;
2101 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2102
2103 tmpdmass = primdMass;
2104 mat = d.GeomGetOffsetRotation(prim_geom);
2105 d.MassRotate(ref tmpdmass, ref mat);
2106 d.MassTranslate(ref tmpdmass,
2107 thispos.X,
2108 thispos.Y,
2109 thispos.Z);
2110
2111 d.MassAdd(ref objdmass, ref tmpdmass);
2112
2113 // fix all positions
2114 IntPtr g = d.BodyGetFirstGeom(Body);
2115 while (g != IntPtr.Zero)
2116 {
2117 thispos = d.GeomGetOffsetPosition(g);
2118 thispos.X -= objdmass.c.X;
2119 thispos.Y -= objdmass.c.Y;
2120 thispos.Z -= objdmass.c.Z;
2121 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2122 g = d.dBodyGetNextGeom(g);
2123 }
2124
2125 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2126 // get current object position and rotation
2127 dobjpos = d.BodyGetPosition(Body);
2128
2129 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2130 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2131 d.BodySetMass(Body, ref objdmass);
2132 _mass = objdmass.mass;
2133 }
2134
2135
2136 #region Mass Calculation
2137
2138 private float CalculatePrimVolume()
2139 {
2140 float volume = _size.X * _size.Y * _size.Z; // default
2141 float tmp;
2142
2143 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
2144 float hollowVolume = hollowAmount * hollowAmount;
2145
2146 switch (_pbs.ProfileShape)
2147 {
2148 case ProfileShape.Square:
2149 // default box
2150
2151 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2152 {
2153 if (hollowAmount > 0.0)
2154 {
2155 switch (_pbs.HollowShape)
2156 {
2157 case HollowShape.Square:
2158 case HollowShape.Same:
2159 break;
2160
2161 case HollowShape.Circle:
2162
2163 hollowVolume *= 0.78539816339f;
2164 break;
2165
2166 case HollowShape.Triangle:
2167
2168 hollowVolume *= (0.5f * .5f);
2169 break;
2170
2171 default:
2172 hollowVolume = 0;
2173 break;
2174 }
2175 volume *= (1.0f - hollowVolume);
2176 }
2177 }
2178
2179 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2180 {
2181 //a tube
2182
2183 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
2184 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
2185 volume -= volume * tmp * tmp;
2186
2187 if (hollowAmount > 0.0)
2188 {
2189 hollowVolume *= hollowAmount;
2190
2191 switch (_pbs.HollowShape)
2192 {
2193 case HollowShape.Square:
2194 case HollowShape.Same:
2195 break;
2196
2197 case HollowShape.Circle:
2198 hollowVolume *= 0.78539816339f;
2199 break;
2200
2201 case HollowShape.Triangle:
2202 hollowVolume *= 0.5f * 0.5f;
2203 break;
2204 default:
2205 hollowVolume = 0;
2206 break;
2207 }
2208 volume *= (1.0f - hollowVolume);
2209 }
2210 }
2211
2212 break;
2213
2214 case ProfileShape.Circle:
2215
2216 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2217 {
2218 volume *= 0.78539816339f; // elipse base
2219
2220 if (hollowAmount > 0.0)
2221 {
2222 switch (_pbs.HollowShape)
2223 {
2224 case HollowShape.Same:
2225 case HollowShape.Circle:
2226 break;
2227
2228 case HollowShape.Square:
2229 hollowVolume *= 0.5f * 2.5984480504799f;
2230 break;
2231
2232 case HollowShape.Triangle:
2233 hollowVolume *= .5f * 1.27323954473516f;
2234 break;
2235
2236 default:
2237 hollowVolume = 0;
2238 break;
2239 }
2240 volume *= (1.0f - hollowVolume);
2241 }
2242 }
2243
2244 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2245 {
2246 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
2247 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2248 volume *= (1.0f - tmp * tmp);
2249
2250 if (hollowAmount > 0.0)
2251 {
2252
2253 // calculate the hollow volume by it's shape compared to the prim shape
2254 hollowVolume *= hollowAmount;
2255
2256 switch (_pbs.HollowShape)
2257 {
2258 case HollowShape.Same:
2259 case HollowShape.Circle:
2260 break;
2261
2262 case HollowShape.Square:
2263 hollowVolume *= 0.5f * 2.5984480504799f;
2264 break;
2265
2266 case HollowShape.Triangle:
2267 hollowVolume *= .5f * 1.27323954473516f;
2268 break;
2269
2270 default:
2271 hollowVolume = 0;
2272 break;
2273 }
2274 volume *= (1.0f - hollowVolume);
2275 }
2276 }
2277 break;
2278
2279 case ProfileShape.HalfCircle:
2280 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2281 {
2282 volume *= 0.5236f;
2283
2284 if (hollowAmount > 0.0)
2285 {
2286 hollowVolume *= hollowAmount;
2287
2288 switch (_pbs.HollowShape)
2289 {
2290 case HollowShape.Circle:
2291 case HollowShape.Triangle: // diference in sl is minor and odd
2292 case HollowShape.Same:
2293 break;
2294
2295 case HollowShape.Square:
2296 hollowVolume *= 0.909f;
2297 break;
2298
2299 // case HollowShape.Triangle:
2300 // hollowVolume *= .827f;
2301 // break;
2302 default:
2303 hollowVolume = 0;
2304 break;
2305 }
2306 volume *= (1.0f - hollowVolume);
2307 }
2308
2309 }
2310 break;
2311
2312 case ProfileShape.EquilateralTriangle:
2313
2314 if (_pbs.PathCurve == (byte)Extrusion.Straight)
2315 {
2316 volume *= 0.32475953f;
2317
2318 if (hollowAmount > 0.0)
2319 {
2320
2321 // calculate the hollow volume by it's shape compared to the prim shape
2322 switch (_pbs.HollowShape)
2323 {
2324 case HollowShape.Same:
2325 case HollowShape.Triangle:
2326 hollowVolume *= .25f;
2327 break;
2328
2329 case HollowShape.Square:
2330 hollowVolume *= 0.499849f * 3.07920140172638f;
2331 break;
2332
2333 case HollowShape.Circle:
2334 // Hollow shape is a perfect cyllinder in respect to the cube's scale
2335 // Cyllinder hollow volume calculation
2336
2337 hollowVolume *= 0.1963495f * 3.07920140172638f;
2338 break;
2339
2340 default:
2341 hollowVolume = 0;
2342 break;
2343 }
2344 volume *= (1.0f - hollowVolume);
2345 }
2346 }
2347 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
2348 {
2349 volume *= 0.32475953f;
2350 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
2351 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
2352 volume *= (1.0f - tmp * tmp);
2353
2354 if (hollowAmount > 0.0)
2355 {
2356
2357 hollowVolume *= hollowAmount;
2358
2359 switch (_pbs.HollowShape)
2360 {
2361 case HollowShape.Same:
2362 case HollowShape.Triangle:
2363 hollowVolume *= .25f;
2364 break;
2365
2366 case HollowShape.Square:
2367 hollowVolume *= 0.499849f * 3.07920140172638f;
2368 break;
2369
2370 case HollowShape.Circle:
2371
2372 hollowVolume *= 0.1963495f * 3.07920140172638f;
2373 break;
2374
2375 default:
2376 hollowVolume = 0;
2377 break;
2378 }
2379 volume *= (1.0f - hollowVolume);
2380 }
2381 }
2382 break;
2383
2384 default:
2385 break;
2386 }
2387
2388 float taperX1;
2389 float taperY1;
2390 float taperX;
2391 float taperY;
2392 float pathBegin;
2393 float pathEnd;
2394 float profileBegin;
2395 float profileEnd;
2396
2397 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
2398 {
2399 taperX1 = _pbs.PathScaleX * 0.01f;
2400 if (taperX1 > 1.0f)
2401 taperX1 = 2.0f - taperX1;
2402 taperX = 1.0f - taperX1;
2403
2404 taperY1 = _pbs.PathScaleY * 0.01f;
2405 if (taperY1 > 1.0f)
2406 taperY1 = 2.0f - taperY1;
2407 taperY = 1.0f - taperY1;
2408 }
2409 else
2410 {
2411 taperX = _pbs.PathTaperX * 0.01f;
2412 if (taperX < 0.0f)
2413 taperX = -taperX;
2414 taperX1 = 1.0f - taperX;
2415
2416 taperY = _pbs.PathTaperY * 0.01f;
2417 if (taperY < 0.0f)
2418 taperY = -taperY;
2419 taperY1 = 1.0f - taperY;
2420 }
2421
2422 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
2423
2424 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
2425 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
2426 volume *= (pathEnd - pathBegin);
2427
2428 // this is crude aproximation
2429 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
2430 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
2431 volume *= (profileEnd - profileBegin);
2432
2433 return volume;
2434 }
2435
2436
2437 private void CalcPrimBodyData()
2438 {
2439 float volume;
2440
2441 if (prim_geom == IntPtr.Zero)
2442 {
2443 // Ubit let's have a initial basic OOB
2444 primOOBsize.X = _size.X;
2445 primOOBsize.Y = _size.Y;
2446 primOOBsize.Z = _size.Z;
2447 primOOBoffset = Vector3.Zero;
2448 }
2449 else
2450 {
2451 d.AABB AABB;
2452 d.GeomGetAABB(prim_geom, out AABB); // get the AABB from engine geom
2453
2454 primOOBsize.X = (AABB.MaxX - AABB.MinX);
2455 primOOBsize.Y = (AABB.MaxY - AABB.MinY);
2456 primOOBsize.Z = (AABB.MaxZ - AABB.MinZ);
2457 if (!hasOOBoffsetFromMesh)
2458 {
2459 primOOBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
2460 primOOBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
2461 primOOBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
2462 }
2463 }
2464
2465 // also its own inertia and mass
2466 // keep using basic shape mass for now
2467 volume = CalculatePrimVolume();
2468
2469 primVolume = volume;
2470 primMass = m_density * volume;
2471
2472 if (primMass <= 0)
2473 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2474 if (primMass > _parent_scene.maximumMassObject)
2475 primMass = _parent_scene.maximumMassObject;
2476
2477 _mass = primMass; // just in case
2478
2479 d.MassSetBoxTotal(out primdMass, primMass, primOOBsize.X, primOOBsize.Y, primOOBsize.Z);
2480
2481 d.MassTranslate(ref primdMass,
2482 primOOBoffset.X,
2483 primOOBoffset.Y,
2484 primOOBoffset.Z);
2485
2486 primOOBsize *= 0.5f; // let obb size be a corner coords
2487 primOOBradiusSQ = primOOBsize.LengthSquared();
2488 }
2489
2490
2491 #endregion
2492
2493
2494 /// <summary>
2495 /// Add a child prim to this parent prim.
2496 /// </summary>
2497 /// <param name="prim">Child prim</param>
2498 // I'm the parent
2499 // prim is the child
2500 public void ParentPrim(OdePrim prim)
2501 {
2502 //Console.WriteLine("ParentPrim " + m_primName);
2503 if (this.m_localID != prim.m_localID)
2504 {
2505 DestroyBody(); // for now we need to rebuil entire object on link change
2506
2507 lock (childrenPrim)
2508 {
2509 // adopt the prim
2510 if (!childrenPrim.Contains(prim))
2511 childrenPrim.Add(prim);
2512
2513 // see if this prim has kids and adopt them also
2514 // should not happen for now
2515 foreach (OdePrim prm in prim.childrenPrim)
2516 {
2517 if (!childrenPrim.Contains(prm))
2518 {
2519 if (prm.Body != IntPtr.Zero)
2520 {
2521 if (prm.prim_geom != IntPtr.Zero)
2522 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2523 if (prm.Body != prim.Body)
2524 prm.DestroyBody(); // don't loose bodies around
2525 prm.Body = IntPtr.Zero;
2526 }
2527
2528 childrenPrim.Add(prm);
2529 prm._parent = this;
2530 }
2531 }
2532 }
2533 //Remove old children from the prim
2534 prim.childrenPrim.Clear();
2535
2536 if (prim.Body != IntPtr.Zero)
2537 {
2538 if (prim.prim_geom != IntPtr.Zero)
2539 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2540 prim.DestroyBody(); // don't loose bodies around
2541 prim.Body = IntPtr.Zero;
2542 }
2543
2544 prim.childPrim = true;
2545 prim._parent = this;
2546
2547 MakeBody(); // full nasty reconstruction
2548 }
2549 }
2550
2551 private void UpdateChildsfromgeom()
2552 {
2553 if (childrenPrim.Count > 0)
2554 {
2555 foreach (OdePrim prm in childrenPrim)
2556 prm.UpdateDataFromGeom();
2557 }
2558 }
2559
2560 private void UpdateDataFromGeom()
2561 {
2562 if (prim_geom != IntPtr.Zero)
2563 {
2564 d.Quaternion qtmp;
2565 d.GeomCopyQuaternion(prim_geom, out qtmp);
2566 _orientation.X = qtmp.X;
2567 _orientation.Y = qtmp.Y;
2568 _orientation.Z = qtmp.Z;
2569 _orientation.W = qtmp.W;
2570
2571 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2572 _position.X = lpos.X;
2573 _position.Y = lpos.Y;
2574 _position.Z = lpos.Z;
2575 }
2576 }
2577
2578 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2579 {
2580 // Okay, we have a delinked child.. destroy all body and remake
2581 if (odePrim != this && !childrenPrim.Contains(odePrim))
2582 return;
2583
2584 DestroyBody();
2585
2586 if (odePrim == this) // delinking the root prim
2587 {
2588 OdePrim newroot = null;
2589 lock (childrenPrim)
2590 {
2591 if (childrenPrim.Count > 0)
2592 {
2593 newroot = childrenPrim[0];
2594 childrenPrim.RemoveAt(0);
2595 foreach (OdePrim prm in childrenPrim)
2596 {
2597 newroot.childrenPrim.Add(prm);
2598 }
2599 childrenPrim.Clear();
2600 }
2601 if (newroot != null)
2602 {
2603 newroot.childPrim = false;
2604 newroot._parent = null;
2605 if (remakebodies)
2606 newroot.MakeBody();
2607 }
2608 }
2609 }
2610
2611 else
2612 {
2613 lock (childrenPrim)
2614 {
2615 childrenPrim.Remove(odePrim);
2616 odePrim.childPrim = false;
2617 odePrim._parent = null;
2618 // odePrim.UpdateDataFromGeom();
2619 if (remakebodies)
2620 odePrim.MakeBody();
2621 }
2622 }
2623 if (remakebodies)
2624 MakeBody();
2625 }
2626
2627 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2628 {
2629 // Okay, we have a delinked child.. destroy all body and remake
2630 if (odePrim != this && !childrenPrim.Contains(odePrim))
2631 return;
2632
2633 DestroyBody();
2634
2635 if (odePrim == this)
2636 {
2637 OdePrim newroot = null;
2638 lock (childrenPrim)
2639 {
2640 if (childrenPrim.Count > 0)
2641 {
2642 newroot = childrenPrim[0];
2643 childrenPrim.RemoveAt(0);
2644 foreach (OdePrim prm in childrenPrim)
2645 {
2646 newroot.childrenPrim.Add(prm);
2647 }
2648 childrenPrim.Clear();
2649 }
2650 if (newroot != null)
2651 {
2652 newroot.childPrim = false;
2653 newroot._parent = null;
2654 newroot.MakeBody();
2655 }
2656 }
2657 if (reMakeBody)
2658 MakeBody();
2659 return;
2660 }
2661 else
2662 {
2663 lock (childrenPrim)
2664 {
2665 childrenPrim.Remove(odePrim);
2666 odePrim.childPrim = false;
2667 odePrim._parent = null;
2668 if (reMakeBody)
2669 odePrim.MakeBody();
2670 }
2671 }
2672 MakeBody();
2673 }
2674
2675 #region changes
2676
2677 private void changeadd()
2678 {
2679 CreateGeom();
2680
2681 if (prim_geom != IntPtr.Zero)
2682 {
2683 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2684 d.Quaternion myrot = new d.Quaternion();
2685 myrot.X = _orientation.X;
2686 myrot.Y = _orientation.Y;
2687 myrot.Z = _orientation.Z;
2688 myrot.W = _orientation.W;
2689 d.GeomSetQuaternion(prim_geom, ref myrot);
2690
2691 if (!m_isphysical)
2692 {
2693 SetInStaticSpace(this);
2694 UpdateCollisionCatFlags();
2695 ApplyCollisionCatFlags();
2696 }
2697 else
2698 MakeBody();
2699 }
2700 }
2701
2702 private void changeAngularLock(Vector3 newLock)
2703 {
2704 // do we have a Physical object?
2705 if (Body != IntPtr.Zero)
2706 {
2707 //Check that we have a Parent
2708 //If we have a parent then we're not authorative here
2709 if (_parent == null)
2710 {
2711 if (!newLock.ApproxEquals(Vector3.One, 0f))
2712 {
2713 createAMotor(newLock);
2714 }
2715 else
2716 {
2717 if (Amotor != IntPtr.Zero)
2718 {
2719 d.JointDestroy(Amotor);
2720 Amotor = IntPtr.Zero;
2721 }
2722 }
2723 }
2724 }
2725 // Store this for later in case we get turned into a separate body
2726 m_angularlock = newLock;
2727 }
2728
2729 private void changeLink(OdePrim NewParent)
2730 {
2731 if (_parent == null && NewParent != null)
2732 {
2733 NewParent.ParentPrim(this);
2734 }
2735 else if (_parent != null)
2736 {
2737 if (_parent is OdePrim)
2738 {
2739 if (NewParent != _parent)
2740 {
2741 (_parent as OdePrim).ChildDelink(this, false); // for now...
2742 childPrim = false;
2743
2744 if (NewParent != null)
2745 {
2746 NewParent.ParentPrim(this);
2747 }
2748 }
2749 }
2750 }
2751 _parent = NewParent;
2752 }
2753
2754
2755 private void Stop()
2756 {
2757 if (!childPrim)
2758 {
2759 m_force = Vector3.Zero;
2760 m_forceacc = Vector3.Zero;
2761 m_angularForceacc = Vector3.Zero;
2762 _torque = Vector3.Zero;
2763 _velocity = Vector3.Zero;
2764 _acceleration = Vector3.Zero;
2765 m_rotationalVelocity = Vector3.Zero;
2766 _target_velocity = Vector3.Zero;
2767 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2768 m_vehicle.Stop();
2769 }
2770
2771 if (Body != IntPtr.Zero)
2772 {
2773 d.BodySetForce(Body, 0f, 0f, 0f);
2774 d.BodySetTorque(Body, 0f, 0f, 0f);
2775 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2776 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2777 }
2778 }
2779
2780 private void changePhantomStatus(bool newval)
2781 {
2782 m_isphantom = newval;
2783
2784 UpdateCollisionCatFlags();
2785 ApplyCollisionCatFlags();
2786 }
2787
2788/* not in use
2789 internal void ChildSelectedChange(bool childSelect)
2790 {
2791 if(childPrim)
2792 return;
2793
2794 if (childSelect == m_isSelected)
2795 return;
2796
2797 if (childSelect)
2798 {
2799 DoSelectedStatus(true);
2800 }
2801
2802 else
2803 {
2804 foreach (OdePrim prm in childrenPrim)
2805 {
2806 if (prm.m_isSelected)
2807 return;
2808 }
2809 DoSelectedStatus(false);
2810 }
2811 }
2812*/
2813 private void changeSelectedStatus(bool newval)
2814 {
2815 if (m_lastdoneSelected == newval)
2816 return;
2817
2818 m_lastdoneSelected = newval;
2819 DoSelectedStatus(newval);
2820 }
2821
2822 private void CheckDelaySelect()
2823 {
2824 if (m_delaySelect)
2825 {
2826 DoSelectedStatus(m_isSelected);
2827 }
2828 }
2829
2830 private void DoSelectedStatus(bool newval)
2831 {
2832 m_isSelected = newval;
2833 Stop();
2834
2835 if (newval)
2836 {
2837 if (!childPrim && Body != IntPtr.Zero)
2838 d.BodyDisable(Body);
2839
2840 if (m_delaySelect || m_isphysical)
2841 {
2842 m_collisionCategories = CollisionCategories.Selected;
2843 m_collisionFlags = 0;
2844
2845 if (!childPrim)
2846 {
2847 foreach (OdePrim prm in childrenPrim)
2848 {
2849 prm.m_collisionCategories = m_collisionCategories;
2850 prm.m_collisionFlags = m_collisionFlags;
2851
2852 if (prm.prim_geom != null)
2853 {
2854
2855 if (prm.m_NoColide)
2856 {
2857 d.GeomSetCategoryBits(prm.prim_geom, 0);
2858 d.GeomSetCollideBits(prm.prim_geom, 0);
2859 }
2860 else
2861 {
2862 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2863 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2864 }
2865 }
2866 prm.m_delaySelect = false;
2867 }
2868 }
2869// else if (_parent != null)
2870// ((OdePrim)_parent).ChildSelectedChange(true);
2871
2872
2873 if (prim_geom != null)
2874 {
2875 if (m_NoColide)
2876 {
2877 d.GeomSetCategoryBits(prim_geom, 0);
2878 d.GeomSetCollideBits(prim_geom, 0);
2879 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2880 {
2881 d.GeomSetCategoryBits(collide_geom, 0);
2882 d.GeomSetCollideBits(collide_geom, 0);
2883 }
2884
2885 }
2886 else
2887 {
2888 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2889 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2890 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2891 {
2892 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2893 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2894 }
2895 }
2896 }
2897
2898 m_delaySelect = false;
2899 }
2900 else if(!m_isphysical)
2901 {
2902 m_delaySelect = true;
2903 }
2904 }
2905 else
2906 {
2907 if (!childPrim)
2908 {
2909 if (Body != IntPtr.Zero && !m_disabled)
2910 d.BodyEnable(Body);
2911 }
2912// else if (_parent != null)
2913// ((OdePrim)_parent).ChildSelectedChange(false);
2914
2915 UpdateCollisionCatFlags();
2916 ApplyCollisionCatFlags();
2917
2918 m_delaySelect = false;
2919 }
2920
2921 resetCollisionAccounting();
2922 }
2923
2924 private void changePosition(Vector3 newPos)
2925 {
2926 CheckDelaySelect();
2927 if (m_isphysical)
2928 {
2929 if (childPrim) // inertia is messed, must rebuild
2930 {
2931 if (m_building)
2932 {
2933 _position = newPos;
2934 }
2935
2936 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2937 {
2938 FixInertia(newPos);
2939 if (!d.BodyIsEnabled(Body))
2940 d.BodyEnable(Body);
2941 }
2942 }
2943 else
2944 {
2945 if (_position != newPos)
2946 {
2947 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2948 _position = newPos;
2949 }
2950 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2951 d.BodyEnable(Body);
2952 }
2953 }
2954 else
2955 {
2956 if (prim_geom != IntPtr.Zero)
2957 {
2958 if (newPos != _position)
2959 {
2960 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2961 _position = newPos;
2962
2963 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2964 }
2965 }
2966 }
2967 givefakepos--;
2968 if (givefakepos < 0)
2969 givefakepos = 0;
2970// changeSelectedStatus();
2971 resetCollisionAccounting();
2972 }
2973
2974 private void changeOrientation(Quaternion newOri)
2975 {
2976 CheckDelaySelect();
2977 if (m_isphysical)
2978 {
2979 if (childPrim) // inertia is messed, must rebuild
2980 {
2981 if (m_building)
2982 {
2983 _orientation = newOri;
2984 }
2985/*
2986 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2987 {
2988 FixInertia(_position, newOri);
2989 if (!d.BodyIsEnabled(Body))
2990 d.BodyEnable(Body);
2991 }
2992*/
2993 }
2994 else
2995 {
2996 if (newOri != _orientation)
2997 {
2998 d.Quaternion myrot = new d.Quaternion();
2999 myrot.X = newOri.X;
3000 myrot.Y = newOri.Y;
3001 myrot.Z = newOri.Z;
3002 myrot.W = newOri.W;
3003 d.GeomSetQuaternion(prim_geom, ref myrot);
3004 _orientation = newOri;
3005 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
3006 createAMotor(m_angularlock);
3007 }
3008 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3009 d.BodyEnable(Body);
3010 }
3011 }
3012 else
3013 {
3014 if (prim_geom != IntPtr.Zero)
3015 {
3016 if (newOri != _orientation)
3017 {
3018 d.Quaternion myrot = new d.Quaternion();
3019 myrot.X = newOri.X;
3020 myrot.Y = newOri.Y;
3021 myrot.Z = newOri.Z;
3022 myrot.W = newOri.W;
3023 d.GeomSetQuaternion(prim_geom, ref myrot);
3024 _orientation = newOri;
3025 }
3026 }
3027 }
3028 givefakeori--;
3029 if (givefakeori < 0)
3030 givefakeori = 0;
3031 resetCollisionAccounting();
3032 }
3033
3034 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
3035 {
3036 CheckDelaySelect();
3037 if (m_isphysical)
3038 {
3039 if (childPrim && m_building) // inertia is messed, must rebuild
3040 {
3041 _position = newPos;
3042 _orientation = newOri;
3043 }
3044 else
3045 {
3046 if (newOri != _orientation)
3047 {
3048 d.Quaternion myrot = new d.Quaternion();
3049 myrot.X = newOri.X;
3050 myrot.Y = newOri.Y;
3051 myrot.Z = newOri.Z;
3052 myrot.W = newOri.W;
3053 d.GeomSetQuaternion(prim_geom, ref myrot);
3054 _orientation = newOri;
3055 if (Body != IntPtr.Zero && !m_angularlock.ApproxEquals(Vector3.One, 0f))
3056 createAMotor(m_angularlock);
3057 }
3058 if (_position != newPos)
3059 {
3060 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
3061 _position = newPos;
3062 }
3063 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3064 d.BodyEnable(Body);
3065 }
3066 }
3067 else
3068 {
3069 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
3070 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
3071
3072 if (prim_geom != IntPtr.Zero)
3073 {
3074 if (newOri != _orientation)
3075 {
3076 d.Quaternion myrot = new d.Quaternion();
3077 myrot.X = newOri.X;
3078 myrot.Y = newOri.Y;
3079 myrot.Z = newOri.Z;
3080 myrot.W = newOri.W;
3081 d.GeomSetQuaternion(prim_geom, ref myrot);
3082 _orientation = newOri;
3083 }
3084
3085 if (newPos != _position)
3086 {
3087 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
3088 _position = newPos;
3089
3090 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
3091 }
3092 }
3093 }
3094 givefakepos--;
3095 if (givefakepos < 0)
3096 givefakepos = 0;
3097 givefakeori--;
3098 if (givefakeori < 0)
3099 givefakeori = 0;
3100 resetCollisionAccounting();
3101 }
3102
3103
3104 private void changeDisable(bool disable)
3105 {
3106 if (disable)
3107 {
3108 if (!m_disabled)
3109 disableBodySoft();
3110 }
3111 else
3112 {
3113 if (m_disabled)
3114 enableBodySoft();
3115 }
3116 }
3117
3118 private void changePhysicsStatus(bool NewStatus)
3119 {
3120 CheckDelaySelect();
3121
3122 m_isphysical = NewStatus;
3123
3124 if (!childPrim)
3125 {
3126 if (NewStatus)
3127 {
3128 if (Body == IntPtr.Zero)
3129 MakeBody();
3130 }
3131 else
3132 {
3133 if (Body != IntPtr.Zero)
3134 {
3135 DestroyBody();
3136 }
3137 Stop();
3138 }
3139 }
3140
3141 resetCollisionAccounting();
3142 }
3143
3144 private void changeprimsizeshape()
3145 {
3146 CheckDelaySelect();
3147
3148 OdePrim parent = (OdePrim)_parent;
3149
3150 bool chp = childPrim;
3151
3152 if (chp)
3153 {
3154 if (parent != null)
3155 {
3156 parent.DestroyBody();
3157 }
3158 }
3159 else
3160 {
3161 DestroyBody();
3162 }
3163
3164 RemoveGeom();
3165
3166 // we don't need to do space calculation because the client sends a position update also.
3167 if (_size.X <= 0)
3168 _size.X = 0.01f;
3169 if (_size.Y <= 0)
3170 _size.Y = 0.01f;
3171 if (_size.Z <= 0)
3172 _size.Z = 0.01f;
3173 // Construction of new prim
3174
3175 CreateGeom();
3176
3177 if (prim_geom != IntPtr.Zero)
3178 {
3179 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3180 d.Quaternion myrot = new d.Quaternion();
3181 myrot.X = _orientation.X;
3182 myrot.Y = _orientation.Y;
3183 myrot.Z = _orientation.Z;
3184 myrot.W = _orientation.W;
3185 d.GeomSetQuaternion(prim_geom, ref myrot);
3186 }
3187
3188 if (m_isphysical)
3189 {
3190 if (chp)
3191 {
3192 if (parent != null)
3193 {
3194 parent.MakeBody();
3195 }
3196 }
3197 else
3198 MakeBody();
3199 }
3200
3201 else
3202 {
3203 UpdateCollisionCatFlags();
3204 ApplyCollisionCatFlags();
3205 }
3206
3207 resetCollisionAccounting();
3208 }
3209
3210 private void changeSize(Vector3 newSize)
3211 {
3212 _size = newSize;
3213 changeprimsizeshape();
3214 }
3215
3216 private void changeShape(PrimitiveBaseShape newShape)
3217 {
3218 if(newShape != null)
3219 _pbs = newShape;
3220 changeprimsizeshape();
3221 }
3222
3223 private void changeFloatOnWater(bool newval)
3224 {
3225 m_collidesWater = newval;
3226
3227 UpdateCollisionCatFlags();
3228 ApplyCollisionCatFlags();
3229 }
3230
3231 private void changeSetTorque(Vector3 newtorque)
3232 {
3233 if (!m_isSelected)
3234 {
3235 if (m_isphysical && Body != IntPtr.Zero)
3236 {
3237 if (m_disabled)
3238 enableBodySoft();
3239 else if (!d.BodyIsEnabled(Body))
3240 d.BodyEnable(Body);
3241
3242 }
3243 _torque = newtorque;
3244 }
3245 }
3246
3247 private void changeForce(Vector3 force)
3248 {
3249 m_force = force;
3250 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3251 d.BodyEnable(Body);
3252 }
3253
3254
3255 private void changeAddForce(Vector3 theforce)
3256 {
3257 m_forceacc += theforce;
3258 if (!m_isSelected)
3259 {
3260 lock (this)
3261 {
3262 //m_log.Info("[PHYSICS]: dequeing forcelist");
3263 if (m_isphysical && Body != IntPtr.Zero)
3264 {
3265 if (m_disabled)
3266 enableBodySoft();
3267 else if (!d.BodyIsEnabled(Body))
3268 d.BodyEnable(Body);
3269 }
3270 }
3271
3272 m_collisionscore = 0;
3273 }
3274 }
3275
3276 // actually angular impulse
3277 private void changeAddAngularImpulse(Vector3 aimpulse)
3278 {
3279 m_angularForceacc += aimpulse * m_invTimeStep;
3280 if (!m_isSelected)
3281 {
3282 lock (this)
3283 {
3284 if (m_isphysical && Body != IntPtr.Zero)
3285 {
3286 if (m_disabled)
3287 enableBodySoft();
3288 else if (!d.BodyIsEnabled(Body))
3289 d.BodyEnable(Body);
3290 }
3291 }
3292 m_collisionscore = 0;
3293 }
3294 }
3295
3296 private void changevelocity(Vector3 newVel)
3297 {
3298 float len = newVel.LengthSquared();
3299 if (len > 100000.0f) // limit to 100m/s
3300 {
3301 len = 100.0f / (float)Math.Sqrt(len);
3302 newVel *= len;
3303 }
3304
3305 if (!m_isSelected)
3306 {
3307 if (Body != IntPtr.Zero)
3308 {
3309 if (m_disabled)
3310 enableBodySoft();
3311 else if (!d.BodyIsEnabled(Body))
3312 d.BodyEnable(Body);
3313
3314 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3315 }
3316 //resetCollisionAccounting();
3317 }
3318 _velocity = newVel;
3319 }
3320
3321
3322 private void changeangvelocity(Vector3 newAngVel)
3323 {
3324 float len = newAngVel.LengthSquared();
3325 if (len > 144.0f) // limit to 12rad/s
3326 {
3327 len = 12.0f / (float)Math.Sqrt(len);
3328 newAngVel *= len;
3329 }
3330
3331 if (!m_isSelected)
3332 {
3333 if (Body != IntPtr.Zero)
3334 {
3335 if (m_disabled)
3336 enableBodySoft();
3337 else if (!d.BodyIsEnabled(Body))
3338 d.BodyEnable(Body);
3339
3340
3341 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3342 }
3343 //resetCollisionAccounting();
3344 }
3345 m_rotationalVelocity = newAngVel;
3346 }
3347
3348 private void changeVolumedetetion(bool newVolDtc)
3349 {
3350 m_isVolumeDetect = newVolDtc;
3351 m_fakeisVolumeDetect = newVolDtc;
3352 UpdateCollisionCatFlags();
3353 ApplyCollisionCatFlags();
3354 }
3355
3356 protected void changeBuilding(bool newbuilding)
3357 {
3358 // Check if we need to do anything
3359 if (newbuilding == m_building)
3360 return;
3361
3362 if ((bool)newbuilding)
3363 {
3364 m_building = true;
3365 if (!childPrim)
3366 DestroyBody();
3367 }
3368 else
3369 {
3370 m_building = false;
3371 CheckDelaySelect();
3372 if (!childPrim)
3373 MakeBody();
3374 }
3375 if (!childPrim && childrenPrim.Count > 0)
3376 {
3377 foreach (OdePrim prm in childrenPrim)
3378 prm.changeBuilding(m_building); // call directly
3379 }
3380 }
3381
3382 public void changeSetVehicle(VehicleData vdata)
3383 {
3384 if (m_vehicle == null)
3385 m_vehicle = new ODEDynamics(this);
3386 m_vehicle.DoSetVehicle(vdata);
3387 }
3388 private void changeVehicleType(int value)
3389 {
3390 if (value == (int)Vehicle.TYPE_NONE)
3391 {
3392 if (m_vehicle != null)
3393 m_vehicle = null;
3394 }
3395 else
3396 {
3397 if (m_vehicle == null)
3398 m_vehicle = new ODEDynamics(this);
3399
3400 m_vehicle.ProcessTypeChange((Vehicle)value);
3401 }
3402 }
3403
3404 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3405 {
3406 if (m_vehicle == null)
3407 return;
3408
3409 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3410 }
3411
3412 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3413 {
3414 if (m_vehicle == null)
3415 return;
3416 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3417 }
3418
3419 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3420 {
3421 if (m_vehicle == null)
3422 return;
3423 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3424 }
3425
3426 private void changeVehicleFlags(strVehicleBoolParam bp)
3427 {
3428 if (m_vehicle == null)
3429 return;
3430 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3431 }
3432
3433 #endregion
3434
3435 public void Move()
3436 {
3437 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3438 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3439 {
3440 if (!d.BodyIsEnabled(Body))
3441 {
3442 // let vehicles sleep
3443 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3444 return;
3445
3446 if (++bodydisablecontrol < 20)
3447 return;
3448
3449
3450 d.BodyEnable(Body);
3451 }
3452
3453 bodydisablecontrol = 0;
3454
3455 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3456
3457 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3458 {
3459 // 'VEHICLES' are dealt with in ODEDynamics.cs
3460 m_vehicle.Step();
3461 return;
3462 }
3463
3464 float fx = 0;
3465 float fy = 0;
3466 float fz = 0;
3467
3468 float m_mass = _mass;
3469
3470 if (m_usePID && m_PIDTau > 0)
3471 {
3472 // for now position error
3473 _target_velocity =
3474 new Vector3(
3475 (m_PIDTarget.X - lpos.X),
3476 (m_PIDTarget.Y - lpos.Y),
3477 (m_PIDTarget.Z - lpos.Z)
3478 );
3479
3480 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3481 {
3482 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3483 d.BodySetLinearVel(Body, 0, 0, 0);
3484 return;
3485 }
3486 else
3487 {
3488 _zeroFlag = false;
3489
3490 float tmp = 1 / m_PIDTau;
3491 _target_velocity *= tmp;
3492
3493 // apply limits
3494 tmp = _target_velocity.Length();
3495 if (tmp > 50.0f)
3496 {
3497 tmp = 50 / tmp;
3498 _target_velocity *= tmp;
3499 }
3500 else if (tmp < 0.05f)
3501 {
3502 tmp = 0.05f / tmp;
3503 _target_velocity *= tmp;
3504 }
3505
3506 d.Vector3 vel = d.BodyGetLinearVel(Body);
3507 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3508 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3509 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3510// d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3511 }
3512 } // end if (m_usePID)
3513
3514 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3515 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3516 {
3517
3518 // Non-Vehicles have a limited set of Hover options.
3519 // determine what our target height really is based on HoverType
3520
3521 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3522
3523 switch (m_PIDHoverType)
3524 {
3525 case PIDHoverType.Ground:
3526 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3527 break;
3528
3529 case PIDHoverType.GroundAndWater:
3530 m_waterHeight = _parent_scene.GetWaterLevel();
3531 if (m_groundHeight > m_waterHeight)
3532 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3533 else
3534 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3535 break;
3536 } // end switch (m_PIDHoverType)
3537
3538 // don't go underground unless volumedetector
3539
3540 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3541 {
3542 d.Vector3 vel = d.BodyGetLinearVel(Body);
3543
3544 fz = (m_targetHoverHeight - lpos.Z);
3545
3546 // if error is zero, use position control; otherwise, velocity control
3547 if (Math.Abs(fz) < 0.01f)
3548 {
3549 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3550 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3551 }
3552 else
3553 {
3554 _zeroFlag = false;
3555 fz /= m_PIDHoverTau;
3556
3557 float tmp = Math.Abs(fz);
3558 if (tmp > 50)
3559 fz = 50 * Math.Sign(fz);
3560 else if (tmp < 0.1)
3561 fz = 0.1f * Math.Sign(fz);
3562
3563 fz = ((fz - vel.Z) * m_invTimeStep);
3564 }
3565 }
3566 }
3567 else
3568 {
3569 float b = (1.0f - m_buoyancy);
3570 fx = _parent_scene.gravityx * b;
3571 fy = _parent_scene.gravityy * b;
3572 fz = _parent_scene.gravityz * b;
3573 }
3574
3575 fx *= m_mass;
3576 fy *= m_mass;
3577 fz *= m_mass;
3578
3579 // constant force
3580 fx += m_force.X;
3581 fy += m_force.Y;
3582 fz += m_force.Z;
3583
3584 fx += m_forceacc.X;
3585 fy += m_forceacc.Y;
3586 fz += m_forceacc.Z;
3587
3588 m_forceacc = Vector3.Zero;
3589
3590 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3591 if (fx != 0 || fy != 0 || fz != 0)
3592 {
3593 d.BodyAddForce(Body, fx, fy, fz);
3594 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3595 }
3596
3597 Vector3 trq;
3598
3599 trq = _torque;
3600 trq += m_angularForceacc;
3601 m_angularForceacc = Vector3.Zero;
3602 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3603 {
3604 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3605 }
3606 }
3607 else
3608 { // is not physical, or is not a body or is selected
3609 // _zeroPosition = d.BodyGetPosition(Body);
3610 return;
3611 //Console.WriteLine("Nothing " + Name);
3612
3613 }
3614 }
3615
3616 public void UpdatePositionAndVelocity()
3617 {
3618 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3619 {
3620 if (d.BodyIsEnabled(Body) || !_zeroFlag)
3621 {
3622 bool lastZeroFlag = _zeroFlag;
3623
3624 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3625
3626 // check outside region
3627 if (lpos.Z < -100 || lpos.Z > 100000f)
3628 {
3629 m_outbounds = true;
3630
3631 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3632 _acceleration.X = 0;
3633 _acceleration.Y = 0;
3634 _acceleration.Z = 0;
3635
3636 _velocity.X = 0;
3637 _velocity.Y = 0;
3638 _velocity.Z = 0;
3639 m_rotationalVelocity.X = 0;
3640 m_rotationalVelocity.Y = 0;
3641 m_rotationalVelocity.Z = 0;
3642
3643 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3644 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3645 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3646 m_lastposition = _position;
3647 m_lastorientation = _orientation;
3648
3649 base.RequestPhysicsterseUpdate();
3650
3651// throttleCounter = 0;
3652 _zeroFlag = true;
3653
3654 disableBodySoft(); // disable it and colisions
3655 base.RaiseOutOfBounds(_position);
3656 return;
3657 }
3658
3659 if (lpos.X < 0f)
3660 {
3661 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3662 m_outbounds = true;
3663 }
3664 else if (lpos.X > _parent_scene.WorldExtents.X)
3665 {
3666 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3667 m_outbounds = true;
3668 }
3669 if (lpos.Y < 0f)
3670 {
3671 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3672 m_outbounds = true;
3673 }
3674 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3675 {
3676 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3677 m_outbounds = true;
3678 }
3679
3680 if (m_outbounds)
3681 {
3682 m_lastposition = _position;
3683 m_lastorientation = _orientation;
3684
3685 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3686 m_rotationalVelocity.X = dtmp.X;
3687 m_rotationalVelocity.Y = dtmp.Y;
3688 m_rotationalVelocity.Z = dtmp.Z;
3689
3690 dtmp = d.BodyGetLinearVel(Body);
3691 _velocity.X = dtmp.X;
3692 _velocity.Y = dtmp.Y;
3693 _velocity.Z = dtmp.Z;
3694
3695 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3696 d.BodySetAngularVel(Body, 0, 0, 0);
3697 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3698 disableBodySoft(); // stop collisions
3699 UnSubscribeEvents();
3700
3701 base.RequestPhysicsterseUpdate();
3702 return;
3703 }
3704
3705 d.Quaternion ori;
3706 d.GeomCopyQuaternion(prim_geom, out ori);
3707
3708 // decide if moving
3709 // use positions since this are integrated quantities
3710 // tolerance values depende a lot on simulation noise...
3711 // use simple math.abs since we dont need to be exact
3712
3713 if (
3714 (Math.Abs(_position.X - lpos.X) < 0.001f)
3715 && (Math.Abs(_position.Y - lpos.Y) < 0.001f)
3716 && (Math.Abs(_position.Z - lpos.Z) < 0.001f)
3717 && (Math.Abs(_orientation.X - ori.X) < 0.0001f)
3718 && (Math.Abs(_orientation.Y - ori.Y) < 0.0001f)
3719 && (Math.Abs(_orientation.Z - ori.Z) < 0.0001f) // ignore W
3720 )
3721 {
3722 _zeroFlag = true;
3723 }
3724 else
3725 _zeroFlag = false;
3726
3727 // update velocities and aceleration
3728 if (!(_zeroFlag && lastZeroFlag))
3729 {
3730 d.Vector3 vel = d.BodyGetLinearVel(Body);
3731
3732 _acceleration = _velocity;
3733
3734 if ((Math.Abs(vel.X) < 0.001f) &&
3735 (Math.Abs(vel.Y) < 0.001f) &&
3736 (Math.Abs(vel.Z) < 0.001f))
3737 {
3738 _velocity = Vector3.Zero;
3739 float t = -m_invTimeStep;
3740 _acceleration = _acceleration * t;
3741 }
3742 else
3743 {
3744 _velocity.X = vel.X;
3745 _velocity.Y = vel.Y;
3746 _velocity.Z = vel.Z;
3747 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3748 }
3749
3750 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3751 (Math.Abs(_acceleration.Y) < 0.01f) &&
3752 (Math.Abs(_acceleration.Z) < 0.01f))
3753 {
3754 _acceleration = Vector3.Zero;
3755 }
3756
3757 if ((Math.Abs(_orientation.X - ori.X) < 0.0001) &&
3758 (Math.Abs(_orientation.Y - ori.Y) < 0.0001) &&
3759 (Math.Abs(_orientation.Z - ori.Z) < 0.0001)
3760 )
3761 {
3762 m_rotationalVelocity = Vector3.Zero;
3763 }
3764 else
3765 {
3766 vel = d.BodyGetAngularVel(Body);
3767 m_rotationalVelocity.X = vel.X;
3768 m_rotationalVelocity.Y = vel.Y;
3769 m_rotationalVelocity.Z = vel.Z;
3770 }
3771 }
3772
3773 if (_zeroFlag)
3774 {
3775 if (lastZeroFlag)
3776 {
3777 _velocity = Vector3.Zero;
3778 _acceleration = Vector3.Zero;
3779 m_rotationalVelocity = Vector3.Zero;
3780 }
3781
3782 if (!m_lastUpdateSent)
3783 {
3784 base.RequestPhysicsterseUpdate();
3785 if (lastZeroFlag)
3786 m_lastUpdateSent = true;
3787 }
3788 return;
3789 }
3790
3791 _position.X = lpos.X;
3792 _position.Y = lpos.Y;
3793 _position.Z = lpos.Z;
3794
3795 _orientation.X = ori.X;
3796 _orientation.Y = ori.Y;
3797 _orientation.Z = ori.Z;
3798 _orientation.W = ori.W;
3799 base.RequestPhysicsterseUpdate();
3800 m_lastUpdateSent = false;
3801 }
3802 }
3803 }
3804
3805 internal static bool QuaternionIsFinite(Quaternion q)
3806 {
3807 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3808 return false;
3809 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3810 return false;
3811 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3812 return false;
3813 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3814 return false;
3815 return true;
3816 }
3817
3818 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3819 {
3820 // assumes object center of mass is zero
3821 float smass = part.mass;
3822 theobj.mass -= smass;
3823
3824 smass *= 1.0f / (theobj.mass); ;
3825
3826 theobj.c.X -= part.c.X * smass;
3827 theobj.c.Y -= part.c.Y * smass;
3828 theobj.c.Z -= part.c.Z * smass;
3829
3830 theobj.I.M00 -= part.I.M00;
3831 theobj.I.M01 -= part.I.M01;
3832 theobj.I.M02 -= part.I.M02;
3833 theobj.I.M10 -= part.I.M10;
3834 theobj.I.M11 -= part.I.M11;
3835 theobj.I.M12 -= part.I.M12;
3836 theobj.I.M20 -= part.I.M20;
3837 theobj.I.M21 -= part.I.M21;
3838 theobj.I.M22 -= part.I.M22;
3839 }
3840
3841 private void donullchange()
3842 {
3843 }
3844
3845 public bool DoAChange(changes what, object arg)
3846 {
3847 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.Remove)
3848 {
3849 return false;
3850 }
3851
3852 // nasty switch
3853 switch (what)
3854 {
3855 case changes.Add:
3856 changeadd();
3857 break;
3858 case changes.Remove:
3859 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3860 //When we return true, it destroys all of the prims in the linkset anyway
3861 if (_parent != null)
3862 {
3863 OdePrim parent = (OdePrim)_parent;
3864 parent.ChildRemove(this, false);
3865 }
3866 else
3867 ChildRemove(this, false);
3868
3869 m_vehicle = null;
3870 RemoveGeom();
3871 m_targetSpace = IntPtr.Zero;
3872 UnSubscribeEvents();
3873 return true;
3874
3875 case changes.Link:
3876 OdePrim tmp = (OdePrim)arg;
3877 changeLink(tmp);
3878 break;
3879
3880 case changes.DeLink:
3881 changeLink(null);
3882 break;
3883
3884 case changes.Position:
3885 changePosition((Vector3)arg);
3886 break;
3887
3888 case changes.Orientation:
3889 changeOrientation((Quaternion)arg);
3890 break;
3891
3892 case changes.PosOffset:
3893 donullchange();
3894 break;
3895
3896 case changes.OriOffset:
3897 donullchange();
3898 break;
3899
3900 case changes.Velocity:
3901 changevelocity((Vector3)arg);
3902 break;
3903
3904// case changes.Acceleration:
3905// changeacceleration((Vector3)arg);
3906// break;
3907
3908 case changes.AngVelocity:
3909 changeangvelocity((Vector3)arg);
3910 break;
3911
3912 case changes.Force:
3913 changeForce((Vector3)arg);
3914 break;
3915
3916 case changes.Torque:
3917 changeSetTorque((Vector3)arg);
3918 break;
3919
3920 case changes.AddForce:
3921 changeAddForce((Vector3)arg);
3922 break;
3923
3924 case changes.AddAngForce:
3925 changeAddAngularImpulse((Vector3)arg);
3926 break;
3927
3928 case changes.AngLock:
3929 changeAngularLock((Vector3)arg);
3930 break;
3931
3932 case changes.Size:
3933 changeSize((Vector3)arg);
3934 break;
3935
3936 case changes.Shape:
3937 changeShape((PrimitiveBaseShape)arg);
3938 break;
3939
3940 case changes.CollidesWater:
3941 changeFloatOnWater((bool)arg);
3942 break;
3943
3944 case changes.VolumeDtc:
3945 changeVolumedetetion((bool)arg);
3946 break;
3947
3948 case changes.Phantom:
3949 changePhantomStatus((bool)arg);
3950 break;
3951
3952 case changes.Physical:
3953 changePhysicsStatus((bool)arg);
3954 break;
3955
3956 case changes.Selected:
3957 changeSelectedStatus((bool)arg);
3958 break;
3959
3960 case changes.disabled:
3961 changeDisable((bool)arg);
3962 break;
3963
3964 case changes.building:
3965 changeBuilding((bool)arg);
3966 break;
3967
3968 case changes.VehicleType:
3969 changeVehicleType((int)arg);
3970 break;
3971
3972 case changes.VehicleFlags:
3973 changeVehicleFlags((strVehicleBoolParam) arg);
3974 break;
3975
3976 case changes.VehicleFloatParam:
3977 changeVehicleFloatParam((strVehicleFloatParam) arg);
3978 break;
3979
3980 case changes.VehicleVectorParam:
3981 changeVehicleVectorParam((strVehicleVectorParam) arg);
3982 break;
3983
3984 case changes.VehicleRotationParam:
3985 changeVehicleRotationParam((strVehicleQuatParam) arg);
3986 break;
3987
3988 case changes.SetVehicle:
3989 changeSetVehicle((VehicleData) arg);
3990 break;
3991 case changes.Null:
3992 donullchange();
3993 break;
3994
3995 default:
3996 donullchange();
3997 break;
3998 }
3999 return false;
4000 }
4001
4002 public void AddChange(changes what, object arg)
4003 {
4004 _parent_scene.AddChange((PhysicsActor) this, what, arg);
4005 }
4006
4007
4008 private struct strVehicleBoolParam
4009 {
4010 public int param;
4011 public bool value;
4012 }
4013
4014 private struct strVehicleFloatParam
4015 {
4016 public int param;
4017 public float value;
4018 }
4019
4020 private struct strVehicleQuatParam
4021 {
4022 public int param;
4023 public Quaternion value;
4024 }
4025
4026 private struct strVehicleVectorParam
4027 {
4028 public int param;
4029 public Vector3 value;
4030 }
4031 }
4032}