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