Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

integration
Diva Canto 2012-11-07 20:05:30 -08:00
commit a407eb287f
18 changed files with 684 additions and 117 deletions

View File

@ -219,6 +219,8 @@ namespace OpenSim.Data.MySQL
public virtual bool Store(T row) public virtual bool Store(T row)
{ {
// m_log.DebugFormat("[MYSQL GENERIC TABLE HANDLER]: Store(T row) invoked");
using (MySqlCommand cmd = new MySqlCommand()) using (MySqlCommand cmd = new MySqlCommand())
{ {
string query = ""; string query = "";
@ -273,6 +275,10 @@ namespace OpenSim.Data.MySQL
public virtual bool Delete(string[] fields, string[] keys) public virtual bool Delete(string[] fields, string[] keys)
{ {
// m_log.DebugFormat(
// "[MYSQL GENERIC TABLE HANDLER]: Delete(string[] fields, string[] keys) invoked with {0}:{1}",
// string.Join(",", fields), string.Join(",", keys));
if (fields.Length != keys.Length) if (fields.Length != keys.Length)
return false; return false;

View File

@ -26,9 +26,10 @@
*/ */
using System; using System;
using System.Data;
using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using log4net; using log4net;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using OpenMetaverse; using OpenMetaverse;
@ -118,22 +119,69 @@ namespace OpenSim.Data.MySQL
public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem> public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem>
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public MySqlItemHandler(string c, string t, string m) : public MySqlItemHandler(string c, string t, string m) :
base(c, t, m) base(c, t, m)
{ {
} }
public override bool Delete(string field, string val)
{
XInventoryItem[] retrievedItems = Get(new string[] { field }, new string[] { val });
if (retrievedItems.Length == 0)
return false;
if (!base.Delete(field, val))
return false;
// Don't increment folder version here since Delete(string, string) calls Delete(string[], string[])
// IncrementFolderVersion(retrievedItems[0].parentFolderID);
return true;
}
public override bool Delete(string[] fields, string[] vals)
{
XInventoryItem[] retrievedItems = Get(fields, vals);
if (retrievedItems.Length == 0)
return false;
if (!base.Delete(fields, vals))
return false;
HashSet<UUID> deletedItemFolderUUIDs = new HashSet<UUID>();
Array.ForEach<XInventoryItem>(retrievedItems, i => deletedItemFolderUUIDs.Add(i.parentFolderID));
foreach (UUID deletedItemFolderUUID in deletedItemFolderUUIDs)
IncrementFolderVersion(deletedItemFolderUUID);
return true;
}
public bool MoveItem(string id, string newParent) public bool MoveItem(string id, string newParent)
{ {
XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
if (retrievedItems.Length == 0)
return false;
UUID oldParent = retrievedItems[0].parentFolderID;
using (MySqlCommand cmd = new MySqlCommand()) using (MySqlCommand cmd = new MySqlCommand())
{ {
cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm); cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm);
cmd.Parameters.AddWithValue("?ParentFolderID", newParent); cmd.Parameters.AddWithValue("?ParentFolderID", newParent);
cmd.Parameters.AddWithValue("?InventoryID", id); cmd.Parameters.AddWithValue("?InventoryID", id);
return ExecuteNonQuery(cmd) == 0 ? false : true; if (ExecuteNonQuery(cmd) == 0)
return false;
} }
IncrementFolderVersion(oldParent);
IncrementFolderVersion(newParent);
return true;
} }
public XInventoryItem[] GetActiveGestures(UUID principalID) public XInventoryItem[] GetActiveGestures(UUID principalID)
@ -184,6 +232,21 @@ namespace OpenSim.Data.MySQL
if (!base.Store(item)) if (!base.Store(item))
return false; return false;
IncrementFolderVersion(item.parentFolderID);
return true;
}
private bool IncrementFolderVersion(UUID folderID)
{
return IncrementFolderVersion(folderID.ToString());
}
private bool IncrementFolderVersion(string folderID)
{
// m_log.DebugFormat("[MYSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
// Util.PrintCallStack();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
dbcon.Open(); dbcon.Open();
@ -193,7 +256,7 @@ namespace OpenSim.Data.MySQL
cmd.Connection = dbcon; cmd.Connection = dbcon;
cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID"); cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID");
cmd.Parameters.AddWithValue("?folderID", item.parentFolderID.ToString()); cmd.Parameters.AddWithValue("?folderID", folderID);
try try
{ {
@ -205,9 +268,11 @@ namespace OpenSim.Data.MySQL
} }
cmd.Dispose(); cmd.Dispose();
} }
dbcon.Close(); dbcon.Close();
} }
return true; return true;
} }
} }
} }

View File

