aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs15
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs4
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs26
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs1
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs8
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs314
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs79
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs40
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs170
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs27
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt60
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs11
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs3
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSPlugin.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/POSScene.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs59
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs127
-rw-r--r--OpenSim/Server/Base/ServerUtils.cs7
29 files changed, 662 insertions, 335 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index a8517e6..967fa44 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -6427,19 +6427,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6427 #endregion 6427 #endregion
6428 6428
6429 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6429 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6430 if (handlerAgentRequestSit != null)
6431 if (!(agentRequestSit.AgentData == null
6432 || agentRequestSit.TargetObject == null
6433 || agentRequestSit.TargetObject.TargetID == null
6434 || agentRequestSit.TargetObject.Offset == null))
6435 {
6436 var sp = m_scene.GetScenePresence(agentRequestSit.AgentData.AgentID);
6437 if (sp == null || sp.ParentID != 0) // ignore packet if agent is already sitting
6438 return true;
6439 6430
6440 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, 6431 if (handlerAgentRequestSit != null)
6441 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); 6432 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
6442 } 6433 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
6443 } 6434 }
6444 return true; 6435 return true;
6445 } 6436 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 232861e..44e8fdf 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -4050,9 +4050,9 @@ namespace OpenSim.Region.Framework.Scenes
4050 rigidBody, 4050 rigidBody,
4051 m_localId); 4051 m_localId);
4052 } 4052 }
4053 catch 4053 catch (Exception e)
4054 { 4054 {
4055 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4055 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4056 pa = null; 4056 pa = null;
4057 } 4057 }
4058 4058
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 0219540..6979c33 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1954,6 +1954,10 @@ namespace OpenSim.Region.Framework.Scenes
1954 { 1954 {
1955 if (ParentID != 0) 1955 if (ParentID != 0)
1956 { 1956 {
1957 var targetPart = m_scene.GetSceneObjectPart(targetID);
1958 if (targetPart != null && targetPart.LocalId == ParentID)
1959 return; // already sitting here, ignore
1960
1957 StandUp(); 1961 StandUp();
1958 } 1962 }
1959 1963
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
index 7ab2a03..373c7e0 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsPlugin.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
49 49
50 public PhysicsScene GetScene(string sceneIdentifier) 50 public PhysicsScene GetScene(string sceneIdentifier)
51 { 51 {
52 return new BasicScene(sceneIdentifier); 52 return new BasicScene(GetName(), sceneIdentifier);
53 } 53 }
54 54
55 public string GetName() 55 public string GetName()
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index f5826ed..c4b9117 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -49,8 +49,10 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
49 49
50 //protected internal string sceneIdentifier; 50 //protected internal string sceneIdentifier;
51 51
52 public BasicScene(string _sceneIdentifier) 52 public BasicScene(string engineType, string _sceneIdentifier)
53 { 53 {
54 EngineType = engineType;
55 Name = EngineType + "/" + _sceneIdentifier;
54 //sceneIdentifier = _sceneIdentifier; 56 //sceneIdentifier = _sceneIdentifier;
55 } 57 }
56 58
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index 14de2eb..ae54499 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -166,7 +166,7 @@ public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParamet
166 166
167 // If Debug logging level, enable logging from the unmanaged code 167 // If Debug logging level, enable logging from the unmanaged code
168 m_DebugLogCallbackHandle = null; 168 m_DebugLogCallbackHandle = null;
169 if (BSScene.m_log.IsDebugEnabled || PhysicsScene.PhysicsLogging.Enabled) 169 if (BSScene.m_log.IsDebugEnabled && PhysicsScene.PhysicsLogging.Enabled)
170 { 170 {
171 BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader); 171 BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader);
172 if (PhysicsScene.PhysicsLogging.Enabled) 172 if (PhysicsScene.PhysicsLogging.Enabled)
@@ -202,7 +202,7 @@ private void BulletLoggerPhysLog(string msg)
202} 202}
203 203
204public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep, 204public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
205 out int updatedEntityCount, out int collidersCount) 205 out int updatedEntityCount, out int collidersCount)
206{ 206{
207 BulletWorldUnman worldu = world as BulletWorldUnman; 207 BulletWorldUnman worldu = world as BulletWorldUnman;
208 return BSAPICPP.PhysicsStep2(worldu.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount); 208 return BSAPICPP.PhysicsStep2(worldu.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount);
@@ -212,6 +212,19 @@ public override void Shutdown(BulletWorld world)
212{ 212{
213 BulletWorldUnman worldu = world as BulletWorldUnman; 213 BulletWorldUnman worldu = world as BulletWorldUnman;
214 BSAPICPP.Shutdown2(worldu.ptr); 214 BSAPICPP.Shutdown2(worldu.ptr);
215
216 if (m_paramsHandle.IsAllocated)
217 {
218 m_paramsHandle.Free();
219 }
220 if (m_collisionArrayPinnedHandle.IsAllocated)
221 {
222 m_collisionArrayPinnedHandle.Free();
223 }
224 if (m_updateArrayPinnedHandle.IsAllocated)
225 {
226 m_updateArrayPinnedHandle.Free();
227 }
215} 228}
216 229
217public override bool PushUpdate(BulletBody obj) 230public override bool PushUpdate(BulletBody obj)
@@ -327,6 +340,12 @@ public override void RemoveChildShapeFromCompoundShape(BulletShape shape, Bullet
327 BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr); 340 BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
328} 341}
329 342
343public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb)
344{
345 BulletShapeUnman shapeu = pShape as BulletShapeUnman;
346 BSAPICPP.UpdateChildTransform2(shapeu.ptr, childIndex, pos, rot, shouldRecalculateLocalAabb);
347}
348
330public override void RecalculateCompoundShapeLocalAabb(BulletShape shape) 349public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
331{ 350{
332 BulletShapeUnman shapeu = shape as BulletShapeUnman; 351 BulletShapeUnman shapeu = shape as BulletShapeUnman;
@@ -1357,6 +1376,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap
1357public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); 1376public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
1358 1377
1359[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1379public static extern void UpdateChildTransform2(IntPtr pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
1380
1381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1360public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape); 1382public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
1361 1383
1362[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1384[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 0c7f315..b6ff52b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1212,6 +1212,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1212 1212
1213 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; } 1213 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
1214 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ } 1214 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
1215 public override void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb) { /* TODO */ }
1215 1216
1216 public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin) 1217 public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
1217 { 1218 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index 794ee17..bc163eb 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -342,6 +342,8 @@ public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape c
342 342
343public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape); 343public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
344 344
345public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Vector3 pos, Quaternion rot, bool shouldRecalculateLocalAabb);
346
345public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape); 347public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
346 348
347public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id); 349public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 939d38a..a5fec87 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -126,9 +126,9 @@ public sealed class BSCharacter : BSPhysObject
126 DetailLog("{0},BSCharacter.Destroy", LocalID); 126 DetailLog("{0},BSCharacter.Destroy", LocalID);
127 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 127 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
128 { 128 {
129 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 129 PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */);
130 PhysBody.Clear(); 130 PhysBody.Clear();
131 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 131 PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */);
132 PhysShape.Clear(); 132 PhysShape.Clear();
133 }); 133 });
134 } 134 }
@@ -328,6 +328,10 @@ public sealed class BSCharacter : BSPhysObject
328 public override bool Selected { 328 public override bool Selected {
329 set { _selected = value; } 329 set { _selected = value; }
330 } 330 }
331 public override bool IsSelected
332 {
333 get { return _selected; }
334 }
331 public override void CrossingFailure() { return; } 335 public override void CrossingFailure() { return; }
332 public override void link(PhysicsActor obj) { return; } 336 public override void link(PhysicsActor obj) { return; }
333 public override void delink() { return; } 337 public override void delink() { return; }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index c34c05a..e434412 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -108,10 +108,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
108 private float m_VhoverEfficiency = 0f; 108 private float m_VhoverEfficiency = 0f;
109 private float m_VhoverTimescale = 0f; 109 private float m_VhoverTimescale = 0f;
110 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height 110 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
111 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. 111 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
112 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) 112 private float m_VehicleBuoyancy = 0f;
113 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. 113 private Vector3 m_VehicleGravity = Vector3.Zero; // Gravity computed when buoyancy set
114 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
115 114
116 //Attractor properties 115 //Attractor properties
117 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); 116 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
@@ -124,17 +123,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 static readonly float PIOverFour = ((float)Math.PI) / 4f; 123 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f; 124 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126 125
126 // For debugging, flags to turn on and off individual corrections.
127 private bool enableAngularVerticalAttraction;
128 private bool enableAngularDeflection;
129 private bool enableAngularBanking;
130
127 public BSDynamics(BSScene myScene, BSPrim myPrim) 131 public BSDynamics(BSScene myScene, BSPrim myPrim)
128 { 132 {
129 PhysicsScene = myScene; 133 PhysicsScene = myScene;
130 Prim = myPrim; 134 Prim = myPrim;
131 Type = Vehicle.TYPE_NONE; 135 Type = Vehicle.TYPE_NONE;
136 SetupVehicleDebugging();
137 }
138
139 // Stopgap debugging enablement. Allows source level debugging but still checking
140 // in changes by making enablement of debugging flags from INI file.
141 public void SetupVehicleDebugging()
142 {
143 enableAngularVerticalAttraction = true;
144 enableAngularDeflection = false;
145 enableAngularBanking = false;
146 if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
147 {
148 enableAngularVerticalAttraction = false;
149 enableAngularDeflection = false;
150 enableAngularBanking = false;
151 }
132 } 152 }
133 153
134 // Return 'true' if this vehicle is doing vehicle things 154 // Return 'true' if this vehicle is doing vehicle things
135 public bool IsActive 155 public bool IsActive
136 { 156 {
137 get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } 157 get { return (Type != Vehicle.TYPE_NONE && !Prim.IsStatic); }
138 } 158 }
139 159
140 #region Vehicle parameter setting 160 #region Vehicle parameter setting
@@ -168,6 +188,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
168 break; 188 break;
169 case Vehicle.BUOYANCY: 189 case Vehicle.BUOYANCY:
170 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); 190 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
191 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
171 break; 192 break;
172 case Vehicle.HOVER_EFFICIENCY: 193 case Vehicle.HOVER_EFFICIENCY:
173 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); 194 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
@@ -540,12 +561,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
540 1f); 561 1f);
541 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 562 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
542 563
564 /* Not implemented
543 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 565 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
544 BSMotor.Infinite, BSMotor.InfiniteVector, 566 BSMotor.Infinite, BSMotor.InfiniteVector,
545 m_verticalAttractionEfficiency); 567 m_verticalAttractionEfficiency);
546 // Z goes away and we keep X and Y 568 // Z goes away and we keep X and Y
547 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); 569 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
548 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 570 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
571 */
549 } 572 }
550 #endregion // Vehicle parameter setting 573 #endregion // Vehicle parameter setting
551 574
@@ -571,15 +594,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
571 // Vehicles report collision events so we know when it's on the ground 594 // Vehicles report collision events so we know when it's on the ground
572 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 595 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
573 596
574 Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); 597 Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
575 PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia); 598 PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia);
576 PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); 599 PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
577 600
578 Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); 601 // Set the gravity for the vehicle depending on the buoyancy
579 PhysicsScene.PE.SetGravity(Prim.PhysBody, grav); 602 // TODO: what should be done if prim and vehicle buoyancy differ?
603 m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy);
604 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
605 PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero);
580 606
581 VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", 607 VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4},grav={5}",
582 Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); 608 Prim.LocalID, m_vehicleMass, friction, Prim.Inertia, angularDamping, m_VehicleGravity);
583 } 609 }
584 else 610 else
585 { 611 {
@@ -619,20 +645,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin
619 private Vector3 m_knownPosition; 645 private Vector3 m_knownPosition;
620 private Vector3 m_knownVelocity; 646 private Vector3 m_knownVelocity;
621 private Vector3 m_knownForce; 647 private Vector3 m_knownForce;
648 private Vector3 m_knownForceImpulse;
622 private Quaternion m_knownOrientation; 649 private Quaternion m_knownOrientation;
623 private Vector3 m_knownRotationalVelocity; 650 private Vector3 m_knownRotationalVelocity;
624 private Vector3 m_knownRotationalForce; 651 private Vector3 m_knownRotationalForce;
652 private Vector3 m_knownRotationalImpulse;
625 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed 653 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
626 654
627 private const int m_knownChangedPosition = 1 << 0; 655 private const int m_knownChangedPosition = 1 << 0;
628 private const int m_knownChangedVelocity = 1 << 1; 656 private const int m_knownChangedVelocity = 1 << 1;
629 private const int m_knownChangedForce = 1 << 2; 657 private const int m_knownChangedForce = 1 << 2;
630 private const int m_knownChangedOrientation = 1 << 3; 658 private const int m_knownChangedForceImpulse = 1 << 3;
631 private const int m_knownChangedRotationalVelocity = 1 << 4; 659 private const int m_knownChangedOrientation = 1 << 4;
632 private const int m_knownChangedRotationalForce = 1 << 5; 660 private const int m_knownChangedRotationalVelocity = 1 << 5;
633 private const int m_knownChangedTerrainHeight = 1 << 6; 661 private const int m_knownChangedRotationalForce = 1 << 6;
634 private const int m_knownChangedWaterLevel = 1 << 7; 662 private const int m_knownChangedRotationalImpulse = 1 << 7;
635 private const int m_knownChangedForwardVelocity = 1 << 8; 663 private const int m_knownChangedTerrainHeight = 1 << 8;
664 private const int m_knownChangedWaterLevel = 1 << 9;
665 private const int m_knownChangedForwardVelocity = 1 <<10;
636 666
637 private void ForgetKnownVehicleProperties() 667 private void ForgetKnownVehicleProperties()
638 { 668 {
@@ -653,21 +683,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin
653 if ((m_knownChanged & m_knownChangedVelocity) != 0) 683 if ((m_knownChanged & m_knownChangedVelocity) != 0)
654 { 684 {
655 Prim.ForceVelocity = m_knownVelocity; 685 Prim.ForceVelocity = m_knownVelocity;
656 PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity); 686 // Fake out Bullet by making it think the velocity is the same as last time.
687 // Bullet does a bunch of smoothing for changing parameters.
688 // Since the vehicle is demanding this setting, we override Bullet's smoothing
689 // by telling Bullet the value was the same last time.
690 PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity);
657 } 691 }
658 692
659 if ((m_knownChanged & m_knownChangedForce) != 0) 693 if ((m_knownChanged & m_knownChangedForce) != 0)
660 Prim.AddForce((Vector3)m_knownForce, false, true); 694 Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/);
695
696 if ((m_knownChanged & m_knownChangedForceImpulse) != 0)
697 Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/);
661 698
662 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) 699 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
663 { 700 {
664 Prim.ForceRotationalVelocity = m_knownRotationalVelocity; 701 Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
665 // Fake out Bullet by making it think the velocity is the same as last time.
666 PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); 702 PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
667 } 703 }
668 704
705 if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0)
706 Prim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/);
707
669 if ((m_knownChanged & m_knownChangedRotationalForce) != 0) 708 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
670 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); 709 {
710 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/);
711 }
671 712
672 // If we set one of the values (ie, the physics engine didn't do it) we must force 713 // If we set one of the values (ie, the physics engine didn't do it) we must force
673 // an UpdateProperties event to send the changes up to the simulator. 714 // an UpdateProperties event to send the changes up to the simulator.
@@ -757,15 +798,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
757 } 798 }
758 } 799 }
759 800
760 private void VehicleAddForce(Vector3 aForce) 801 private void VehicleAddForce(Vector3 pForce)
761 { 802 {
762 if ((m_knownHas & m_knownChangedForce) == 0) 803 if ((m_knownHas & m_knownChangedForce) == 0)
763 { 804 {
764 m_knownForce = Vector3.Zero; 805 m_knownForce = Vector3.Zero;
806 m_knownHas |= m_knownChangedForce;
765 } 807 }
766 m_knownForce += aForce; 808 m_knownForce += pForce;
767 m_knownChanged |= m_knownChangedForce; 809 m_knownChanged |= m_knownChangedForce;
768 m_knownHas |= m_knownChangedForce; 810 }
811
812 private void VehicleAddForceImpulse(Vector3 pImpulse)
813 {
814 if ((m_knownHas & m_knownChangedForceImpulse) == 0)
815 {
816 m_knownForceImpulse = Vector3.Zero;
817 m_knownHas |= m_knownChangedForceImpulse;
818 }
819 m_knownForceImpulse += pImpulse;
820 m_knownChanged |= m_knownChangedForceImpulse;
769 } 821 }
770 822
771 private Vector3 VehicleRotationalVelocity 823 private Vector3 VehicleRotationalVelocity
@@ -796,6 +848,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
796 m_knownChanged |= m_knownChangedRotationalForce; 848 m_knownChanged |= m_knownChangedRotationalForce;
797 m_knownHas |= m_knownChangedRotationalForce; 849 m_knownHas |= m_knownChangedRotationalForce;
798 } 850 }
851 private void VehicleAddRotationalImpulse(Vector3 pImpulse)
852 {
853 if ((m_knownHas & m_knownChangedRotationalImpulse) == 0)
854 {
855 m_knownRotationalImpulse = Vector3.Zero;
856 m_knownHas |= m_knownChangedRotationalImpulse;
857 }
858 m_knownRotationalImpulse += pImpulse;
859 m_knownChanged |= m_knownChangedRotationalImpulse;
860 }
861
799 // Vehicle relative forward velocity 862 // Vehicle relative forward velocity
800 private Vector3 VehicleForwardVelocity 863 private Vector3 VehicleForwardVelocity
801 { 864 {
@@ -844,86 +907,92 @@ namespace OpenSim.Region.Physics.BulletSPlugin
844 if (PhysicsScene.VehiclePhysicalLoggingEnabled) 907 if (PhysicsScene.VehiclePhysicalLoggingEnabled)
845 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); 908 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
846 909
847 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 910 VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}",
848 Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); 911 Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
849 } 912 }
850 913
851 // Apply the effect of the linear motor and other linear motions (like hover and float). 914 // Apply the effect of the linear motor and other linear motions (like hover and float).
852 private void MoveLinear(float pTimestep) 915 private void MoveLinear(float pTimestep)
853 { 916 {
854 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); 917 ComputeLinearVelocity(pTimestep);
855
856 // The movement computed in the linear motor is relative to the vehicle
857 // coordinates. Rotate the movement to world coordinates.
858 linearMotorContribution *= VehicleOrientation;
859 // All the contributions after this are world relative (mostly Z modifications)
860
861 // ==================================================================
862 // Buoyancy: force to overcome gravity.
863 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
864 // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
865 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
866 918
867 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); 919 ComputeLinearTerrainHeightCorrection(pTimestep);
868 920
869 Vector3 hoverContribution = ComputeLinearHover(pTimestep); 921 ComputeLinearHover(pTimestep);
870 922
871 ComputeLinearBlockingEndPoint(pTimestep); 923 ComputeLinearBlockingEndPoint(pTimestep);
872 924
873 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); 925 ComputeLinearMotorUp(pTimestep);
874
875 // ==================================================================
876 Vector3 newVelocity = linearMotorContribution
877 + terrainHeightContribution
878 + hoverContribution
879 + limitMotorUpContribution;
880 926
881 Vector3 newForce = buoyancyContribution; 927 ApplyGravity(pTimestep);
882 928
883 // If not changing some axis, reduce out velocity 929 // If not changing some axis, reduce out velocity
884 if ((m_flags & (VehicleFlag.NO_X)) != 0) 930 if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0)
885 newVelocity.X = 0; 931 {
886 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 932 Vector3 vel = VehicleVelocity;
887 newVelocity.Y = 0; 933 if ((m_flags & (VehicleFlag.NO_X)) != 0)
888 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 934 vel.X = 0;
889 newVelocity.Z = 0; 935 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
936 vel.Y = 0;
937 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
938 vel.Z = 0;
939 VehicleVelocity = vel;
940 }
890 941
891 // ================================================================== 942 // ==================================================================
892 // Clamp high or low velocities 943 // Clamp high or low velocities
893 float newVelocityLengthSq = newVelocity.LengthSquared(); 944 float newVelocityLengthSq = VehicleVelocity.LengthSquared();
894 if (newVelocityLengthSq > 1000f) 945 if (newVelocityLengthSq > 1000f)
895 { 946 {
896 newVelocity /= newVelocity.Length(); 947 VehicleVelocity /= VehicleVelocity.Length();
897 newVelocity *= 1000f; 948 VehicleVelocity *= 1000f;
898 } 949 }
899 else if (newVelocityLengthSq < 0.001f) 950 else if (newVelocityLengthSq < 0.001f)
900 newVelocity = Vector3.Zero; 951 VehicleVelocity = Vector3.Zero;
901 952
902 // ================================================================== 953 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity );
903 // Stuff new linear velocity into the vehicle. 954
904 // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. 955 } // end MoveLinear()
905 VehicleVelocity = newVelocity;
906 956
907 // Other linear forces are applied as forces. 957 public void ComputeLinearVelocity(float pTimestep)
908 Vector3 totalDownForce = newForce * m_vehicleMass; 958 {
909 if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) 959 Vector3 linearMotorStep = m_linearMotor.Step(pTimestep);
960
961 // The movement computed in the linear motor is relative to the vehicle
962 // coordinates. Rotate the movement to world coordinates.
963 Vector3 linearMotorVelocity = linearMotorStep * VehicleOrientation;
964
965 // If we're a ground vehicle, don't loose any Z action (like gravity acceleration).
966 float mixFactor = 1f; // 1 means use all linear motor Z value, 0 means use all existing Z
967 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
968 {
969 if (!Prim.IsColliding)
970 {
971 // If a ground vehicle and not on the ground, I want gravity effect
972 mixFactor = 0.2f;
973 }
974 }
975 else
910 { 976 {
911 VehicleAddForce(totalDownForce); 977 // I'm not a ground vehicle but don't totally loose the effect of the environment
978 mixFactor = 0.8f;
912 } 979 }
980 linearMotorVelocity.Z = mixFactor * linearMotorVelocity.Z + (1f - mixFactor) * VehicleVelocity.Z;
913 981
914 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", 982 // What we want to contribute to the vehicle's existing velocity
915 Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); 983 Vector3 linearMotorForce = linearMotorVelocity - VehicleVelocity;
916 VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
917 Prim.LocalID,
918 linearMotorContribution, terrainHeightContribution, hoverContribution,
919 limitMotorUpContribution, buoyancyContribution
920 );
921 984
922 } // end MoveLinear() 985 // Act against the inertia of the vehicle
986 linearMotorForce *= m_vehicleMass;
923 987
924 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) 988 VehicleAddForceImpulse(linearMotorForce * pTimestep);
989
990 VDetailLog("{0}, MoveLinear,velocity,vehVel={1},step={2},stepVel={3},mix={4},force={5}",
991 Prim.LocalID, VehicleVelocity, linearMotorStep, linearMotorVelocity, mixFactor, linearMotorForce);
992 }
993
994 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
925 { 995 {
926 Vector3 ret = Vector3.Zero;
927 // If below the terrain, move us above the ground a little. 996 // If below the terrain, move us above the ground a little.
928 // TODO: Consider taking the rotated size of the object or possibly casting a ray. 997 // TODO: Consider taking the rotated size of the object or possibly casting a ray.
929 if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) 998 if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
@@ -935,13 +1004,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
935 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", 1004 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
936 Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); 1005 Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
937 } 1006 }
938 return ret;
939 } 1007 }
940 1008
941 public Vector3 ComputeLinearHover(float pTimestep) 1009 public void ComputeLinearHover(float pTimestep)
942 { 1010 {
943 Vector3 ret = Vector3.Zero;
944
945 // m_VhoverEfficiency: 0=bouncy, 1=totally damped 1011 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
946 // m_VhoverTimescale: time to achieve height 1012 // m_VhoverTimescale: time to achieve height
947 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 1013 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
@@ -974,23 +1040,42 @@ namespace OpenSim.Region.Physics.BulletSPlugin
974 Vector3 pos = VehiclePosition; 1040 Vector3 pos = VehiclePosition;
975 pos.Z = m_VhoverTargetHeight; 1041 pos.Z = m_VhoverTargetHeight;
976 VehiclePosition = pos; 1042 VehiclePosition = pos;
1043
1044 VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos);
977 } 1045 }
978 } 1046 }
979 else 1047 else
980 { 1048 {
981 // Error is positive if below the target and negative if above. 1049 // Error is positive if below the target and negative if above.
982 float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; 1050 Vector3 hpos = VehiclePosition;
1051 float verticalError = m_VhoverTargetHeight - hpos.Z;
1052 float verticalCorrection = verticalError / m_VhoverTimescale;
1053 verticalCorrection *= m_VhoverEfficiency;
1054
1055 hpos.Z += verticalCorrection;
1056 VehiclePosition = hpos;
1057
1058 // Since we are hovering, we need to do the opposite of falling -- get rid of world Z
1059 Vector3 vel = VehicleVelocity;
1060 vel.Z = 0f;
1061 VehicleVelocity = vel;
1062
1063 /*
983 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; 1064 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
1065 Vector3 verticalCorrection = new Vector3(0f, 0f, verticalCorrectionVelocity);
1066 verticalCorrection *= m_vehicleMass;
984 1067
985 // TODO: implement m_VhoverEfficiency correctly 1068 // TODO: implement m_VhoverEfficiency correctly
986 ret = new Vector3(0f, 0f, verticalCorrectionVelocity); 1069 VehicleAddForceImpulse(verticalCorrection);
1070 */
1071
1072 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}",
1073 Prim.LocalID, VehiclePosition, m_VhoverEfficiency,
1074 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1075 verticalError, verticalCorrection);
987 } 1076 }
988 1077
989 VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},ret={6}",
990 Prim.LocalID, VehiclePosition, m_VhoverEfficiency, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, ret);
991 } 1078 }
992
993 return ret;
994 } 1079 }
995 1080
996 public bool ComputeLinearBlockingEndPoint(float pTimestep) 1081 public bool ComputeLinearBlockingEndPoint(float pTimestep)
@@ -1045,30 +1130,67 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1045 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1130 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1046 // This is just using the ground and a general collision check. Should really be using 1131 // This is just using the ground and a general collision check. Should really be using
1047 // a downward raycast to find what is below. 1132 // a downward raycast to find what is below.
1048 public Vector3 ComputeLinearMotorUp(float pTimestep) 1133 public void ComputeLinearMotorUp(float pTimestep)
1049 { 1134 {
1050 Vector3 ret = Vector3.Zero; 1135 Vector3 ret = Vector3.Zero;
1051 float distanceAboveGround = 0f;
1052 1136
1053 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 1137 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
1054 { 1138 {
1139 // This code tries to decide if the object is not on the ground and then pushing down
1140 /*
1055 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1141 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1056 distanceAboveGround = VehiclePosition.Z - targetHeight; 1142 distanceAboveGround = VehiclePosition.Z - targetHeight;
1057 // Not colliding if the vehicle is off the ground 1143 // Not colliding if the vehicle is off the ground
1058 if (!Prim.IsColliding) 1144 if (!Prim.IsColliding)
1059 { 1145 {
1060 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1146 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1061 ret = new Vector3(0, 0, -distanceAboveGround); 1147 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
1062 } 1148 }
1063 // TODO: this calculation is wrong. From the description at 1149 // TODO: this calculation is wrong. From the description at
1064 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce 1150 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
1065 // has a decay factor. This says this force should 1151 // has a decay factor. This says this force should
1066 // be computed with a motor. 1152 // be computed with a motor.
1067 // TODO: add interaction with banking. 1153 // TODO: add interaction with banking.
1068 } 1154 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1069 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1070 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1155 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
1071 return ret; 1156 */
1157
1158 // Another approach is to measure if we're going up. If going up and not colliding,
1159 // the vehicle is in the air. Fix that by pushing down.
1160 if (!Prim.IsColliding && VehicleVelocity.Z > 0.1)
1161 {
1162 // Get rid of any of the velocity vector that is pushing us up.
1163 VehicleVelocity += new Vector3(0, 0, -VehicleVelocity.Z);
1164
1165 // If we're pointed up into the air, we should nose down
1166 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1167 // The rotation around the Y axis is pitch up or down
1168 if (pointingDirection.Y > 0.01f)
1169 {
1170 float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y);
1171 Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f);
1172 // Rotate into world coordinates and apply to vehicle
1173 angularCorrectionVector *= VehicleOrientation;
1174 VehicleAddAngularForce(angularCorrectionVector);
1175 VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}",
1176 Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector);
1177 }
1178 else
1179 {
1180 VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2}",
1181 Prim.LocalID, VehicleVelocity, pointingDirection);
1182 }
1183 }
1184 }
1185 }
1186
1187 private void ApplyGravity(float pTimeStep)
1188 {
1189 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1190 VehicleAddForce(appliedGravity);
1191
1192 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},appliedForce-{2}",
1193 Prim.LocalID, m_VehicleGravity, appliedGravity);
1072 } 1194 }
1073 1195
1074 // ======================================================================= 1196 // =======================================================================
@@ -1088,6 +1210,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1088 // for preventing ground vehicles with large linear deflection, like bumper cars, 1210 // for preventing ground vehicles with large linear deflection, like bumper cars,
1089 // from climbing their linear deflection into the sky. 1211 // from climbing their linear deflection into the sky.
1090 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1212 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1213 // TODO: This is here because this is where ODE put it but documentation says it
1214 // is a linear effect. Where should this check go?
1091 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1215 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1092 { 1216 {
1093 angularMotorContribution.X = 0f; 1217 angularMotorContribution.X = 0f;
@@ -1179,7 +1303,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1179 Vector3 ret = Vector3.Zero; 1303 Vector3 ret = Vector3.Zero;
1180 1304
1181 // If vertical attaction timescale is reasonable 1305 // If vertical attaction timescale is reasonable
1182 if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1306 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1183 { 1307 {
1184 // Take a vector pointing up and convert it from world to vehicle relative coords. 1308 // Take a vector pointing up and convert it from world to vehicle relative coords.
1185 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; 1309 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@@ -1230,7 +1354,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1230 // this creates an over-correction and then wabbling as the target is overshot. 1354 // this creates an over-correction and then wabbling as the target is overshot.
1231 // TODO: rethink how the different correction computations inter-relate. 1355 // TODO: rethink how the different correction computations inter-relate.
1232 1356
1233 if (m_angularDeflectionEfficiency != 0 && VehicleVelocity != Vector3.Zero) 1357 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1234 { 1358 {
1235 // The direction the vehicle is moving 1359 // The direction the vehicle is moving
1236 Vector3 movingDirection = VehicleVelocity; 1360 Vector3 movingDirection = VehicleVelocity;
@@ -1303,7 +1427,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1303 { 1427 {
1304 Vector3 ret = Vector3.Zero; 1428 Vector3 ret = Vector3.Zero;
1305 1429
1306 if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1430 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1307 { 1431 {
1308 // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. 1432 // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
1309 // As the vehicle rolls to the right or left, the Y value will increase from 1433 // As the vehicle rolls to the right or left, the Y value will increase from
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 756faed..cbd160f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -152,6 +152,7 @@ public abstract class BSLinkset
152 if (IsRoot(child)) 152 if (IsRoot(child))
153 { 153 {
154 // Cannot remove the root from a linkset. 154 // Cannot remove the root from a linkset.
155 child.PositionDisplacement = OMV.Vector3.Zero;
155 return this; 156 return this;
156 } 157 }
157 RemoveChildFromLinkset(child); 158 RemoveChildFromLinkset(child);
@@ -159,6 +160,7 @@ public abstract class BSLinkset
159 } 160 }
160 161
161 // The child is down to a linkset of just itself 162 // The child is down to a linkset of just itself
163 child.PositionDisplacement = OMV.Vector3.Zero;
162 return BSLinkset.Factory(PhysicsScene, child); 164 return BSLinkset.Factory(PhysicsScene, child);
163 } 165 }
164 166
@@ -310,7 +312,7 @@ public abstract class BSLinkset
310 312
311 foreach (BSPhysObject bp in m_children) 313 foreach (BSPhysObject bp in m_children)
312 { 314 {
313 com += bp.Position * bp.RawMass; 315 com += bp.Position;
314 } 316 }
315 com /= (m_children.Count + 1); 317 com /= (m_children.Count + 1);
316 } 318 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index bd03d31..2dc89b5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -40,23 +40,33 @@ namespace OpenSim.Region.Physics.BulletSPlugin
40// removed from the linkset. 40// removed from the linkset.
41sealed class BSLinksetCompoundInfo : BSLinksetInfo 41sealed class BSLinksetCompoundInfo : BSLinksetInfo
42{ 42{
43 public OMV.Vector3 OffsetPos; 43 public int Index;
44 public OMV.Vector3 OffsetFromRoot;
45 public OMV.Vector3 OffsetFromCenterOfMass;
44 public OMV.Quaternion OffsetRot; 46 public OMV.Quaternion OffsetRot;
45 public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r) 47 public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
46 { 48 {
47 OffsetPos = p; 49 Index = indx;
50 OffsetFromRoot = p;
51 OffsetFromCenterOfMass = p;
48 OffsetRot = r; 52 OffsetRot = r;
49 } 53 }
50 public override void Clear() 54 public override void Clear()
51 { 55 {
52 OffsetPos = OMV.Vector3.Zero; 56 Index = 0;
57 OffsetFromRoot = OMV.Vector3.Zero;
58 OffsetFromCenterOfMass = OMV.Vector3.Zero;
53 OffsetRot = OMV.Quaternion.Identity; 59 OffsetRot = OMV.Quaternion.Identity;
54 } 60 }
55 public override string ToString() 61 public override string ToString()
56 { 62 {
57 StringBuilder buff = new StringBuilder(); 63 StringBuilder buff = new StringBuilder();
58 buff.Append("<p="); 64 buff.Append("<i=");
59 buff.Append(OffsetPos.ToString()); 65 buff.Append(Index.ToString());
66 buff.Append(",p=");
67 buff.Append(OffsetFromRoot.ToString());
68 buff.Append(",m=");
69 buff.Append(OffsetFromCenterOfMass.ToString());
60 buff.Append(",r="); 70 buff.Append(",r=");
61 buff.Append(OffsetRot.ToString()); 71 buff.Append(OffsetRot.ToString());
62 buff.Append(">"); 72 buff.Append(">");
@@ -170,6 +180,8 @@ public sealed class BSLinksetCompound : BSLinkset
170 return ret; 180 return ret;
171 } 181 }
172 182
183 // 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
184 // Called at taint-time.
173 public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate) 185 public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
174 { 186 {
175 // The user moving a child around requires the rebuilding of the linkset compound shape 187 // The user moving a child around requires the rebuilding of the linkset compound shape
@@ -182,8 +194,12 @@ public sealed class BSLinksetCompound : BSLinkset
182 && !physicalUpdate 194 && !physicalUpdate
183 && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 195 && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
184 { 196 {
185 updated.LinksetInfo = null; 197 // TODO: replace this with are calculation of the child prim's orientation and pos.
186 ScheduleRebuild(updated); 198 // TODO: for the moment, don't rebuild the compound shape.
199 // This is often just the car turning its wheels. When we can just reorient the one
200 // member shape of the compound shape, the overhead of rebuilding won't be a problem.
201 // updated.LinksetInfo = null;
202 // ScheduleRebuild(updated);
187 } 203 }
188 } 204 }
189 205
@@ -230,7 +246,7 @@ public sealed class BSLinksetCompound : BSLinkset
230 if (inTaintTime) 246 if (inTaintTime)
231 { 247 {
232 OMV.Vector3 oldPos = child.RawPosition; 248 OMV.Vector3 oldPos = child.RawPosition;
233 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; 249 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
234 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; 250 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
235 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", 251 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
236 child.LocalID, oldPos, lci, child.RawPosition); 252 child.LocalID, oldPos, lci, child.RawPosition);
@@ -238,7 +254,7 @@ public sealed class BSLinksetCompound : BSLinkset
238 else 254 else
239 { 255 {
240 // TaintedObject is not used here so the raw position is set now and not at taint-time. 256 // TaintedObject is not used here so the raw position is set now and not at taint-time.
241 child.Position = LinksetRoot.RawPosition + lci.OffsetPos; 257 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
242 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; 258 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
243 } 259 }
244 } 260 }
@@ -306,6 +322,7 @@ public sealed class BSLinksetCompound : BSLinkset
306 // Constraint linksets are rebuilt every time. 322 // Constraint linksets are rebuilt every time.
307 // Note that this works for rebuilding just the root after a linkset is taken apart. 323 // Note that this works for rebuilding just the root after a linkset is taken apart.
308 // Called at taint time!! 324 // Called at taint time!!
325 private bool disableCOM = true; // disable until we get this debugged
309 private void RecomputeLinksetCompound() 326 private void RecomputeLinksetCompound()
310 { 327 {
311 try 328 try
@@ -316,10 +333,34 @@ public sealed class BSLinksetCompound : BSLinkset
316 // Cause the root shape to be rebuilt as a compound object with just the root in it 333 // Cause the root shape to be rebuilt as a compound object with just the root in it
317 LinksetRoot.ForceBodyShapeRebuild(true); 334 LinksetRoot.ForceBodyShapeRebuild(true);
318 335
336 // The center of mass for the linkset is the geometric center of the group.
337 // Compute a displacement for each component so it is relative to the center-of-mass.
338 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
339 OMV.Vector3 centerOfMass;
340 OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
341 if (disableCOM) // DEBUG DEBUG
342 { // DEBUG DEBUG
343 centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
344 LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
345 } // DEBUG DEBUG
346 else
347 {
348 centerOfMass = ComputeLinksetGeometricCenter();
349 centerDisplacement = centerOfMass - LinksetRoot.RawPosition;
350
351 // Since we're displacing the center of the shape, we need to move the body in the world
352 LinksetRoot.PositionDisplacement = centerDisplacement;
353
354 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
355 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
356 LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
357 }
358
319 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", 359 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
320 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); 360 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
321 361
322 // Add a shape for each of the other children in the linkset 362 // Add a shape for each of the other children in the linkset
363 int memberIndex = 1;
323 ForEachMember(delegate(BSPhysObject cPrim) 364 ForEachMember(delegate(BSPhysObject cPrim)
324 { 365 {
325 if (!IsRoot(cPrim)) 366 if (!IsRoot(cPrim))
@@ -331,19 +372,21 @@ public sealed class BSLinksetCompound : BSLinkset
331 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; 372 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
332 if (lci == null) 373 if (lci == null)
333 { 374 {
334 // Each child position and rotation is given relative to the root. 375 // Each child position and rotation is given relative to the center-of-mass.
335 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 376 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
336 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; 377 OMV.Vector3 displacementFromRoot = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
378 OMV.Vector3 displacementFromCOM = displacementFromRoot - centerDisplacement;
337 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; 379 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
338 380
339 // Save relative position for recomputing child's world position after moving linkset. 381 // Save relative position for recomputing child's world position after moving linkset.
340 lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); 382 lci = new BSLinksetCompoundInfo(memberIndex, displacementFromCOM, displacementRot);
383 lci.OffsetFromRoot = displacementFromRoot;
341 cPrim.LinksetInfo = lci; 384 cPrim.LinksetInfo = lci;
342 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); 385 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
343 } 386 }
344 387
345 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", 388 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
346 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); 389 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
347 390
348 if (cPrim.PhysShape.isNativeShape) 391 if (cPrim.PhysShape.isNativeShape)
349 { 392 {
@@ -359,7 +402,7 @@ public sealed class BSLinksetCompound : BSLinkset
359 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); 402 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
360 BulletShape newShape = cPrim.PhysShape; 403 BulletShape newShape = cPrim.PhysShape;
361 cPrim.PhysShape = saveShape; 404 cPrim.PhysShape = saveShape;
362 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot); 405 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
363 } 406 }
364 else 407 else
365 { 408 {
@@ -371,8 +414,10 @@ public sealed class BSLinksetCompound : BSLinkset
371 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", 414 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
372 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); 415 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
373 } 416 }
374 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); 417 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
375 } 418 }
419 lci.Index = memberIndex;
420 memberIndex++;
376 } 421 }
377 return false; // 'false' says to move onto the next child in the list 422 return false; // 'false' says to move onto the next child in the list
378 }); 423 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 23d573f..862dbf6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -80,6 +80,7 @@ public static class BSParam
80 public static float AvatarStepForceFactor { get; private set; } 80 public static float AvatarStepForceFactor { get; private set; }
81 81
82 public static float VehicleAngularDamping { get; private set; } 82 public static float VehicleAngularDamping { get; private set; }
83 public static float VehicleDebuggingEnabled { get; private set; }
83 84
84 public static float LinksetImplementation { get; private set; } 85 public static float LinksetImplementation { get; private set; }
85 public static float LinkConstraintUseFrameOffset { get; private set; } 86 public static float LinkConstraintUseFrameOffset { get; private set; }
@@ -317,13 +318,13 @@ public static class BSParam
317 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); }, 318 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); },
318 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), 319 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
319 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 320 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
320 0f, // set to zero to disable 321 0.3f, // set to zero to disable
321 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); }, 322 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
322 (s) => { return CcdMotionThreshold; }, 323 (s) => { return CcdMotionThreshold; },
323 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); }, 324 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); },
324 (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ), 325 (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ),
325 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 326 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
326 0f, 327 0.2f,
327 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); }, 328 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
328 (s) => { return CcdSweptSphereRadius; }, 329 (s) => { return CcdSweptSphereRadius; },
329 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); }, 330 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); },
@@ -427,6 +428,11 @@ public static class BSParam
427 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); }, 428 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
428 (s) => { return VehicleAngularDamping; }, 429 (s) => { return VehicleAngularDamping; },
429 (s,p,l,v) => { VehicleAngularDamping = v; } ), 430 (s,p,l,v) => { VehicleAngularDamping = v; } ),
431 new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
432 ConfigurationParameters.numericFalse,
433 (s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
434 (s) => { return VehicleDebuggingEnabled; },
435 (s,p,l,v) => { VehicleDebuggingEnabled = v; } ),
430 436
431 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 437 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
432 0f, 438 0f,
@@ -459,7 +465,7 @@ public static class BSParam
459 (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; }, 465 (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; },
460 (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), 466 (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
461 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", 467 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
462 ConfigurationParameters.numericFalse, 468 ConfigurationParameters.numericTrue,
463 (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, 469 (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
464 (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; }, 470 (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; },
465 (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), 471 (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e8575f6..821f470 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -73,6 +73,8 @@ public abstract class BSPhysObject : PhysicsActor
73 73
74 // A linkset of just me 74 // A linkset of just me
75 Linkset = BSLinkset.Factory(PhysicsScene, this); 75 Linkset = BSLinkset.Factory(PhysicsScene, this);
76 PositionDisplacement = OMV.Vector3.Zero;
77
76 LastAssetBuildFailed = false; 78 LastAssetBuildFailed = false;
77 79
78 // Default material type 80 // Default material type
@@ -135,6 +137,7 @@ public abstract class BSPhysObject : PhysicsActor
135 public virtual OMV.Vector3 Scale { get; set; } 137 public virtual OMV.Vector3 Scale { get; set; }
136 public abstract bool IsSolid { get; } 138 public abstract bool IsSolid { get; }
137 public abstract bool IsStatic { get; } 139 public abstract bool IsStatic { get; }
140 public abstract bool IsSelected { get; }
138 141
139 // Materialness 142 // Materialness
140 public MaterialAttributes.Material Material { get; private set; } 143 public MaterialAttributes.Material Material { get; private set; }
@@ -156,6 +159,14 @@ public abstract class BSPhysObject : PhysicsActor
156 public abstract OMV.Vector3 RawPosition { get; set; } 159 public abstract OMV.Vector3 RawPosition { get; set; }
157 public abstract OMV.Vector3 ForcePosition { get; set; } 160 public abstract OMV.Vector3 ForcePosition { get; set; }
158 161
162 // Position is what the simulator thinks the positions of the prim is.
163 // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
164 // sometimes it is necessary to displace the position the physics engine thinks
165 // the position is. PositionDisplacement must be added and removed from the
166 // position as the simulator position is stored and fetched from the physics
167 // engine.
168 public virtual OMV.Vector3 PositionDisplacement { get; set; }
169
159 public abstract OMV.Quaternion RawOrientation { get; set; } 170 public abstract OMV.Quaternion RawOrientation { get; set; }
160 public abstract OMV.Quaternion ForceOrientation { get; set; } 171 public abstract OMV.Quaternion ForceOrientation { get; set; }
161 172
@@ -371,10 +382,13 @@ public abstract class BSPhysObject : PhysicsActor
371 { 382 {
372 string identifier = op + "-" + id.ToString(); 383 string identifier = op + "-" + id.ToString();
373 384
374 // Clean out any existing action 385 lock (RegisteredActions)
375 UnRegisterPreStepAction(op, id); 386 {
387 // Clean out any existing action
388 UnRegisterPreStepAction(op, id);
376 389
377 RegisteredActions[identifier] = actn; 390 RegisteredActions[identifier] = actn;
391 }
378 PhysicsScene.BeforeStep += actn; 392 PhysicsScene.BeforeStep += actn;
379 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); 393 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
380 } 394 }
@@ -384,22 +398,28 @@ public abstract class BSPhysObject : PhysicsActor
384 { 398 {
385 string identifier = op + "-" + id.ToString(); 399 string identifier = op + "-" + id.ToString();
386 bool removed = false; 400 bool removed = false;
387 if (RegisteredActions.ContainsKey(identifier)) 401 lock (RegisteredActions)
388 { 402 {
389 PhysicsScene.BeforeStep -= RegisteredActions[identifier]; 403 if (RegisteredActions.ContainsKey(identifier))
390 RegisteredActions.Remove(identifier); 404 {
391 removed = true; 405 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
406 RegisteredActions.Remove(identifier);
407 removed = true;
408 }
392 } 409 }
393 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed); 410 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
394 } 411 }
395 412
396 protected void UnRegisterAllPreStepActions() 413 protected void UnRegisterAllPreStepActions()
397 { 414 {
398 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions) 415 lock (RegisteredActions)
399 { 416 {
400 PhysicsScene.BeforeStep -= kvp.Value; 417 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
418 {
419 PhysicsScene.BeforeStep -= kvp.Value;
420 }
421 RegisteredActions.Clear();
401 } 422 }
402 RegisteredActions.Clear();
403 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID); 423 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
404 } 424 }
405 425
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 65be52a..9442854 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -59,7 +59,7 @@ public class BSPlugin : IPhysicsPlugin
59 { 59 {
60 if (_mScene == null) 60 if (_mScene == null)
61 { 61 {
62 _mScene = new BSScene(sceneIdentifier); 62 _mScene = new BSScene(GetName(), sceneIdentifier);
63 } 63 }
64 return (_mScene); 64 return (_mScene);
65 } 65 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 8fd054f..79fe632 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -50,7 +50,10 @@ public sealed class BSPrim : BSPhysObject
50 private bool _grabbed; 50 private bool _grabbed;
51 private bool _isSelected; 51 private bool _isSelected;
52 private bool _isVolumeDetect; 52 private bool _isVolumeDetect;
53
54 // _position is what the simulator thinks the positions of the prim is.
53 private OMV.Vector3 _position; 55 private OMV.Vector3 _position;
56
54 private float _mass; // the mass of this object 57 private float _mass; // the mass of this object
55 private float _density; 58 private float _density;
56 private OMV.Vector3 _force; 59 private OMV.Vector3 _force;
@@ -204,6 +207,10 @@ public sealed class BSPrim : BSPhysObject
204 } 207 }
205 } 208 }
206 } 209 }
210 public override bool IsSelected
211 {
212 get { return _isSelected; }
213 }
207 public override void CrossingFailure() { return; } 214 public override void CrossingFailure() { return; }
208 215
209 // link me to the specified parent 216 // link me to the specified parent
@@ -290,7 +297,7 @@ public sealed class BSPrim : BSPhysObject
290 */ 297 */
291 298
292 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 299 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
293 // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody); 300 // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody) - PositionDisplacement;
294 return _position; 301 return _position;
295 } 302 }
296 set { 303 set {
@@ -316,18 +323,37 @@ public sealed class BSPrim : BSPhysObject
316 } 323 }
317 public override OMV.Vector3 ForcePosition { 324 public override OMV.Vector3 ForcePosition {
318 get { 325 get {
319 _position = PhysicsScene.PE.GetPosition(PhysBody); 326 _position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
320 return _position; 327 return _position;
321 } 328 }
322 set { 329 set {
323 _position = value; 330 _position = value;
324 if (PhysBody.HasPhysicalBody) 331 if (PhysBody.HasPhysicalBody)
325 { 332 {
326 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 333 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
327 ActivateIfPhysical(false); 334 ActivateIfPhysical(false);
328 } 335 }
329 } 336 }
330 } 337 }
338 // Override to have position displacement immediately update the physical position.
339 // A feeble attempt to keep the sim and physical positions in sync
340 // Must be called at taint time.
341 public override OMV.Vector3 PositionDisplacement
342 {
343 get
344 {
345 return base.PositionDisplacement;
346 }
347 set
348 {
349 base.PositionDisplacement = value;
350 PhysicsScene.TaintedObject(PhysicsScene.InTaintTime, "BSPrim.setPosition", delegate()
351 {
352 if (PhysBody.HasPhysicalBody)
353 PhysicsScene.PE.SetTranslation(PhysBody, _position + base.PositionDisplacement, _orientation);
354 });
355 }
356 }
331 357
332 // Check that the current position is sane and, if not, modify the position to make it so. 358 // Check that the current position is sane and, if not, modify the position to make it so.
333 // Check for being below terrain and being out of bounds. 359 // Check for being below terrain and being out of bounds.
@@ -336,7 +362,7 @@ public sealed class BSPrim : BSPhysObject
336 { 362 {
337 bool ret = false; 363 bool ret = false;
338 364
339 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position)) 365 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
340 { 366 {
341 // The physical object is out of the known/simulated area. 367 // The physical object is out of the known/simulated area.
342 // Upper levels of code will handle the transition to other areas so, for 368 // Upper levels of code will handle the transition to other areas so, for
@@ -350,8 +376,11 @@ public sealed class BSPrim : BSPhysObject
350 { 376 {
351 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 377 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
352 float targetHeight = terrainHeight + (Size.Z / 2f); 378 float targetHeight = terrainHeight + (Size.Z / 2f);
353 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. 379 // If the object is below ground it just has to be moved up because pushing will
354 upForce.Z = (terrainHeight - RawPosition.Z) * 1f; 380 // not get it through the terrain
381 _position.Z = targetHeight;
382 if (inTaintTime)
383 ForcePosition = _position;
355 ret = true; 384 ret = true;
356 } 385 }
357 386
@@ -363,20 +392,15 @@ public sealed class BSPrim : BSPhysObject
363 { 392 {
364 // Upforce proportional to the distance away from the water. Correct the error in 1 sec. 393 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
365 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 394 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
395
396 // Apply upforce and overcome gravity.
397 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
398 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
399 AddForce(correctionForce, false, inTaintTime);
366 ret = true; 400 ret = true;
367 } 401 }
368 } 402 }
369 403
370 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
371 // TODO: This should be intergrated with a geneal physics action mechanism.
372 // TODO: This should be moderated with PID'ness.
373 if (ret)
374 {
375 // Apply upforce and overcome gravity.
376 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
377 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
378 AddForce(correctionForce, false, inTaintTime);
379 }
380 return ret; 404 return ret;
381 } 405 }
382 406
@@ -410,7 +434,7 @@ public sealed class BSPrim : BSPhysObject
410 } 434 }
411 else 435 else
412 { 436 {
413 OMV.Vector3 grav = ComputeGravity(); 437 OMV.Vector3 grav = ComputeGravity(Buoyancy);
414 438
415 if (inWorld) 439 if (inWorld)
416 { 440 {
@@ -445,12 +469,12 @@ public sealed class BSPrim : BSPhysObject
445 } 469 }
446 470
447 // Return what gravity should be set to this very moment 471 // Return what gravity should be set to this very moment
448 private OMV.Vector3 ComputeGravity() 472 public OMV.Vector3 ComputeGravity(float buoyancy)
449 { 473 {
450 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 474 OMV.Vector3 ret = PhysicsScene.DefaultGravity;
451 475
452 if (!IsStatic) 476 if (!IsStatic)
453 ret *= (1f - Buoyancy); 477 ret *= (1f - buoyancy);
454 478
455 return ret; 479 return ret;
456 } 480 }
@@ -586,6 +610,7 @@ public sealed class BSPrim : BSPhysObject
586 _velocity = value; 610 _velocity = value;
587 if (PhysBody.HasPhysicalBody) 611 if (PhysBody.HasPhysicalBody)
588 { 612 {
613 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity);
589 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 614 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
590 ActivateIfPhysical(false); 615 ActivateIfPhysical(false);
591 } 616 }
@@ -650,12 +675,7 @@ public sealed class BSPrim : BSPhysObject
650 675
651 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 676 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
652 { 677 {
653 if (PhysBody.HasPhysicalBody) 678 ForceOrientation = _orientation;
654 {
655 // _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody);
656 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
657 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
658 }
659 }); 679 });
660 } 680 }
661 } 681 }
@@ -670,7 +690,8 @@ public sealed class BSPrim : BSPhysObject
670 set 690 set
671 { 691 {
672 _orientation = value; 692 _orientation = value;
673 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 693 if (PhysBody.HasPhysicalBody)
694 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
674 } 695 }
675 } 696 }
676 public override int PhysicsActorType { 697 public override int PhysicsActorType {
@@ -809,7 +830,7 @@ public sealed class BSPrim : BSPhysObject
809 // PhysicsScene.PE.ClearAllForces(BSBody); 830 // PhysicsScene.PE.ClearAllForces(BSBody);
810 831
811 // For good measure, make sure the transform is set through to the motion state 832 // For good measure, make sure the transform is set through to the motion state
812 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 833 PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
813 834
814 // Center of mass is at the center of the object 835 // Center of mass is at the center of the object
815 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation); 836 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
@@ -1153,33 +1174,70 @@ public sealed class BSPrim : BSPhysObject
1153 // This added force will only last the next simulation tick. 1174 // This added force will only last the next simulation tick.
1154 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1175 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1155 // for an object, doesn't matter if force is a pushforce or not 1176 // for an object, doesn't matter if force is a pushforce or not
1156 if (!IsStatic && force.IsFinite()) 1177 if (!IsStatic)
1157 { 1178 {
1158 float magnitude = force.Length(); 1179 if (force.IsFinite())
1159 if (magnitude > BSParam.MaxAddForceMagnitude)
1160 { 1180 {
1161 // Force has a limit 1181 float magnitude = force.Length();
1162 force = force / magnitude * BSParam.MaxAddForceMagnitude; 1182 if (magnitude > BSParam.MaxAddForceMagnitude)
1163 } 1183 {
1184 // Force has a limit
1185 force = force / magnitude * BSParam.MaxAddForceMagnitude;
1186 }
1164 1187
1165 OMV.Vector3 addForce = force; 1188 OMV.Vector3 addForce = force;
1166 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1189 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1167 1190
1168 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1191 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1169 {
1170 // Bullet adds this central force to the total force for this tick
1171 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1172 if (PhysBody.HasPhysicalBody)
1173 { 1192 {
1174 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1193 // Bullet adds this central force to the total force for this tick
1175 ActivateIfPhysical(false); 1194 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1176 } 1195 if (PhysBody.HasPhysicalBody)
1177 }); 1196 {
1197 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
1198 ActivateIfPhysical(false);
1199 }
1200 });
1201 }
1202 else
1203 {
1204 m_log.WarnFormat("{0}: AddForce: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
1205 return;
1206 }
1178 } 1207 }
1179 else 1208 }
1209
1210 public void AddForceImpulse(OMV.Vector3 impulse, bool pushforce, bool inTaintTime) {
1211 // for an object, doesn't matter if force is a pushforce or not
1212 if (!IsStatic)
1180 { 1213 {
1181 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 1214 if (impulse.IsFinite())
1182 return; 1215 {
1216 float magnitude = impulse.Length();
1217 if (magnitude > BSParam.MaxAddForceMagnitude)
1218 {
1219 // Force has a limit
1220 impulse = impulse / magnitude * BSParam.MaxAddForceMagnitude;
1221 }
1222
1223 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1224 OMV.Vector3 addImpulse = impulse;
1225 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
1226 {
1227 // Bullet adds this impulse immediately to the velocity
1228 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1229 if (PhysBody.HasPhysicalBody)
1230 {
1231 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1232 ActivateIfPhysical(false);
1233 }
1234 });
1235 }
1236 else
1237 {
1238 m_log.WarnFormat("{0}: AddForceImpulse: Got a NaN impulse applied to a prim. LocalID={1}", LogHeader, LocalID);
1239 return;
1240 }
1183 } 1241 }
1184 } 1242 }
1185 1243
@@ -1561,21 +1619,6 @@ public sealed class BSPrim : BSPhysObject
1561 1619
1562 // The physics engine says that properties have updated. Update same and inform 1620 // The physics engine says that properties have updated. Update same and inform
1563 // the world that things have changed. 1621 // the world that things have changed.
1564 // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
1565 enum UpdatedProperties {
1566 Position = 1 << 0,
1567 Rotation = 1 << 1,
1568 Velocity = 1 << 2,
1569 Acceleration = 1 << 3,
1570 RotationalVel = 1 << 4
1571 }
1572
1573 const float ROTATION_TOLERANCE = 0.01f;
1574 const float VELOCITY_TOLERANCE = 0.001f;
1575 const float POSITION_TOLERANCE = 0.05f;
1576 const float ACCELERATION_TOLERANCE = 0.01f;
1577 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1578
1579 public override void UpdateProperties(EntityProperties entprop) 1622 public override void UpdateProperties(EntityProperties entprop)
1580 { 1623 {
1581 // Updates only for individual prims and for the root object of a linkset. 1624 // Updates only for individual prims and for the root object of a linkset.
@@ -1588,7 +1631,8 @@ public sealed class BSPrim : BSPhysObject
1588 entprop.RotationalVelocity = OMV.Vector3.Zero; 1631 entprop.RotationalVelocity = OMV.Vector3.Zero;
1589 } 1632 }
1590 1633
1591 // Assign directly to the local variables so the normal set action does not happen 1634 // Assign directly to the local variables so the normal set actions do not happen
1635 entprop.Position -= PositionDisplacement;
1592 _position = entprop.Position; 1636 _position = entprop.Position;
1593 _orientation = entprop.Rotation; 1637 _orientation = entprop.Rotation;
1594 _velocity = entprop.Velocity; 1638 _velocity = entprop.Velocity;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 7017194..e0b4992 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -167,11 +167,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
167 public bool VehiclePhysicalLoggingEnabled { get; private set; } 167 public bool VehiclePhysicalLoggingEnabled { get; private set; }
168 168
169 #region Construction and Initialization 169 #region Construction and Initialization
170 public BSScene(string identifier) 170 public BSScene(string engineType, string identifier)
171 { 171 {
172 m_initialized = false; 172 m_initialized = false;
173 // we are passed the name of the region we're working for. 173
174 // The name of the region we're working for is passed to us. Keep for identification.
174 RegionName = identifier; 175 RegionName = identifier;
176
177 // Set identifying variables in the PhysicsScene interface.
178 EngineType = engineType;
179 Name = EngineType + "/" + RegionName;
175 } 180 }
176 181
177 public override void Initialise(IMesher meshmerizer, IConfigSource config) 182 public override void Initialise(IMesher meshmerizer, IConfigSource config)
@@ -382,12 +387,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
382 if (!m_initialized) return null; 387 if (!m_initialized) return null;
383 388
384 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 389 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
385 lock (PhysObjects) PhysObjects.Add(localID, actor); 390 lock (PhysObjects)
391 PhysObjects.Add(localID, actor);
386 392
387 // TODO: Remove kludge someday. 393 // TODO: Remove kludge someday.
388 // We must generate a collision for avatars whether they collide or not. 394 // We must generate a collision for avatars whether they collide or not.
389 // This is required by OpenSim to update avatar animations, etc. 395 // This is required by OpenSim to update avatar animations, etc.
390 lock (m_avatars) m_avatars.Add(actor); 396 lock (m_avatars)
397 m_avatars.Add(actor);
391 398
392 return actor; 399 return actor;
393 } 400 }
@@ -403,9 +410,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
403 { 410 {
404 try 411 try
405 { 412 {
406 lock (PhysObjects) PhysObjects.Remove(actor.LocalID); 413 lock (PhysObjects)
414 PhysObjects.Remove(bsactor.LocalID);
407 // Remove kludge someday 415 // Remove kludge someday
408 lock (m_avatars) m_avatars.Remove(bsactor); 416 lock (m_avatars)
417 m_avatars.Remove(bsactor);
409 } 418 }
410 catch (Exception e) 419 catch (Exception e)
411 { 420 {
@@ -414,6 +423,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
414 bsactor.Destroy(); 423 bsactor.Destroy();
415 // bsactor.dispose(); 424 // bsactor.dispose();
416 } 425 }
426 else
427 {
428 m_log.ErrorFormat("{0}: Requested to remove avatar that is not a BSCharacter. ID={1}, type={2}",
429 LogHeader, actor.LocalID, actor.GetType().Name);
430 }
417 } 431 }
418 432
419 public override void RemovePrim(PhysicsActor prim) 433 public override void RemovePrim(PhysicsActor prim)
@@ -486,6 +500,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
486 ProcessTaints(); 500 ProcessTaints();
487 501
488 // Some of the physical objects requre individual, pre-step calls 502 // Some of the physical objects requre individual, pre-step calls
503 // (vehicles and avatar movement, in particular)
489 TriggerPreStepEvent(timeStep); 504 TriggerPreStepEvent(timeStep);
490 505
491 // the prestep actions might have added taints 506 // the prestep actions might have added taints
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index f0c6b99..addab29 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -906,7 +906,7 @@ public sealed class BSShapeCollection : IDisposable
906 } 906 }
907 } 907 }
908 908
909 // While we figure out the real problem, stick a simple native shape on the object. 909 // While we figure out the real problem, stick in a simple box for the object.
910 BulletShape fillinShape = 910 BulletShape fillinShape =
911 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 911 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
912 912
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 29bd4e4..59cbab9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,12 +1,17 @@
1CURRENT PRIORITIES 1CURRENT PRIORITIES
2================================================= 2=================================================
3Nebadon vehicles turning funny in arena
4limitMotorUp calibration (more down?)
5Vehicle angular vertical attraction
6Vehicle angular deflection
7 Preferred orientation angular correction fix
8vehicle angular banking
3Avatars walking up stairs (HALF DONE) 9Avatars walking up stairs (HALF DONE)
10 Radius of the capsule affects ability to climb edges.
4Vehicle movement on terrain smoothness 11Vehicle movement on terrain smoothness
5limitMotorUp calibration (more down?)
6Preferred orientation angular correction fix
7Surfboard go wonky when turning 12Surfboard go wonky when turning
8 Angular motor direction is global coordinates rather than local coordinates? 13 Angular motor direction is global coordinates rather than local coordinates?
9Boats float low in the water 14Boats float low in the water (DONE)
10Avatar movement 15Avatar movement
11 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) 16 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
12 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) 17 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
@@ -33,19 +38,15 @@ CRASHES
33 38
34VEHICLES TODO LIST: 39VEHICLES TODO LIST:
35================================================= 40=================================================
36Angular motor direction is global coordinates rather than local coordinates
37Border crossing with linked vehicle causes crash 41Border crossing with linked vehicle causes crash
38Vehicles (Move smoothly) 42Vehicles (Move smoothly)
39Add vehicle collisions so IsColliding is properly reported.
40 Needed for banking, limitMotorUp, movementLimiting, ...
41VehicleAddForce is not scaled by the simulation step but it is only
42 applied for one step. Should it be scaled?
43Some vehicles should not be able to turn if no speed or off ground. 43Some vehicles should not be able to turn if no speed or off ground.
44Cannot edit/move a vehicle being ridden: it jumps back to the origional position. 44Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
45Neb car jiggling left and right 45Neb car jiggling left and right
46 Happens on terrain and any other mesh object. Flat cubes are much smoother. 46 Happens on terrain and any other mesh object. Flat cubes are much smoother.
47 This has been reduced but not eliminated. 47 This has been reduced but not eliminated.
48Implement referenceFrame for all the motion routines. 48Implement referenceFrame for all the motion routines.
49For limitMotorUp, use raycast down to find if vehicle is in the air.
49Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. 50Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
50 Verify that angular motion specified around Z moves in the vehicle coordinates. 51 Verify that angular motion specified around Z moves in the vehicle coordinates.
51Verify llGetVel() is returning a smooth and good value for vehicle movement. 52Verify llGetVel() is returning a smooth and good value for vehicle movement.
@@ -54,14 +55,13 @@ Implement function efficiency for lineaar and angular motion.
54After getting off a vehicle, the root prim is phantom (can be walked through) 55After getting off a vehicle, the root prim is phantom (can be walked through)
55 Need to force a position update for the root prim after compound shape destruction 56 Need to force a position update for the root prim after compound shape destruction
56Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) 57Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
57For limitMotorUp, use raycast down to find if vehicle is in the air.
58Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). 58Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
59 A kludge that isn't fixing the real problem of Bullet adding extra motion. 59 A kludge that isn't fixing the real problem of Bullet adding extra motion.
60Incorporate inter-relationship of angular corrections. For instance, angularDeflection 60Incorporate inter-relationship of angular corrections. For instance, angularDeflection
61 and angularMotorUp will compute same X or Y correction. When added together 61 and angularMotorUp will compute same X or Y correction. When added together
62 creates over-correction and over-shoot and wabbling. 62 creates over-correction and over-shoot and wabbling.
63 63
64BULLETSIM TODO LIST: 64GENERAL TODO LIST:
65================================================= 65=================================================
66Implement an avatar mesh shape. The Bullet capsule is way too limited. 66Implement an avatar mesh shape. The Bullet capsule is way too limited.
67 Consider just hand creating a vertex/index array in a new BSShapeAvatar. 67 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
121Verify/think through scripts in children of linksets. What do they reference 121Verify/think through scripts in children of linksets. What do they reference
122 and return when getting position, velocity, ... 122 and return when getting position, velocity, ...
123Confirm constraint linksets still work after making all the changes for compound linksets. 123Confirm constraint linksets still work after making all the changes for compound linksets.
124Use PostTaint callback to do rebuilds for constraint linksets to reduce rebuilding
124Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt. 125Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
125 For compound linksets, add ability to remove or reposition individual child shapes. 126 For compound linksets, add ability to remove or reposition individual child shapes.
126Disable activity of passive linkset children.
127 Since the linkset is a compound object, the old prims are left lying
128 around and need to be phantomized so they don't collide, ...
129Speed up creation of large physical linksets 127Speed up creation of large physical linksets
130 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical. 128 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
131 REALLY bad for very large physical linksets (freezes the sim for many seconds). 129 REALLY bad for very large physical linksets (freezes the sim for many seconds).
@@ -138,25 +136,21 @@ MORE
138Use the HACD convex hull routine in Bullet rather than the C# version. 136Use the HACD convex hull routine in Bullet rather than the C# version.
139Do we need to do convex hulls all the time? Can complex meshes be left meshes? 137Do we need to do convex hulls all the time? Can complex meshes be left meshes?
140 There is some problem with meshes and collisions 138 There is some problem with meshes and collisions
141Test avatar walking up stairs. How does compare with SL. 139 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
142 Radius of the capsule affects ability to climb edges.
143Debounce avatar contact so legs don't keep folding up when standing. 140Debounce avatar contact so legs don't keep folding up when standing.
144Implement LSL physics controls. Like STATUS_ROTATE_X. 141Implement LSL physics controls. Like STATUS_ROTATE_X.
145Add border extensions to terrain to help region crossings and objects leaving region. 142Add border extensions to terrain to help region crossings and objects leaving region.
146Use a different capsule shape for avatar when sitting 143Use a different capsule shape for avatar when sitting
147 LL uses a pyrimidal shape scaled by the avatar's bounding box 144 LL uses a pyrimidal shape scaled by the avatar's bounding box
148 http://wiki.secondlife.com/wiki/File:Avmeshforms.png 145 http://wiki.secondlife.com/wiki/File:Avmeshforms.png
149
150Performance test with lots of avatars. Can BulletSim support a thousand? 146Performance test with lots of avatars. Can BulletSim support a thousand?
151Optimize collisions in C++: only send up to the object subscribed to collisions. 147Optimize collisions in C++: only send up to the object subscribed to collisions.
152 Use collision subscription and remove the collsion(A,B) and collision(B,A) 148 Use collision subscription and remove the collsion(A,B) and collision(B,A)
153Check whether SimMotionState needs large if statement (see TODO). 149Check whether SimMotionState needs large if statement (see TODO).
154
155Implement 'top colliders' info. 150Implement 'top colliders' info.
156Avatar jump 151Avatar jump
157Performance measurement and changes to make quicker. 152Performance measurement and changes to make quicker.
158Implement detailed physics stats (GetStats()). 153Implement detailed physics stats (GetStats()).
159
160Measure performance improvement from hulls 154Measure performance improvement from hulls
161Test not using ghost objects for volume detect implementation. 155Test not using ghost objects for volume detect implementation.
162Performance of closures and delegates for taint processing 156Performance of closures and delegates for taint processing
@@ -164,9 +158,7 @@ Performance of closures and delegates for taint processing
164 Is any slowdown introduced by the existing implementation significant? 158 Is any slowdown introduced by the existing implementation significant?
165Is there are more efficient method of implementing pre and post step actions? 159Is there are more efficient method of implementing pre and post step actions?
166 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C 160 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
167
168Physics Arena central pyramid: why is one side permiable? 161Physics Arena central pyramid: why is one side permiable?
169
170In SL, perfect spheres don't seem to have rolling friction. Add special case. 162In SL, perfect spheres don't seem to have rolling friction. Add special case.
171Enforce physical parameter min/max: 163Enforce physical parameter min/max:
172 Gravity: [-1, 28] 164 Gravity: [-1, 28]
@@ -178,6 +170,8 @@ Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/3179
178 170
179INTERNAL IMPROVEMENT/CLEANUP 171INTERNAL IMPROVEMENT/CLEANUP
180================================================= 172=================================================
173Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
174 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
181Create the physical wrapper classes (BulletBody, BulletShape) by methods on 175Create the physical wrapper classes (BulletBody, BulletShape) by methods on
182 BSAPITemplate and make their actual implementation Bullet engine specific. 176 BSAPITemplate and make their actual implementation Bullet engine specific.
183 For the short term, just call the existing functions in ShapeCollection. 177 For the short term, just call the existing functions in ShapeCollection.
@@ -197,22 +191,19 @@ Generalize Dynamics and PID with standardized motors.
197Generalize Linkset and vehicles into PropertyManagers 191Generalize Linkset and vehicles into PropertyManagers
198 Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies 192 Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
199 Potentially add events for shape destruction, etc. 193 Potentially add events for shape destruction, etc.
200Complete implemention of preStepActions 194Better mechanism for resetting linkset set and vehicle parameters when body rebuilt.
201 Replace vehicle step call with prestep event. 195 BSPrim.CreateGeomAndObject is kludgy with the callbacks, etc.
202 Is there a need for postStepActions? postStepTaints?
203Implement linkset by setting position of children when root updated. (LinksetManual) 196Implement linkset by setting position of children when root updated. (LinksetManual)
204 Linkset implementation using manual prim movement. 197 Linkset implementation using manual prim movement.
205LinkablePrim class? Would that simplify/centralize the linkset logic? 198LinkablePrim class? Would that simplify/centralize the linkset logic?
206BSScene.UpdateParameterSet() is broken. How to set params on objects? 199BSScene.UpdateParameterSet() is broken. How to set params on objects?
207Remove HeightmapInfo from terrain specification
208 Since C++ code does not need terrain height, this structure et al are not needed.
209Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will 200Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
210 bob at the water level. BSPrim.PositionSanityCheck(). 201 bob at the water level. BSPrim.PositionSanityCheck()
211Should taints check for existance or activeness of target? 202Should taints check for existance or activeness of target?
212 When destroying linksets/etc, taints can be generated for objects that are 203 When destroying linksets/etc, taints can be generated for objects that are
213 actually gone when the taint happens. Crashes don't happen because the taint closure 204 actually gone when the taint happens. Crashes don't happen because the taint closure
214 keeps the object from being freed, but that is just an accident. 205 keeps the object from being freed, but that is just an accident.
215 Possibly have and 'active' flag that is checked by the taint processor? 206 Possibly have an 'active' flag that is checked by the taint processor?
216Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones) 207Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
217Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'? 208Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
218There are TOO MANY interfaces from BulletSim core to Bullet itself 209There 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)
282Meshes rendering as bounding boxes (DONE) 273Meshes rendering as bounding boxes (DONE)
283 (Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box) 274 (Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
284llMoveToTarget (Resolution: added simple motor to update the position.) 275llMoveToTarget (Resolution: added simple motor to update the position.)
276Angular motor direction is global coordinates rather than local coordinates (DONE)
277Add vehicle collisions so IsColliding is properly reported. (DONE)
278 Needed for banking, limitMotorUp, movementLimiting, ...
279 (Resolution: added CollisionFlags.BS_VEHICLE_COLLISION and code to use it)
280VehicleAddForce is not scaled by the simulation step but it is only
281 applied for one step. Should it be scaled? (DONE)
282 (Resolution: use force for timed things, Impulse for immediate, non-timed things)
283Complete implemention of preStepActions (DONE)
284 Replace vehicle step call with prestep event.
285 Is there a need for postStepActions? postStepTaints?
286Disable activity of passive linkset children. (DONE)
287 Since the linkset is a compound object, the old prims are left lying
288 around and need to be phantomized so they don't collide, ...
289Remove HeightmapInfo from terrain specification (DONE)
290 Since C++ code does not need terrain height, this structure et al are not needed. \ No newline at end of file
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 488900e..201007b 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -62,13 +62,20 @@ namespace OpenSim.Region.Physics.Manager
62// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63 63
64 /// <summary> 64 /// <summary>
65 /// Name of this scene. Useful in debug messages to distinguish one OdeScene instance from another. 65 /// A unique identifying string for this instance of the physics engine.
66 /// Useful in debug messages to distinguish one OdeScene instance from another.
67 /// Usually set to include the region name that the physics engine is acting for.
66 /// </summary> 68 /// </summary>
67 public string Name { get; protected set; } 69 public string Name { get; protected set; }
68 70
71 /// <summary>
72 /// A string identifying the family of this physics engine. Most common values returned
73 /// are "OpenDynamicsEngine" and "BulletSim" but others are possible.
74 /// </summary>
75 public string EngineType { get; protected set; }
76
69 // The only thing that should register for this event is the SceneGraph 77 // The only thing that should register for this event is the SceneGraph
70 // Anything else could cause problems. 78 // Anything else could cause problems.
71
72 public event physicsCrash OnPhysicsCrash; 79 public event physicsCrash OnPhysicsCrash;
73 80
74 public static PhysicsScene Null 81 public static PhysicsScene Null
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 478dd95..07663b3 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.Physics.OdePlugin
72 // http://opensimulator.org/mantis/view.php?id=2750). 72 // http://opensimulator.org/mantis/view.php?id=2750).
73 d.InitODE(); 73 d.InitODE();
74 74
75 m_scene = new OdeScene(sceneIdentifier); 75 m_scene = new OdeScene(GetName(), sceneIdentifier);
76 } 76 }
77 77
78 return m_scene; 78 return m_scene;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index d53bd90..02a0b15 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -526,11 +526,12 @@ namespace OpenSim.Region.Physics.OdePlugin
526 /// These settings need to be tweaked 'exactly' right or weird stuff happens. 526 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
527 /// </summary> 527 /// </summary>
528 /// <param value="name">Name of the scene. Useful in debug messages.</param> 528 /// <param value="name">Name of the scene. Useful in debug messages.</param>
529 public OdeScene(string name) 529 public OdeScene(string engineType, string name)
530 { 530 {
531 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name); 531 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
532 532
533 Name = name; 533 Name = name;
534 EngineType = engineType;
534 535
535 nearCallback = near; 536 nearCallback = near;
536 triCallback = TriCallback; 537 triCallback = TriCallback;
diff --git a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
index e6b42e6..ed086dd 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSPlugin.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Physics.POSPlugin
49 49
50 public PhysicsScene GetScene(string sceneIdentifier) 50 public PhysicsScene GetScene(string sceneIdentifier)
51 { 51 {
52 return new POSScene(sceneIdentifier); 52 return new POSScene(GetName(), sceneIdentifier);
53 } 53 }
54 54
55 public string GetName() 55 public string GetName()
diff --git a/OpenSim/Region/Physics/POSPlugin/POSScene.cs b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
index 2f24a50..d30d482 100644
--- a/OpenSim/Region/Physics/POSPlugin/POSScene.cs
+++ b/OpenSim/Region/Physics/POSPlugin/POSScene.cs
@@ -43,8 +43,10 @@ namespace OpenSim.Region.Physics.POSPlugin
43 43
44 //protected internal string sceneIdentifier; 44 //protected internal string sceneIdentifier;
45 45
46 public POSScene(String _sceneIdentifier) 46 public POSScene(string engineType, String _sceneIdentifier)
47 { 47 {
48 EngineType = engineType;
49 Name = EngineType + "/" + _sceneIdentifier;
48 //sceneIdentifier = _sceneIdentifier; 50 //sceneIdentifier = _sceneIdentifier;
49 } 51 }
50 52
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 33c02ef..958a448 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -245,11 +245,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
245 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 245 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
246 } 246 }
247 247
248 // Returns of the function is allowed. Throws a script exception if not allowed.
248 public void CheckThreatLevel(ThreatLevel level, string function) 249 public void CheckThreatLevel(ThreatLevel level, string function)
249 { 250 {
250 if (!m_OSFunctionsEnabled) 251 if (!m_OSFunctionsEnabled)
251 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws 252 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
252 253
254 string reasonWhyNot = CheckThreatLevelTest(level, function);
255 if (!String.IsNullOrEmpty(reasonWhyNot))
256 {
257 OSSLError(reasonWhyNot);
258 }
259 }
260
261 // Check to see if function is allowed. Returns an empty string if function permitted
262 // or a string explaining why this function can't be used.
263 private string CheckThreatLevelTest(ThreatLevel level, string function)
264 {
253 if (!m_FunctionPerms.ContainsKey(function)) 265 if (!m_FunctionPerms.ContainsKey(function))
254 { 266 {
255 FunctionPerms perms = new FunctionPerms(); 267 FunctionPerms perms = new FunctionPerms();
@@ -329,10 +341,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 { 341 {
330 // Allow / disallow by threat level 342 // Allow / disallow by threat level
331 if (level > m_MaxThreatLevel) 343 if (level > m_MaxThreatLevel)
332 OSSLError( 344 return
333 String.Format( 345 String.Format(
334 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", 346 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
335 function, m_MaxThreatLevel, level)); 347 function, m_MaxThreatLevel, level);
336 } 348 }
337 else 349 else
338 { 350 {
@@ -342,7 +354,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
342 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) 354 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
343 { 355 {
344 // prim owner is in the list of allowed owners 356 // prim owner is in the list of allowed owners
345 return; 357 return String.Empty;
346 } 358 }
347 359
348 UUID ownerID = m_item.OwnerID; 360 UUID ownerID = m_item.OwnerID;
@@ -354,7 +366,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
354 366
355 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) 367 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
356 { 368 {
357 return; 369 return String.Empty;
358 } 370 }
359 } 371 }
360 372
@@ -365,7 +377,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
365 377
366 if (land.LandData.OwnerID == ownerID) 378 if (land.LandData.OwnerID == ownerID)
367 { 379 {
368 return; 380 return String.Empty;
369 } 381 }
370 } 382 }
371 383
@@ -375,7 +387,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
375 //Only Estate Managers may use the function 387 //Only Estate Managers may use the function
376 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 388 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
377 { 389 {
378 return; 390 return String.Empty;
379 } 391 }
380 } 392 }
381 393
@@ -384,25 +396,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 { 396 {
385 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) 397 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
386 { 398 {
387 return; 399 return String.Empty;
388 } 400 }
389 } 401 }
390 402
391 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) 403 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
392 OSSLError( 404 return(
393 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.", 405 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.",
394 function)); 406 function));
395 407
396 if (m_item.CreatorID != ownerID) 408 if (m_item.CreatorID != ownerID)
397 { 409 {
398 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) 410 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
399 OSSLError( 411 return String.Format("{0} permission denied. Script permissions error.", function);
400 String.Format("{0} permission denied. Script permissions error.",
401 function));
402 412
403 } 413 }
404 } 414 }
405 } 415 }
416 return String.Empty;
406 } 417 }
407 418
408 internal void OSSLDeprecated(string function, string replacement) 419 internal void OSSLDeprecated(string function, string replacement)
@@ -1558,6 +1569,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1558 } 1569 }
1559 } 1570 }
1560 1571
1572 public string osGetPhysicsEngineType()
1573 {
1574 // High because it can be used to target attacks to known weaknesses
1575 // This would allow a new class of griefer scripts that don't even
1576 // require their user to know what they are doing (see script
1577 // kiddie)
1578 // Because it would be nice if scripts didn't blow up if the information
1579 // about the physics engine, this function returns an empty string if
1580 // the user does not have permission to see it. This as opposed to
1581 // throwing an exception.
1582 m_host.AddScriptLPS(1);
1583 string ret = String.Empty;
1584 if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
1585 {
1586 if (m_ScriptEngine.World.PhysicsScene != null)
1587 {
1588 ret = m_ScriptEngine.World.PhysicsScene.EngineType;
1589 // An old physics engine might have an uninitialized engine type
1590 if (ret == null)
1591 ret = "unknown";
1592 }
1593 }
1594
1595 return ret;
1596 }
1597
1561 public string osGetSimulatorVersion() 1598 public string osGetSimulatorVersion()
1562 { 1599 {
1563 // High because it can be used to target attacks to known weaknesses 1600 // High because it can be used to target attacks to known weaknesses
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index cdd9ea8..51d0581 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -259,6 +259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
259 259
260 string osGetScriptEngineName(); 260 string osGetScriptEngineName();
261 string osGetSimulatorVersion(); 261 string osGetSimulatorVersion();
262 string osGetPhysicsEngineType();
262 Object osParseJSONNew(string JSON); 263 Object osParseJSONNew(string JSON);
263 Hashtable osParseJSON(string JSON); 264 Hashtable osParseJSON(string JSON);
264 265
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index afa9ae0..c9902e4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -420,6 +420,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
420 return m_OSSL_Functions.osGetScriptEngineName(); 420 return m_OSSL_Functions.osGetScriptEngineName();
421 } 421 }
422 422
423 public string osGetPhysicsEngineType()
424 {
425 return m_OSSL_Functions.osGetPhysicsEngineType();
426 }
427
423 public string osGetSimulatorVersion() 428 public string osGetSimulatorVersion()
424 { 429 {
425 return m_OSSL_Functions.osGetSimulatorVersion(); 430 return m_OSSL_Functions.osGetSimulatorVersion();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 01a5e34..f172216 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -157,19 +157,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
157 157
158 public UUID AppDomain { get; set; } 158 public UUID AppDomain { get; set; }
159 159
160 /// <summary>
161 /// Scene part in which this script instance is contained.
162 /// </summary>
163 public SceneObjectPart Part { get; private set; }
164
160 public string PrimName { get; private set; } 165 public string PrimName { get; private set; }
161 166
162 public string ScriptName { get; private set; } 167 public string ScriptName { get; private set; }
163 168
164 public UUID ItemID { get; private set; } 169 public UUID ItemID { get; private set; }
165 170
166 public UUID ObjectID { get; private set; } 171 public UUID ObjectID { get { return Part.UUID; } }
167 172
168 public uint LocalID { get; private set; } 173 public uint LocalID { get { return Part.LocalId; } }
169 174
170 public UUID RootObjectID { get; private set; } 175 public UUID RootObjectID { get { return Part.ParentGroup.UUID; } }
171 176
172 public uint RootLocalID { get; private set; } 177 public uint RootLocalID { get { return Part.ParentGroup.LocalId; } }
173 178
174 public UUID AssetID { get; private set; } 179 public UUID AssetID { get; private set; }
175 180
@@ -214,10 +219,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
214 EventQueue = new Queue(32); 219 EventQueue = new Queue(32);
215 220
216 Engine = engine; 221 Engine = engine;
217 LocalID = part.LocalId; 222 Part = part;
218 ObjectID = part.UUID;
219 RootLocalID = part.ParentGroup.LocalId;
220 RootObjectID = part.ParentGroup.UUID;
221 ItemID = itemID; 223 ItemID = itemID;
222 AssetID = assetID; 224 AssetID = assetID;
223 PrimName = primName; 225 PrimName = primName;
@@ -227,17 +229,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
227 m_MaxScriptQueue = maxScriptQueue; 229 m_MaxScriptQueue = maxScriptQueue;
228 m_stateSource = stateSource; 230 m_stateSource = stateSource;
229 m_postOnRez = postOnRez; 231 m_postOnRez = postOnRez;
230 m_AttachedAvatar = part.ParentGroup.AttachedAvatar; 232 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
231 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID; 233 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
232 234
233 if (part != null) 235 lock (Part.TaskInventory)
234 { 236 {
235 lock (part.TaskInventory) 237 if (Part.TaskInventory.ContainsKey(ItemID))
236 { 238 {
237 if (part.TaskInventory.ContainsKey(ItemID)) 239 ScriptTask = Part.TaskInventory[ItemID];
238 {
239 ScriptTask = part.TaskInventory[ItemID];
240 }
241 } 240 }
242 } 241 }
243 242
@@ -322,7 +321,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
322 321
323// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName); 322// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName);
324 323
325 part.SetScriptEvents(ItemID, 324 Part.SetScriptEvents(ItemID,
326 (int)m_Script.GetStateEventFlags(State)); 325 (int)m_Script.GetStateEventFlags(State));
327 326
328 if (!Running) 327 if (!Running)
@@ -418,33 +417,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
418 PostEvent(new EventParams("attach", 417 PostEvent(new EventParams("attach",
419 new object[] { new LSL_Types.LSLString(m_AttachedAvatar.ToString()) }, new DetectParams[0])); 418 new object[] { new LSL_Types.LSLString(m_AttachedAvatar.ToString()) }, new DetectParams[0]));
420 } 419 }
421
422 } 420 }
423 } 421 }
424 422
425 private void ReleaseControls() 423 private void ReleaseControls()
426 { 424 {
427 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 425 int permsMask;
428 426 UUID permsGranter;
429 if (part != null) 427 lock (Part.TaskInventory)
430 { 428 {
431 int permsMask; 429 if (!Part.TaskInventory.ContainsKey(ItemID))
432 UUID permsGranter; 430 return;
433 lock (part.TaskInventory)
434 {
435 if (!part.TaskInventory.ContainsKey(ItemID))
436 return;
437 431
438 permsGranter = part.TaskInventory[ItemID].PermsGranter; 432 permsGranter = Part.TaskInventory[ItemID].PermsGranter;
439 permsMask = part.TaskInventory[ItemID].PermsMask; 433 permsMask = Part.TaskInventory[ItemID].PermsMask;
440 } 434 }
441 435
442 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 436 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
443 { 437 {
444 ScenePresence presence = Engine.World.GetScenePresence(permsGranter); 438 ScenePresence presence = Engine.World.GetScenePresence(permsGranter);
445 if (presence != null) 439 if (presence != null)
446 presence.UnRegisterControlEventsToScript(LocalID, ItemID); 440 presence.UnRegisterControlEventsToScript(LocalID, ItemID);
447 }
448 } 441 }
449 } 442 }
450 443
@@ -706,19 +699,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
706 m_CollisionInQueue = false; 699 m_CollisionInQueue = false;
707 } 700 }
708 701
709 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
710
711 if (DebugLevel >= 2) 702 if (DebugLevel >= 2)
712 m_log.DebugFormat( 703 m_log.DebugFormat(
713 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}", 704 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
714 data.EventName, 705 data.EventName,
715 ScriptName, 706 ScriptName,
716 part.Name, 707 Part.Name,
717 part.LocalId, 708 Part.LocalId,
718 part.ParentGroup.Name, 709 Part.ParentGroup.Name,
719 part.ParentGroup.UUID, 710 Part.ParentGroup.UUID,
720 part.AbsolutePosition, 711 Part.AbsolutePosition,
721 part.ParentGroup.Scene.Name); 712 Part.ParentGroup.Scene.Name);
722 713
723 m_DetectParams = data.DetectParams; 714 m_DetectParams = data.DetectParams;
724 715
@@ -731,21 +722,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
731 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}", 722 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
732 State, 723 State,
733 ScriptName, 724 ScriptName,
734 part.Name, 725 Part.Name,
735 part.LocalId, 726 Part.LocalId,
736 part.ParentGroup.Name, 727 Part.ParentGroup.Name,
737 part.ParentGroup.UUID, 728 Part.ParentGroup.UUID,
738 part.AbsolutePosition, 729 Part.AbsolutePosition,
739 part.ParentGroup.Scene.Name); 730 Part.ParentGroup.Scene.Name);
740 731
741 AsyncCommandManager.RemoveScript(Engine, 732 AsyncCommandManager.RemoveScript(Engine,
742 LocalID, ItemID); 733 LocalID, ItemID);
743 734
744 if (part != null) 735 Part.SetScriptEvents(ItemID, (int)m_Script.GetStateEventFlags(State));
745 {
746 part.SetScriptEvents(ItemID,
747 (int)m_Script.GetStateEventFlags(State));
748 }
749 } 736 }
750 else 737 else
751 { 738 {
@@ -804,17 +791,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
804 text = text.Substring(0, 1000); 791 text = text.Substring(0, 1000);
805 Engine.World.SimChat(Utils.StringToBytes(text), 792 Engine.World.SimChat(Utils.StringToBytes(text),
806 ChatTypeEnum.DebugChannel, 2147483647, 793 ChatTypeEnum.DebugChannel, 2147483647,
807 part.AbsolutePosition, 794 Part.AbsolutePosition,
808 part.Name, part.UUID, false); 795 Part.Name, Part.UUID, false);
809 796
810 797
811 m_log.DebugFormat( 798 m_log.DebugFormat(
812 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}", 799 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
813 ScriptName, 800 ScriptName,
814 PrimName, 801 PrimName,
815 part.UUID, 802 Part.UUID,
816 part.AbsolutePosition, 803 Part.AbsolutePosition,
817 part.ParentGroup.Scene.Name, 804 Part.ParentGroup.Scene.Name,
818 text.Replace("\n", "\\n"), 805 text.Replace("\n", "\\n"),
819 e.InnerException); 806 e.InnerException);
820 } 807 }
@@ -834,14 +821,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
834 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) 821 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
835 { 822 {
836 m_InSelfDelete = true; 823 m_InSelfDelete = true;
837 if (part != null) 824 Engine.World.DeleteSceneObject(Part.ParentGroup, false);
838 Engine.World.DeleteSceneObject(part.ParentGroup, false);
839 } 825 }
840 else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) 826 else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException))
841 { 827 {
842 m_InSelfDelete = true; 828 m_InSelfDelete = true;
843 if (part != null) 829 Part.Inventory.RemoveInventoryItem(ItemID);
844 part.Inventory.RemoveInventoryItem(ItemID);
845 } 830 }
846 } 831 }
847 } 832 }
@@ -888,15 +873,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
888 ReleaseControls(); 873 ReleaseControls();
889 874
890 Stop(timeout); 875 Stop(timeout);
891 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 876 Part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
892 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 877 Part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
893 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
894 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 878 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
895 EventQueue.Clear(); 879 EventQueue.Clear();
896 m_Script.ResetVars(); 880 m_Script.ResetVars();
897 State = "default"; 881 State = "default";
898 882
899 part.SetScriptEvents(ItemID, 883 Part.SetScriptEvents(ItemID,
900 (int)m_Script.GetStateEventFlags(State)); 884 (int)m_Script.GetStateEventFlags(State));
901 if (running) 885 if (running)
902 Start(); 886 Start();
@@ -913,16 +897,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
913 ReleaseControls(); 897 ReleaseControls();
914 898
915 m_Script.ResetVars(); 899 m_Script.ResetVars();
916 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 900 Part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
917 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 901 Part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
918 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
919 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 902 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
920 903
921 EventQueue.Clear(); 904 EventQueue.Clear();
922 m_Script.ResetVars(); 905 m_Script.ResetVars();
923 State = "default"; 906 State = "default";
924 907
925 part.SetScriptEvents(ItemID, 908 Part.SetScriptEvents(ItemID,
926 (int)m_Script.GetStateEventFlags(State)); 909 (int)m_Script.GetStateEventFlags(State));
927 910
928 if (m_CurrentEvent != "state_entry") 911 if (m_CurrentEvent != "state_entry")
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index 3f208bf..2e6d279 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -280,8 +280,11 @@ namespace OpenSim.Server.Base
280 { 280 {
281 if (!(e is System.MissingMethodException)) 281 if (!(e is System.MissingMethodException))
282 { 282 {
283 m_log.ErrorFormat("Error loading plugin {0} from {1}. Exception: {2}", 283 m_log.ErrorFormat("Error loading plugin {0} from {1}. Exception: {2}, {3}",
284 interfaceName, dllName, e.InnerException == null ? e.Message : e.InnerException.Message); 284 interfaceName,
285 dllName,
286 e.InnerException == null ? e.Message : e.InnerException.Message,
287 e.StackTrace);
285 } 288 }
286 return null; 289 return null;
287 } 290 }