Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
						commit
						c846cefda9
					
				| 
						 | 
					@ -6428,9 +6428,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
 | 
					                AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
 | 
				
			||||||
                if (handlerAgentRequestSit != null)
 | 
					                if (handlerAgentRequestSit != null)
 | 
				
			||||||
 | 
					                    if (!(agentRequestSit.AgentData == null
 | 
				
			||||||
 | 
					                        || agentRequestSit.TargetObject == null
 | 
				
			||||||
 | 
					                        || agentRequestSit.TargetObject.TargetID == null
 | 
				
			||||||
 | 
					                        || agentRequestSit.TargetObject.Offset == null))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        var sp = m_scene.GetScenePresence(agentRequestSit.AgentData.AgentID);
 | 
				
			||||||
 | 
					                        if (sp == null || sp.ParentID != 0) // ignore packet if agent is already sitting
 | 
				
			||||||
 | 
					                            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
 | 
					                        handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
 | 
				
			||||||
                                               agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
 | 
					                                               agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4050,9 +4050,9 @@ namespace OpenSim.Region.Framework.Scenes
 | 
				
			||||||
                        rigidBody,
 | 
					                        rigidBody,
 | 
				
			||||||
                        m_localId);
 | 
					                        m_localId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch
 | 
					            catch (Exception e)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
 | 
					                m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
 | 
				
			||||||
                pa = null;
 | 
					                pa = null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public PhysicsScene GetScene(string sceneIdentifier)
 | 
					        public PhysicsScene GetScene(string sceneIdentifier)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new BasicScene(sceneIdentifier);
 | 
					            return new BasicScene(GetName(), sceneIdentifier);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string GetName()
 | 
					        public string GetName()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,8 +49,10 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //protected internal string sceneIdentifier;
 | 
					        //protected internal string sceneIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public BasicScene(string _sceneIdentifier)
 | 
					        public BasicScene(string engineType, string _sceneIdentifier)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            EngineType = engineType;
 | 
				
			||||||
 | 
					            Name = EngineType + "/" + _sceneIdentifier;
 | 
				
			||||||
            //sceneIdentifier = _sceneIdentifier;
 | 
					            //sceneIdentifier = _sceneIdentifier;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,6 +327,12 @@ public override void RemoveChildShapeFromCompoundShape(BulletShape shape, Bullet
 | 
				
			||||||
    BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
 | 
					    BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BulletShapeUnman shapeu = pShape as BulletShapeUnman;
 | 
				
			||||||
 | 
					    BSAPICPP.UpdateChildTransform2(shapeu.ptr, childIndex, pos, rot, shouldRecalculateLocalAabb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
 | 
					public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BulletShapeUnman shapeu = shape as BulletShapeUnman;
 | 
					    BulletShapeUnman shapeu = shape as BulletShapeUnman;
 | 
				
			||||||
| 
						 | 
					@ -1356,6 +1362,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap
 | 
				
			||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
 | 
					[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
 | 
				
			||||||
public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
 | 
					public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
 | 
				
			||||||
 | 
					public static extern void UpdateChildTransform2(IntPtr pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
 | 
					[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
 | 
				
			||||||
public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
 | 
					public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1212,6 +1212,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
 | 
					    public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
 | 
				
			||||||
    public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
 | 
					    public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
 | 
				
			||||||
 | 
					    public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb) { /* TODO */ }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
 | 
					    public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,6 +342,8 @@ public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
 | 
					public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
 | 
					public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
 | 
					public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,9 +126,9 @@ public sealed class BSCharacter : BSPhysObject
 | 
				
			||||||
        DetailLog("{0},BSCharacter.Destroy", LocalID);
 | 
					        DetailLog("{0},BSCharacter.Destroy", LocalID);
 | 
				
			||||||
        PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
 | 
					        PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
 | 
					            PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */);
 | 
				
			||||||
            PhysBody.Clear();
 | 
					            PhysBody.Clear();
 | 
				
			||||||
            PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
 | 
					            PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */);
 | 
				
			||||||
            PhysShape.Clear();
 | 
					            PhysShape.Clear();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -328,6 +328,10 @@ public sealed class BSCharacter : BSPhysObject
 | 
				
			||||||
    public override bool Selected {
 | 
					    public override bool Selected {
 | 
				
			||||||
        set { _selected = value; }
 | 
					        set { _selected = value; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public override bool IsSelected
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get { return _selected; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public override void CrossingFailure() { return; }
 | 
					    public override void CrossingFailure() { return; }
 | 
				
			||||||
    public override void link(PhysicsActor obj) { return; }
 | 
					    public override void link(PhysicsActor obj) { return; }
 | 
				
			||||||
    public override void delink() { return; }
 | 
					    public override void delink() { return; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,10 +108,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        private float m_VhoverEfficiency = 0f;
 | 
					        private float m_VhoverEfficiency = 0f;
 | 
				
			||||||
        private float m_VhoverTimescale = 0f;
 | 
					        private float m_VhoverTimescale = 0f;
 | 
				
			||||||
        private float m_VhoverTargetHeight = -1.0f;     // if <0 then no hover, else its the current target height
 | 
					        private float m_VhoverTargetHeight = -1.0f;     // if <0 then no hover, else its the current target height
 | 
				
			||||||
        private float m_VehicleBuoyancy = 0f;           //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
 | 
					 | 
				
			||||||
        // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
 | 
					        // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
 | 
				
			||||||
                    // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
 | 
					        private float m_VehicleBuoyancy = 0f;
 | 
				
			||||||
                    // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
 | 
					        private Vector3 m_VehicleGravity = Vector3.Zero;    // Gravity computed when buoyancy set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //Attractor properties
 | 
					        //Attractor properties
 | 
				
			||||||
        private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
 | 
					        private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
 | 
				
			||||||
| 
						 | 
					@ -124,17 +123,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        static readonly float PIOverFour = ((float)Math.PI) / 4f;
 | 
					        static readonly float PIOverFour = ((float)Math.PI) / 4f;
 | 
				
			||||||
        static readonly float PIOverTwo = ((float)Math.PI) / 2f;
 | 
					        static readonly float PIOverTwo = ((float)Math.PI) / 2f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // For debugging, flags to turn on and off individual corrections.
 | 
				
			||||||
 | 
					        private bool enableAngularVerticalAttraction = true;
 | 
				
			||||||
 | 
					        private bool enableAngularDeflection = true;
 | 
				
			||||||
 | 
					        private bool enableAngularBanking = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public BSDynamics(BSScene myScene, BSPrim myPrim)
 | 
					        public BSDynamics(BSScene myScene, BSPrim myPrim)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            PhysicsScene = myScene;
 | 
					            PhysicsScene = myScene;
 | 
				
			||||||
            Prim = myPrim;
 | 
					            Prim = myPrim;
 | 
				
			||||||
            Type = Vehicle.TYPE_NONE;
 | 
					            Type = Vehicle.TYPE_NONE;
 | 
				
			||||||
 | 
					            SetupVehicleDebugging();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Stopgap debugging enablement. Allows source level debugging but still checking
 | 
				
			||||||
 | 
					        //    in changes by making enablement of debugging flags from INI file.
 | 
				
			||||||
 | 
					        public void SetupVehicleDebugging()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            enableAngularVerticalAttraction = true;
 | 
				
			||||||
 | 
					            enableAngularDeflection = true;
 | 
				
			||||||
 | 
					            enableAngularBanking = true;
 | 
				
			||||||
 | 
					            if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                enableAngularVerticalAttraction = false;
 | 
				
			||||||
 | 
					                enableAngularDeflection = false;
 | 
				
			||||||
 | 
					                enableAngularBanking = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Return 'true' if this vehicle is doing vehicle things
 | 
					        // Return 'true' if this vehicle is doing vehicle things
 | 
				
			||||||
        public bool IsActive
 | 
					        public bool IsActive
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; }
 | 
					            get { return (Type != Vehicle.TYPE_NONE && !Prim.IsStatic); }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Vehicle parameter setting
 | 
					        #region Vehicle parameter setting
 | 
				
			||||||
| 
						 | 
					@ -168,6 +188,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case Vehicle.BUOYANCY:
 | 
					                case Vehicle.BUOYANCY:
 | 
				
			||||||
                    m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
 | 
					                    m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
 | 
				
			||||||
 | 
					                    m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case Vehicle.HOVER_EFFICIENCY:
 | 
					                case Vehicle.HOVER_EFFICIENCY:
 | 
				
			||||||
                    m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
 | 
					                    m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
 | 
				
			||||||
| 
						 | 
					@ -540,12 +561,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                                1f);
 | 
					                                1f);
 | 
				
			||||||
            m_angularMotor.PhysicsScene = PhysicsScene;  // DEBUG DEBUG DEBUG (enables detail logging)
 | 
					            m_angularMotor.PhysicsScene = PhysicsScene;  // DEBUG DEBUG DEBUG (enables detail logging)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*  Not implemented
 | 
				
			||||||
            m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
 | 
					            m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
 | 
				
			||||||
                                BSMotor.Infinite, BSMotor.InfiniteVector,
 | 
					                                BSMotor.Infinite, BSMotor.InfiniteVector,
 | 
				
			||||||
                                m_verticalAttractionEfficiency);
 | 
					                                m_verticalAttractionEfficiency);
 | 
				
			||||||
            // Z goes away and we keep X and Y
 | 
					            // Z goes away and we keep X and Y
 | 
				
			||||||
            m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
 | 
					            m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
 | 
				
			||||||
            m_verticalAttractionMotor.PhysicsScene = PhysicsScene;  // DEBUG DEBUG DEBUG (enables detail logging)
 | 
					            m_verticalAttractionMotor.PhysicsScene = PhysicsScene;  // DEBUG DEBUG DEBUG (enables detail logging)
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        #endregion // Vehicle parameter setting
 | 
					        #endregion // Vehicle parameter setting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -571,15 +594,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                // Vehicles report collision events so we know when it's on the ground
 | 
					                // Vehicles report collision events so we know when it's on the ground
 | 
				
			||||||
                PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
 | 
					                PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
 | 
					                Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
 | 
				
			||||||
                PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia);
 | 
					                PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia);
 | 
				
			||||||
                PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
 | 
					                PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy);
 | 
					                // Set the gravity for the vehicle depending on the buoyancy
 | 
				
			||||||
                PhysicsScene.PE.SetGravity(Prim.PhysBody, grav);
 | 
					                // TODO: what should be done if prim and vehicle buoyancy differ?
 | 
				
			||||||
 | 
					                m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
 | 
				
			||||||
 | 
					                // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
 | 
				
			||||||
 | 
					                PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
 | 
					                VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4},grav={5}",
 | 
				
			||||||
                                Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
 | 
					                        Prim.LocalID, m_vehicleMass, friction, Prim.Inertia, angularDamping, m_VehicleGravity);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -619,6 +645,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        private Vector3 m_knownPosition;
 | 
					        private Vector3 m_knownPosition;
 | 
				
			||||||
        private Vector3 m_knownVelocity;
 | 
					        private Vector3 m_knownVelocity;
 | 
				
			||||||
        private Vector3 m_knownForce;
 | 
					        private Vector3 m_knownForce;
 | 
				
			||||||
 | 
					        private Vector3 m_knownForceImpulse;
 | 
				
			||||||
        private Quaternion m_knownOrientation;
 | 
					        private Quaternion m_knownOrientation;
 | 
				
			||||||
        private Vector3 m_knownRotationalVelocity;
 | 
					        private Vector3 m_knownRotationalVelocity;
 | 
				
			||||||
        private Vector3 m_knownRotationalForce;
 | 
					        private Vector3 m_knownRotationalForce;
 | 
				
			||||||