@ -121,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (sp != null || agentID == kickUserID) if (sp != null || agentID == kickUserID)
{ {
m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
if (m_scene.Permissions.IsGod(godID)) if (m_scene.Permissions.IsGod(godID))
{ {
if (kickflags == 0) if (kickflags == 0)
@ -162,20 +163,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
if (kickflags == 1) if (kickflags == 1)
{ {
sp.AllowMovement = false; sp.AllowMovement = false;
m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); if (m_dialogModule != null)
m_dialogModule.SendAlertToUser(godID, "User Frozen"); {
m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
m_dialogModule.SendAlertToUser(godID, "User Frozen");
}
} }
if (kickflags == 2) if (kickflags == 2)
{ {
sp.AllowMovement = true; sp.AllowMovement = true;
m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason)); if (m_dialogModule != null)
m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); {
m_dialogModule.SendAlertToUser(agentID, Utils.BytesToString(reason));
m_dialogModule.SendAlertToUser(godID, "User Unfrozen");
}
} }
} }
else else
{ {
m_dialogModule.SendAlertToUser(godID, "Kick request denied"); if (m_dialogModule != null)
m_dialogModule.SendAlertToUser(godID, "Kick request denied");
} }
} }
} }

View File

@ -103,7 +103,7 @@ public sealed class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.create", delegate() PhysicsScene.TaintedObject("BSCharacter.create", delegate()
{ {
DetailLog("{0},BSCharacter.create,taint", LocalID); DetailLog("{0},BSCharacter.create,taint", LocalID);
// New body and shape into BSBody and BSShape // New body and shape into PhysBody and PhysShape
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null);
SetPhysicalProperties(); SetPhysicalProperties();
@ -126,7 +126,7 @@ public sealed class BSCharacter : BSPhysObject
{ {
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
ZeroMotion(); ZeroMotion(true);
ForcePosition = _position; ForcePosition = _position;
// Set the velocity and compute the proper friction // Set the velocity and compute the proper friction
ForceVelocity = _velocity; ForceVelocity = _velocity;
@ -218,18 +218,31 @@ public sealed class BSCharacter : BSPhysObject
// Do it to the properties so the values get set in the physics engine. // Do it to the properties so the values get set in the physics engine.
// Push the setting of the values to the viewer. // Push the setting of the values to the viewer.
// Called at taint time! // Called at taint time!
public override void ZeroMotion() public override void ZeroMotion(bool inTaintTime)
{ {
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_acceleration = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties directly into the physics engine // Zero some other properties directly into the physics engine
BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); {
BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); BulletSimAPI.ClearAllForces2(PhysBody.ptr);
BulletSimAPI.ClearForces2(PhysBody.ptr); });
} }
public override void ZeroAngularMotion(bool inTaintTime)
{
_rotationalVelocity = OMV.Vector3.Zero;
PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
{
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
// The next also get rid of applied linear force but the linear velocity is untouched.
BulletSimAPI.ClearForces2(PhysBody.ptr);
});
}
public override void LockAngularMotion(OMV.Vector3 axis) { return; } public override void LockAngularMotion(OMV.Vector3 axis) { return; }

View File

