diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index a16d17421d..fd00fe8288 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -16,7 +16,7 @@ people that make the day to day of OpenSim happen.
* BlueWall (James Hughes)
* Nebadon Izumi (Michael Cerquoni, OSgrid)
* Snoopy Pfeffer
-* Richard Adams (Intel)
+* Robert Adams (Intel)
= Core Developers Following the White Rabbit =
Core developers who have temporarily (we hope) gone chasing the white rabbit.
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 130c869bc7..2a513e91d8 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -406,6 +406,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
+ {
+ DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
+ }
+
+ public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
{
if (!Enabled)
return;
@@ -448,7 +453,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.FromItemID = UUID.Zero;
SceneObjectPart rootPart = so.RootPart;
- so.AbsolutePosition = sp.AbsolutePosition;
+ so.AbsolutePosition = absolutePos;
+ if (absoluteRot != Quaternion.Identity)
+ {
+ so.UpdateGroupRotationR(absoluteRot);
+ }
so.AttachedAvatar = UUID.Zero;
rootPart.SetParentLocalId(0);
so.ClearPartAttachmentData();
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
index 65e4c90ba5..fd8d5e32bd 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -1,161 +1,170 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.IO;
-using System.Text;
-using log4net;
-
-namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
-{
- ///
- /// Class for writing a high performance, high volume log file.
- /// Sometimes, to debug, one has a high volume logging to do and the regular
- /// log file output is not appropriate.
- /// Create a new instance with the parameters needed and
- /// call Write() to output a line. Call Close() when finished.
- /// If created with no parameters, it will not log anything.
- ///
- public class LogWriter : IDisposable
- {
- public bool Enabled { get; private set; }
-
- private string m_logDirectory = ".";
- private int m_logMaxFileTimeMin = 5; // 5 minutes
- public String LogFileHeader { get; set; }
-
- private StreamWriter m_logFile = null;
- private TimeSpan m_logFileLife;
- private DateTime m_logFileEndTime;
- private Object m_logFileWriteLock = new Object();
-
- // set externally when debugging. If let 'null', this does not write any error messages.
- public ILog ErrorLogger = null;
- private string LogHeader = "[LOG WRITER]";
-
- ///
- /// Create a log writer that will not write anything. Good for when not enabled
- /// but the write statements are still in the code.
- ///
- public LogWriter()
- {
- Enabled = false;
- m_logFile = null;
- }
-
- ///
- /// Create a log writer instance.
- ///
- /// The directory to create the log file in. May be 'null' for default.
- /// The characters that begin the log file name. May be 'null' for default.
- /// Maximum age of a log file in minutes. If zero, will set default.
- public LogWriter(string dir, string headr, int maxFileTime)
- {
- m_logDirectory = dir == null ? "." : dir;
-
- LogFileHeader = headr == null ? "log-" : headr;
-
- m_logMaxFileTimeMin = maxFileTime;
- if (m_logMaxFileTimeMin < 1)
- m_logMaxFileTimeMin = 5;
-
- m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
- m_logFileEndTime = DateTime.Now + m_logFileLife;
-
- Enabled = true;
- }
-
- public void Dispose()
- {
- this.Close();
- }
-
- public void Close()
- {
- Enabled = false;
- if (m_logFile != null)
- {
- m_logFile.Close();
- m_logFile.Dispose();
- m_logFile = null;
- }
- }
-
- public void Write(string line, params object[] args)
- {
- if (!Enabled) return;
- Write(String.Format(line, args));
- }
-
- public void Write(string line)
- {
- if (!Enabled) return;
- try
- {
- lock (m_logFileWriteLock)
- {
- DateTime now = DateTime.Now;
- if (m_logFile == null || now > m_logFileEndTime)
- {
- if (m_logFile != null)
- {
- m_logFile.Close();
- m_logFile.Dispose();
- m_logFile = null;
- }
-
- // First log file or time has expired, start writing to a new log file
- m_logFileEndTime = now + m_logFileLife;
- string path = (m_logDirectory.Length > 0 ? m_logDirectory
- + System.IO.Path.DirectorySeparatorChar.ToString() : "")
- + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
- m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
- }
- if (m_logFile != null)
- {
- StringBuilder buff = new StringBuilder(line.Length + 25);
- buff.Append(now.ToString("yyyyMMddHHmmssfff"));
- // buff.Append(now.ToString("yyyyMMddHHmmss"));
- buff.Append(",");
- buff.Append(line);
- buff.Append("\r\n");
- m_logFile.Write(buff.ToString());
- }
- }
- }
- catch (Exception e)
- {
- if (ErrorLogger != null)
- {
- ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
- }
- Enabled = false;
- }
- return;
- }
- }
-}
\ No newline at end of file
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using log4net;
+
+namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
+{
+ ///
+ /// Class for writing a high performance, high volume log file.
+ /// Sometimes, to debug, one has a high volume logging to do and the regular
+ /// log file output is not appropriate.
+ /// Create a new instance with the parameters needed and
+ /// call Write() to output a line. Call Close() when finished.
+ /// If created with no parameters, it will not log anything.
+ ///
+ public class LogWriter : IDisposable
+ {
+ public bool Enabled { get; private set; }
+
+ private string m_logDirectory = ".";
+ private int m_logMaxFileTimeMin = 5; // 5 minutes
+ public String LogFileHeader { get; set; }
+
+ private StreamWriter m_logFile = null;
+ private TimeSpan m_logFileLife;
+ private DateTime m_logFileEndTime;
+ private Object m_logFileWriteLock = new Object();
+
+ // set externally when debugging. If let 'null', this does not write any error messages.
+ public ILog ErrorLogger = null;
+ private string LogHeader = "[LOG WRITER]";
+
+ ///
+ /// Create a log writer that will not write anything. Good for when not enabled
+ /// but the write statements are still in the code.
+ ///
+ public LogWriter()
+ {
+ Enabled = false;
+ m_logFile = null;
+ }
+
+ ///
+ /// Create a log writer instance.
+ ///
+ /// The directory to create the log file in. May be 'null' for default.
+ /// The characters that begin the log file name. May be 'null' for default.
+ /// Maximum age of a log file in minutes. If zero, will set default.
+ public LogWriter(string dir, string headr, int maxFileTime)
+ {
+ m_logDirectory = dir == null ? "." : dir;
+
+ LogFileHeader = headr == null ? "log-" : headr;
+
+ m_logMaxFileTimeMin = maxFileTime;
+ if (m_logMaxFileTimeMin < 1)
+ m_logMaxFileTimeMin = 5;
+
+ m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
+ m_logFileEndTime = DateTime.Now + m_logFileLife;
+
+ Enabled = true;
+ }
+
+ public void Dispose()
+ {
+ this.Close();
+ }
+
+ public void Close()
+ {
+ Enabled = false;
+ if (m_logFile != null)
+ {
+ m_logFile.Close();
+ m_logFile.Dispose();
+ m_logFile = null;
+ }
+ }
+
+ public void Write(string line, params object[] args)
+ {
+ if (!Enabled) return;
+ Write(String.Format(line, args));
+ }
+
+ public void Flush()
+ {
+ if (!Enabled) return;
+ if (m_logFile != null)
+ {
+ m_logFile.Flush();
+ }
+ }
+
+ public void Write(string line)
+ {
+ if (!Enabled) return;
+ try
+ {
+ lock (m_logFileWriteLock)
+ {
+ DateTime now = DateTime.Now;
+ if (m_logFile == null || now > m_logFileEndTime)
+ {
+ if (m_logFile != null)
+ {
+ m_logFile.Close();
+ m_logFile.Dispose();
+ m_logFile = null;
+ }
+
+ // First log file or time has expired, start writing to a new log file
+ m_logFileEndTime = now + m_logFileLife;
+ string path = (m_logDirectory.Length > 0 ? m_logDirectory
+ + System.IO.Path.DirectorySeparatorChar.ToString() : "")
+ + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
+ m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
+ }
+ if (m_logFile != null)
+ {
+ StringBuilder buff = new StringBuilder(line.Length + 25);
+ buff.Append(now.ToString("yyyyMMddHHmmssfff"));
+ // buff.Append(now.ToString("yyyyMMddHHmmss"));
+ buff.Append(",");
+ buff.Append(line);
+ buff.Append("\r\n");
+ m_logFile.Write(buff.ToString());
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (ErrorLogger != null)
+ {
+ ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
+ }
+ Enabled = false;
+ }
+ return;
+ }
+ }
+}
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 8155eabbbe..620ec22cc8 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -108,6 +108,15 @@ namespace OpenSim.Region.Framework.Interfaces
///
void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
+ ///
+ /// Detach the given item to the ground at the specified coordinates & rotation
+ ///
+ ///
+ ///
+ ///
+ ///
+ void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot);
+
///
/// Detach the given attachment so that it remains in the user's inventory.
///
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index b88ec3cf9d..2a52e0145b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -218,6 +218,18 @@ public class BSCharacter : BSPhysObject
});
}
}
+ public override OMV.Vector3 ForcePosition {
+ get {
+ _position = BulletSimAPI.GetPosition2(BSBody.ptr);
+ return _position;
+ }
+ set {
+ _position = value;
+ PositionSanityCheck();
+ BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
+ }
+ }
+
// Check that the current position is sane and, if not, modify the position to make it so.
// Check for being below terrain and being out of bounds.
@@ -234,6 +246,15 @@ public class BSCharacter : BSPhysObject
_position.Z = terrainHeight + 2.0f;
ret = true;
}
+ if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
+ {
+ float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
+ if (Position.Z < waterHeight)
+ {
+ _position.Z = waterHeight;
+ ret = true;
+ }
+ }
// TODO: check for out of bounds
return ret;
@@ -242,18 +263,22 @@ public class BSCharacter : BSPhysObject
// A version of the sanity check that also makes sure a new position value is
// pushed back to the physics engine. This routine would be used by anyone
// who is not already pushing the value.
- private bool PositionSanityCheck2()
+ private bool PositionSanityCheck2(bool atTaintTime)
{
bool ret = false;
if (PositionSanityCheck())
{
// The new position value must be pushed into the physics engine but we can't
// just assign to "Position" because of potential call loops.
- PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
+ BSScene.TaintCallback sanityOperation = delegate()
{
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
- });
+ };
+ if (atTaintTime)
+ sanityOperation();
+ else
+ PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
ret = true;
}
return ret;
@@ -333,6 +358,20 @@ public class BSCharacter : BSPhysObject
});
}
}
+ // Go directly to Bullet to get/set the value.
+ public override OMV.Quaternion ForceOrientation
+ {
+ get
+ {
+ _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
+ return _orientation;
+ }
+ set
+ {
+ _orientation = value;
+ BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
+ }
+ }
public override int PhysicsActorType {
get { return _physicsActorType; }
set { _physicsActorType = value;
@@ -378,7 +417,16 @@ public class BSCharacter : BSPhysObject
set { _collidingObj = value; }
}
public override bool FloatOnWater {
- set { _floatOnWater = value; }
+ set {
+ _floatOnWater = value;
+ PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
+ {
+ if (_floatOnWater)
+ CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
+ else
+ CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
+ });
+ }
}
public override OMV.Vector3 RotationalVelocity {
get { return _rotationalVelocity; }
@@ -493,15 +541,14 @@ public class BSCharacter : BSPhysObject
_velocity = entprop.Velocity;
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
+ // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
+ PositionSanityCheck2(true);
+
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate();
- // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
- PositionSanityCheck2();
-
- float heightHere = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
- DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
- LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
+ DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
+ LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
}
}
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 65b38d696a..4ba2f62639 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
- // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
+ private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
//Deflection properties
// private float m_angularDeflectionEfficiency = 0;
@@ -138,74 +138,55 @@ namespace OpenSim.Region.Physics.BulletSPlugin
switch (pParam)
{
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_angularDeflectionEfficiency = pValue;
+ // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f);
break;
case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_angularDeflectionTimescale = pValue;
+ // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_angularMotorDecayTimescale = pValue;
+ m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_angularMotorTimescale = pValue;
+ m_angularMotorTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.BANKING_EFFICIENCY:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_bankingEfficiency = pValue;
+ // m_bankingEfficiency = Math.Max(pValue, 0.01f);
break;
case Vehicle.BANKING_MIX:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_bankingMix = pValue;
+ // m_bankingMix = Math.Max(pValue, 0.01f);
break;
case Vehicle.BANKING_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_bankingTimescale = pValue;
+ // m_bankingTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.BUOYANCY:
- if (pValue < -1f) pValue = -1f;
- if (pValue > 1f) pValue = 1f;
- m_VehicleBuoyancy = pValue;
+ m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f));
break;
// case Vehicle.HOVER_EFFICIENCY:
-// if (pValue < 0f) pValue = 0f;
-// if (pValue > 1f) pValue = 1f;
-// m_VhoverEfficiency = pValue;
+// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f));
// break;
case Vehicle.HOVER_HEIGHT:
m_VhoverHeight = pValue;
break;
case Vehicle.HOVER_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_VhoverTimescale = pValue;
+ m_VhoverTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_linearDeflectionEfficiency = pValue;
+ // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- // m_linearDeflectionTimescale = pValue;
+ // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_linearMotorDecayTimescale = pValue;
+ m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_linearMotorTimescale = pValue;
+ m_linearMotorTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
- if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
- if (pValue > 1.0f) pValue = 1.0f;
- m_verticalAttractionEfficiency = pValue;
+ m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
break;
case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
- if (pValue < 0.01f) pValue = 0.01f;
- m_verticalAttractionTimescale = pValue;
+ m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
break;
// These are vector properties but the engine lets you use a single float value to
@@ -371,8 +352,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 1;
// m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity;
- m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
- VehicleFlag.LIMIT_MOTOR_UP);
+ m_flags |= (VehicleFlag.NO_DEFLECTION_UP
+ | VehicleFlag.LIMIT_ROLL_ONLY
+ | VehicleFlag.LIMIT_MOTOR_UP);
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
m_flags |= (VehicleFlag.HOVER_UP_ONLY);
break;
@@ -399,12 +381,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.8f;
// m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity;
- m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
- VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
- m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
- m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
- VehicleFlag.LIMIT_MOTOR_UP);
- m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
+ m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
+ | VehicleFlag.HOVER_GLOBAL_HEIGHT
+ | VehicleFlag.LIMIT_ROLL_ONLY
+ | VehicleFlag.HOVER_UP_ONLY);
+ m_flags |= (VehicleFlag.NO_DEFLECTION_UP
+ | VehicleFlag.LIMIT_MOTOR_UP
+ | VehicleFlag.HOVER_WATER_ONLY);
break;
case Vehicle.TYPE_AIRPLANE:
m_linearFrictionTimescale = new Vector3(200, 10, 5);
@@ -429,9 +412,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.7f;
// m_bankingTimescale = 2;
// m_referenceFrame = Quaternion.Identity;
- m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
- VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
- m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
+ m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
+ | VehicleFlag.HOVER_TERRAIN_ONLY
+ | VehicleFlag.HOVER_GLOBAL_HEIGHT
+ | VehicleFlag.HOVER_UP_ONLY
+ | VehicleFlag.NO_DEFLECTION_UP
+ | VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
break;
case Vehicle.TYPE_BALLOON:
@@ -457,11 +443,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.7f;
// m_bankingTimescale = 5;
// m_referenceFrame = Quaternion.Identity;
- m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
- VehicleFlag.HOVER_UP_ONLY);
- m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
- m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
- m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
+ m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
+ | VehicleFlag.HOVER_TERRAIN_ONLY
+ | VehicleFlag.HOVER_UP_ONLY
+ | VehicleFlag.NO_DEFLECTION_UP
+ | VehicleFlag.LIMIT_MOTOR_UP);
+ m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
+ | VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
}//end SetDefaultsForType
@@ -470,7 +458,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Do any updating needed for a vehicle
public void Refresh()
{
- if (Type == Vehicle.TYPE_NONE) return;
+ if (!IsActive)
+ return;
// Set the prim's inertia to zero. The vehicle code handles that and this
// removes the torque action introduced by Bullet.
@@ -489,7 +478,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
LimitRotation(pTimestep);
// remember the position so next step we can limit absolute movement effects
- m_lastPositionVector = Prim.Position;
+ m_lastPositionVector = Prim.ForcePosition;
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
Prim.LocalID, Prim.Position, Prim.Force, Prim.Velocity, Prim.RotationalVelocity);
@@ -543,7 +532,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
// convert requested object velocity to object relative vector
- Quaternion rotq = Prim.Orientation;
+ Quaternion rotq = Prim.ForceOrientation;
m_newVelocity = m_lastLinearVelocityVector * rotq;
// Add the various forces into m_dir which will be our new direction vector (velocity)
@@ -560,19 +549,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
*/
- Vector3 pos = Prim.Position;
+ Vector3 pos = Prim.ForcePosition;
// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
// If below the terrain, move us above the ground a little.
float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
// Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
// Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
- // Vector3 rotatedSize = m_prim.Size * m_prim.Orientation;
+ // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
// if (rotatedSize.Z < terrainHeight)
if (pos.Z < terrainHeight)
{
pos.Z = terrainHeight + 2;
- Prim.Position = pos;
+ Prim.ForcePosition = pos;
VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
}
@@ -602,7 +591,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
{
- Prim.Position = pos;
+ Prim.ForcePosition = pos;
}
}
else
@@ -654,12 +643,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
if (changed)
{
- Prim.Position = pos;
+ Prim.ForcePosition = pos;
VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
Prim.LocalID, m_BlockingEndPoint, posChange, pos);
}
}
+ // Limit absolute vertical change
float Zchange = Math.Abs(posChange.Z);
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
{
@@ -678,6 +668,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
grav.Z = (float)(grav.Z * 1.037125);
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav);
}
+
+ // If not changing some axis, reduce out velocity
if ((m_flags & (VehicleFlag.NO_X)) != 0)
m_newVelocity.X = 0;
if ((m_flags & (VehicleFlag.NO_Y)) != 0)
@@ -720,19 +712,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// a newly set velocity, this routine steps the value from the previous
// value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
// There are m_angularMotorApply steps.
- Vector3 origAngularVelocity = m_angularMotorVelocity;
+ Vector3 origVel = m_angularMotorVelocity;
+ Vector3 origDir = m_angularMotorDirection;
+
// ramp up to new value
- // current velocity += error / ( time to get there / step interval)
+ // new velocity += error / ( time to get there / step interval)
// requested speed - last motor speed
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
- VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},dir={5},vel={6}",
- Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
+ VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}",
+ Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
- // This is done so that if script request rate is less than phys frame rate the expected
- // velocity may still be acheived.
m_angularMotorApply--;
}
else
@@ -746,25 +738,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Vertical attractor section
Vector3 vertattr = Vector3.Zero;
- if (m_verticalAttractionTimescale < 300)
+ Vector3 deflection = Vector3.Zero;
+ Vector3 banking = Vector3.Zero;
+
+ if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
{
float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
+ VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
+
// get present body rotation
- Quaternion rotq = Prim.Orientation;
- // make a vector pointing up
+ Quaternion rotq = Prim.ForceOrientation;
+ // vector pointing up
Vector3 verterr = Vector3.Zero;
verterr.Z = 1.0f;
+
// rotate it to Body Angle
verterr = verterr * rotq;
- // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
+ // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
// As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
// negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
+
+ // Error is 0 (no error) to +/- 2 (max error)
if (verterr.Z < 0.0f)
{
verterr.X = 2.0f - verterr.X;
verterr.Y = 2.0f - verterr.Y;
}
- // Error is 0 (no error) to +/- 2 (max error)
// scale it by VAservo
verterr = verterr * VAservo;
@@ -784,7 +783,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} // else vertical attractor is off
- // m_lastVertAttractor = vertattr;
+ m_lastVertAttractor = vertattr;
// Bank section tba
@@ -818,7 +817,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void LimitRotation(float timestep)
{
- Quaternion rotq = Prim.Orientation;
+ Quaternion rotq = Prim.ForceOrientation;
Quaternion m_rot = rotq;
bool changed = false;
if (m_RollreferenceFrame != Quaternion.Identity)
@@ -853,7 +852,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
if (changed)
{
- Prim.Orientation = m_rot;
+ Prim.ForceOrientation = m_rot;
VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4f225ae0f0..3e82642e52 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSLinkset
{
- private static string LogHeader = "[BULLETSIM LINKSET]";
+ // private static string LogHeader = "[BULLETSIM LINKSET]";
public BSPhysObject LinksetRoot { get; protected set; }
@@ -331,21 +331,21 @@ public class BSLinkset
m_children.Add(child);
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
- BulletBody rootBodyx = LinksetRoot.BSBody;
BSPhysObject childx = child;
- BulletBody childBodyx = child.BSBody;
DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
rootx.LocalID,
- rootx.LocalID, rootBodyx.ptr.ToString("X"),
- childx.LocalID, childBodyx.ptr.ToString("X"));
+ rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
+ childx.LocalID, childx.BSBody.ptr.ToString("X"));
PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
{
DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID);
// build the physical binding between me and the child
m_taintChildren.Add(childx);
- PhysicallyLinkAChildToRoot(rootx, rootBodyx, childx, childBodyx);
+
+ // Since this is taint-time, the body and shape could have changed for the child
+ PhysicallyLinkAChildToRoot(rootx, rootx.BSBody, childx, childx.BSBody);
});
}
return;
@@ -369,21 +369,19 @@ public class BSLinkset
if (m_children.Remove(child))
{
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
- BulletBody rootBodyx = LinksetRoot.BSBody;
BSPhysObject childx = child;
- BulletBody childBodyx = child.BSBody;
DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
childx.LocalID,
- rootx.LocalID, rootBodyx.ptr.ToString("X"),
- childx.LocalID, childBodyx.ptr.ToString("X"));
+ rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
+ childx.LocalID, childx.BSBody.ptr.ToString("X"));
PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
{
if (m_taintChildren.Contains(childx))
m_taintChildren.Remove(childx);
- PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx);
+ PhysicallyUnlinkAChildFromRoot(rootx, rootx.BSBody, childx, childx.BSBody);
RecomputeLinksetConstraintVariables();
});
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index d9b738b865..1ac8c59e07 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -81,6 +81,10 @@ public abstract class BSPhysObject : PhysicsActor
// Tell the object to clean up.
public abstract void Destroy();
+ public abstract OMV.Vector3 ForcePosition { get; set; }
+
+ public abstract OMV.Quaternion ForceOrientation { get; set; }
+
#region Collisions
// Requested number of milliseconds between collision events. Zero means disabled.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index a0e627ec66..f7b68bacc3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -46,19 +46,13 @@ public sealed class BSPrim : BSPhysObject
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS PRIM]";
- private IMesh _mesh;
private PrimitiveBaseShape _pbs;
- private ShapeData.PhysicsShapeType _shapeType;
- private ulong _meshKey;
- private ulong _hullKey;
- private List _hulls;
// _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
// Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
- private bool _stopped;
private bool _grabbed;
private bool _isSelected;
private bool _isVolumeDetect;
@@ -109,8 +103,6 @@ public sealed class BSPrim : BSPhysObject
_buoyancy = 1f;
_velocity = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero;
- _hullKey = 0;
- _meshKey = 0;
_pbs = pbs;
_isPhysical = pisPhysical;
_isVolumeDetect = false;
@@ -160,8 +152,9 @@ public sealed class BSPrim : BSPhysObject
});
}
+ // No one uses this property.
public override bool Stopped {
- get { return _stopped; }
+ get { return false; }
}
public override OMV.Vector3 Size {
get { return _size; }
@@ -274,6 +267,7 @@ public sealed class BSPrim : BSPhysObject
set {
_position = value;
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
+ PositionSanityCheck();
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
{
// DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
@@ -281,6 +275,74 @@ public sealed class BSPrim : BSPhysObject
});
}
}
+ public override OMV.Vector3 ForcePosition {
+ get {
+ _position = BulletSimAPI.GetPosition2(BSBody.ptr);
+ return _position;
+ }
+ set {
+ _position = value;
+ PositionSanityCheck();
+ BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
+ }
+ }
+
+ // Check that the current position is sane and, if not, modify the position to make it so.
+ // Check for being below terrain and being out of bounds.
+ // Returns 'true' of the position was made sane by some action.
+ private bool PositionSanityCheck()
+ {
+ bool ret = false;
+
+ // If totally below the ground, move the prim up
+ // TODO: figure out the right solution for this... only for dynamic objects?
+ /*
+ float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
+ if (Position.Z < terrainHeight)
+ {
+ DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
+ _position.Z = terrainHeight + 2.0f;
+ ret = true;
+ }
+ */
+ if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
+ {
+ float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
+ if (Position.Z < waterHeight)
+ {
+ _position.Z = waterHeight;
+ ret = true;
+ }
+ }
+
+ // TODO: check for out of bounds
+ return ret;
+ }
+
+ // A version of the sanity check that also makes sure a new position value is
+ // pushed back to the physics engine. This routine would be used by anyone
+ // who is not already pushing the value.
+ private bool PositionSanityCheck2(bool atTaintTime)
+ {
+ bool ret = false;
+ if (PositionSanityCheck())
+ {
+ // The new position value must be pushed into the physics engine but we can't
+ // just assign to "Position" because of potential call loops.
+ BSScene.TaintCallback sanityOperation = delegate()
+ {
+ DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
+ BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
+ };
+ if (atTaintTime)
+ sanityOperation();
+ else
+ PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
+
+ ret = true;
+ }
+ return ret;
+ }
// Return the effective mass of the object.
// If there are multiple items in the linkset, add them together for the root
@@ -326,14 +388,15 @@ public sealed class BSPrim : BSPhysObject
}
set {
Vehicle type = (Vehicle)value;
- BSPrim vehiclePrim = this;
+
+ // Tell the scene about the vehicle so it will get processing each frame.
+ PhysicsScene.VehicleInSceneTypeChanged(this, type);
+
PhysicsScene.TaintedObject("setVehicleType", delegate()
{
// Done at taint time so we're sure the physics engine is not using the variables
// Vehicle code changes the parameters for this vehicle type.
- _vehicle.ProcessTypeChange(type);
- // Tell the scene about the vehicle so it will get processing each frame.
- PhysicsScene.VehicleInSceneTypeChanged(this, type);
+ this._vehicle.ProcessTypeChange(type);
});
}
}
@@ -371,7 +434,9 @@ public sealed class BSPrim : BSPhysObject
public override void StepVehicle(float timeStep)
{
if (IsPhysical)
+ {
_vehicle.Step(timeStep);
+ }
}
// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
@@ -435,6 +500,20 @@ public sealed class BSPrim : BSPhysObject
});
}
}
+ // Go directly to Bullet to get/set the value.
+ public override OMV.Quaternion ForceOrientation
+ {
+ get
+ {
+ _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
+ return _orientation;
+ }
+ set
+ {
+ _orientation = value;
+ BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
+ }
+ }
public override int PhysicsActorType {
get { return _physicsActorType; }
set { _physicsActorType = value; }
@@ -488,11 +567,10 @@ public sealed class BSPrim : BSPhysObject
// This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
-
// Set up the object physicalness (does gravity and collisions move this object)
MakeDynamic(IsStatic);
- // Do any vehicle stuff
+ // Update vehicle specific parameters
_vehicle.Refresh();
// Arrange for collision events if the simulator wants them
@@ -563,7 +641,6 @@ public sealed class BSPrim : BSPhysObject
// A dynamic object has mass
IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
- // OMV.Vector3 inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
@@ -573,7 +650,7 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
- // There can be special things needed for implementing linksets.
+ // There might be special things needed for implementing linksets.
Linkset.MakeDynamic(this);
// Force activation of the object so Bullet will act on it.
@@ -663,7 +740,16 @@ public sealed class BSPrim : BSPhysObject
}
}
public override bool FloatOnWater {
- set { _floatOnWater = value; }
+ set {
+ _floatOnWater = value;
+ PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
+ {
+ if (_floatOnWater)
+ CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
+ else
+ CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
+ });
+ }
}
public override OMV.Vector3 RotationalVelocity {
get {
@@ -1082,15 +1168,15 @@ public sealed class BSPrim : BSPhysObject
public void FillShapeInfo(out ShapeData shape)
{
shape.ID = LocalID;
- shape.Type = _shapeType;
+ shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
shape.Position = _position;
shape.Rotation = _orientation;
shape.Velocity = _velocity;
shape.Scale = _scale;
shape.Mass = _isPhysical ? _mass : 0f;
shape.Buoyancy = _buoyancy;
- shape.HullKey = _hullKey;
- shape.MeshKey = _meshKey;
+ shape.HullKey = 0;
+ shape.MeshKey = 0;
shape.Friction = _friction;
shape.Restitution = _restitution;
shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
@@ -1112,7 +1198,8 @@ public sealed class BSPrim : BSPhysObject
// Create the correct physical representation for this type of object.
// Updates BSBody and BSShape with the new information.
- PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs,
+ // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
+ PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, _pbs,
null, delegate(BulletBody dBody)
{
// Called if the current prim body is about to be destroyed.
@@ -1205,6 +1292,8 @@ public sealed class BSPrim : BSPhysObject
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
+ PositionSanityCheck2(true);
+
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 0cf8c91a2d..aaed7de73d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -493,6 +493,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// step the physical world one interval
m_simulationStep++;
int numSubSteps = 0;
+
+ // Sometimes needed for debugging to find out what happened before the step
+ // PhysicsLogging.Flush();
+
try
{
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
@@ -536,7 +540,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
}
// This is a kludge to get avatar movement updates.
- // ODE sends collisions for avatars even if there are have been no collisions. This updates
+ // the simulator expects collisions for avatars even if there are have been no collisions. This updates
// avatar animations and stuff.
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
foreach (BSPhysObject bsp in m_avatars)
@@ -556,7 +560,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
}
// Objects that are done colliding are removed from the ObjectsWithCollisions list.
- // This can't be done by SendCollisions because it is inside an iteration of ObjectWithCollisions.
+ // Not done above because it is inside an iteration of ObjectWithCollisions.
if (ObjectsWithNoMoreCollisions.Count > 0)
{
foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
@@ -726,13 +730,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
{
- if (newType == Vehicle.TYPE_NONE)
+ RemoveVehiclePrim(vehic);
+ if (newType != Vehicle.TYPE_NONE)
{
- RemoveVehiclePrim(vehic);
- }
- else
- {
- // make it so the scene will call us each tick to do vehicle things
+ // make it so the scene will call us each tick to do vehicle things
AddVehiclePrim(vehic);
}
}
@@ -764,7 +765,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
}
// Some prims have extra vehicle actions
- // no locking because only called when physics engine is not busy
+ // Called at taint time!
private void ProcessVehicles(float timeStep)
{
foreach (BSPhysObject pobj in m_vehicles)
@@ -1008,12 +1009,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
- 0f, // zero to disable
+ 0f,
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
(s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
- 0f, // zero to disable
+ 0f,
(s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
(s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
@@ -1028,7 +1029,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
(s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
- ConfigurationParameters.numericFalse,
+ ConfigurationParameters.numericTrue,
(s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
(s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
(s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
@@ -1152,7 +1153,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
{
if (SettableParameters.Length < ParameterDefinitions.Length)
{
-
List entries = new List();
for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
{
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index dee6243b7a..399a133493 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSShapeCollection : IDisposable
{
- private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
+ // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
protected BSScene PhysicsScene { get; set; }
@@ -108,7 +108,8 @@ public class BSShapeCollection : IDisposable
// If we had to select a new shape geometry for the object,
// rebuild the body around it.
// Updates prim.BSBody with information/pointers to requested body
- bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback);
+ bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
+ prim.BSShape, shapeData, bodyCallback);
ret = newGeom || newBody;
}
DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
@@ -140,7 +141,7 @@ public class BSShapeCollection : IDisposable
bodyDesc.lastReferenced = System.DateTime.Now;
Bodies[body.ID] = bodyDesc;
}
-}
+ }
// Release the usage of a body.
// Called when releasing use of a BSBody. BSShape is handled separately.
@@ -167,7 +168,7 @@ public class BSShapeCollection : IDisposable
{
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}",
body.ID, body.ptr.ToString("X"));
- // If the caller needs to know, pass the event up.
+ // If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
// Zero any reference to the shape so it is not freed when the body is deleted.
@@ -448,7 +449,8 @@ public class BSShapeCollection : IDisposable
ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
// if this new shape is the same as last time, don't recreate the mesh
- if (prim.BSShape.shapeKey == newMeshKey) return false;
+ if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
+ return false;
DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 1125d7eb6a..a43880d337 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -71,7 +71,7 @@ public struct BulletBody
buff.Append(ID.ToString());
buff.Append(",p=");
buff.Append(ptr.ToString("X"));
- if (collisionFilter != 0 && collisionMask != 0)
+ if (collisionFilter != 0 || collisionMask != 0)
{
buff.Append(",f=");
buff.Append(collisionFilter.ToString("X"));
@@ -344,10 +344,7 @@ public enum CollisionFlags : uint
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
// Following used by BulletSim to control collisions
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
- // BS_VOLUME_DETECT_OBJECT = 1 << 11,
- // BS_PHANTOM_OBJECT = 1 << 12,
- // BS_PHYSICAL_OBJECT = 1 << 13,
- // BS_TERRAIN_OBJECT = 1 << 14,
+ BS_FLOATS_ON_WATER = 1 << 11,
BS_NONE = 0,
BS_ALL = 0xFFFFFFFF,
@@ -356,9 +353,6 @@ public enum CollisionFlags : uint
BS_ACTIVE = CF_STATIC_OBJECT
| CF_KINEMATIC_OBJECT
| CF_NO_CONTACT_RESPONSE
- // | BS_VOLUME_DETECT_OBJECT
- // | BS_PHANTOM_OBJECT
- // | BS_PHYSICAL_OBJECT,
};
// Values for collisions groups and masks
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 8b73cd9ae0..31be45021c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3538,7 +3538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
}
-
+
///
/// Sets the response type for an HTTP request/response
///
@@ -3549,6 +3549,91 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_UrlModule != null)
m_UrlModule.HttpContentType(new UUID(id),type);
}
-
- }
+ /// Shout an error if the object owner did not grant the script the specified permissions.
+ ///
+ ///
+ /// boolean indicating whether an error was shouted.
+ protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix)
+ {
+ CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
+ m_host.AddScriptLPS(1);
+ bool fail = false;
+ if (m_item.PermsGranter != m_host.OwnerID)
+ {
+ fail = true;
+ OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix));
+ }
+ else if ((m_item.PermsMask & perms) == 0)
+ {
+ fail = true;
+ OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix));
+ }
+
+ return fail;
+ }
+
+ protected void DropAttachment(bool checkPerms)
+ {
+ if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
+ {
+ return;
+ }
+
+ IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
+ ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
+
+ if (attachmentsModule != null && sp != null)
+ {
+ attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId);
+ }
+ }
+
+ protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot)
+ {
+ if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
+ {
+ return;
+ }
+
+ IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
+ ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
+
+ if (attachmentsModule != null && sp != null)
+ {
+ attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot);
+ }
+ }
+
+ public void osDropAttachment()
+ {
+ CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
+ m_host.AddScriptLPS(1);
+
+ DropAttachment(true);
+ }
+
+ public void osForceDropAttachment()
+ {
+ CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment");
+ m_host.AddScriptLPS(1);
+
+ DropAttachment(false);
+ }
+
+ public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
+ {
+ CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt");
+ m_host.AddScriptLPS(1);
+
+ DropAttachmentAt(true, pos, rot);
+ }
+
+ public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
+ {
+ CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt");
+ m_host.AddScriptLPS(1);
+
+ DropAttachmentAt(false, pos, rot);
+ }
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 3985e6629c..93188c9ec8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -394,5 +394,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
///
///
void osSetContentType(LSL_Key id, string type);
+
+ ///
+ /// Attempts to drop an attachment to the ground
+ ///
+ void osDropAttachment();
+
+ ///
+ /// Attempts to drop an attachment to the ground while bypassing the script permissions
+ ///
+ void osForceDropAttachment();
+
+ ///
+ /// Attempts to drop an attachment at the specified coordinates.
+ ///
+ ///
+ ///
+ void osDropAttachmentAt(vector pos, rotation rot);
+
+ ///
+ /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions
+ ///
+ ///
+ ///
+ void osForceDropAttachmentAt(vector pos, rotation rot);
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 52ca3da154..dee1b28cca 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -972,5 +972,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
m_OSSL_Functions.osSetContentType(id,type);
}
+
+ public void osDropAttachment()
+ {
+ m_OSSL_Functions.osDropAttachment();
+ }
+
+ public void osForceDropAttachment()
+ {
+ m_OSSL_Functions.osForceDropAttachment();
+ }
+
+ public void osDropAttachmentAt(vector pos, rotation rot)
+ {
+ m_OSSL_Functions.osDropAttachmentAt(pos, rot);
+ }
+
+ public void osForceDropAttachmentAt(vector pos, rotation rot)
+ {
+ m_OSSL_Functions.osForceDropAttachmentAt(pos, rot);
+ }
}
}
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 495dc5297c..59fb55981b 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -293,7 +293,7 @@ namespace OpenSim.Services.LLLoginService
{
m_log.InfoFormat(
"[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}",
- firstName, lastName, m_MinLoginLevel, account.UserLevel);
+ firstName, lastName, account.UserLevel, m_MinLoginLevel);
return LLFailedLoginResponse.LoginBlockedProblem;
}