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