@ -54,10 +54,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public sealed class BSDynamics public sealed class BSDynamics
{ {
private static string LogHeader = "[BULLETSIM VEHICLE]";
private BSScene PhysicsScene { get; set; } private BSScene PhysicsScene { get; set; }
// the prim this dynamic controller belongs to // the prim this dynamic controller belongs to
private BSPrim Prim { get; set; } private BSPrim Prim { get; set; }
// mass of the vehicle fetched each time we're calles
private float m_vehicleMass;
// Vehicle properties // Vehicle properties
public Vehicle Type { get; set; } public Vehicle Type { get; set; }
@ -516,9 +521,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Friction effects are handled by this vehicle code // Friction effects are handled by this vehicle code
BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
// BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f);
VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID);
} }
} }
public bool RemoveBodyDependencies(BSPhysObject prim)
{
// If active, we need to add our properties back when the body is rebuilt.
return IsActive;
}
public void RestoreBodyDependencies(BSPhysObject prim)
{
if (Prim.LocalID != prim.LocalID)
{
// The call should be on us by our prim. Error if not.
PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}",
LogHeader, prim.LocalID, Prim.LocalID);
return;
}
Refresh();
}
// One step of the vehicle properties for the next 'pTimestep' seconds. // One step of the vehicle properties for the next 'pTimestep' seconds.
internal void Step(float pTimestep) internal void Step(float pTimestep)
{ {
@ -533,16 +560,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
// END DEBUG // END DEBUG
MoveLinear(pTimestep); m_vehicleMass = Prim.Linkset.LinksetMass;
MoveAngular(pTimestep);
LimitRotation(pTimestep);
// DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. MoveLinear(pTimestep);
// BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG // Commented out for debug
MoveAngular(pTimestep);
// Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG
// Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG
LimitRotation(pTimestep);
// remember the position so next step we can limit absolute movement effects // remember the position so next step we can limit absolute movement effects
m_lastPositionVector = Prim.ForcePosition; m_lastPositionVector = Prim.ForcePosition;
VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG
Prim.LocalID,
BulletSimAPI.GetFriction2(Prim.PhysBody.ptr),
BulletSimAPI.GetGravity2(Prim.PhysBody.ptr),
Prim.Inertia,
m_vehicleMass
);
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
}// end Step }// end Step
@ -555,25 +592,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_lastLinearVelocityVector is the current speed we are moving in that direction // m_lastLinearVelocityVector is the current speed we are moving in that direction
if (m_linearMotorDirection.LengthSquared() > 0.001f) if (m_linearMotorDirection.LengthSquared() > 0.001f)
{ {
Vector3 origDir = m_linearMotorDirection; Vector3 origDir = m_linearMotorDirection; // DEBUG
Vector3 origVel = m_lastLinearVelocityVector; Vector3 origVel = m_lastLinearVelocityVector; // DEBUG
// DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison
Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
// add drive to body // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete
Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep;
// lastLinearVelocityVector is the current body velocity vector
m_lastLinearVelocityVector += addAmount; m_lastLinearVelocityVector += addAmount;
float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep;
m_linearMotorDirection *= (1f - decayFactor); m_linearMotorDirection *= (1f - decayFactor);
Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
// Rotate new object velocity from vehicle relative to world coordinates // Rotate new object velocity from vehicle relative to world coordinates
m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation;
VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", // Apply friction for next time
Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}",
Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor,
m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity);
} }
@ -607,7 +645,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// If below the terrain, move us above the ground a little. // If below the terrain, move us above the ground a little.
float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 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. // 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. // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
// Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
// if (rotatedSize.Z < terrainHeight) // if (rotatedSize.Z < terrainHeight)
if (pos.Z < terrainHeight) if (pos.Z < terrainHeight)
@ -638,13 +676,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
{ {
// If body is aready heigher, use its height as target height // If body is already heigher, use its height as target height
if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; if (pos.Z > m_VhoverTargetHeight)
m_VhoverTargetHeight = pos.Z;
} }
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
{ {
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f)
{ {
pos.Z = m_VhoverTargetHeight;
Prim.ForcePosition = pos; Prim.ForcePosition = pos;
} }
} }
@ -709,25 +749,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
} }
// Limit absolute vertical change #region downForce
float Zchange = Math.Abs(posChange.Z); Vector3 downForce = Vector3.Zero;
if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
{ {
if (Zchange > .3) // If the vehicle is motoring into the sky, get it going back down.
grav.Z = (float)(grav.Z * 3); // Is this an angular force or both linear and angular??
if (Zchange > .15) float distanceAboveGround = pos.Z - terrainHeight;
grav.Z = (float)(grav.Z * 2); if (distanceAboveGround > 2f)
if (Zchange > .75) {
grav.Z = (float)(grav.Z * 1.5); // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
if (Zchange > .05) // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
grav.Z = (float)(grav.Z * 1.25); downForce = new Vector3(0, 0, -distanceAboveGround);
if (Zchange > .025) }
grav.Z = (float)(grav.Z * 1.125); // TODO: this calculation is all wrong. From the description at
float postemp = (pos.Z - terrainHeight); // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
if (postemp > 2.5f) // has a decay factor. This says this force should
grav.Z = (float)(grav.Z * 1.037125); // be computed with a motor.
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
Prim.LocalID, distanceAboveGround, downForce);
} }
#endregion // downForce
// If not changing some axis, reduce out velocity // If not changing some axis, reduce out velocity
if ((m_flags & (VehicleFlag.NO_X)) != 0) if ((m_flags & (VehicleFlag.NO_X)) != 0)
@ -737,13 +780,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if ((m_flags & (VehicleFlag.NO_Z)) != 0) if ((m_flags & (VehicleFlag.NO_Z)) != 0)
m_newVelocity.Z = 0; m_newVelocity.Z = 0;
// Apply velocity // Clamp REALLY high or low velocities
Prim.ForceVelocity = m_newVelocity; if (m_newVelocity.LengthSquared() > 1e6f)
// Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); {
Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); m_newVelocity /= m_newVelocity.Length();
m_newVelocity *= 1000f;
}
else if (m_newVelocity.LengthSquared() < 1e-6f)
m_newVelocity = Vector3.Zero;
VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", // Stuff new linear velocity into the vehicle
Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); Prim.ForceVelocity = m_newVelocity;
// Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
Vector3 totalDownForce = downForce + grav;
if (totalDownForce != Vector3.Zero)
{
Prim.AddForce(totalDownForce * m_vehicleMass, false);
// Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false);
}
VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce);
} // end MoveLinear() } // end MoveLinear()
@ -765,7 +823,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 origDir = m_angularMotorDirection; Vector3 origDir = m_angularMotorDirection;
// new velocity += error / ( time to get there / step interval) // new velocity += error / ( time to get there / step interval)
// requested speed - last motor speed // requested direction - current vehicle direction
m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
// decay requested direction // decay requested direction
m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
@ -784,10 +842,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 deflection = Vector3.Zero; Vector3 deflection = Vector3.Zero;
Vector3 banking = Vector3.Zero; Vector3 banking = Vector3.Zero;
// If vertical attaction timescale is reasonable and we applied an angular force last time...
if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
{ {
float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale;
if (Prim.Linkset.LinksetIsColliding) if (Prim.IsColliding)
VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale);
VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
@ -806,7 +865,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
verticalError.X = 2.0f - verticalError.X; verticalError.X = 2.0f - verticalError.X;
verticalError.Y = 2.0f - verticalError.Y; verticalError.Y = 2.0f - verticalError.Y;
} }
// scale it by VAservo // scale it by VAservo (timestep and timescale)
verticalError = verticalError * VAservo; verticalError = verticalError * VAservo;
// As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y
@ -822,25 +881,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
vertattr.X += bounce * angularVelocity.X; vertattr.X += bounce * angularVelocity.X;
vertattr.Y += bounce * angularVelocity.Y; vertattr.Y += bounce * angularVelocity.Y;
VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}",
Prim.LocalID, verticalError, bounce, vertattr); Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr);
} }
#endregion // Vertical attactor #endregion // Vertical attactor
#region Deflection #region Deflection
//Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well
if (m_angularDeflectionEfficiency != 0) if (m_angularDeflectionEfficiency != 0)
{ {
Vector3 preferredAxisOfMotion = // Compute a scaled vector that points in the preferred axis (X direction)
Vector3 scaledDefaultDirection =
new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); // Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
// Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
// Scale by efficiency and timescale
deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
Prim.LocalID, preferredAxisOfMotion, deflection); Prim.LocalID, preferredAxisOfMotion, deflection);
// This deflection computation is not correct.
deflection = Vector3.Zero;
} }
#endregion #endregion
@ -875,7 +939,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
else else
banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4;
if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
//If they are colliding, we probably shouldn't shove the prim around... probably //If they are colliding, we probably shouldn't shove the prim around... probably
{ {
float angVelZ = m_angularMotorVelocity.X*-1; float angVelZ = m_angularMotorVelocity.X*-1;
@ -904,6 +968,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Sum velocities // Sum velocities
m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection;
#region Linear Motor Offset
//Offset section
if (m_linearMotorOffset != Vector3.Zero)
{
//Offset of linear velocity doesn't change the linear velocity,
// but causes a torque to be applied, for example...
//
// IIIII >>> IIIII
// IIIII >>> IIIII
// IIIII >>> IIIII
// ^
// | Applying a force at the arrow will cause the object to move forward, but also rotate
//
//
// The torque created is the linear velocity crossed with the offset
// NOTE: this computation does should be in the linear section
// because there we know the impulse being applied.
Vector3 torqueFromOffset = Vector3.Zero;
// torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
if (float.IsNaN(torqueFromOffset.X))
torqueFromOffset.X = 0;
if (float.IsNaN(torqueFromOffset.Y))
torqueFromOffset.Y = 0;
if (float.IsNaN(torqueFromOffset.Z))
torqueFromOffset.Z = 0;
torqueFromOffset *= m_vehicleMass;
Prim.ApplyTorqueImpulse(torqueFromOffset, true);
VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
}
#endregion
if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
{ {
m_lastAngularVelocity.X = 0; m_lastAngularVelocity.X = 0;
@ -914,25 +1012,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
{ {
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); Prim.ZeroAngularMotion(true);
VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
} }
else
{
// Apply to the body.
// The above calculates the absolute angular velocity needed. Angular velocity is massless.
// Since we are stuffing the angular velocity directly into the object, the computed
// velocity needs to be scaled by the timestep.
Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity);
Prim.ForceRotationalVelocity = applyAngularForce;
// Apply to the body // Decay the angular movement for next time
// The above calculates the absolute angular velocity needed Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep;
// Prim.ForceRotationalVelocity = m_lastAngularVelocity; m_lastAngularVelocity *= Vector3.One - decayamount;
// Apply a force to overcome current angular velocity VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}",
Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
// Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); }
// Prim.AddAngularForce(applyAngularForce, false);
Prim.ApplyTorqueImpulse(applyAngularForce, false);
// Apply friction for next time
Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep;
m_lastAngularVelocity *= Vector3.One - decayamount;
VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}",
Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
} //end MoveAngular } //end MoveAngular
internal void LimitRotation(float timestep) internal void LimitRotation(float timestep)

View File

@ -49,6 +49,9 @@ public abstract class BSLinkset
switch ((int)physScene.Params.linksetImplementation) switch ((int)physScene.Params.linksetImplementation)
{ {
case (int)LinksetImplementation.Constraint:
ret = new BSLinksetConstraints(physScene, parent);
break;
case (int)LinksetImplementation.Compound: case (int)LinksetImplementation.Compound:
ret = new BSLinksetCompound(physScene, parent); ret = new BSLinksetCompound(physScene, parent);
break; break;
@ -56,7 +59,7 @@ public abstract class BSLinkset
// ret = new BSLinksetManual(physScene, parent); // ret = new BSLinksetManual(physScene, parent);
break; break;
default: default:
ret = new BSLinksetConstraints(physScene, parent); ret = new BSLinksetCompound(physScene, parent);
break; break;
} }
return ret; return ret;
@ -97,7 +100,6 @@ public abstract class BSLinkset
{ {
get get
{ {
m_mass = ComputeLinksetMass();
return m_mass; return m_mass;
} }
} }
@ -138,6 +140,7 @@ public abstract class BSLinkset
// Don't add the root to its own linkset // Don't add the root to its own linkset
if (!IsRoot(child)) if (!IsRoot(child))
AddChildToLinkset(child); AddChildToLinkset(child);
m_mass = ComputeLinksetMass();
} }
return this; return this;
} }
@ -156,6 +159,7 @@ public abstract class BSLinkset
return this; return this;
} }
RemoveChildFromLinkset(child); RemoveChildFromLinkset(child);
m_mass = ComputeLinksetMass();
} }
// The child is down to a linkset of just itself // The child is down to a linkset of just itself