| 
						 | 
					@ -627,12 +654,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        private const int m_knownChangedPosition           = 1 << 0;
 | 
					        private const int m_knownChangedPosition           = 1 << 0;
 | 
				
			||||||
        private const int m_knownChangedVelocity           = 1 << 1;
 | 
					        private const int m_knownChangedVelocity           = 1 << 1;
 | 
				
			||||||
        private const int m_knownChangedForce              = 1 << 2;
 | 
					        private const int m_knownChangedForce              = 1 << 2;
 | 
				
			||||||
        private const int m_knownChangedOrientation        = 1 << 3;
 | 
					        private const int m_knownChangedForceImpulse       = 1 << 3;
 | 
				
			||||||
        private const int m_knownChangedRotationalVelocity = 1 << 4;
 | 
					        private const int m_knownChangedOrientation        = 1 << 4;
 | 
				
			||||||
        private const int m_knownChangedRotationalForce    = 1 << 5;
 | 
					        private const int m_knownChangedRotationalVelocity = 1 << 5;
 | 
				
			||||||
        private const int m_knownChangedTerrainHeight      = 1 << 6;
 | 
					        private const int m_knownChangedRotationalForce    = 1 << 6;
 | 
				
			||||||
        private const int m_knownChangedWaterLevel         = 1 << 7;
 | 
					        private const int m_knownChangedTerrainHeight      = 1 << 7;
 | 
				
			||||||
        private const int m_knownChangedForwardVelocity    = 1 << 8;
 | 
					        private const int m_knownChangedWaterLevel         = 1 << 8;
 | 
				
			||||||
 | 
					        private const int m_knownChangedForwardVelocity    = 1 << 9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void ForgetKnownVehicleProperties()
 | 
					        private void ForgetKnownVehicleProperties()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -653,21 +681,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                if ((m_knownChanged & m_knownChangedVelocity) != 0)
 | 
					                if ((m_knownChanged & m_knownChangedVelocity) != 0)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Prim.ForceVelocity = m_knownVelocity;
 | 
					                    Prim.ForceVelocity = m_knownVelocity;
 | 
				
			||||||
                    PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity);
 | 
					                    // Fake out Bullet by making it think the velocity is the same as last time.
 | 
				
			||||||
 | 
					                    // Bullet does a bunch of smoothing for changing parameters.
 | 
				
			||||||
 | 
					                    //    Since the vehicle is demanding this setting, we override Bullet's smoothing
 | 
				
			||||||
 | 
					                    //    by telling Bullet the value was the same last time.
 | 
				
			||||||
 | 
					                    PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((m_knownChanged & m_knownChangedForce) != 0)
 | 
					                if ((m_knownChanged & m_knownChangedForce) != 0)
 | 
				
			||||||
                    Prim.AddForce((Vector3)m_knownForce, false, true);
 | 
					                    Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
 | 
				
			||||||
 | 
					                    Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
 | 
					                if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
 | 
					                    Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
 | 
				
			||||||
                    // Fake out Bullet by making it think the velocity is the same as last time.
 | 
					 | 
				
			||||||
                    PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
 | 
					                    PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
 | 
					                if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
 | 
				
			||||||
                    Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
 | 
					                {
 | 
				
			||||||
 | 
					                    Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // If we set one of the values (ie, the physics engine didn't do it) we must force
 | 
					                // If we set one of the values (ie, the physics engine didn't do it) we must force
 | 
				
			||||||
                //      an UpdateProperties event to send the changes up to the simulator.
 | 
					                //      an UpdateProperties event to send the changes up to the simulator.
 | 
				
			||||||
| 
						 | 
					@ -757,16 +793,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void VehicleAddForce(Vector3 aForce)
 | 
					        private void VehicleAddForce(Vector3 pForce)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if ((m_knownHas & m_knownChangedForce) == 0)
 | 
					            if ((m_knownHas & m_knownChangedForce) == 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                m_knownForce = Vector3.Zero;
 | 
					                m_knownForce = Vector3.Zero;
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            m_knownForce += aForce;
 | 
					 | 
				
			||||||
            m_knownChanged |= m_knownChangedForce;
 | 
					 | 
				
			||||||
                m_knownHas |= m_knownChangedForce;
 | 
					                m_knownHas |= m_knownChangedForce;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            m_knownForce += pForce;
 | 
				
			||||||
 | 
					            m_knownChanged |= m_knownChangedForce;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void VehicleAddForceImpulse(Vector3 pImpulse)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((m_knownHas & m_knownChangedForceImpulse) == 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                m_knownForceImpulse = Vector3.Zero;
 | 
				
			||||||
 | 
					                m_knownHas |= m_knownChangedForceImpulse;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            m_knownForceImpulse += pImpulse;
 | 
				
			||||||
 | 
					            m_knownChanged |= m_knownChangedForceImpulse;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private Vector3 VehicleRotationalVelocity
 | 
					        private Vector3 VehicleRotationalVelocity
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -845,85 +892,91 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
 | 
					                PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}",
 | 
					            VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}",
 | 
				
			||||||
                    Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
 | 
					                    Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Apply the effect of the linear motor and other linear motions (like hover and float).
 | 
					        // Apply the effect of the linear motor and other linear motions (like hover and float).
 | 
				
			||||||
        private void MoveLinear(float pTimestep)
 | 
					        private void MoveLinear(float pTimestep)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
 | 
					            ComputeLinearVelocity(pTimestep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // The movement computed in the linear motor is relative to the vehicle
 | 
					            ComputeLinearTerrainHeightCorrection(pTimestep);
 | 
				
			||||||
            //     coordinates. Rotate the movement to world coordinates.
 | 
					 | 
				
			||||||
            linearMotorContribution *= VehicleOrientation;
 | 
					 | 
				
			||||||
            // All the contributions after this are world relative (mostly Z modifications)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // ==================================================================
 | 
					            ComputeLinearHover(pTimestep);
 | 
				
			||||||
            // Buoyancy: force to overcome gravity.
 | 
					 | 
				
			||||||
            // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
 | 
					 | 
				
			||||||
            // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
 | 
					 | 
				
			||||||
            Vector3 buoyancyContribution =  Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Vector3 hoverContribution = ComputeLinearHover(pTimestep);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ComputeLinearBlockingEndPoint(pTimestep);
 | 
					            ComputeLinearBlockingEndPoint(pTimestep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep);
 | 
					            ComputeLinearMotorUp(pTimestep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // ==================================================================
 | 
					            ApplyGravity(pTimestep);
 | 
				
			||||||
            Vector3 newVelocity = linearMotorContribution
 | 
					 | 
				
			||||||
                            + terrainHeightContribution
 | 
					 | 
				
			||||||
                            + hoverContribution
 | 
					 | 
				
			||||||
                            + limitMotorUpContribution;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Vector3 newForce = buoyancyContribution;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If not changing some axis, reduce out velocity
 | 
					            // If not changing some axis, reduce out velocity
 | 
				
			||||||
 | 
					            if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Vector3 vel = VehicleVelocity;
 | 
				
			||||||
                if ((m_flags & (VehicleFlag.NO_X)) != 0)
 | 
					                if ((m_flags & (VehicleFlag.NO_X)) != 0)
 | 
				
			||||||
                newVelocity.X = 0;
 | 
					                    vel.X = 0;
 | 
				
			||||||
                if ((m_flags & (VehicleFlag.NO_Y)) != 0)
 | 
					                if ((m_flags & (VehicleFlag.NO_Y)) != 0)
 | 
				
			||||||
                newVelocity.Y = 0;
 | 
					                    vel.Y = 0;
 | 
				
			||||||
                if ((m_flags & (VehicleFlag.NO_Z)) != 0)
 | 
					                if ((m_flags & (VehicleFlag.NO_Z)) != 0)
 | 
				
			||||||
                newVelocity.Z = 0;
 | 
					                    vel.Z = 0;
 | 
				
			||||||
 | 
					                VehicleVelocity = vel;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // ==================================================================
 | 
					            // ==================================================================
 | 
				
			||||||
            // Clamp high or low velocities
 | 
					            // Clamp high or low velocities
 | 
				
			||||||
            float newVelocityLengthSq = newVelocity.LengthSquared();
 | 
					            float newVelocityLengthSq = VehicleVelocity.LengthSquared();
 | 
				
			||||||
            if (newVelocityLengthSq > 1000f)
 | 
					            if (newVelocityLengthSq > 1000f)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                newVelocity /= newVelocity.Length();
 | 
					                VehicleVelocity /= VehicleVelocity.Length();
 | 
				
			||||||
                newVelocity *= 1000f;
 | 
					                VehicleVelocity *= 1000f;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (newVelocityLengthSq < 0.001f)
 | 
					            else if (newVelocityLengthSq < 0.001f)
 | 
				
			||||||
                newVelocity = Vector3.Zero;
 | 
					                VehicleVelocity = Vector3.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // ==================================================================
 | 
					            VDetailLog("{0},  MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity );
 | 
				
			||||||
            // Stuff new linear velocity into the vehicle.
 | 
					 | 
				
			||||||
            // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us.
 | 
					 | 
				
			||||||
            VehicleVelocity = newVelocity;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Other linear forces are applied as forces.
 | 
					 | 
				
			||||||
            Vector3 totalDownForce = newForce * m_vehicleMass;
 | 
					 | 
				
			||||||
            if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                VehicleAddForce(totalDownForce);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            VDetailLog("{0},  MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
 | 
					 | 
				
			||||||
                                Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
 | 
					 | 
				
			||||||
            VDetailLog("{0},  MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
 | 
					 | 
				
			||||||
                                Prim.LocalID,
 | 
					 | 
				
			||||||
                                linearMotorContribution, terrainHeightContribution, hoverContribution, 
 | 
					 | 
				
			||||||
                                limitMotorUpContribution, buoyancyContribution
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } // end MoveLinear()
 | 
					        } // end MoveLinear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep)
 | 
					        public void ComputeLinearVelocity(float pTimestep)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Vector3 linearMotorStep = m_linearMotor.Step(pTimestep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The movement computed in the linear motor is relative to the vehicle
 | 
				
			||||||
 | 
					            //     coordinates. Rotate the movement to world coordinates.
 | 
				
			||||||
 | 
					            Vector3 linearMotorVelocity = linearMotorStep * VehicleOrientation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If we're a ground vehicle, don't loose any Z action (like gravity acceleration).
 | 
				
			||||||
 | 
					            float mixFactor = 1f;   // 1 means use all linear motor Z value, 0 means use all existing Z
 | 
				
			||||||
 | 
					            if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (!Prim.IsColliding)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // If a ground vehicle and not on the ground, I want gravity effect
 | 
				
			||||||
 | 
					                    mixFactor = 0.2f;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // I'm not a ground vehicle but don't totally loose the effect of the environment
 | 
				
			||||||
 | 
					                mixFactor = 0.8f;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            linearMotorVelocity.Z = mixFactor * linearMotorVelocity.Z + (1f - mixFactor) * VehicleVelocity.Z;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // What we want to contribute to the vehicle's existing velocity
 | 
				
			||||||
 | 
					            Vector3 linearMotorForce = linearMotorVelocity - VehicleVelocity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Act against the inertia of the vehicle
 | 
				
			||||||
 | 
					            linearMotorForce *= m_vehicleMass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            VehicleAddForceImpulse(linearMotorForce * pTimestep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            VDetailLog("{0},  MoveLinear,velocity,vehVel={1},step={2},stepVel={3},mix={4},force={5}",
 | 
				
			||||||
 | 
					                        Prim.LocalID, VehicleVelocity, linearMotorStep, linearMotorVelocity, mixFactor, linearMotorForce);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void ComputeLinearTerrainHeightCorrection(float pTimestep)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Vector3 ret = Vector3.Zero;
 | 
					 | 
				
			||||||
            // If below the terrain, move us above the ground a little.
 | 
					            // If below the terrain, move us above the ground a little.
 | 
				
			||||||
            // TODO: Consider taking the rotated size of the object or possibly casting a ray.
 | 
					            // TODO: Consider taking the rotated size of the object or possibly casting a ray.
 | 
				
			||||||
            if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
 | 
					            if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
 | 
				
			||||||
| 
						 | 
					@ -935,13 +988,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                VDetailLog("{0},  MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
 | 
					                VDetailLog("{0},  MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
 | 
				
			||||||
                        Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
 | 
					                        Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return ret;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Vector3 ComputeLinearHover(float pTimestep)
 | 
					        public void ComputeLinearHover(float pTimestep)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Vector3 ret = Vector3.Zero;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // m_VhoverEfficiency: 0=bouncy, 1=totally damped
 | 
					            // m_VhoverEfficiency: 0=bouncy, 1=totally damped
 | 
				
			||||||
            // m_VhoverTimescale: time to achieve height
 | 
					            // m_VhoverTimescale: time to achieve height
 | 
				
			||||||
            if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
 | 
					            if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
 | 
				
			||||||
| 
						 | 
					@ -974,23 +1024,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
                        Vector3 pos = VehiclePosition;
 | 
					                        Vector3 pos = VehiclePosition;
 | 
				
			||||||
                        pos.Z = m_VhoverTargetHeight;
 | 
					                        pos.Z = m_VhoverTargetHeight;
 | 
				
			||||||
                        VehiclePosition = pos;
 | 
					                        VehiclePosition = pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        VDetailLog("{0},  MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // Error is positive if below the target and negative if above.
 | 
					                    // Error is positive if below the target and negative if above.
 | 
				
			||||||
                    float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
 | 
					                    float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
 | 
				
			||||||
                    float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
 | 
					                    float verticalCorrectionVelocity = verticalError / m_VhoverTimescale * pTimestep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // TODO: implement m_VhoverEfficiency correctly
 | 
					                    // TODO: implement m_VhoverEfficiency correctly
 | 
				
			||||||
                    ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
 | 
					                    VehicleAddForceImpulse(new Vector3(0f, 0f, verticalCorrectionVelocity));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    VDetailLog("{0},  MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corrVel={7}",
 | 
				
			||||||
 | 
					                                    Prim.LocalID, VehiclePosition, m_VhoverEfficiency,
 | 
				
			||||||
 | 
					                                    m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
 | 
				
			||||||
 | 
					                                    verticalError, verticalCorrectionVelocity);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                VDetailLog("{0},  MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},ret={6}",
 | 
					 | 
				
			||||||
                                Prim.LocalID, VehiclePosition, m_VhoverEfficiency, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, ret);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            return ret;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool ComputeLinearBlockingEndPoint(float pTimestep)
 | 
					        public bool ComputeLinearBlockingEndPoint(float pTimestep)
 | 
				
			||||||
| 
						 | 
					@ -1045,30 +1098,67 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        // TODO: this code is wrong. Also, what should it do for boats (height from water)?
 | 
					        // TODO: this code is wrong. Also, what should it do for boats (height from water)?
 | 
				
			||||||
        //    This is just using the ground and a general collision check. Should really be using
 | 
					        //    This is just using the ground and a general collision check. Should really be using
 | 
				
			||||||
        //    a downward raycast to find what is below.
 | 
					        //    a downward raycast to find what is below.
 | 
				
			||||||
        public Vector3 ComputeLinearMotorUp(float pTimestep)
 | 
					        public void ComputeLinearMotorUp(float pTimestep)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Vector3 ret = Vector3.Zero;
 | 
					            Vector3 ret = Vector3.Zero;
 | 
				
			||||||
            float distanceAboveGround = 0f;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
 | 
					            if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                // This code tries to decide if the object is not on the ground and then pushing down
 | 
				
			||||||
 | 
					                /*
 | 
				
			||||||
                float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
 | 
					                float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
 | 
				
			||||||
                distanceAboveGround = VehiclePosition.Z - targetHeight;
 | 
					                distanceAboveGround = VehiclePosition.Z - targetHeight;
 | 
				
			||||||
                // Not colliding if the vehicle is off the ground
 | 
					                // Not colliding if the vehicle is off the ground
 | 
				
			||||||
                if (!Prim.IsColliding)
 | 
					                if (!Prim.IsColliding)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
 | 
					                    // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
 | 
				
			||||||
                    ret = new Vector3(0, 0, -distanceAboveGround);
 | 
					                    VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                // TODO: this calculation is wrong. From the description at
 | 
					                // TODO: this calculation is wrong. From the description at
 | 
				
			||||||
                //     (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
 | 
					                //     (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
 | 
				
			||||||
                //     has a decay factor. This says this force should
 | 
					                //     has a decay factor. This says this force should
 | 
				
			||||||
                //     be computed with a motor.
 | 
					                //     be computed with a motor.
 | 
				
			||||||
                // TODO: add interaction with banking.
 | 
					                // TODO: add interaction with banking.
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                VDetailLog("{0},  MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
 | 
					                VDetailLog("{0},  MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
 | 
				
			||||||
                                Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
 | 
					                                Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
 | 
				
			||||||
            return ret;
 | 
					                 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Another approach is to measure if we're going up. If going up and not colliding,
 | 
				
			||||||
 | 
					                //     the vehicle is in the air.  Fix that by pushing down.
 | 
				
			||||||
 | 
					                if (!Prim.IsColliding && VehicleVelocity.Z > 0.1)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Get rid of any of the velocity vector that is pushing us up.
 | 
				
			||||||
 | 
					                    VehicleVelocity += new Vector3(0, 0, -VehicleVelocity.Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // If we're pointed up into the air, we should nose down
 | 
				
			||||||
 | 
					                    Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
 | 
				
			||||||
 | 
					                    // The rotation around the Y axis is pitch up or down
 | 
				
			||||||
 | 
					                    if (pointingDirection.Y > 0.01f)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y);
 | 
				
			||||||
 | 
					                        Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f);
 | 
				
			||||||
 | 
					                        // Rotate into world coordinates and apply to vehicle
 | 
				
			||||||
 | 
					                        angularCorrectionVector *= VehicleOrientation;
 | 
				
			||||||
 | 
					                        VehicleAddAngularForce(angularCorrectionVector);
 | 
				
			||||||
 | 
					                        VDetailLog("{0},  MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}",
 | 
				
			||||||
 | 
					                                    Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        VDetailLog("{0},  MoveLinear,limitMotorUp,newVel={1},pntDir={2}",
 | 
				
			||||||
 | 
					                                    Prim.LocalID, VehicleVelocity, pointingDirection);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void ApplyGravity(float pTimeStep)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
 | 
				
			||||||
 | 
					            VehicleAddForce(appliedGravity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            VDetailLog("{0},  MoveLinear,applyGravity,vehGrav={1},appliedForce-{2}", 
 | 
				
			||||||
 | 
					                            Prim.LocalID, m_VehicleGravity, appliedGravity);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // =======================================================================
 | 
					        // =======================================================================
 | 
				
			||||||
| 
						 | 
					@ -1088,6 +1178,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
            //    for preventing ground vehicles with large linear deflection, like bumper cars,
 | 
					            //    for preventing ground vehicles with large linear deflection, like bumper cars,
 | 
				
			||||||
            //    from climbing their linear deflection into the sky. 
 | 
					            //    from climbing their linear deflection into the sky. 
 | 
				
			||||||
            // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
 | 
					            // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
 | 
				
			||||||
 | 
					            // TODO: This is here because this is where ODE put it but documentation says it
 | 
				
			||||||
 | 
					            //    is a linear effect. Where should this check go?
 | 
				
			||||||
            if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
 | 
					            if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                angularMotorContribution.X = 0f;
 | 
					                angularMotorContribution.X = 0f;
 | 
				
			||||||
| 
						 | 
					@ -1179,7 +1271,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
            Vector3 ret = Vector3.Zero;
 | 
					            Vector3 ret = Vector3.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If vertical attaction timescale is reasonable
 | 
					            // If vertical attaction timescale is reasonable
 | 
				
			||||||
            if (m_verticalAttractionTimescale < m_verticalAttractionCutoff)
 | 
					            if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Take a vector pointing up and convert it from world to vehicle relative coords.
 | 
					                // Take a vector pointing up and convert it from world to vehicle relative coords.
 | 
				
			||||||
                Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
 | 
					                Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
 | 
				
			||||||
| 
						 | 
					@ -1230,7 +1322,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
            //     this creates an over-correction and then wabbling as the target is overshot.
 | 
					            //     this creates an over-correction and then wabbling as the target is overshot.
 | 
				
			||||||
            // TODO: rethink how the different correction computations inter-relate.
 | 
					            // TODO: rethink how the different correction computations inter-relate.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (m_angularDeflectionEfficiency != 0 && VehicleVelocity != Vector3.Zero)
 | 
					            if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // The direction the vehicle is moving
 | 
					                // The direction the vehicle is moving
 | 
				
			||||||
                Vector3 movingDirection = VehicleVelocity;
 | 
					                Vector3 movingDirection = VehicleVelocity;
 | 
				
			||||||
| 
						 | 
					@ -1303,7 +1395,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Vector3 ret = Vector3.Zero;
 | 
					            Vector3 ret = Vector3.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
 | 
					            if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
 | 
					                // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
 | 
				
			||||||
                // As the vehicle rolls to the right or left, the Y value will increase from
 | 
					                // As the vehicle rolls to the right or left, the Y value will increase from
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,6 +152,7 @@ public abstract class BSLinkset
 | 
				
			||||||
            if (IsRoot(child))
 | 
					            if (IsRoot(child))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Cannot remove the root from a linkset.
 | 
					                // Cannot remove the root from a linkset.
 | 
				
			||||||
 | 
					                child.PositionDisplacement = OMV.Vector3.Zero;
 | 
				
			||||||
                return this;
 | 
					                return this;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            RemoveChildFromLinkset(child);
 | 
					            RemoveChildFromLinkset(child);
 | 
				
			||||||
| 
						 | 
					@ -159,6 +160,7 @@ public abstract class BSLinkset
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The child is down to a linkset of just itself
 | 
					        // The child is down to a linkset of just itself
 | 
				
			||||||
 | 
					        child.PositionDisplacement = OMV.Vector3.Zero;
 | 
				
			||||||
        return BSLinkset.Factory(PhysicsScene, child);
 | 
					        return BSLinkset.Factory(PhysicsScene, child);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,7 +312,7 @@ public abstract class BSLinkset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            foreach (BSPhysObject bp in m_children)
 | 
					            foreach (BSPhysObject bp in m_children)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                com += bp.Position * bp.RawMass;
 | 
					                com += bp.Position;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            com /= (m_children.Count + 1);
 | 
					            com /= (m_children.Count + 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,23 +40,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
 | 
				
			||||||
//    removed from the linkset.
 | 
					//    removed from the linkset.
 | 
				
			||||||
sealed class BSLinksetCompoundInfo : BSLinksetInfo
 | 
					sealed class BSLinksetCompoundInfo : BSLinksetInfo
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public OMV.Vector3 OffsetPos;
 | 
					    public int Index;
 | 
				
			||||||
 | 
					    public OMV.Vector3 OffsetFromRoot;
 | 
				
			||||||
 | 
					    public OMV.Vector3 OffsetFromCenterOfMass;
 | 
				
			||||||
    public OMV.Quaternion OffsetRot;
 | 
					    public OMV.Quaternion OffsetRot;
 | 
				
			||||||
    public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
 | 
					    public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        OffsetPos = p;
 | 
					        Index = indx;
 | 
				
			||||||
 | 
					        OffsetFromRoot = p;
 | 
				
			||||||
 | 
					        OffsetFromCenterOfMass = p;
 | 
				
			||||||
        OffsetRot = r;
 | 
					        OffsetRot = r;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public override void Clear()
 | 
					    public override void Clear()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        OffsetPos = OMV.Vector3.Zero;
 | 
					        Index = 0;
 | 
				
			||||||
 | 
					        OffsetFromRoot = OMV.Vector3.Zero;
 | 
				
			||||||
 | 
					        OffsetFromCenterOfMass = OMV.Vector3.Zero;
 | 
				
			||||||
        OffsetRot = OMV.Quaternion.Identity;
 | 
					        OffsetRot = OMV.Quaternion.Identity;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public override string ToString()
 | 
					    public override string ToString()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        StringBuilder buff = new StringBuilder();
 | 
					        StringBuilder buff = new StringBuilder();
 | 
				
			||||||
        buff.Append("<p=");
 | 
					        buff.Append("<i=");
 | 
				
			||||||
        buff.Append(OffsetPos.ToString());
 | 
					        buff.Append(Index.ToString());
 | 
				
			||||||
 | 
					        buff.Append(",p=");
 | 
				
			||||||
 | 
					        buff.Append(OffsetFromRoot.ToString());
 | 
				
			||||||
 | 
					        buff.Append(",m=");
 | 
				
			||||||
 | 
					        buff.Append(OffsetFromCenterOfMass.ToString());
 | 
				
			||||||
        buff.Append(",r=");
 | 
					        buff.Append(",r=");
 | 
				
			||||||
        buff.Append(OffsetRot.ToString());
 | 
					        buff.Append(OffsetRot.ToString());
 | 
				
			||||||
        buff.Append(">");
 | 
					        buff.Append(">");
 | 
				
			||||||
| 
						 | 
					@ -170,6 +180,8 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
 | 
				
			||||||
 | 
					    // Called at taint-time.
 | 
				
			||||||
    public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
 | 
					    public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // The user moving a child around requires the rebuilding of the linkset compound shape
 | 
					        // The user moving a child around requires the rebuilding of the linkset compound shape
 | 
				
			||||||
| 
						 | 
					@ -182,6 +194,7 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
                && !physicalUpdate 
 | 
					                && !physicalUpdate 
 | 
				
			||||||
                && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
 | 
					                && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO: replace this with are calculation of the child prim's orientation and pos.
 | 
				
			||||||
            updated.LinksetInfo = null;
 | 
					            updated.LinksetInfo = null;
 | 
				
			||||||
            ScheduleRebuild(updated);
 | 
					            ScheduleRebuild(updated);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -230,7 +243,7 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
            if (inTaintTime)
 | 
					            if (inTaintTime)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                OMV.Vector3 oldPos = child.RawPosition;
 | 
					                OMV.Vector3 oldPos = child.RawPosition;
 | 
				
			||||||
                child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
 | 
					                child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
 | 
				
			||||||
                child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
 | 
					                child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
 | 
				
			||||||
                DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
 | 
					                DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
 | 
				
			||||||
                                            child.LocalID, oldPos, lci, child.RawPosition);
 | 
					                                            child.LocalID, oldPos, lci, child.RawPosition);
 | 
				
			||||||
| 
						 | 
					@ -238,7 +251,7 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // TaintedObject is not used here so the raw position is set now and not at taint-time.
 | 
					                // TaintedObject is not used here so the raw position is set now and not at taint-time.
 | 
				
			||||||
                child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
 | 
					                child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
 | 
				
			||||||
                child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
 | 
					                child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -306,6 +319,7 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
    // Constraint linksets are rebuilt every time.
 | 
					    // Constraint linksets are rebuilt every time.
 | 
				
			||||||
    // Note that this works for rebuilding just the root after a linkset is taken apart.
 | 
					    // Note that this works for rebuilding just the root after a linkset is taken apart.
 | 
				
			||||||
    // Called at taint time!!
 | 
					    // Called at taint time!!
 | 
				
			||||||
 | 
					    private bool disableCOM = true;     // disable until we get this debugged
 | 
				
			||||||
    private void RecomputeLinksetCompound()
 | 
					    private void RecomputeLinksetCompound()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        try
 | 
					        try
 | 
				
			||||||
| 
						 | 
					@ -316,10 +330,34 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
            // Cause the root shape to be rebuilt as a compound object with just the root in it
 | 
					            // Cause the root shape to be rebuilt as a compound object with just the root in it
 | 
				
			||||||
            LinksetRoot.ForceBodyShapeRebuild(true);
 | 
					            LinksetRoot.ForceBodyShapeRebuild(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The center of mass for the linkset is the geometric center of the group.
 | 
				
			||||||
 | 
					            // Compute a displacement for each component so it is relative to the center-of-mass.
 | 
				
			||||||
 | 
					            // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
 | 
				
			||||||
 | 
					            OMV.Vector3 centerOfMass;
 | 
				
			||||||
 | 
					            OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
 | 
				
			||||||
 | 
					            if (disableCOM)                             // DEBUG DEBUG
 | 
				
			||||||
 | 
					            {                                           // DEBUG DEBUG
 | 
				
			||||||
 | 
					                centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
 | 
				
			||||||
 | 
					                LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
 | 
				
			||||||
 | 
					            }                                           // DEBUG DEBUG
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                centerOfMass = ComputeLinksetGeometricCenter();
 | 
				
			||||||
 | 
					                centerDisplacement = centerOfMass - LinksetRoot.RawPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Since we're displacing the center of the shape, we need to move the body in the world
 | 
				
			||||||
 | 
					                LinksetRoot.PositionDisplacement = centerDisplacement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
 | 
				
			||||||
 | 
					                DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
 | 
				
			||||||
 | 
					                                        LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
 | 
					            DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
 | 
				
			||||||
                            LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
 | 
					                            LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Add a shape for each of the other children in the linkset
 | 
					            // Add a shape for each of the other children in the linkset
 | 
				
			||||||
 | 
					            int memberIndex = 1;
 | 
				
			||||||
            ForEachMember(delegate(BSPhysObject cPrim)
 | 
					            ForEachMember(delegate(BSPhysObject cPrim)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (!IsRoot(cPrim))
 | 
					                if (!IsRoot(cPrim))
 | 
				
			||||||
| 
						 | 
					@ -331,19 +369,21 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
                    BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
 | 
					                    BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
 | 
				
			||||||
                    if (lci == null)
 | 
					                    if (lci == null)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // Each child position and rotation is given relative to the root.
 | 
					                        // Each child position and rotation is given relative to the center-of-mass.
 | 
				
			||||||
                        OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
 | 
					                        OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
 | 
				
			||||||
                        OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
 | 
					                        OMV.Vector3 displacementFromRoot = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
 | 
				
			||||||
 | 
					                        OMV.Vector3 displacementFromCOM = displacementFromRoot - centerDisplacement;
 | 
				
			||||||
                        OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
 | 
					                        OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Save relative position for recomputing child's world position after moving linkset.
 | 
					                        // Save relative position for recomputing child's world position after moving linkset.
 | 
				
			||||||
                        lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
 | 
					                        lci = new BSLinksetCompoundInfo(memberIndex, displacementFromCOM, displacementRot);
 | 
				
			||||||
 | 
					                        lci.OffsetFromRoot = displacementFromRoot;
 | 
				
			||||||
                        cPrim.LinksetInfo = lci;
 | 
					                        cPrim.LinksetInfo = lci;
 | 
				
			||||||
                        DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
 | 
					                        DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
 | 
					                    DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
 | 
				
			||||||
                        LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
 | 
					                                                LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (cPrim.PhysShape.isNativeShape)
 | 
					                    if (cPrim.PhysShape.isNativeShape)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
| 
						 | 
					@ -359,7 +399,7 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
                        PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
 | 
					                        PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
 | 
				
			||||||
                        BulletShape newShape = cPrim.PhysShape;
 | 
					                        BulletShape newShape = cPrim.PhysShape;
 | 
				
			||||||
                        cPrim.PhysShape = saveShape;
 | 
					                        cPrim.PhysShape = saveShape;
 | 
				
			||||||
                        PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot);
 | 
					                        PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
| 
						 | 
					@ -371,8 +411,10 @@ public sealed class BSLinksetCompound : BSLinkset
 | 
				
			||||||
                            PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
 | 
					                            PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
 | 
				
			||||||
                                                LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
 | 
					                                                LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
 | 
					                        PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    lci.Index = memberIndex;
 | 
				
			||||||
 | 
					                    memberIndex++;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return false;   // 'false' says to move onto the next child in the list
 | 
					                return false;   // 'false' says to move onto the next child in the list
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,6 +80,7 @@ public static class BSParam
 | 
				
			||||||
	public static float AvatarStepForceFactor { get; private set; }
 | 
						public static float AvatarStepForceFactor { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static float VehicleAngularDamping { get; private set; }
 | 
					    public static float VehicleAngularDamping { get; private set; }
 | 
				
			||||||
 | 
					    public static float VehicleDebuggingEnabled { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static float LinksetImplementation { get; private set; }
 | 
					    public static float LinksetImplementation { get; private set; }
 | 
				
			||||||
    public static float LinkConstraintUseFrameOffset { get; private set; }
 | 
					    public static float LinkConstraintUseFrameOffset { get; private set; }
 | 
				
			||||||
| 
						 | 
					@ -427,6 +428,11 @@ public static class BSParam
 | 
				
			||||||
            (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
 | 
					            (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
 | 
				
			||||||
            (s) => { return VehicleAngularDamping; },
 | 
					            (s) => { return VehicleAngularDamping; },
 | 
				
			||||||
            (s,p,l,v) => { VehicleAngularDamping = v; } ),
 | 
					            (s,p,l,v) => { VehicleAngularDamping = v; } ),
 | 
				
			||||||
 | 
					        new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
 | 
				
			||||||
 | 
					            ConfigurationParameters.numericFalse,
 | 
				
			||||||
 | 
					            (s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
 | 
				
			||||||
 | 
					            (s) => { return VehicleDebuggingEnabled; },
 | 
				
			||||||
 | 
					            (s,p,l,v) => { VehicleDebuggingEnabled = v; } ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
 | 
						    new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
 | 
				
			||||||
            0f,
 | 
					            0f,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,8 @@ public abstract class BSPhysObject : PhysicsActor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // A linkset of just me
 | 
					        // A linkset of just me
 | 
				
			||||||
        Linkset = BSLinkset.Factory(PhysicsScene, this);
 | 
					        Linkset = BSLinkset.Factory(PhysicsScene, this);
 | 
				
			||||||
 | 
					        PositionDisplacement = OMV.Vector3.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LastAssetBuildFailed = false;
 | 
					        LastAssetBuildFailed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Default material type
 | 
					        // Default material type
 | 
				
			||||||
| 
						 | 
					@ -135,6 +137,7 @@ public abstract class BSPhysObject : PhysicsActor
 | 
				
			||||||
    public virtual OMV.Vector3 Scale { get; set; }
 | 
					    public virtual OMV.Vector3 Scale { get; set; }
 | 
				
			||||||
    public abstract bool IsSolid { get; }
 | 
					    public abstract bool IsSolid { get; }
 | 
				
			||||||
    public abstract bool IsStatic { get; }
 | 
					    public abstract bool IsStatic { get; }
 | 
				
			||||||
 | 
					    public abstract bool IsSelected { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Materialness
 | 
					    // Materialness
 | 
				
			||||||
    public MaterialAttributes.Material Material { get; private set; }
 | 
					    public MaterialAttributes.Material Material { get; private set; }
 | 
				
			||||||
| 
						 | 
					@ -156,6 +159,14 @@ public abstract class BSPhysObject : PhysicsActor
 | 
				
			||||||
    public abstract OMV.Vector3 RawPosition { get; set; }
 | 
					    public abstract OMV.Vector3 RawPosition { get; set; }
 | 
				
			||||||
    public abstract OMV.Vector3 ForcePosition { get; set; }
 | 
					    public abstract OMV.Vector3 ForcePosition { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Position is what the simulator thinks the positions of the prim is.
 | 
				
			||||||
 | 
					    // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
 | 
				
			||||||
 | 
					    //     sometimes it is necessary to displace the position the physics engine thinks
 | 
				
			||||||
 | 
					    //     the position is. PositionDisplacement must be added and removed from the
 | 
				
			||||||
 | 
					    //     position as the simulator position is stored and fetched from the physics
 | 
				
			||||||
 | 
					    //     engine. 
 | 
				
			||||||
 | 
					    public virtual OMV.Vector3 PositionDisplacement { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract OMV.Quaternion RawOrientation { get; set; }
 | 
					    public abstract OMV.Quaternion RawOrientation { get; set; }
 | 
				
			||||||
    public abstract OMV.Quaternion ForceOrientation { get; set; }
 | 
					    public abstract OMV.Quaternion ForceOrientation { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -371,10 +382,13 @@ public abstract class BSPhysObject : PhysicsActor
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        string identifier = op + "-" + id.ToString();
 | 
					        string identifier = op + "-" + id.ToString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lock (RegisteredActions)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            // Clean out any existing action
 | 
					            // Clean out any existing action
 | 
				
			||||||
            UnRegisterPreStepAction(op, id);
 | 
					            UnRegisterPreStepAction(op, id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            RegisteredActions[identifier] = actn;
 | 
					            RegisteredActions[identifier] = actn;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        PhysicsScene.BeforeStep += actn;
 | 
					        PhysicsScene.BeforeStep += actn;
 | 
				
			||||||
        DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
 | 
					        DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -384,22 +398,28 @@ public abstract class BSPhysObject : PhysicsActor
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        string identifier = op + "-" + id.ToString();
 | 
					        string identifier = op + "-" + id.ToString();
 | 
				
			||||||
        bool removed = false;
 | 
					        bool removed = false;
 | 
				
			||||||
 | 
					        lock (RegisteredActions)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            if (RegisteredActions.ContainsKey(identifier))
 | 
					            if (RegisteredActions.ContainsKey(identifier))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                PhysicsScene.BeforeStep -= RegisteredActions[identifier];
 | 
					                PhysicsScene.BeforeStep -= RegisteredActions[identifier];
 | 
				
			||||||
                RegisteredActions.Remove(identifier);
 | 
					                RegisteredActions.Remove(identifier);
 | 
				
			||||||
                removed = true;
 | 
					                removed = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
 | 
					        DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected void UnRegisterAllPreStepActions()
 | 
					    protected void UnRegisterAllPreStepActions()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        lock (RegisteredActions)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
 | 
					            foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                PhysicsScene.BeforeStep -= kvp.Value;
 | 
					                PhysicsScene.BeforeStep -= kvp.Value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            RegisteredActions.Clear();
 | 
					            RegisteredActions.Clear();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
 | 
					        DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ public class BSPlugin : IPhysicsPlugin
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (_mScene == null)
 | 
					        if (_mScene == null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _mScene = new BSScene(sceneIdentifier);
 | 
					            _mScene = new BSScene(GetName(), sceneIdentifier);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return (_mScene);
 | 
					        return (_mScene);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,10 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    private bool _grabbed;
 | 
					    private bool _grabbed;
 | 
				
			||||||
    private bool _isSelected;
 | 
					    private bool _isSelected;
 | 
				
			||||||
    private bool _isVolumeDetect;
 | 
					    private bool _isVolumeDetect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // _position is what the simulator thinks the positions of the prim is.
 | 
				
			||||||
    private OMV.Vector3 _position;
 | 
					    private OMV.Vector3 _position;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private float _mass;    // the mass of this object
 | 
					    private float _mass;    // the mass of this object
 | 
				
			||||||
    private float _density;
 | 
					    private float _density;
 | 
				
			||||||
    private OMV.Vector3 _force;
 | 
					    private OMV.Vector3 _force;
 | 
				
			||||||
| 
						 | 
					@ -169,6 +172,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    public override PrimitiveBaseShape Shape {
 | 
					    public override PrimitiveBaseShape Shape {
 | 
				
			||||||
        set {
 | 
					        set {
 | 
				
			||||||
            BaseShape = value;
 | 
					            BaseShape = value;
 | 
				
			||||||
 | 
					            LastAssetBuildFailed = false;
 | 
				
			||||||
            ForceBodyShapeRebuild(false);
 | 
					            ForceBodyShapeRebuild(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -178,7 +182,6 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override bool ForceBodyShapeRebuild(bool inTaintTime)
 | 
					    public override bool ForceBodyShapeRebuild(bool inTaintTime)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        LastAssetBuildFailed = false;
 | 
					 | 
				
			||||||
        PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
 | 
					        PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _mass = CalculateMass();   // changing the shape changes the mass
 | 
					            _mass = CalculateMass();   // changing the shape changes the mass
 | 
				
			||||||
| 
						 | 
					@ -204,6 +207,10 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public override bool IsSelected
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get { return _isSelected; }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public override void CrossingFailure() { return; }
 | 
					    public override void CrossingFailure() { return; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // link me to the specified parent
 | 
					    // link me to the specified parent
 | 
				
			||||||
| 
						 | 
					@ -290,7 +297,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            */
 | 
					            */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // don't do the GetObjectPosition for root elements because this function is called a zillion times.
 | 
					            // don't do the GetObjectPosition for root elements because this function is called a zillion times.
 | 
				
			||||||
            // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody);
 | 
					            // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody) - PositionDisplacement;
 | 
				
			||||||
            return _position;
 | 
					            return _position;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        set {
 | 
					        set {
 | 
				
			||||||
| 
						 | 
					@ -316,18 +323,37 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public override OMV.Vector3 ForcePosition {
 | 
					    public override OMV.Vector3 ForcePosition {
 | 
				
			||||||
        get {
 | 
					        get {
 | 
				
			||||||
            _position = PhysicsScene.PE.GetPosition(PhysBody);
 | 
					            _position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
 | 
				
			||||||
            return _position;
 | 
					            return _position;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        set {
 | 
					        set {
 | 
				
			||||||
            _position = value;
 | 
					            _position = value;
 | 
				
			||||||
            if (PhysBody.HasPhysicalBody)
 | 
					            if (PhysBody.HasPhysicalBody)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
 | 
					                PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
 | 
				
			||||||
                ActivateIfPhysical(false);
 | 
					                ActivateIfPhysical(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    // Override to have position displacement immediately update the physical position.
 | 
				
			||||||
 | 
					    // A feeble attempt to keep the sim and physical positions in sync
 | 
				
			||||||
 | 
					    // Must be called at taint time.
 | 
				
			||||||
 | 
					    public override OMV.Vector3 PositionDisplacement
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        get
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return base.PositionDisplacement;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        set
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.PositionDisplacement = value;
 | 
				
			||||||
 | 
					            PhysicsScene.TaintedObject(PhysicsScene.InTaintTime, "BSPrim.setPosition", delegate()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (PhysBody.HasPhysicalBody)
 | 
				
			||||||
 | 
					                    PhysicsScene.PE.SetTranslation(PhysBody, _position + base.PositionDisplacement, _orientation);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check that the current position is sane and, if not, modify the position to make it so.
 | 
					    // Check that the current position is sane and, if not, modify the position to make it so.
 | 
				
			||||||
    // Check for being below terrain and being out of bounds.
 | 
					    // Check for being below terrain and being out of bounds.
 | 
				
			||||||
| 
						 | 
					@ -336,7 +362,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        bool ret = false;
 | 
					        bool ret = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position))
 | 
					        if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // The physical object is out of the known/simulated area.
 | 
					            // The physical object is out of the known/simulated area.
 | 
				
			||||||
            // Upper levels of code will handle the transition to other areas so, for
 | 
					            // Upper levels of code will handle the transition to other areas so, for
 | 
				
			||||||
| 
						 | 
					@ -350,8 +376,11 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
 | 
					            DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
 | 
				
			||||||
            float targetHeight = terrainHeight + (Size.Z / 2f);
 | 
					            float targetHeight = terrainHeight + (Size.Z / 2f);
 | 
				
			||||||
            // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
 | 
					            // If the object is below ground it just has to be moved up because pushing will
 | 
				
			||||||
            upForce.Z = (terrainHeight - RawPosition.Z) * 1f;
 | 
					            //     not get it through the terrain
 | 
				
			||||||
 | 
					            _position.Z = targetHeight;
 | 
				
			||||||
 | 
					            if (inTaintTime)
 | 
				
			||||||
 | 
					                ForcePosition = _position;
 | 
				
			||||||
            ret = true;
 | 
					            ret = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -363,20 +392,15 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
 | 
					                // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
 | 
				
			||||||
                upForce.Z = (waterHeight - RawPosition.Z) * 1f;
 | 
					                upForce.Z = (waterHeight - RawPosition.Z) * 1f;
 | 
				
			||||||
                ret = true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
 | 
					 | 
				
			||||||
        // TODO: This should be intergrated with a geneal physics action mechanism.
 | 
					 | 
				
			||||||
        // TODO: This should be moderated with PID'ness.
 | 
					 | 
				
			||||||
        if (ret)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
                // Apply upforce and overcome gravity.
 | 
					                // Apply upforce and overcome gravity.
 | 
				
			||||||
                OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
 | 
					                OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
 | 
				
			||||||
                DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
 | 
					                DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
 | 
				
			||||||
                AddForce(correctionForce, false, inTaintTime);
 | 
					                AddForce(correctionForce, false, inTaintTime);
 | 
				
			||||||
 | 
					                ret = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -410,7 +434,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                OMV.Vector3 grav = ComputeGravity();
 | 
					                OMV.Vector3 grav = ComputeGravity(Buoyancy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (inWorld)
 | 
					                if (inWorld)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -445,12 +469,12 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Return what gravity should be set to this very moment
 | 
					    // Return what gravity should be set to this very moment
 | 
				
			||||||
    private OMV.Vector3 ComputeGravity()
 | 
					    public OMV.Vector3 ComputeGravity(float buoyancy)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        OMV.Vector3 ret = PhysicsScene.DefaultGravity;
 | 
					        OMV.Vector3 ret = PhysicsScene.DefaultGravity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!IsStatic)
 | 
					        if (!IsStatic)
 | 
				
			||||||
            ret *= (1f - Buoyancy);
 | 
					            ret *= (1f - buoyancy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -586,6 +610,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            _velocity = value;
 | 
					            _velocity = value;
 | 
				
			||||||
            if (PhysBody.HasPhysicalBody)
 | 
					            if (PhysBody.HasPhysicalBody)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
 | 
				
			||||||
                PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
 | 
					                PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
 | 
				
			||||||
                ActivateIfPhysical(false);
 | 
					                ActivateIfPhysical(false);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -650,12 +675,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
 | 
					            PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (PhysBody.HasPhysicalBody)
 | 
					                ForceOrientation = _orientation;
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody);
 | 
					 | 
				
			||||||
                    // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
 | 
					 | 
				
			||||||
                    PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -670,7 +690,8 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
        set
 | 
					        set
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _orientation = value;
 | 
					            _orientation = value;
 | 
				
			||||||
            PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
 | 
					            if (PhysBody.HasPhysicalBody)
 | 
				
			||||||
 | 
					                PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public override int PhysicsActorType {
 | 
					    public override int PhysicsActorType {
 | 
				
			||||||
| 
						 | 
					@ -809,7 +830,7 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            // PhysicsScene.PE.ClearAllForces(BSBody);
 | 
					            // PhysicsScene.PE.ClearAllForces(BSBody);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // For good measure, make sure the transform is set through to the motion state
 | 
					            // For good measure, make sure the transform is set through to the motion state
 | 
				
			||||||
            PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
 | 
					            PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Center of mass is at the center of the object
 | 
					            // Center of mass is at the center of the object
 | 
				
			||||||
            // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
 | 
					            // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
 | 
				
			||||||
| 
						 | 
					@ -1153,7 +1174,9 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
    // This added force will only last the next simulation tick.
 | 
					    // This added force will only last the next simulation tick.
 | 
				
			||||||
    public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
 | 
					    public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
 | 
				
			||||||
        // for an object, doesn't matter if force is a pushforce or not
 | 
					        // for an object, doesn't matter if force is a pushforce or not
 | 
				
			||||||
        if (!IsStatic && force.IsFinite())
 | 
					        if (!IsStatic)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (force.IsFinite())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float magnitude = force.Length();
 | 
					                float magnitude = force.Length();
 | 
				
			||||||
                if (magnitude > BSParam.MaxAddForceMagnitude)
 | 
					                if (magnitude > BSParam.MaxAddForceMagnitude)
 | 
				
			||||||
| 
						 | 
					@ -1178,10 +1201,45 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
            m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
 | 
					                m_log.WarnFormat("{0}: AddForce: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void AddForceImpulse(OMV.Vector3 impulse, bool pushforce, bool inTaintTime) {
 | 
				
			||||||
 | 
					        // for an object, doesn't matter if force is a pushforce or not
 | 
				
			||||||
 | 
					        if (!IsStatic)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (impulse.IsFinite())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                float magnitude = impulse.Length();
 | 
				
			||||||
 | 
					                if (magnitude > BSParam.MaxAddForceMagnitude)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Force has a limit
 | 
				
			||||||
 | 
					                    impulse = impulse / magnitude * BSParam.MaxAddForceMagnitude;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
 | 
				
			||||||
 | 
					                OMV.Vector3 addImpulse = impulse;
 | 
				
			||||||
 | 
					                PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Bullet adds this impulse immediately to the velocity
 | 
				
			||||||
 | 
					                    DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
 | 
				
			||||||
 | 
					                    if (PhysBody.HasPhysicalBody)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
 | 
				
			||||||
 | 
					                        ActivateIfPhysical(false);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                m_log.WarnFormat("{0}: AddForceImpulse: Got a NaN impulse applied to a prim. LocalID={1}", LogHeader, LocalID);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
 | 
					    public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
 | 
				
			||||||
        AddAngularForce(force, pushforce, false);
 | 
					        AddAngularForce(force, pushforce, false);
 | 
				
			||||||
| 
						 | 
					@ -1561,21 +1619,6 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The physics engine says that properties have updated. Update same and inform
 | 
					    // The physics engine says that properties have updated. Update same and inform
 | 
				
			||||||
    // the world that things have changed.
 | 
					    // the world that things have changed.
 | 
				
			||||||
    // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
 | 
					 | 
				
			||||||
    enum UpdatedProperties {
 | 
					 | 
				
			||||||
        Position      = 1 << 0,
 | 
					 | 
				
			||||||
        Rotation      = 1 << 1,
 | 
					 | 
				
			||||||
        Velocity      = 1 << 2,
 | 
					 | 
				
			||||||
        Acceleration  = 1 << 3,
 | 
					 | 
				
			||||||
        RotationalVel = 1 << 4
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const float ROTATION_TOLERANCE = 0.01f;
 | 
					 | 
				
			||||||
    const float VELOCITY_TOLERANCE = 0.001f;
 | 
					 | 
				
			||||||
    const float POSITION_TOLERANCE = 0.05f;
 | 
					 | 
				
			||||||
    const float ACCELERATION_TOLERANCE = 0.01f;
 | 
					 | 
				
			||||||
    const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public override void UpdateProperties(EntityProperties entprop)
 | 
					    public override void UpdateProperties(EntityProperties entprop)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Updates only for individual prims and for the root object of a linkset.
 | 
					        // Updates only for individual prims and for the root object of a linkset.
 | 
				
			||||||
| 
						 | 
					@ -1588,7 +1631,8 @@ public sealed class BSPrim : BSPhysObject
 | 
				
			||||||
                entprop.RotationalVelocity = OMV.Vector3.Zero;
 | 
					                entprop.RotationalVelocity = OMV.Vector3.Zero;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Assign directly to the local variables so the normal set action does not happen
 | 
					            // Assign directly to the local variables so the normal set actions do not happen
 | 
				
			||||||
 | 
					            entprop.Position -= PositionDisplacement;
 | 
				
			||||||
            _position = entprop.Position;
 | 
					            _position = entprop.Position;
 | 
				
			||||||
            _orientation = entprop.Rotation;
 | 
					            _orientation = entprop.Rotation;
 | 
				
			||||||
            _velocity = entprop.Velocity;
 | 
					            _velocity = entprop.Velocity;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -167,11 +167,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
 | 
				
			||||||
    public bool VehiclePhysicalLoggingEnabled { get; private set; }
 | 
					    public bool VehiclePhysicalLoggingEnabled { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #region Construction and Initialization
 | 
					    #region Construction and Initialization
 | 
				
			||||||
    public BSScene(string identifier)
 | 
					    public BSScene(string engineType, string identifier)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        m_initialized = false;
 | 
					        m_initialized = false;
 | 
				
			||||||
        // we are passed the name of the region we're working for.
 | 
					
 | 
				
			||||||
 | 
					        // The name of the region we're working for is passed to us. Keep for identification.
 | 
				
			||||||
        RegionName = identifier;
 | 
					        RegionName = identifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set identifying variables in the PhysicsScene interface.
 | 
				
			||||||
 | 
					        EngineType = engineType;
 | 
				
			||||||
 | 
					        Name = EngineType + "/" + RegionName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void Initialise(IMesher meshmerizer, IConfigSource config)
 | 
					    public override void Initialise(IMesher meshmerizer, IConfigSource config)
 | 
				
			||||||
| 
						 | 
					@ -382,12 +387,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
 | 
				
			||||||
        if (!m_initialized) return null;
 | 
					        if (!m_initialized) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
 | 
					        BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
 | 
				
			||||||
        lock (PhysObjects) PhysObjects.Add(localID, actor);
 | 
					        lock (PhysObjects)
 | 
				
			||||||
 | 
					            PhysObjects.Add(localID, actor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO: Remove kludge someday.
 | 
					        // TODO: Remove kludge someday.
 | 
				
			||||||
        // We must generate a collision for avatars whether they collide or not.
 | 
					        // We must generate a collision for avatars whether they collide or not.
 | 
				
			||||||
        // This is required by OpenSim to update avatar animations, etc.
 | 
					        // This is required by OpenSim to update avatar animations, etc.
 | 
				
			||||||
        lock (m_avatars) m_avatars.Add(actor);
 | 
					        lock (m_avatars)
 | 
				
			||||||
 | 
					            m_avatars.Add(actor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return actor;
 | 
					        return actor;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -403,9 +410,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
 | 
					                lock (PhysObjects)
 | 
				
			||||||
 | 
					                    PhysObjects.Remove(bsactor.LocalID);
 | 
				
			||||||
                // Remove kludge someday
 | 
					                // Remove kludge someday
 | 
				
			||||||
                lock (m_avatars) m_avatars.Remove(bsactor);
 | 
					                lock (m_avatars)
 | 
				
			||||||
 | 
					                    m_avatars.Remove(bsactor);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (Exception e)
 | 
					            catch (Exception e)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -414,6 +423,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
 | 
				
			||||||
            bsactor.Destroy();
 | 
					            bsactor.Destroy();
 | 
				
			||||||
            // bsactor.dispose();
 | 
					            // bsactor.dispose();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_log.ErrorFormat("{0}: Requested to remove avatar that is not a BSCharacter. ID={1}, type={2}",
 | 
				
			||||||
 | 
					                                        LogHeader, actor.LocalID, actor.GetType().Name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public override void RemovePrim(PhysicsActor prim)
 | 
					    public override void RemovePrim(PhysicsActor prim)
 | 
				
			||||||
| 
						 | 
					@ -486,6 +500,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
 | 
				
			||||||
        ProcessTaints();
 | 
					        ProcessTaints();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Some of the physical objects requre individual, pre-step calls
 | 
					        // Some of the physical objects requre individual, pre-step calls
 | 
				
			||||||
 | 
					        //      (vehicles and avatar movement, in particular)
 | 
				
			||||||
        TriggerPreStepEvent(timeStep);
 | 
					        TriggerPreStepEvent(timeStep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // the prestep actions might have added taints
 | 
					        // the prestep actions might have added taints
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -906,7 +906,7 @@ public sealed class BSShapeCollection : IDisposable
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // While we figure out the real problem, stick a simple native shape on the object.
 | 
					        // While we figure out the real problem, stick in a simple box for the object.
 | 
				
			||||||
        BulletShape fillinShape =
 | 
					        BulletShape fillinShape =
 | 
				
			||||||
            BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
 | 
					            BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,17 @@
 | 
				
			||||||
CURRENT PRIORITIES
 | 
					CURRENT PRIORITIES
 | 
				
			||||||
=================================================
 | 
					=================================================
 | 
				
			||||||
Avatars walking up stairs (HALF DONE)
 | 
					Nebadon vehicles turning funny in arena
 | 
				
			||||||
Vehicle movement on terrain smoothness
 | 
					 | 
				
			||||||
limitMotorUp calibration (more down?)
 | 
					limitMotorUp calibration (more down?)
 | 
				
			||||||
 | 
					Vehicle angular vertical attraction
 | 
				
			||||||
 | 
					Vehicle angular deflection
 | 
				
			||||||
	Preferred orientation angular correction fix
 | 
						Preferred orientation angular correction fix
 | 
				
			||||||
 | 
					vehicle angular banking
 | 
				
			||||||
 | 
					Avatars walking up stairs (HALF DONE)
 | 
				
			||||||
 | 
					    Radius of the capsule affects ability to climb edges.
 | 
				
			||||||
 | 
					Vehicle movement on terrain smoothness
 | 
				
			||||||
Surfboard go wonky when turning
 | 
					Surfboard go wonky when turning
 | 
				
			||||||
	Angular motor direction is global coordinates rather than local coordinates?
 | 
						Angular motor direction is global coordinates rather than local coordinates?
 | 
				
			||||||
Boats float low in the water
 | 
					Boats float low in the water (DONE)
 | 
				
			||||||
Avatar movement
 | 
					Avatar movement
 | 
				
			||||||
	flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
 | 
						flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
 | 
				
			||||||
	walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
 | 
						walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
 | 
				
			||||||
| 
						 | 
					@ -33,19 +38,15 @@ CRASHES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VEHICLES TODO LIST:
 | 
					VEHICLES TODO LIST:
 | 
				
			||||||
=================================================
 | 
					=================================================
 | 
				
			||||||
Angular motor direction is global coordinates rather than local coordinates
 | 
					 | 
				
			||||||
Border crossing with linked vehicle causes crash
 | 
					Border crossing with linked vehicle causes crash
 | 
				
			||||||
Vehicles (Move smoothly)
 | 
					Vehicles (Move smoothly)
 | 
				
			||||||
Add vehicle collisions so IsColliding is properly reported.
 | 
					 | 
				
			||||||
	Needed for banking, limitMotorUp, movementLimiting, ...
 | 
					 | 
				
			||||||
VehicleAddForce is not scaled by the simulation step but it is only
 | 
					 | 
				
			||||||
	applied for one step. Should it be scaled?
 | 
					 | 
				
			||||||
Some vehicles should not be able to turn if no speed or off ground.
 | 
					Some vehicles should not be able to turn if no speed or off ground.
 | 
				
			||||||
Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
 | 
					Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
 | 
				
			||||||
Neb car jiggling left and right
 | 
					Neb car jiggling left and right
 | 
				
			||||||
	Happens on terrain and any other mesh object. Flat cubes are much smoother.
 | 
						Happens on terrain and any other mesh object. Flat cubes are much smoother.
 | 
				
			||||||
	This has been reduced but not eliminated.
 | 
						This has been reduced but not eliminated.
 | 
				
			||||||
Implement referenceFrame for all the motion routines.
 | 
					Implement referenceFrame for all the motion routines.
 | 
				
			||||||
 | 
					For limitMotorUp, use raycast down to find if vehicle is in the air.
 | 
				
			||||||
Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
 | 
					Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
 | 
				
			||||||
	Verify that angular motion specified around Z moves in the vehicle coordinates.
 | 
						Verify that angular motion specified around Z moves in the vehicle coordinates.
 | 
				
			||||||
Verify llGetVel() is returning a smooth and good value for vehicle movement.
 | 
					Verify llGetVel() is returning a smooth and good value for vehicle movement.
 | 
				
			||||||
| 
						 | 
					@ -54,14 +55,13 @@ Implement function efficiency for lineaar and angular motion.
 | 
				
			||||||
After getting off a vehicle, the root prim is phantom (can be walked through)
 | 
					After getting off a vehicle, the root prim is phantom (can be walked through)
 | 
				
			||||||
    Need to force a position update for the root prim after compound shape destruction
 | 
					    Need to force a position update for the root prim after compound shape destruction
 | 
				
			||||||
Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
 | 
					Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
 | 
				
			||||||
For limitMotorUp, use raycast down to find if vehicle is in the air.
 | 
					 | 
				
			||||||
Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
 | 
					Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
 | 
				
			||||||
	A kludge that isn't fixing the real problem of Bullet adding extra motion.
 | 
						A kludge that isn't fixing the real problem of Bullet adding extra motion.
 | 
				
			||||||
Incorporate inter-relationship of angular corrections. For instance, angularDeflection
 | 
					Incorporate inter-relationship of angular corrections. For instance, angularDeflection
 | 
				
			||||||
	and angularMotorUp will compute same X or Y correction. When added together
 | 
						and angularMotorUp will compute same X or Y correction. When added together
 | 
				
			||||||
	creates over-correction and over-shoot and wabbling.
 | 
						creates over-correction and over-shoot and wabbling.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BULLETSIM TODO LIST:
 | 
					GENERAL TODO LIST:
 | 
				
			||||||
=================================================
 | 
					=================================================
 | 
				
			||||||
Implement an avatar mesh shape. The Bullet capsule is way too limited.
 | 
					Implement an avatar mesh shape. The Bullet capsule is way too limited.
 | 
				
			||||||
	Consider just hand creating a vertex/index array in a new BSShapeAvatar.
 | 
						Consider just hand creating a vertex/index array in a new BSShapeAvatar.
 | 
				
			||||||
| 
						 | 
					@ -121,11 +121,9 @@ LinksetCompound: when one of the children changes orientation (like tires
 | 
				
			||||||
Verify/think through scripts in children of linksets. What do they reference
 | 
					Verify/think through scripts in children of linksets. What do they reference
 | 
				
			||||||
	and return when getting position, velocity, ...
 | 
						and return when getting position, velocity, ...
 | 
				
			||||||
Confirm constraint linksets still work after making all the changes for compound linksets.
 | 
					Confirm constraint linksets still work after making all the changes for compound linksets.
 | 
				
			||||||
 | 
					Use PostTaint callback to do rebuilds for constraint linksets to reduce rebuilding
 | 
				
			||||||
Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
 | 
					Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
 | 
				
			||||||
	For compound linksets, add ability to remove or reposition individual child shapes.
 | 
						For compound linksets, add ability to remove or reposition individual child shapes.
 | 
				
			||||||
Disable activity of passive linkset children.
 | 
					 | 
				
			||||||
	Since the linkset is a compound object, the old prims are left lying
 | 
					 | 
				
			||||||
	around and need to be phantomized so they don't collide, ...
 | 
					 | 
				
			||||||
Speed up creation of large physical linksets
 | 
					Speed up creation of large physical linksets
 | 
				
			||||||
	For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
 | 
						For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
 | 
				
			||||||
	REALLY bad for very large physical linksets (freezes the sim for many seconds).
 | 
						REALLY bad for very large physical linksets (freezes the sim for many seconds).
 | 
				
			||||||
| 
						 | 
					@ -138,25 +136,21 @@ MORE
 | 
				
			||||||
Use the HACD convex hull routine in Bullet rather than the C# version.
 | 
					Use the HACD convex hull routine in Bullet rather than the C# version.
 | 
				
			||||||
Do we need to do convex hulls all the time? Can complex meshes be left meshes?
 | 
					Do we need to do convex hulls all the time? Can complex meshes be left meshes?
 | 
				
			||||||
	There is some problem with meshes and collisions
 | 
						There is some problem with meshes and collisions
 | 
				
			||||||
Test avatar walking up stairs. How does compare with SL.
 | 
						Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
 | 
				
			||||||
    Radius of the capsule affects ability to climb edges.
 | 
					 | 
				
			||||||
Debounce avatar contact so legs don't keep folding up when standing.
 | 
					Debounce avatar contact so legs don't keep folding up when standing.
 | 
				
			||||||
Implement LSL physics controls. Like STATUS_ROTATE_X.
 | 
					Implement LSL physics controls. Like STATUS_ROTATE_X.
 | 
				
			||||||
Add border extensions to terrain to help region crossings and objects leaving region.
 | 
					Add border extensions to terrain to help region crossings and objects leaving region.
 | 
				
			||||||
Use a different capsule shape for avatar when sitting
 | 
					Use a different capsule shape for avatar when sitting
 | 
				
			||||||
	LL uses a pyrimidal shape scaled by the avatar's bounding box
 | 
						LL uses a pyrimidal shape scaled by the avatar's bounding box
 | 
				
			||||||
	http://wiki.secondlife.com/wiki/File:Avmeshforms.png
 | 
						http://wiki.secondlife.com/wiki/File:Avmeshforms.png
 | 
				
			||||||
 | 
					 | 
				
			||||||
Performance test with lots of avatars. Can BulletSim support a thousand?
 | 
					Performance test with lots of avatars. Can BulletSim support a thousand?
 | 
				
			||||||
Optimize collisions in C++: only send up to the object subscribed to collisions.
 | 
					Optimize collisions in C++: only send up to the object subscribed to collisions.
 | 
				
			||||||
    Use collision subscription and remove the collsion(A,B) and collision(B,A)
 | 
					    Use collision subscription and remove the collsion(A,B) and collision(B,A)
 | 
				
			||||||
Check whether SimMotionState needs large if statement (see TODO).
 | 
					Check whether SimMotionState needs large if statement (see TODO).
 | 
				
			||||||
 | 
					 | 
				
			||||||
Implement 'top colliders' info.
 | 
					Implement 'top colliders' info.
 | 
				
			||||||
Avatar jump
 | 
					Avatar jump
 | 
				
			||||||
Performance measurement and changes to make quicker.
 | 
					Performance measurement and changes to make quicker.
 | 
				
			||||||
Implement detailed physics stats (GetStats()).
 | 
					Implement detailed physics stats (GetStats()).
 | 
				
			||||||
 | 
					 | 
				
			||||||
Measure performance improvement from hulls
 | 
					Measure performance improvement from hulls
 | 
				
			||||||
Test not using ghost objects for volume detect implementation.
 | 
					Test not using ghost objects for volume detect implementation.
 | 
				
			||||||
Performance of closures and delegates for taint processing
 | 
					Performance of closures and delegates for taint processing
 | 
				
			||||||
| 
						 | 
					@ -164,9 +158,7 @@ Performance of closures and delegates for taint processing
 | 
				
			||||||
	Is any slowdown introduced by the existing implementation significant?
 | 
						Is any slowdown introduced by the existing implementation significant?
 | 
				
			||||||
Is there are more efficient method of implementing pre and post step actions?
 | 
					Is there are more efficient method of implementing pre and post step actions?
 | 
				
			||||||
	See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
 | 
						See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
 | 
				
			||||||
 | 
					 | 
				
			||||||
Physics Arena central pyramid: why is one side permiable?
 | 
					Physics Arena central pyramid: why is one side permiable?
 | 
				
			||||||
 | 
					 | 
				
			||||||
In SL, perfect spheres don't seem to have rolling friction. Add special case.
 | 
					In SL, perfect spheres don't seem to have rolling friction. Add special case.
 | 
				
			||||||
Enforce physical parameter min/max:
 | 
					Enforce physical parameter min/max:
 | 
				
			||||||
	Gravity: [-1, 28]
 | 
						Gravity: [-1, 28]
 | 
				
			||||||
| 
						 | 
					@ -178,6 +170,8 @@ Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/3179
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INTERNAL IMPROVEMENT/CLEANUP
 | 
					INTERNAL IMPROVEMENT/CLEANUP
 | 
				
			||||||
=================================================
 | 
					=================================================
 | 
				
			||||||
 | 
					Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
 | 
				
			||||||
 | 
						BSScene.TaintedObject() could immediately execute the callback if already in taint time.
 | 
				
			||||||
Create the physical wrapper classes (BulletBody, BulletShape) by methods on
 | 
					Create the physical wrapper classes (BulletBody, BulletShape) by methods on
 | 
				
			||||||
	BSAPITemplate and make their actual implementation Bullet engine specific.
 | 
						BSAPITemplate and make their actual implementation Bullet engine specific.
 | 
				
			||||||
	For the short term, just call the existing functions in ShapeCollection.
 | 
						For the short term, just call the existing functions in ShapeCollection.
 | 
				
			||||||
| 
						 | 
					@ -197,22 +191,19 @@ Generalize Dynamics and PID with standardized motors.
 | 
				
			||||||
Generalize Linkset and vehicles into PropertyManagers
 | 
					Generalize Linkset and vehicles into PropertyManagers
 | 
				
			||||||
    Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
 | 
					    Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
 | 
				
			||||||
	Potentially add events for shape destruction, etc.
 | 
						Potentially add events for shape destruction, etc.
 | 
				
			||||||
Complete implemention of preStepActions
 | 
					Better mechanism for resetting linkset set and vehicle parameters when body rebuilt.
 | 
				
			||||||
	Replace vehicle step call with prestep event.
 | 
						BSPrim.CreateGeomAndObject is kludgy with the callbacks, etc.
 | 
				
			||||||
	Is there a need for postStepActions? postStepTaints?
 | 
					 | 
				
			||||||
Implement linkset by setting position of children when root updated. (LinksetManual)
 | 
					Implement linkset by setting position of children when root updated. (LinksetManual)
 | 
				
			||||||
	Linkset implementation using manual prim movement.
 | 
						Linkset implementation using manual prim movement.
 | 
				
			||||||
LinkablePrim class? Would that simplify/centralize the linkset logic?
 | 
					LinkablePrim class? Would that simplify/centralize the linkset logic?
 | 
				
			||||||
BSScene.UpdateParameterSet() is broken. How to set params on objects?
 | 
					BSScene.UpdateParameterSet() is broken. How to set params on objects?
 | 
				
			||||||
Remove HeightmapInfo from terrain specification
 | 
					 | 
				
			||||||
    Since C++ code does not need terrain height, this structure et al are not needed.
 | 
					 | 
				
			||||||
Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
 | 
					Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
 | 
				
			||||||
    bob at the water level. BSPrim.PositionSanityCheck().
 | 
					    bob at the water level. BSPrim.PositionSanityCheck()
 | 
				
			||||||
Should taints check for existance or activeness of target?
 | 
					Should taints check for existance or activeness of target?
 | 
				
			||||||
	When destroying linksets/etc, taints can be generated for objects that are
 | 
						When destroying linksets/etc, taints can be generated for objects that are
 | 
				
			||||||
	actually gone when the taint happens. Crashes don't happen because the taint closure
 | 
						actually gone when the taint happens. Crashes don't happen because the taint closure
 | 
				
			||||||
	keeps the object from being freed, but that is just an accident.
 | 
						keeps the object from being freed, but that is just an accident.
 | 
				
			||||||
	Possibly have and 'active' flag that is checked by the taint processor?
 | 
						Possibly have an 'active' flag that is checked by the taint processor?
 | 
				
			||||||
Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
 | 
					Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
 | 
				
			||||||
Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
 | 
					Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
 | 
				
			||||||
There are TOO MANY interfaces from BulletSim core to Bullet itself
 | 
					There are TOO MANY interfaces from BulletSim core to Bullet itself
 | 
				
			||||||
| 
						 | 
					@ -282,3 +273,18 @@ Redo BulletSimAPI to allow native C# implementation of Bullet option (DONE)
 | 
				
			||||||
Meshes rendering as bounding boxes (DONE)
 | 
					Meshes rendering as bounding boxes (DONE)
 | 
				
			||||||
	(Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
 | 
						(Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
 | 
				
			||||||
llMoveToTarget (Resolution: added simple motor to update the position.)
 | 
					llMoveToTarget (Resolution: added simple motor to update the position.)
 | 
				
			||||||
 | 
					Angular motor direction is global coordinates rather than local coordinates (DONE)
 | 
				
			||||||
 | 
					Add vehicle collisions so IsColliding is properly reported. (DONE)
 | 
				
			||||||
 | 
						Needed for banking, limitMotorUp, movementLimiting, ...
 | 
				
			||||||
 | 
						(Resolution: added CollisionFlags.BS_VEHICLE_COLLISION and code to use it)
 | 
				
			||||||
 | 
					VehicleAddForce is not scaled by the simulation step but it is only
 | 
				
			||||||
 | 
						applied for one step. Should it be scaled? (DONE)
 | 
				
			||||||
 | 
						(Resolution: use force for timed things, Impulse for immediate, non-timed things)
 | 
				
			||||||
 | 
					Complete implemention of preStepActions (DONE)
 | 
				
			||||||
 | 
						Replace vehicle step call with prestep event.
 | 
				
			||||||
 | 
						Is there a need for postStepActions? postStepTaints?
 | 
				
			||||||
 | 
					Disable activity of passive linkset children. (DONE)
 | 
				
			||||||
 | 
						Since the linkset is a compound object, the old prims are left lying
 | 
				
			||||||
 | 
						around and need to be phantomized so they don't collide, ...
 | 
				
			||||||
 | 
					Remove HeightmapInfo from terrain specification (DONE)
 | 
				
			||||||
 | 
					    Since C++ code does not need terrain height, this structure et al are not needed.
 | 
				
			||||||
| 
						 | 
					@ -62,13 +62,20 @@ namespace OpenSim.Region.Physics.Manager
 | 
				
			||||||
//        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
					//        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Name of this scene.  Useful in debug messages to distinguish one OdeScene instance from another.
 | 
					        /// A unique identifying string for this instance of the physics engine.
 | 
				
			||||||
 | 
					        /// Useful in debug messages to distinguish one OdeScene instance from another.
 | 
				
			||||||
 | 
					        /// Usually set to include the region name that the physics engine is acting for.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public string Name { get; protected set; }
 | 
					        public string Name { get; protected set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// A string identifying the family of this physics engine. Most common values returned
 | 
				
			||||||
 | 
					        /// are "OpenDynamicsEngine" and "BulletSim" but others are possible.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string EngineType { get; protected set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The only thing that should register for this event is the SceneGraph
 | 
					        // The only thing that should register for this event is the SceneGraph
 | 
				
			||||||
        // Anything else could cause problems.
 | 
					        // Anything else could cause problems.
 | 
				
			||||||
 | 
					 | 
				
			||||||
        public event physicsCrash OnPhysicsCrash;
 | 
					        public event physicsCrash OnPhysicsCrash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static PhysicsScene Null
 | 
					        public static PhysicsScene Null
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ namespace OpenSim.Region.Physics.OdePlugin
 | 
				
			||||||
                // http://opensimulator.org/mantis/view.php?id=2750).
 | 
					                // http://opensimulator.org/mantis/view.php?id=2750).
 | 
				
			||||||
                d.InitODE();
 | 
					                d.InitODE();
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                m_scene = new OdeScene(sceneIdentifier);
 | 
					                m_scene = new OdeScene(GetName(), sceneIdentifier);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return m_scene;
 | 
					            return m_scene;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -526,11 +526,12 @@ namespace OpenSim.Region.Physics.OdePlugin
 | 
				
			||||||
        /// These settings need to be tweaked 'exactly' right or weird stuff happens.
 | 
					        /// These settings need to be tweaked 'exactly' right or weird stuff happens.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param value="name">Name of the scene.  Useful in debug messages.</param>
 | 
					        /// <param value="name">Name of the scene.  Useful in debug messages.</param>
 | 
				
			||||||
        public OdeScene(string name)
 | 
					        public OdeScene(string engineType, string name)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
 | 
					            m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Name = name;
 | 
					            Name = name;
 | 
				
			||||||
 | 
					            EngineType = engineType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            nearCallback = near;
 | 
					            nearCallback = near;
 | 
				
			||||||
            triCallback = TriCallback;
 | 
					            triCallback = TriCallback;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.POSPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public PhysicsScene GetScene(string sceneIdentifier)
 | 
					        public PhysicsScene GetScene(string sceneIdentifier)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return new POSScene(sceneIdentifier);
 | 
					            return new POSScene(GetName(), sceneIdentifier);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string GetName()
 | 
					        public string GetName()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,8 +43,10 @@ namespace OpenSim.Region.Physics.POSPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //protected internal string sceneIdentifier;
 | 
					        //protected internal string sceneIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public POSScene(String _sceneIdentifier)
 | 
					        public POSScene(string engineType, String _sceneIdentifier)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            EngineType = engineType;
 | 
				
			||||||
 | 
					            Name = EngineType + "/" + _sceneIdentifier;
 | 
				
			||||||
            //sceneIdentifier = _sceneIdentifier;
 | 
					            //sceneIdentifier = _sceneIdentifier;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,11 +245,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
            wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
 | 
					            wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Returns of the function is allowed. Throws a script exception if not allowed.
 | 
				
			||||||
        public void CheckThreatLevel(ThreatLevel level, string function)
 | 
					        public void CheckThreatLevel(ThreatLevel level, string function)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!m_OSFunctionsEnabled)
 | 
					            if (!m_OSFunctionsEnabled)
 | 
				
			||||||
                OSSLError(String.Format("{0} permission denied.  All OS functions are disabled.", function)); // throws
 | 
					                OSSLError(String.Format("{0} permission denied.  All OS functions are disabled.", function)); // throws
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            string reasonWhyNot = CheckThreatLevelTest(level, function);
 | 
				
			||||||
 | 
					            if (!String.IsNullOrEmpty(reasonWhyNot))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                OSSLError(reasonWhyNot);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check to see if function is allowed. Returns an empty string if function permitted
 | 
				
			||||||
 | 
					        //     or a string explaining why this function can't be used.
 | 
				
			||||||
 | 
					        private string CheckThreatLevelTest(ThreatLevel level, string function)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            if (!m_FunctionPerms.ContainsKey(function))
 | 
					            if (!m_FunctionPerms.ContainsKey(function))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                FunctionPerms perms = new FunctionPerms();
 | 
					                FunctionPerms perms = new FunctionPerms();
 | 
				
			||||||
| 
						 | 
					@ -329,10 +341,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Allow / disallow by threat level
 | 
					                // Allow / disallow by threat level
 | 
				
			||||||
                if (level > m_MaxThreatLevel)
 | 
					                if (level > m_MaxThreatLevel)
 | 
				
			||||||
                    OSSLError(
 | 
					                    return
 | 
				
			||||||
                        String.Format(
 | 
					                        String.Format(
 | 
				
			||||||
                            "{0} permission denied.  Allowed threat level is {1} but function threat level is {2}.",
 | 
					                            "{0} permission denied.  Allowed threat level is {1} but function threat level is {2}.",
 | 
				
			||||||
                            function, m_MaxThreatLevel, level));
 | 
					                            function, m_MaxThreatLevel, level);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -342,7 +354,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
                    if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
 | 
					                    if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // prim owner is in the list of allowed owners
 | 
					                        // prim owner is in the list of allowed owners
 | 
				
			||||||
                        return;
 | 
					                        return String.Empty;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    UUID ownerID = m_item.OwnerID;
 | 
					                    UUID ownerID = m_item.OwnerID;
 | 
				
			||||||
| 
						 | 
					@ -354,7 +366,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
 | 
					                        if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            return;
 | 
					                            return String.Empty;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -365,7 +377,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (land.LandData.OwnerID == ownerID)
 | 
					                        if (land.LandData.OwnerID == ownerID)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            return;
 | 
					                            return String.Empty;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -375,7 +387,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
                        //Only Estate Managers may use the function
 | 
					                        //Only Estate Managers may use the function
 | 
				
			||||||
                        if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
 | 
					                        if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            return;
 | 
					                            return String.Empty;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,25 +396,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
 | 
					                        if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            return;
 | 
					                            return String.Empty;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
 | 
					                    if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
 | 
				
			||||||
                        OSSLError(
 | 
					                        return(
 | 
				
			||||||
                            String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
 | 
					                            String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
 | 
				
			||||||
                            function));
 | 
					                            function));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (m_item.CreatorID != ownerID)
 | 
					                    if (m_item.CreatorID != ownerID)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
 | 
					                        if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
 | 
				
			||||||
                            OSSLError(
 | 
					                            return String.Format("{0} permission denied. Script permissions error.", function);
 | 
				
			||||||
                                String.Format("{0} permission denied. Script permissions error.",
 | 
					 | 
				
			||||||
                                function));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            return String.Empty;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        internal void OSSLDeprecated(string function, string replacement)
 | 
					        internal void OSSLDeprecated(string function, string replacement)
 | 
				
			||||||
| 
						 | 
					@ -1558,6 +1569,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string osGetPhysicsEngineType()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // High because it can be used to target attacks to known weaknesses
 | 
				
			||||||
 | 
					            // This would allow a new class of griefer scripts that don't even
 | 
				
			||||||
 | 
					            // require their user to know what they are doing (see script
 | 
				
			||||||
 | 
					            // kiddie)
 | 
				
			||||||
 | 
					            // Because it would be nice if scripts didn't blow up if the information
 | 
				
			||||||
 | 
					            //    about the physics engine, this function returns an empty string if
 | 
				
			||||||
 | 
					            //    the user does not have permission to see it. This as opposed to
 | 
				
			||||||
 | 
					            //    throwing an exception.
 | 
				
			||||||
 | 
					            m_host.AddScriptLPS(1);
 | 
				
			||||||
 | 
					            string ret = String.Empty;
 | 
				
			||||||
 | 
					            if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (m_ScriptEngine.World.PhysicsScene != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ret = m_ScriptEngine.World.PhysicsScene.EngineType;
 | 
				
			||||||
 | 
					                    // An old physics engine might have an uninitialized engine type
 | 
				
			||||||
 | 
					                    if (ret == null)
 | 
				
			||||||
 | 
					                        ret = "unknown";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string osGetSimulatorVersion()
 | 
					        public string osGetSimulatorVersion()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // High because it can be used to target attacks to known weaknesses
 | 
					            // High because it can be used to target attacks to known weaknesses
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        string osGetScriptEngineName();
 | 
					        string osGetScriptEngineName();
 | 
				
			||||||
        string osGetSimulatorVersion();
 | 
					        string osGetSimulatorVersion();
 | 
				
			||||||
 | 
					        string osGetPhysicsEngineType();
 | 
				
			||||||
        Object osParseJSONNew(string JSON);
 | 
					        Object osParseJSONNew(string JSON);
 | 
				
			||||||
        Hashtable osParseJSON(string JSON);
 | 
					        Hashtable osParseJSON(string JSON);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -420,6 +420,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
 | 
				
			||||||
            return m_OSSL_Functions.osGetScriptEngineName();
 | 
					            return m_OSSL_Functions.osGetScriptEngineName();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public string osGetPhysicsEngineType()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return m_OSSL_Functions.osGetPhysicsEngineType();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string osGetSimulatorVersion()
 | 
					        public string osGetSimulatorVersion()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
           return m_OSSL_Functions.osGetSimulatorVersion();
 | 
					           return m_OSSL_Functions.osGetSimulatorVersion();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue