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