View File

@ -264,6 +264,8 @@ public sealed class BSLinksetCompound : BSLinkset
float linksetMass = LinksetMass; float linksetMass = LinksetMass;
LinksetRoot.UpdatePhysicalMassProperties(linksetMass); LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
// DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets.
// BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
// (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);

View File

@ -184,7 +184,7 @@ public sealed class BSLinksetConstraints : BSLinkset
private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
{ {
// Zero motion for children so they don't interpolate // Zero motion for children so they don't interpolate
childPrim.ZeroMotion(); childPrim.ZeroMotion(true);
// Relative position normalized to the root prim // Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of childPrim // Essentually a vector pointing from center of rootPrim to center of childPrim

View File

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public abstract class BSMotor
{
public virtual void Reset() { }
public virtual void Zero() { }
}
// Can all the incremental stepping be replaced with motor classes?
public class BSVMotor : BSMotor
{
public Vector3 FrameOfReference { get; set; }
public Vector3 Offset { get; set; }
public float TimeScale { get; set; }
public float TargetValueDecayTimeScale { get; set; }
public Vector3 CurrentValueReductionTimescale { get; set; }
public float Efficiency { get; set; }
public Vector3 TargetValue { get; private set; }
public Vector3 CurrentValue { get; private set; }
BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
{
TimeScale = timeScale;
TargetValueDecayTimeScale = decayTimeScale;
CurrentValueReductionTimescale = frictionTimeScale;
Efficiency = efficiency;
}
public void SetCurrent(Vector3 current)
{
CurrentValue = current;
}
public void SetTarget(Vector3 target)
{
TargetValue = target;
}
public Vector3 Step(float timeStep)
{
if (CurrentValue.LengthSquared() > 0.001f)
{
// Vector3 origDir = Target; // DEBUG
// Vector3 origVel = CurrentValue; // DEBUG
// Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete
Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep;
CurrentValue += addAmount;
float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
TargetValue *= (1f - decayFactor);
Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep;
CurrentValue *= (Vector3.One - frictionFactor);
}
else
{
// if what remains of direction is very small, zero it.
TargetValue = Vector3.Zero;
CurrentValue = Vector3.Zero;
// VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
}
return CurrentValue;
}
}
public class BSFMotor : BSMotor
{
public float TimeScale { get; set; }
public float DecayTimeScale { get; set; }
public float Friction { get; set; }
public float Efficiency { get; set; }
public float Target { get; private set; }
public float CurrentValue { get; private set; }
BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency)
{
}
public void SetCurrent(float target)
{
}
public void SetTarget(float target)
{
}
public float Step(float timeStep)
{
return 0f;
}
}
public class BSPIDMotor : BSMotor
{
// TODO: write and use this one
BSPIDMotor()
{
}
}
}

