From e9153e1d1aae50024d8cd05fe14a9bce34343a0e Mon Sep 17 00:00:00 2001 From: teravus Date: Thu, 15 Nov 2012 10:05:16 -0500 Subject: Revert "Merge master into teravuswork", it should have been avination, not master. This reverts commit dfac269032300872c4d0dc507f4f9062d102b0f4, reversing changes made to 619c39e5144f15aca129d6d999bcc5c34133ee64. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 689 +++++++++------------ 1 file changed, 291 insertions(+), 398 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e..e2f7af9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -28,48 +28,62 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using OMV = OpenMetaverse; +using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSCharacter : BSPhysObject +public class BSCharacter : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; + private BSScene _scene; + public BSScene Scene { get { return _scene; } } + private String _avName; // private bool _stopped; - private OMV.Vector3 _size; + private Vector3 _size; + private Vector3 _scale; + private PrimitiveBaseShape _pbs; + private uint _localID = 0; private bool _grabbed; private bool _selected; - private OMV.Vector3 _position; + private Vector3 _position; private float _mass; - private float _avatarDensity; - private float _avatarVolume; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; + public float _density; + public float _avatarVolume; + private Vector3 _force; + private Vector3 _velocity; + private Vector3 _torque; private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; + private Vector3 _acceleration; + private Quaternion _orientation; private int _physicsActorType; private bool _isPhysical; private bool _flying; private bool _setAlwaysRun; private bool _throttleUpdates; private bool _isColliding; + private long _collidingStep; + private bool _collidingGround; + private long _collidingGroundStep; private bool _collidingObj; private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; + private Vector3 _rotationalVelocity; private bool _kinematic; private float _buoyancy; - // The friction and velocity of the avatar is modified depending on whether walking or not. - private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar - private float _currentFriction; // the friction currently being used (changed by setVelocity). + private BulletBody m_body; + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } + + private int _subscribedEventsMs = 0; + private int _nextCollisionOkTime = 0; - private OMV.Vector3 _PIDTarget; + private Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; private bool _useHoverPID; @@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject private PIDHoverType _PIDHoverType; private float _PIDHoverTao; - public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) + public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) { - base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); - _physicsActorType = (int)ActorTypes.Agent; + _localID = localID; + _avName = avName; + _scene = parent_scene; _position = pos; _size = size; _flying = isFlying; - _orientation = OMV.Quaternion.Identity; - _velocity = OMV.Vector3.Zero; - _appliedVelocity = OMV.Vector3.Zero; + _orientation = Quaternion.Identity; + _velocity = Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - _avatarDensity = PhysicsScene.Params.avatarDensity; - // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - ComputeAvatarScale(_size); - // set _avatarVolume and _mass based on capsule size, _density and Scale - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); + _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); + _density = _scene.Params.avatarDensity; + ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + + ShapeData shapeData = new ShapeData(); + shapeData.ID = _localID; + shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; + shapeData.Position = _position; + shapeData.Rotation = _orientation; + shapeData.Velocity = _velocity; + shapeData.Scale = _scale; + shapeData.Mass = _mass; + shapeData.Buoyancy = _buoyancy; + shapeData.Static = ShapeData.numericFalse; + shapeData.Friction = _scene.Params.avatarFriction; + shapeData.Restitution = _scene.Params.avatarRestitution; // do actual create at taint time - PhysicsScene.TaintedObject("BSCharacter.create", delegate() + _scene.TaintedObject("BSCharacter.create", delegate() { - DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into BSBody and BSShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); + BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); - SetPhysicalProperties(); + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + // avatars get all collisions no matter what + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); + return; } // called when this character is being destroyed and the resources should be released - public override void Destroy() + public void Destroy() { - DetailLog("{0},BSCharacter.Destroy", LocalID); - PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() + // DetailLog("{0},BSCharacter.Destroy", LocalID); + _scene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + BulletSimAPI.DestroyObject(_scene.WorldID, _localID); }); } - private void SetPhysicalProperties() - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - ZeroMotion(); - ForcePosition = _position; - // Set the velocity and compute the proper friction - ForceVelocity = _velocity; - - BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - UpdatePhysicalMassProperties(RawMass); - - // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - - BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Do this after the object has been added to the world - BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, - (uint)CollisionFilterGroups.AvatarMask); - } - public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { get { return false; } } - - public override OMV.Vector3 Size { + public override bool Stopped { + get { return false; } + } + public override Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - // return _size; - return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); + return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); } - set { - // When an avatar's size is set, only the height is changed. + set { + // When an avatar's size is set, only the height is changed + // and that really only depends on the radius. _size = value; - ComputeAvatarScale(_size); + _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); + + // TODO: something has to be done with the avatar's vertical position + ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); - PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() + _scene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(RawMass); + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); }); - } + } } - - public override OMV.Vector3 Scale { get; set; } - - public override PrimitiveBaseShape Shape - { - set { BaseShape = value; } + public override PrimitiveBaseShape Shape { + set { _pbs = value; + } } - // I want the physics engine to make an avatar capsule - public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { - get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + public override uint LocalID { + set { _localID = value; + } + get { return _localID; } } - - public override bool Grabbed { - set { _grabbed = value; } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { - set { _selected = value; } + public override bool Selected { + set { _selected = value; + } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } public override void delink() { return; } + public override void LockAngularMotion(Vector3 axis) { return; } - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion() - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(PhysBody.ptr); - } - - public override void LockAngularMotion(OMV.Vector3 axis) { return; } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { + public override Vector3 Position { get { - // Don't refetch the position because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); - return _position; - } + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + return _position; + } set { _position = value; PositionSanityCheck(); - PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() + _scene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } + } } - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain or on water. + // Check for being below terrain and being out of bounds. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) + float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); + if (_position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); _position.Z = terrainHeight + 2.0f; ret = true; } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } // TODO: check for out of bounds - return ret; - } - // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() - { - DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }); - ret = true; - } return ret; } - public override float Mass { get { return _mass; } } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get {return _mass; } - } - public override void UpdatePhysicalMassProperties(float physMass) - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); + public override float Mass { + get { + return _mass; + } } - - public override OMV.Vector3 Force { - get { return _force; } + public override Vector3 Force { + get { return _force; } set { _force = value; // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() + Scene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); }); - } + } } - // Avatars don't do vehicles - public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } + public override int VehicleType { + get { return 0; } + set { return; } + } public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, OMV.Vector3 value) {} - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } + public override void VehicleVectorParam(int param, Vector3 value) {} + public override void VehicleRotationParam(int param, Quaternion rotation) { } public override void VehicleFlags(int param, bool remove) { } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { return; } - public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 Velocity { - get { return _velocity; } + public override Vector3 GeometricCenter { get { return Vector3.Zero; } } + public override Vector3 CenterOfMass { get { return Vector3.Zero; } } + public override Vector3 Velocity { + get { return _velocity; } set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() + _scene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; + BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); }); - } - } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - // Depending on whether the avatar is moving or not, change the friction - // to keep the avatar from slipping around - if (_velocity.Length() == 0) - { - if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) - { - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - else - { - if (_currentFriction != PhysicsScene.Params.avatarFriction) - { - _currentFriction = PhysicsScene.Params.avatarFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - _velocity = value; - // Remember the set velocity so we can suppress the reduction by friction, ... - _appliedVelocity = value; - - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - BulletSimAPI.Activate2(PhysBody.ptr, true); - } + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } + public override Vector3 Torque { + get { return _torque; } + set { _torque = value; + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { return _orientation; } + public override Quaternion Orientation { + get { return _orientation; } set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() + _scene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { _isPhysical = value; - } - } - public override bool IsSolid { - get { return true; } + } } - public override bool IsStatic { - get { return false; } - } - public override bool Flying { - get { return _flying; } + public override bool Flying { + get { return _flying; } set { - _flying = value; - // simulate flying by changing the effect of gravity - Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + if (_flying != value) + { + _flying = value; + // simulate flying by changing the effect of gravity + this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + } + } } - // Flying is implimented by changing the avatar's buoyancy. - // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } - public override bool - SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool + SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (_collidingStep == _scene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { CollidingGround = value; } - } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + get { return (_collidingGroundStep == _scene.SimulationStep); } + set { _collidingGround = value; } } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 ForceRotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override Vector3 RotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; } } // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() + public override float Buoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - ForceBuoyancy = _buoyancy; + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } // For RotLookAt - public override OMV.Quaternion APIDTarget { set { return; } } + public override Quaternion APIDTarget { set { return; } } public override bool APIDActive { set { return; } } public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } - public override void AddForce(OMV.Vector3 force, bool pushforce) { + public override void AddForce(Vector3 force, bool pushforce) { if (force.IsFinite()) { _force.X += force.X; _force.Y += force.Y; _force.Z += force.Z; // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() + _scene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.AddObjectForce2(Body.Ptr, _force); }); } else @@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject //m_lastUpdateSent = false; } - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + public override void AddAngularForce(Vector3 force, bool pushforce) { } - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(Vector3 momentum) { } - private void ComputeAvatarScale(OMV.Vector3 size) - { - // The 'size' given by the simulator is the mid-point of the avatar - // and X and Y are unspecified. - - OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + // Turn on collision events at a rate no faster than one every the given milliseconds + public override void SubscribeEvents(int ms) { + _subscribedEventsMs = ms; + if (ms > 0) + { + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z- (newScale.X + newScale.Y); - Scale = newScale; + Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() + { + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + } + // Stop collision events + public override void UnSubscribeEvents() { + _subscribedEventsMs = 0; + // Avatars get all their collision events + // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() + // { + // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + // }); + } + // Return 'true' if someone has subscribed to events + public override bool SubscribedEvents() { + return (_subscribedEventsMs > 0); } - // set _avatarVolume and _mass based on capsule size, _density and Scale + // set _avatarVolume and _mass based on capsule size, _density and _scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder + * _scale.X + * _scale.Y // the area of capsule cylinder + * _scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps + * _scale.X + * Math.Min(_scale.X, _scale.Y) + * _scale.Y // plus the volume of the capsule end caps ); - _mass = _avatarDensity * _avatarVolume; + _mass = _density * _avatarVolume; } // The physics engine says that properties have updated. Update same and inform // the world that things have changed. - public override void UpdateProperties(EntityProperties entprop) + public void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); + // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. + // base.RequestPhysicsterseUpdate(); + + /* + DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + entprop.Acceleration, entprop.RotationalVelocity); + */ + } - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; + // Called by the scene when a collision with this object is reported + // The collision, if it should be reported to the character, is placed in a collection + // that will later be sent to the simulator when SendCollisions() is called. + CollisionEventUpdate collisionCollection = null; + public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + { + // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); - if (entprop.Velocity != LastEntityProperties.Velocity) + // The following makes IsColliding() and IsCollidingGround() work + _collidingStep = _scene.SimulationStep; + if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) { - // Changes in the velocity are suppressed in avatars. - // That's just the way they are defined. - OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); - _velocity = avVel; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); + _collidingGroundStep = _scene.SimulationStep; } + // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); - // Tell the linkset about value changes - Linkset.UpdateProperties(this); + // throttle collisions to the rate specified in the subscription + if (_subscribedEventsMs != 0) { + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; - // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. - // base.RequestPhysicsterseUpdate(); + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } + } - DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + public void SendCollisions() + { + /* + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + collisionCollection = null; + } + */ + // Kludge to make a collision call even if there are no collisions. + // This causes the avatar animation to get updated. + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + base.SendCollisionUpdate(collisionCollection); + // If there were any collisions in the collection, make sure we don't use the + // same instance next time. + if (collisionCollection.Count > 0) + collisionCollection = null; + // End kludge + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); } } } -- cgit v1.1