28 using System.Collections.Generic;
29 using System.Reflection;
31 using OMV = OpenMetaverse;
32 using OpenSim.Framework;
33 using OpenSim.Region.PhysicsModules.SharedBase;
35 namespace OpenSim.
Region.PhysicsModule.BulletS
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly
string LogHeader =
"[BULLETS CHAR]";
43 private bool _grabbed;
44 private bool _selected;
46 private float _avatarVolume;
47 private float _collisionScore;
48 private OMV.Vector3 _acceleration;
49 private int _physicsActorType;
50 private bool _isPhysical;
52 private bool _setAlwaysRun;
53 private bool _throttleUpdates;
54 private bool _floatOnWater;
55 private OMV.Vector3 _rotationalVelocity;
56 private bool _kinematic;
57 private float _buoyancy;
59 private OMV.Vector3 _size;
60 private float _footOffset;
63 private const string AvatarMoveActorName =
"BSCharacter.AvatarMove";
65 private OMV.Vector3 _PIDTarget;
66 private float _PIDTau;
78 public override bool IsIncomplete {
get {
return false; } }
81 uint localID, String avName,
BSScene parent_scene,
OMV.Vector3 pos,
OMV.Vector3 vel,
OMV.Vector3 size,
float footOffset,
bool isFlying)
83 : base(parent_scene, localID, avName,
"BSCharacter")
89 RawOrientation =
OMV.Quaternion.Identity;
91 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
92 Friction = BSParam.AvatarStandingFriction;
93 Density = BSParam.AvatarDensity;
98 SetAvatarSize(size, footOffset,
true );
101 "{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6},vel={7}",
102 LocalID,
Size,
Scale, Density, _avatarVolume, RawMass, pos, vel);
105 PhysScene.TaintedObject(LocalID,
"BSCharacter.create", delegate()
107 DetailLog(
"{0},BSCharacter.create,taint", LocalID);
110 PhysScene.Shapes.GetBodyAndShape(
true, PhysScene.World,
this);
117 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
119 SetPhysicalProperties();
121 IsInitialized =
true;
129 IsInitialized =
false;
133 DetailLog(
"{0},BSCharacter.Destroy", LocalID);
134 PhysScene.TaintedObject(LocalID,
"BSCharacter.destroy", delegate()
136 PhysScene.Shapes.DereferenceBody(PhysBody, null );
138 PhysShape.Dereference(PhysScene);
143 private void SetPhysicalProperties()
145 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
147 ForcePosition = RawPosition;
150 if (m_moveActor != null)
151 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity,
false);
153 ForceVelocity = RawVelocity;
154 TargetVelocity = RawVelocity;
160 PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
161 PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
162 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo,
Scale);
163 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
164 if (BSParam.CcdMotionThreshold > 0f)
166 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
167 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
170 UpdatePhysicalMassProperties(RawMass,
false);
173 PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
176 PhysicalActors.Refresh();
178 PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
180 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
183 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
184 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
187 if (BSParam.AvatarToAvatarCollisionsByDefault)
188 PhysBody.collisionType = CollisionType.Avatar;
190 PhysBody.collisionType = CollisionType.PhantomToOthersAvatar;
192 PhysBody.ApplyCollisionMask(PhysScene);
197 base.RequestPhysicsterseUpdate();
201 public override bool Stopped {
get {
return false; } }
203 public override OMV.Vector3
Size {
210 setAvatarSize(value, _footOffset);
217 SetAvatarSize(size, feetOffset,
false );
223 OMV.Vector3 newSize = size;
224 if (newSize.IsFinite())
228 if (newSize.X == 0f) newSize.X = BSParam.AvatarCapsuleDepth;
229 if (newSize.Y == 0f) newSize.Y = BSParam.AvatarCapsuleWidth;
231 if (newSize.X < 0.01f) newSize.X = 0.01f;
232 if (newSize.Y < 0.01f) newSize.Y = 0.01f;
233 if (newSize.Z < 0.01f) newSize.Z = BSParam.AvatarCapsuleHeight;
237 newSize =
new OMV.Vector3(BSParam.AvatarCapsuleDepth, BSParam.AvatarCapsuleWidth, BSParam.AvatarCapsuleHeight);
242 float heightChange = newSize.Z - Size.Z;
247 ComputeAvatarVolumeAndMass();
248 DetailLog(
"{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
249 LocalID, _size,
Scale, Density, _avatarVolume, RawMass);
251 PhysScene.TaintedObject(LocalID,
"BSCharacter.setSize", delegate()
253 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
255 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo,
Scale);
256 UpdatePhysicalMassProperties(RawMass,
true);
259 ForcePosition =
new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
262 PhysScene.PE.PushUpdate(PhysBody);
269 set { BaseShape = value; }
272 public override bool Grabbed {
273 set { _grabbed = value; }
275 public override bool Selected {
276 set { _selected = value; }
278 public override bool IsSelected
280 get {
return _selected; }
284 public override void delink() {
return; }
292 RawVelocity = OMV.Vector3.Zero;
293 _acceleration = OMV.Vector3.Zero;
294 _rotationalVelocity = OMV.Vector3.Zero;
297 PhysScene.TaintedObject(inTaintTime, LocalID,
"BSCharacter.ZeroMotion", delegate()
299 if (PhysBody.HasPhysicalBody)
300 PhysScene.PE.ClearAllForces(PhysBody);
306 _rotationalVelocity = OMV.Vector3.Zero;
308 PhysScene.TaintedObject(inTaintTime, LocalID,
"BSCharacter.ZeroMotion", delegate()
310 if (PhysBody.HasPhysicalBody)
312 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
313 PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
315 PhysScene.PE.ClearForces(PhysBody);
332 PhysScene.TaintedObject(LocalID,
"BSCharacter.setPosition", delegate()
334 DetailLog(
"{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
335 PositionSanityCheck();
336 ForcePosition = RawPosition;
340 public override OMV.Vector3 ForcePosition {
342 RawPosition = PhysScene.PE.GetPosition(PhysBody);
347 if (PhysBody.HasPhysicalBody)
349 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
358 private bool PositionSanityCheck()
363 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
368 RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
369 DetailLog(
"{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
374 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
377 DetailLog(
"{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
378 RawPosition =
new OMV.Vector3(RawPosition.X, RawPosition.Y, terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters);
381 if ((CurrentCollisionFlags &
CollisionFlags.BS_FLOATS_ON_WATER) != 0)
383 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
386 RawPosition =
new OMV.Vector3(RawPosition.X, RawPosition.Y, waterHeight);
397 private bool PositionSanityCheck(
bool inTaintTime)
400 if (PositionSanityCheck())
404 PhysScene.TaintedObject(inTaintTime, LocalID,
"BSCharacter.PositionSanityCheck", delegate()
406 DetailLog(
"{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
407 ForcePosition = RawPosition;
414 public override float Mass {
get {
return _mass; } }
417 public override float RawMass {
422 OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
423 PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
426 public override OMV.Vector3 Force {
427 get {
return RawForce; }
431 PhysScene.TaintedObject(LocalID,
"BSCharacter.SetForce", delegate()
433 DetailLog(
"{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
434 if (PhysBody.HasPhysicalBody)
435 PhysScene.PE.SetObjectForce(PhysBody, RawForce);
441 public override int VehicleType {
get {
return (
int)Vehicle.TYPE_NONE; } set {
return; } }
449 public override bool IsVolumeDetect {
get {
return false; } }
451 public override OMV.Vector3 GeometricCenter {
get {
return OMV.Vector3.Zero; } }
452 public override OMV.Vector3 CenterOfMass {
get {
return OMV.Vector3.Zero; } }
455 public override OMV.Vector3 TargetVelocity
459 return base.m_targetVelocity;
463 DetailLog(
"{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
464 m_targetVelocity = value;
465 OMV.Vector3 targetVel = value;
466 if (_setAlwaysRun && !_flying)
467 targetVel *=
new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 1f);
469 if (m_moveActor != null)
470 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel,
false );
475 get {
return RawVelocity; }
478 OMV.Vector3 vel = RawVelocity;
480 DetailLog(
"{0}: set Velocity = {1}", LocalID, value);
482 PhysScene.TaintedObject(LocalID,
"BSCharacter.setVelocity", delegate()
484 if (m_moveActor != null)
485 m_moveActor.SetVelocityAndTarget(vel, vel,
true );
487 DetailLog(
"{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, vel);
493 public override OMV.Vector3 ForceVelocity {
494 get {
return RawVelocity; }
496 PhysScene.AssertInTaintTime(
"BSCharacter.ForceVelocity");
498 DetailLog(
"{0}: set ForceVelocity = {1}", LocalID, value);
501 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
502 PhysScene.PE.Activate(PhysBody,
true);
506 public override OMV.Vector3 Torque {
507 get {
return RawTorque; }
508 set { RawTorque = value;
512 public override float CollisionScore {
513 get {
return _collisionScore; }
514 set { _collisionScore = value;
518 get {
return _acceleration; }
519 set { _acceleration = value; }
522 get {
return RawOrientation; }
526 if (RawOrientation != value)
528 RawOrientation = value;
529 PhysScene.TaintedObject(LocalID,
"BSCharacter.setOrientation", delegate()
535 float oRoll, oPitch, oYaw;
536 RawOrientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
537 OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
541 ForceOrientation = trimmedOrientation;
547 public override OMV.Quaternion ForceOrientation
551 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
552 return RawOrientation;
556 RawOrientation = value;
557 if (PhysBody.HasPhysicalBody)
560 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
564 public override int PhysicsActorType {
565 get {
return _physicsActorType; }
566 set { _physicsActorType = value;
569 public override bool IsPhysical {
570 get {
return _isPhysical; }
571 set { _isPhysical = value;
574 public override bool IsSolid {
577 public override bool IsStatic {
578 get {
return false; }
580 public override bool IsPhysicallyActive {
583 public override bool Flying {
584 get {
return _flying; }
589 Buoyancy = ComputeBuoyancyFromFlying(_flying);
594 private float ComputeBuoyancyFromFlying(
bool ifFlying) {
595 return ifFlying ? 1f : 0f;
599 get {
return _setAlwaysRun; }
600 set { _setAlwaysRun = value; }
602 public override bool ThrottleUpdates {
603 get {
return _throttleUpdates; }
604 set { _throttleUpdates = value; }
606 public override bool FloatOnWater {
608 _floatOnWater = value;
609 PhysScene.TaintedObject(LocalID,
"BSCharacter.setFloatOnWater", delegate()
611 if (PhysBody.HasPhysicalBody)
614 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
616 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
622 get {
return _rotationalVelocity; }
623 set { _rotationalVelocity = value; }
625 public override OMV.Vector3 ForceRotationalVelocity {
626 get {
return _rotationalVelocity; }
627 set { _rotationalVelocity = value; }
629 public override bool Kinematic {
630 get {
return _kinematic; }
631 set { _kinematic = value; }
634 public override float Buoyancy {
635 get {
return _buoyancy; }
636 set { _buoyancy = value;
637 PhysScene.TaintedObject(LocalID,
"BSCharacter.setBuoyancy", delegate()
639 DetailLog(
"{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
640 ForceBuoyancy = _buoyancy;
644 public override float ForceBuoyancy {
645 get {
return _buoyancy; }
647 PhysScene.AssertInTaintTime(
"BSCharacter.ForceBuoyancy");
650 DetailLog(
"{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
652 float grav = BSParam.Gravity * (1f - _buoyancy);
653 Gravity =
new OMV.Vector3(0f, 0f, grav);
654 if (PhysBody.HasPhysicalBody)
655 PhysScene.PE.SetGravity(PhysBody, Gravity);
660 public override OMV.Vector3 PIDTarget {
661 set { _PIDTarget = value; }
664 public override bool PIDActive {
get; set; }
666 public override float PIDTau {
667 set { _PIDTau = value; }
673 OMV.Vector3 addForce = force;
680 addForce *= Mass * BSParam.AvatarAddForcePushFactor;
682 DetailLog(
"{0},BSCharacter.addForce,call,force={1},addForce={2},push={3},mass={4}", LocalID, force, addForce, pushforce, Mass);
683 AddForce(
false, addForce);
686 public override void AddForce(
bool inTaintTime,
OMV.Vector3 force) {
687 if (force.IsFinite())
689 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
692 PhysScene.TaintedObject(inTaintTime, LocalID,
"BSCharacter.AddForce", delegate()
696 if (PhysBody.HasPhysicalBody)
701 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
702 PhysScene.PE.Activate(PhysBody,
true);
704 if (m_moveActor != null)
706 m_moveActor.SuppressStationayCheckUntilLowVelocity();
712 m_log.WarnFormat(
"{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID);
724 private OMV.Vector3 ComputeAvatarScale(
OMV.Vector3 size)
726 OMV.Vector3 newScale = size;
728 if (BSParam.AvatarUseBefore09SizeComputation)
743 float heightAdjust = BSParam.AvatarHeightMidFudge;
744 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
746 const float AVATAR_LOW = 1.1f;
747 const float AVATAR_MID = 1.775f;
748 const float AVATAR_HI = 2.45f;
750 float midHeightOffset = size.Z - AVATAR_MID;
751 if (midHeightOffset < 0f)
754 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
759 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
762 if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule)
764 newScale.X = size.X / 2f;
765 newScale.Y = size.Y / 2f;
767 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f;
771 newScale.Z = size.Z + heightAdjust;
779 DetailLog(
"{0},BSCharacter.ComputeAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
780 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
784 newScale.Z = size.Z + _footOffset;
785 DetailLog(
"{0},BSCharacter.ComputeAvatarScale,using newScale={1}, footOffset={2}", LocalID, newScale, _footOffset);
792 private void ComputeAvatarVolumeAndMass()
794 if (BSParam.AvatarShape == BSShapeCollection.AvatarShapeCapsule)
796 _avatarVolume = (float)(
810 _avatarVolume = Size.X * Size.Y * Size.Z;
812 _mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
820 TriggerPreUpdatePropertyAction(ref entprop);
822 RawPosition = entprop.Position;
823 RawOrientation = entprop.Rotation;
841 RawVelocity = entprop.Velocity;
843 _acceleration = entprop.Acceleration;
844 _rotationalVelocity = entprop.RotationalVelocity;
847 if (PositionSanityCheck(
true))
849 DetailLog(
"{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, RawPosition);
850 entprop.Position = RawPosition;
854 LastEntityProperties = CurrentEntityProperties;
855 CurrentEntityProperties = entprop;
863 DetailLog(
"{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
864 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
override void CrossingFailure()
override void UpdateProperties(EntityProperties entprop)
delegate void SetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun)
override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
override void AddForce(OMV.Vector3 force, bool pushforce)
override void VehicleFloatParam(int param, float value)
override void setAvatarSize(OMV.Vector3 size, float feetOffset)
override void AddForce(bool inTaintTime, OMV.Vector3 force)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion rotation
override void SetVolumeDetect(int param)
Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more ...
BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 vel, OMV.Vector3 size, float footOffset, bool isFlying)
override void ZeroAngularMotion(bool inTaintTime)
override void ZeroMotion(bool inTaintTime)
override void RequestPhysicsterseUpdate()
override void LockAngularMotion(byte axislocks)
override void SetMomentum(OMV.Vector3 momentum)
override void VehicleFlags(int param, bool remove)
override void AddAngularForce(bool inTaintTime, OMV.Vector3 force)
override void link(PhysicsActor obj)
void SetAvatarSize(OMV.Vector3 size, float feetOffset, bool initializing)
override void VehicleVectorParam(int param, OMV.Vector3 value)
override void VehicleRotationParam(int param, OMV.Quaternion rotation)