View File

@ -34,9 +34,17 @@ using OpenSim.Region.Physics.Manager;
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
// Class to wrap all objects. /*
// The rest of BulletSim doesn't need to keep checking for avatars or prims * Class to wrap all objects.
// unless the difference is significant. * The rest of BulletSim doesn't need to keep checking for avatars or prims
* unless the difference is significant.
*
* Variables in the physicsl objects are in three forms:
* VariableName: used by the simulator and performs taint operations, etc
* RawVariableName: direct reference to the BulletSim storage for the variable value
* ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
* The last two (and certainly the last one) should be referenced only in taint-time.
*/
public abstract class BSPhysObject : PhysicsActor public abstract class BSPhysObject : PhysicsActor
{ {
protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName)
@ -67,6 +75,9 @@ public abstract class BSPhysObject : PhysicsActor
// Set the raw mass but also update physical mass properties (inertia, ...) // Set the raw mass but also update physical mass properties (inertia, ...)
public abstract void UpdatePhysicalMassProperties(float mass); public abstract void UpdatePhysicalMassProperties(float mass);
// The last value calculated for the prim's inertia
public OMV.Vector3 Inertia { get; set; }
// Reference to the physical body (btCollisionObject) of this object // Reference to the physical body (btCollisionObject) of this object
public BulletBody PhysBody; public BulletBody PhysBody;
// Reference to the physical shape (btCollisionShape) of this object // Reference to the physical shape (btCollisionShape) of this object
@ -96,7 +107,8 @@ public abstract class BSPhysObject : PhysicsActor
public abstract bool IsStatic { get; } public abstract bool IsStatic { get; }
// Stop all physical motion. // Stop all physical motion.
public abstract void ZeroMotion(); public abstract void ZeroMotion(bool inTaintTime);
public abstract void ZeroAngularMotion(bool inTaintTime);
// Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
public virtual void StepVehicle(float timeStep) { } public virtual void StepVehicle(float timeStep) { }

View File

@ -25,8 +25,6 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
// Uncomment this it enable code to do all shape an body memory management
// in the C# code.
using System; using System;
using System.Reflection; using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
@ -236,14 +234,27 @@ public sealed class BSPrim : BSPhysObject
// Do it to the properties so the values get set in the physics engine. // Do it to the properties so the values get set in the physics engine.
// Push the setting of the values to the viewer. // Push the setting of the values to the viewer.
// Called at taint time! // Called at taint time!
public override void ZeroMotion() public override void ZeroMotion(bool inTaintTime)
{ {
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_acceleration = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties in the physics engine // Zero some other properties in the physics engine
BulletSimAPI.ClearAllForces2(PhysBody.ptr); PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
{
BulletSimAPI.ClearAllForces2(PhysBody.ptr);
});
}
public override void ZeroAngularMotion(bool inTaintTime)
{
_rotationalVelocity = OMV.Vector3.Zero;
// Zero some other properties in the physics engine
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
{
BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
});
} }
public override void LockAngularMotion(OMV.Vector3 axis) public override void LockAngularMotion(OMV.Vector3 axis)
@ -371,17 +382,18 @@ public sealed class BSPrim : BSPhysObject
{ {
if (IsStatic) if (IsStatic)
{ {
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); Inertia = OMV.Vector3.Zero;
BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
} }
else else
{ {
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
// center of mass is at the zero of the object // center of mass is at the zero of the object
BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
// BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia);
} }
} }
@ -582,7 +594,7 @@ public sealed class BSPrim : BSPhysObject
// DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
SetObjectDynamic(true); SetObjectDynamic(true);
// whether phys-to-static or static-to-phys, the object is not moving. // whether phys-to-static or static-to-phys, the object is not moving.
ZeroMotion(); ZeroMotion(true);
}); });
} }
} }
@ -648,6 +660,7 @@ public sealed class BSPrim : BSPhysObject
// Recompute any linkset parameters. // Recompute any linkset parameters.
// When going from non-physical to physical, this re-enables the constraints that // When going from non-physical to physical, this re-enables the constraints that
// had been automatically disabled when the mass was set to zero. // had been automatically disabled when the mass was set to zero.
// For compound based linksets, this enables and disables interactions of the children.
Linkset.Refresh(this); Linkset.Refresh(this);
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
@ -666,9 +679,9 @@ public sealed class BSPrim : BSPhysObject
// Become a Bullet 'static' object type // Become a Bullet 'static' object type
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
// Stop all movement // Stop all movement
ZeroMotion(); ZeroMotion(true);
// Center of mass is at the center of the object // Center of mass is at the center of the object
BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
// Mass is zero which disables a bunch of physics stuff in Bullet // Mass is zero which disables a bunch of physics stuff in Bullet
UpdatePhysicalMassProperties(0f); UpdatePhysicalMassProperties(0f);
// Set collision detection parameters // Set collision detection parameters
@ -704,7 +717,7 @@ public sealed class BSPrim : BSPhysObject
BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
// Center of mass is at the center of the object // Center of mass is at the center of the object
BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
// A dynamic object has mass // A dynamic object has mass
UpdatePhysicalMassProperties(RawMass); UpdatePhysicalMassProperties(RawMass);
@ -958,6 +971,16 @@ public sealed class BSPrim : BSPhysObject
}); });
} }
public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
{
OMV.Vector3 applyImpulse = impulse;
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
{
DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
});
}
private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
AddAngularForce(force, pushforce, false); AddAngularForce(force, pushforce, false);
@ -1001,7 +1024,6 @@ public sealed class BSPrim : BSPhysObject
OMV.Vector3 applyImpulse = impulse; OMV.Vector3 applyImpulse = impulse;
PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
{ {
DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
}); });
} }
@ -1315,9 +1337,10 @@ public sealed class BSPrim : BSPhysObject
// If this prim is part of a linkset, we must remove and restore the physical // If this prim is part of a linkset, we must remove and restore the physical
// links if the body is rebuilt. // links if the body is rebuilt.
bool needToRestoreLinkset = false; bool needToRestoreLinkset = false;
bool needToRestoreVehicle = false;
// Create the correct physical representation for this type of object. // Create the correct physical representation for this type of object.
// Updates BSBody and BSShape with the new information. // Updates PhysBody and PhysShape with the new information.
// Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
// Returns 'true' if either the body or the shape was changed. // Returns 'true' if either the body or the shape was changed.
PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
@ -1326,6 +1349,7 @@ public sealed class BSPrim : BSPhysObject
// Remove all the physical dependencies on the old body. // Remove all the physical dependencies on the old body.
// (Maybe someday make the changing of BSShape an event handled by BSLinkset.) // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this);
}); });
if (needToRestoreLinkset) if (needToRestoreLinkset)
@ -1333,6 +1357,11 @@ public sealed class BSPrim : BSPhysObject
// If physical body dependencies were removed, restore them // If physical body dependencies were removed, restore them
Linkset.RestoreBodyDependencies(this); Linkset.RestoreBodyDependencies(this);
} }
if (needToRestoreVehicle)
{
// If physical body dependencies were removed, restore them
_vehicle.RestoreBodyDependencies(this);
}
// Make sure the properties are set on the new object // Make sure the properties are set on the new object
UpdatePhysicalParameters(); UpdatePhysicalParameters();

