diff --git a/.gitignore b/.gitignore index 0fd1e586cf..36a1757338 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ bin/Physics* bin/Terrain* bin/Regions/* bin/UserAssets +bin/assetcache +bin/maptiles bin/estate_settings.xml bin/config-include/CenomeCache.ini bin/config-include/FlotsamCache.ini diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index a5055247c7..2080a1682e 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -480,9 +480,16 @@ namespace OpenSim.Framework MainConsole.Instance.Output("=====================================\n"); if (name == String.Empty) - name = MainConsole.Instance.CmdPrompt("New region name", name); - if (name == String.Empty) - throw new Exception("Cannot interactively create region with no name"); + { + while (name.Trim() == string.Empty) + { + name = MainConsole.Instance.CmdPrompt("New region name", name); + if (name.Trim() == string.Empty) + { + MainConsole.Instance.Output("Cannot interactively create region with no name"); + } + } + } source.AddConfig(name); @@ -513,15 +520,20 @@ namespace OpenSim.Framework // allKeys.Remove("RegionUUID"); string regionUUID = config.GetString("RegionUUID", string.Empty); - if (regionUUID == String.Empty) + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) { UUID newID = UUID.Random(); - - regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + while (RegionID == UUID.Zero) + { + regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); + if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) + { + MainConsole.Instance.Output("RegionUUID must be a valid UUID"); + } + } config.Set("RegionUUID", regionUUID); } - RegionID = new UUID(regionUUID); originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) // Location diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index d768a1ac16..14c1a3947e 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -119,17 +119,20 @@ namespace OpenSim.Region.CoreModules.World.Sound m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); + if (dis > 100.0) // Max audio distance return; + float thisSpGain; + // Scale by distance if (radius == 0) - gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); else - gain = (float)((double)gain * ((radius - dis) / radius)); + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); sp.ControllingClient.SendTriggeredSound( - soundId, ownerID, objectID, parentID, handle, position, (float)gain); + soundId, ownerID, objectID, parentID, handle, position, thisSpGain); }); } } diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index bfe1e8dc33..ed71a951cb 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -67,6 +67,10 @@ namespace OpenSim.Region.Framework.Interfaces /// void DispatchReply(UUID scriptId, int code, string text, string key); + /// For constants + void RegisterConstant(string cname, object value); + object LookupModConstant(string cname); + // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1734704cf6..eb4ba41d7b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1199,15 +1199,17 @@ namespace OpenSim.Region.Framework.Scenes avatar.ControllingClient.SendShutdownConnectionNotice(); }); + // Stop updating the scene objects and agents. + m_shuttingDown = true; + // Wait here, or the kick messages won't actually get to the agents before the scene terminates. + // We also need to wait to avoid a race condition with the scene update loop which might not yet + // have checked ShuttingDown. Thread.Sleep(500); // Stop all client threads. ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); - // Stop updating the scene objects and agents. - m_shuttingDown = true; - m_log.Debug("[SCENE]: Persisting changed objects"); EventManager.TriggerSceneShuttingDown(this); diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index 74a85e2cd5..705a84700d 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -46,6 +46,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Dictionary m_constants = new Dictionary(); + #region ScriptInvocation protected class ScriptInvocationData { @@ -269,6 +271,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms Delegate fn = LookupScriptInvocation(fname); return fn.DynamicInvoke(olist.ToArray()); } + + /// + /// Operation to for a region module to register a constant to be used + /// by the script engine + /// + public void RegisterConstant(string cname, object value) + { + m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); + lock (m_constants) + { + m_constants.Add(cname,value); + } + } + + /// + /// Operation to check for a registered constant + /// + public object LookupModConstant(string cname) + { + // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname); + + lock (m_constants) + { + object value = null; + if (m_constants.TryGetValue(cname,out value)) + return value; + } + + return null; + } + #endregion } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index fbb9e21958..ea3093a96b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -50,7 +50,8 @@ public class BSConstraint : IDisposable m_body2 = obj2; m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, frame1, frame1rot, - frame2, frame2rot)); + frame2, frame2rot, + true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); m_enabled = true; } @@ -83,6 +84,15 @@ public class BSConstraint : IDisposable return ret; } + public bool SetCFMAndERP(float cfm, float erp) + { + bool ret = true; + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + return ret; + } + public bool UseFrameOffset(bool useOffset) { bool ret = false; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index a2650fbd36..c88e6455b9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -83,7 +83,8 @@ public class BSConstraintCollection : IDisposable return true; } - // Get the constraint between two bodies. There can be only one the way we're using them. + // Get the constraint between two bodies. There can be only one. + // Return 'true' if a constraint was found. public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) { bool found = false; @@ -105,6 +106,9 @@ public class BSConstraintCollection : IDisposable return found; } + // Remove any constraint between the passed bodies. + // Presumed there is only one such constraint possible. + // Return 'true' if a constraint was found and destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) { // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); @@ -125,6 +129,8 @@ public class BSConstraintCollection : IDisposable return ret; } + // Remove all constraints that reference the passed body. + // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3bc210084e..6f8430c8cc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -117,10 +117,50 @@ public class BSLinkset } // An existing linkset had one of its members rebuilt or something. - // Undo all the physical linking and rebuild the physical linkset. - public bool RefreshLinkset(BSPrim requestor) + // Go through the linkset and rebuild the pointers to the bodies of the linkset members. + public BSLinkset RefreshLinkset(BSPrim requestor) { - return true; + BSLinkset ret = requestor.Linkset; + + lock (m_linksetActivityLock) + { + System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); + if (aPtr == System.IntPtr.Zero) + { + // That's odd. We can't find the root of the linkset. + // The linkset is somehow dead. The requestor is now a member of a linkset of one. + DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID); + ret = RemoveMeFromLinkset(m_linksetRoot); + } + else + { + // Reconstruct the pointer to the body of the linkset root. + DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr); + m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr); + + List toRemove = new List(); + foreach (BSPrim bsp in m_children) + { + aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID); + if (aPtr == System.IntPtr.Zero) + { + toRemove.Add(bsp); + } + else + { + // Reconstruct the pointer to the body of the linkset root. + DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr); + bsp.Body = new BulletBody(bsp.LocalID, aPtr); + } + } + foreach (BSPrim bsp in toRemove) + { + RemoveChildFromLinkset(bsp); + } + } + } + + return ret; } @@ -256,10 +296,13 @@ public class BSLinkset DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); BSConstraint constrain = m_scene.Constraints.CreateConstraint( m_scene.World, m_linksetRoot.Body, childPrim.Body, - childRelativePosition, - childRelativeRotation, + // childRelativePosition, + // childRelativeRotation, OMV.Vector3.Zero, - OMV.Quaternion.Identity); + OMV.Quaternion.Identity, + OMV.Vector3.Zero, + OMV.Quaternion.Identity + ); constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); @@ -268,6 +311,7 @@ public class BSLinkset constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), m_scene.Params.linkConstraintTransMotorMaxVel, m_scene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7590d936a4..a4ab702f60 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -103,7 +103,10 @@ public sealed class BSPrim : PhysicsActor long _collidingGroundStep; private BulletBody m_body; - public BulletBody Body { get { return m_body; } } + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } private BSDynamics _vehicle; @@ -184,6 +187,7 @@ public sealed class BSPrim : PhysicsActor { _mass = CalculateMass(); // changing size changes the mass BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); + DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); RecreateGeomAndObject(); }); } @@ -477,9 +481,11 @@ public sealed class BSPrim : PhysicsActor // Only called at taint time so it is save to call into Bullet. private void SetObjectDynamic() { - // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); - - RecreateGeomAndObject(); + // RA: remove this for the moment. + // The problem is that dynamic objects are hulls so if we are becoming physical + // the shape has to be checked and possibly built. + // Maybe a VerifyCorrectPhysicalShape() routine? + // RecreateGeomAndObject(); float mass = _mass; // Bullet wants static objects have a mass of zero @@ -967,25 +973,27 @@ public sealed class BSPrim : PhysicsActor if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) { // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); - if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE) + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) { DetailLog("{0},CreateGeom,sphere", LocalID); _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; - ret = true; // Bullet native objects are scaled by the Bullet engine so pass the size in _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; } } } else { - // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); - if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX) + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) { DetailLog("{0},CreateGeom,box", LocalID); _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; - ret = true; _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; } } } @@ -1194,7 +1202,8 @@ public sealed class BSPrim : PhysicsActor // Create an object in Bullet if it has not already been created // No locking here because this is done when the physics engine is not simulating - private void CreateObject() + // Returns 'true' if an object was actually created. + private bool CreateObject() { // this routine is called when objects are rebuilt. @@ -1202,12 +1211,12 @@ public sealed class BSPrim : PhysicsActor ShapeData shape; FillShapeInfo(out shape); // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); - BulletSimAPI.CreateObject(_scene.WorldID, shape); + bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); + // the CreateObject() may have recreated the rigid body. Make sure we have the latest. m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); - // The root object could have been recreated. Make sure everything linksety is up to date. - _linkset.RefreshLinkset(this); + return ret; } // Copy prim's info into the BulletSim shape description structure @@ -1236,8 +1245,8 @@ public sealed class BSPrim : PhysicsActor private void RecreateGeomAndObject() { // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); - CreateGeom(true); - CreateObject(); + if (CreateGeom(true)) + CreateObject(); return; } @@ -1322,6 +1331,13 @@ public sealed class BSPrim : PhysicsActor base.RequestPhysicsterseUpdate(); } + else + { + // For debugging, we can also report the movement of children + DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + entprop.Acceleration, entprop.RotationalVelocity); + } } // I've collided with something diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c6d622b621..28d5cb5b62 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -315,6 +315,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) { // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName); + + if (!m_initialized) return null; + BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); lock (m_avatars) m_avatars.Add(localID, actor); return actor; @@ -323,6 +326,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void RemoveAvatar(PhysicsActor actor) { // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); + + if (!m_initialized) return; + BSCharacter bsactor = actor as BSCharacter; if (bsactor != null) { @@ -341,6 +347,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void RemovePrim(PhysicsActor prim) { + if (!m_initialized) return; + BSPrim bsprim = prim as BSPrim; if (bsprim != null) { @@ -366,6 +374,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters Vector3 size, Quaternion rotation, bool isPhysical, uint localID) { // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); + + if (!m_initialized) return null; + BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); lock (m_prims) m_prims.Add(localID, prim); return prim; @@ -807,6 +818,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // List of all of the externally visible parameters. // For each parameter, this table maps a text name to getter and setters. + // To add a new externally referencable/settable parameter, add the paramter storage + // location somewhere in the program and make an entry in this table with the + // getters and setters. + // To add a new variable, it is easiest to find an existing definition and copy it. + // Parameter values are floats. Booleans are converted to a floating value. + // // A ParameterDefn() takes the following parameters: // -- the text name of the parameter. This is used for console input and ini file. // -- a short text description of the parameter. This shows up in the console listing. @@ -815,7 +832,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters // -- a delegate for getting the value as a float // -- a delegate for setting the value from a float // - // To add a new variable, it is best to find an existing definition and copy it. + // The single letter parameters for the delegates are: + // s = BSScene + // p = string parameter name + // l = localID of referenced object + // v = float value + // cf = parameter configuration class (for fetching values from ini file) private ParameterDefn[] ParameterDefinitions = { new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", @@ -1048,6 +1070,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), + new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", + 0.0f, + (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintCFM; }, + (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), + new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", + 0.2f, + (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].linkConstraintERP; }, + (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 65e3145698..0ffbc94040 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -66,13 +66,14 @@ public struct ShapeData { public enum PhysicsShapeType { - SHAPE_AVATAR = 0, - SHAPE_BOX = 1, - SHAPE_CONE = 2, - SHAPE_CYLINDER = 3, - SHAPE_SPHERE = 4, - SHAPE_MESH = 5, - SHAPE_HULL = 6 + SHAPE_UNKNOWN = 0, + SHAPE_AVATAR = 1, + SHAPE_BOX = 2, + SHAPE_CONE = 3, + SHAPE_CYLINDER = 4, + SHAPE_SPHERE = 5, + SHAPE_MESH = 6, + SHAPE_HULL = 7 }; public uint ID; public PhysicsShapeType Type; @@ -86,12 +87,12 @@ public struct ShapeData public System.UInt64 MeshKey; public float Friction; public float Restitution; - public int Collidable; - public int Static; // true if a static object. Otherwise gravity, etc. + public float Collidable; // true of things bump into this + public float Static; // true if a static object. Otherwise gravity, etc. - // note that bools are passed as ints since bool size changes by language and architecture - public const int numericTrue = 1; - public const int numericFalse = 0; + // note that bools are passed as floats since bool size changes by language and architecture + public const float numericTrue = 1f; + public const float numericFalse = 0f; } [StructLayout(LayoutKind.Sequential)] public struct SweepHit @@ -168,6 +169,8 @@ public struct ConfigurationParameters public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; public float linkConstraintTransMotorMaxForce; + public float linkConstraintERP; + public float linkConstraintCFM; public const float numericTrue = 1f; public const float numericFalse = 0f; @@ -189,6 +192,28 @@ public enum CollisionFlags : uint PHYSICAL_OBJECT = 1 << 12, }; +// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 +// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. +public enum ConstraintParams : int +{ + BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730 + BT_CONSTRAINT_STOP_ERP, + BT_CONSTRAINT_CFM, + BT_CONSTRAINT_STOP_CFM, +}; +public enum ConstraintParamAxis : int +{ + AXIS_LINEAR_X = 0, + AXIS_LINEAR_Y, + AXIS_LINEAR_Z, + AXIS_ANGULAR_X, + AXIS_ANGULAR_Y, + AXIS_ANGULAR_Z, + AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls + AXIS_ANGULAR_ALL, + AXIS_ALL +}; + // =============================================================================== static class BulletSimAPI { @@ -380,7 +405,8 @@ public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, - Vector3 frame2loc, Quaternion frame2rot); + Vector3 frame2loc, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); @@ -397,6 +423,9 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CalculateTransforms2(IntPtr constrain); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 0db936f7f4..929b019ecf 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin private readonly IntPtr contactgroup; - internal IntPtr LandGeom; internal IntPtr WaterGeom; private float nmTerrainContactFriction = 255.0f; @@ -1512,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) - && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) - && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) { if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) { @@ -1542,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin //d.GeomGetAABB(contactGeom.g2, out aabb2); //d.GeomGetAABB(contactGeom.g1, out aabb1); //aabb1. - if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) { if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 084bd41bf1..c3b1f3d7e4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10446,7 +10446,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); break; case ScriptBaseClass.OBJECT_ROT: - ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); + { + Quaternion rot = Quaternion.Identity; + + if (obj.ParentGroup.RootPart == obj) + rot = obj.ParentGroup.GroupRotation; + else + rot = obj.GetWorldRotation(); + + LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); + ret.Add(objrot); + } break; case ScriptBaseClass.OBJECT_VELOCITY: ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index faad75d8b8..44de176609 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3286,5 +3286,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID test; return UUID.TryParse(thing, out test) ? 1 : 0; } + + /// + /// Wraps to Math.Min() + /// + /// + /// + /// + public LSL_Float osMin(double a, double b) + { + CheckThreatLevel(ThreatLevel.None, "osMin"); + m_host.AddScriptLPS(1); + + return Math.Min(a, b); + } + + /// + /// Wraps to Math.max() + /// + /// + /// + /// + public LSL_Float osMax(double a, double b) + { + CheckThreatLevel(ThreatLevel.None, "osMax"); + m_host.AddScriptLPS(1); + + return Math.Max(a, b); + } } } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index f2c8b6085a..a626be8211 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -51,8 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { get { - lock (SenseRepeatListLock) - return SenseRepeaters.Count; + return SenseRepeaters.Count; } } @@ -61,8 +60,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins m_CmdManager = CmdManager; maximumRange = CmdManager.m_ScriptEngine.Config.GetDouble("SensorMaxRange", 96.0d); maximumToReturn = CmdManager.m_ScriptEngine.Config.GetInt("SensorMaxResults", 16); + m_npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); } + private INPCModule m_npcModule; + private Object SenseLock = new Object(); private const int AGENT = 1; @@ -116,6 +118,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins public double distance; } + /// + /// Sensors to process. + /// + /// + /// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated + /// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger + /// of deadlocks with future code updates. + /// + /// Always lock SenseRepeatListLock when updating this list. + /// private List SenseRepeaters = new List(); private object SenseRepeatListLock = new object(); @@ -125,6 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { // Always remove first, in case this is a re-set UnSetSenseRepeaterEvents(m_localID, m_itemID); + if (sec == 0) // Disabling timer return; @@ -144,9 +157,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins ts.host = host; ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + + AddSenseRepeater(ts); + } + + private void AddSenseRepeater(SenseRepeatClass senseRepeater) + { lock (SenseRepeatListLock) { - SenseRepeaters.Add(ts); + List newSenseRepeaters = new List(SenseRepeaters); + newSenseRepeaters.Add(senseRepeater); + SenseRepeaters = newSenseRepeaters; } } @@ -155,39 +176,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // Remove from timer lock (SenseRepeatListLock) { - List NewSensors = new List(); + List newSenseRepeaters = new List(); foreach (SenseRepeatClass ts in SenseRepeaters) { if (ts.localID != m_localID || ts.itemID != m_itemID) { - NewSensors.Add(ts); + newSenseRepeaters.Add(ts); } } - SenseRepeaters.Clear(); - SenseRepeaters = NewSensors; + + SenseRepeaters = newSenseRepeaters; } } public void CheckSenseRepeaterEvents() { - lock (SenseRepeatListLock) + // Go through all timers + foreach (SenseRepeatClass ts in SenseRepeaters) { - // Nothing to do here? - if (SenseRepeaters.Count == 0) - return; - - // Go through all timers - foreach (SenseRepeatClass ts in SenseRepeaters) + // Time has passed? + if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) { - // Time has passed? - if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) - { - SensorSweep(ts); - // set next interval - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - } + SensorSweep(ts); + // set next interval + ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); } - } // lock + } } public void SenseOnce(uint m_localID, UUID m_itemID, @@ -439,8 +453,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private List doAgentSensor(SenseRepeatClass ts) { - INPCModule npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); - List sensedEntities = new List(); // If nobody about quit fast @@ -473,7 +485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); Vector3 toRegionPos; double dis; - + Action senseEntity = new Action(presence => { // m_log.DebugFormat( @@ -482,7 +494,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins if ((ts.type & NPC) == 0 && (ts.type & OS_NPC) == 0 && presence.PresenceType == PresenceType.Npc) { - INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); + INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData == null || !npcData.SenseAsAgent) { // m_log.DebugFormat( @@ -500,7 +512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins } else { - INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); + INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene); if (npcData != null && npcData.SenseAsAgent) { // m_log.DebugFormat( @@ -615,21 +627,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins { List data = new List(); - lock (SenseRepeatListLock) + foreach (SenseRepeatClass ts in SenseRepeaters) { - foreach (SenseRepeatClass ts in SenseRepeaters) + if (ts.itemID == itemID) { - if (ts.itemID == itemID) - { - data.Add(ts.interval); - data.Add(ts.name); - data.Add(ts.keyID); - data.Add(ts.type); - data.Add(ts.range); - data.Add(ts.arc); - } + data.Add(ts.interval); + data.Add(ts.name); + data.Add(ts.keyID); + data.Add(ts.type); + data.Add(ts.range); + data.Add(ts.arc); } } + return data.ToArray(); } @@ -663,8 +673,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - lock (SenseRepeatListLock) - SenseRepeaters.Add(ts); + AddSenseRepeater(ts); idx += 6; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index c9403ebc29..f73a85e3e7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -283,5 +283,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// 1 if thing is a valid UUID, 0 otherwise LSL_Integer osIsUUID(string thing); + + /// + /// Wraps to Math.Min() + /// + /// + /// + /// + LSL_Float osMin(double a, double b); + + /// + /// Wraps to Math.max() + /// + /// + /// + /// + LSL_Float osMax(double a, double b); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 99995a7171..53daa13d49 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -935,5 +935,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osIsUUID(thing); } + + public LSL_Float osMin(double a, double b) + { + return m_OSSL_Functions.osMin(a, b); + } + + public LSL_Float osMax(double a, double b) + { + return m_OSSL_Functions.osMax(a, b); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index b24f016a08..97dd0f6122 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { public class CSCodeGenerator : ICodeConverter { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private SYMBOL m_astRoot = null; private Dictionary, KeyValuePair> m_positionMap; @@ -255,7 +255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools else if (s is IdentDotExpression) retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s); else if (s is IdentExpression) - retstr += Generate(CheckName(((IdentExpression) s).Name), s); + retstr += GenerateIdentifier(((IdentExpression) s).Name, s); else if (s is IDENT) retstr += Generate(CheckName(((TOKEN) s).yytext), s); else @@ -867,6 +867,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools return retstr; } + /// + /// Generates the code for an identifier + /// + /// The symbol name + /// The Symbol node. + /// String containing C# code for identifier reference. + private string GenerateIdentifier(string id, SYMBOL s) + { + if (m_comms != null) + { + object value = m_comms.LookupModConstant(id); + if (value != null) + { + string retval = null; + if (value is int) + retval = ((int)value).ToString(); + else if (value is float) + retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString()); + else if (value is string) + retval = String.Format("new LSL_Types.LSLString(\"{0}\")",((string)value)); + else if (value is OpenMetaverse.UUID) + retval = String.Format("new LSL_Types.key(\"{0}\")",((OpenMetaverse.UUID)value).ToString()); + else if (value is OpenMetaverse.Vector3) + retval = String.Format("new LSL_Types.Vector3(\"{0}\")",((OpenMetaverse.Vector3)value).ToString()); + else if (value is OpenMetaverse.Quaternion) + retval = String.Format("new LSL_Types.Quaternion(\"{0}\")",((OpenMetaverse.Quaternion)value).ToString()); + else retval = id; + + return Generate(retval, s); + } + } + + return Generate(CheckName(id), s); + } + /// /// Generates the code for a FunctionCall node. /// diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 9d96703c1a..44f5e0180c 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -122,7 +122,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e); } return fldrs; @@ -191,7 +191,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolderContent: {0}", e.Message); + m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message); } return inventory; @@ -432,7 +432,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetItem: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); } return null; @@ -456,7 +456,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolder: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e); } return null; @@ -474,7 +474,7 @@ namespace OpenSim.Services.Connectors List items = new List(); - foreach (Object o in ret.Values) // getting the values directly, we don't care about the keys item_i + foreach (Object o in ((Dictionary)ret["ITEMS"]).Values) items.Add(BuildItem((Dictionary)o)); return items; @@ -525,7 +525,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetUserInventory: ", e); } return inventory; @@ -574,7 +574,7 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building folder: {0}", e.Message); + m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e); } return folder; @@ -613,11 +613,10 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building item: {0}", e.Message); + m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e); } return item; } - } -} +} \ No newline at end of file diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index c6bb76af7f..fd8f39ab7c 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 6ca98cc8fe..72847e7c6e 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 0924dd01da..300e4be8eb 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 70bcdb7983..1acc0dd5ae 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