View File

@ -491,7 +491,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Some of the prims operate with special vehicle properties // Some of the prims operate with special vehicle properties
ProcessVehicles(timeStep); ProcessVehicles(timeStep);
numTaints += _taintOperations.Count;
ProcessTaints(); // the vehicles might have added taints ProcessTaints(); // the vehicles might have added taints
// step the physical world one interval // step the physical world one interval
@ -500,7 +499,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
try try
{ {
// DumpVehicles(); // DEBUG if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@ -509,7 +508,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
// DumpVehicles(); // DEBUG if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
} }
catch (Exception e) catch (Exception e)
{ {
@ -521,7 +520,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
collidersCount = 0; collidersCount = 0;
} }
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
// Get a value for 'now' so all the collision and update routines don't have to get their own // Get a value for 'now' so all the collision and update routines don't have to get their own
@ -724,6 +722,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
{ {
/*
// Code to limit the number of taints processed per step. Meant to limit step time.
// Unsure if a good idea as code assumes that taints are done before the step.
int taintCount = m_taintsToProcessPerStep; int taintCount = m_taintsToProcessPerStep;
TaintCallbackEntry oneCallback = new TaintCallbackEntry(); TaintCallbackEntry oneCallback = new TaintCallbackEntry();
while (_taintOperations.Count > 0 && taintCount-- > 0) while (_taintOperations.Count > 0 && taintCount-- > 0)
@ -752,13 +753,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
} }
} }
} }
/* if (_taintOperations.Count > 0)
{
DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
}
*/
// swizzle a new list into the list location so we can process what's there // swizzle a new list into the list location so we can process what's there
List<TaintCallbackEntry> oldList; List<TaintCallbackEntry> oldList;
lock (_taintLock) lock (_taintLock)
{ {
oldList = _taintedObjects; oldList = _taintOperations;
_taintedObjects = new List<TaintCallbackEntry>(); _taintOperations = new List<TaintCallbackEntry>();
} }
foreach (TaintCallbackEntry tcbe in oldList) foreach (TaintCallbackEntry tcbe in oldList)
@ -774,7 +779,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
} }
} }
oldList.Clear(); oldList.Clear();
*/
} }
} }
@ -1043,7 +1047,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return (float)s.m_maxUpdatesPerFrame; }, (s) => { return (float)s.m_maxUpdatesPerFrame; },
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
100f, 500f,
(s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_taintsToProcessPerStep; }, (s) => { return (float)s.m_taintsToProcessPerStep; },
(s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
@ -1097,13 +1101,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].linearDamping; }, (s) => { return s.m_params[0].linearDamping; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
(s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ),
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
0f, 0f,
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].angularDamping; }, (s) => { return s.m_params[0].angularDamping; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
(s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ),
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
0.2f, 0.2f,
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
@ -1473,7 +1477,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
PhysicsLogging.Write(msg, args); PhysicsLogging.Write(msg, args);
// Add the Flush() if debugging crashes. Gets all the messages written out. // Add the Flush() if debugging crashes. Gets all the messages written out.
PhysicsLogging.Flush(); // PhysicsLogging.Flush();
} }
// Used to fill in the LocalID when there isn't one. It's the correct number of characters. // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
public const string DetailLogZero = "0000000000"; public const string DetailLogZero = "0000000000";

View File

@ -0,0 +1,213 @@
/*
* 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 copyrightD
* 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.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenSim.Region.Physics.BulletSPlugin
{
public abstract class BSShape
{
public IntPtr ptr { get; set; }
public ShapeData.PhysicsShapeType type { get; set; }
public System.UInt64 key { get; set; }
public int referenceCount { get; set; }
public DateTime lastReferenced { get; set; }
protected void Initialize()
{
ptr = IntPtr.Zero;
type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
key = 0;
referenceCount = 0;
lastReferenced = DateTime.Now;
}
// Get a reference to a physical shape. Create if it doesn't exist
public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
BSShape ret = null;
if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
{
// an avatar capsule is close to a native shape (it is not shared)
ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR,
ShapeData.FixedShapeKey.KEY_CAPSULE);
physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
}
// Compound shapes are handled special as they are rebuilt from scratch.
// This isn't too great a hardship since most of the child shapes will already been created.
if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND)
{
// Getting a reference to a compound shape gets you the compound shape with the root prim shape added
ret = BSShapeCompound.GetReference(prim);
physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
}
if (ret == null)
ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
return ret;
}
public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
return null;
}
public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
return null;
}
// Release the use of a physical shape.
public abstract void Dereference(BSScene physicsScene);
// All shapes have a static call to get a reference to the physical shape
// protected abstract static BSShape GetReference();
public override string ToString()
{
StringBuilder buff = new StringBuilder();
buff.Append("<p=");
buff.Append(ptr.ToString("X"));
buff.Append(",s=");
buff.Append(type.ToString());
buff.Append(",k=");
buff.Append(key.ToString("X"));
buff.Append(",c=");
buff.Append(referenceCount.ToString());
buff.Append(">");
return buff.ToString();
}
}
public class BSShapeNull : BSShape
{
public BSShapeNull()
{
base.Initialize();
}
public static BSShape GetReference() { return new BSShapeNull(); }
public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
}
public class BSShapeNative : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
public BSShapeNative()
{
base.Initialize();
}
public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey)
{
// Native shapes are not shared and are always built anew.
return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
}
private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey)
{
ShapeData nativeShapeData = new ShapeData();
nativeShapeData.Type = shapeType;
nativeShapeData.ID = prim.LocalID;
nativeShapeData.Scale = prim.Scale;
nativeShapeData.Size = prim.Scale;
nativeShapeData.MeshKey = (ulong)shapeKey;
nativeShapeData.HullKey = (ulong)shapeKey;
if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
{
ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale);
physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
}
else
{
ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData);
}
if (ptr == IntPtr.Zero)
{
physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
LogHeader, prim.LocalID, shapeType);
}
type = shapeType;
key = (UInt64)shapeKey;
}
// Make this reference to the physical shape go away since native shapes are not shared.
public override void Dereference(BSScene physicsScene)
{
// Native shapes are not tracked and are released immediately
physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr);
ptr = IntPtr.Zero;
// Garbage collection will free up this instance.
}
}
public class BSShapeMesh : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE MESH]";
private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
public BSShapeMesh()
{
base.Initialize();
}
public static BSShape GetReference() { return new BSShapeNull(); }
public override void Dereference(BSScene physicsScene) { }
}
public class BSShapeHull : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE HULL]";
private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
public BSShapeHull()
{
base.Initialize();
}
public static BSShape GetReference() { return new BSShapeNull(); }
public override void Dereference(BSScene physicsScene) { }
}
public class BSShapeCompound : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
public BSShapeCompound()
{
base.Initialize();
}
public static BSShape GetReference(BSPhysObject prim)
{
return new BSShapeNull();
}
public override void Dereference(BSScene physicsScene) { }
}
}

View File

@ -631,6 +631,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
@ -918,6 +921,12 @@ public static extern Vector3 GetGravity2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetLinearDamping2(IntPtr obj, float lin_damping);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetAngularDamping2(IntPtr obj, float ang_damping);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern float GetLinearDamping2(IntPtr obj); public static extern float GetLinearDamping2(IntPtr obj);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.