Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
avinationmerge
Melanie 2013-01-31 02:53:11 +00:00
commit 9a4de546fe
28 changed files with 1008 additions and 166 deletions

View File

@ -4963,8 +4963,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// in that direction, even though we don't model this on the server. Implementing this in the future
// may improve movement smoothness.
// acceleration = new Vector3(1, 0, 0);
angularVelocity = Vector3.Zero;
angularVelocity = presence.AngularVelocity;
rotation = presence.Rotation;
if (sendTexture)
textureEntry = presence.Appearance.Texture.GetBytes();

View File

@ -214,9 +214,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
public void HandleTaskItemUpdateFromTransaction(
IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
{
m_log.DebugFormat(
"[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
// m_log.DebugFormat(
// "[ASSET TRANSACTION MODULE]: Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
// item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
AgentAssetTransactions transactions =
GetUserTransactions(remoteClient.AgentId);
@ -230,15 +230,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="assetID"></param>
/// <param name="transaction"></param>
/// <param name="transactionID"></param>
/// <param name="type"></param>
/// <param name="data"></param></param>
/// <param name="tempFile"></param>
public void HandleUDPUploadRequest(IClientAPI remoteClient,
UUID assetID, UUID transaction, sbyte type, byte[] data,
UUID assetID, UUID transactionID, sbyte type, byte[] data,
bool storeLocal, bool tempFile)
{
// m_log.Debug("HandleUDPUploadRequest - assetID: " + assetID.ToString() + " transaction: " + transaction.ToString() + " type: " + type.ToString() + " storelocal: " + storeLocal + " tempFile: " + tempFile);
// m_log.DebugFormat(
// "[ASSET TRANSACTION MODULE]: HandleUDPUploadRequest - assetID: {0}, transaction {1}, type {2}, storeLocal {3}, tempFile {4}, data.Length {5}",
// assetID, transactionID, type, storeLocal, tempFile, data.Length);
if (((AssetType)type == AssetType.Texture ||
(AssetType)type == AssetType.Sound ||
@ -274,8 +276,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
}
AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
AssetXferUploader uploader = transactions.RequestXferUploader(transactionID);
uploader.StartUpload(remoteClient, assetID, transactionID, type, data, storeLocal, tempFile);
}
/// <summary>

View File

@ -37,6 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
{
bool CreateStore(string value, ref UUID result);
bool DestroyStore(UUID storeID);
bool TestStore(UUID storeID);
bool TestPath(UUID storeID, string path, bool useJson);
bool SetValue(UUID storeID, string path, string value, bool useJson);
bool RemoveValue(UUID storeID, string path);

View File

@ -204,6 +204,11 @@ namespace OpenSim.Region.Framework.Scenes
private const int LAND_VELOCITYMAG_MAX = 12;
private const float FLY_ROLL_MAX_RADIANS = 1.1f;
private const float FLY_ROLL_RADIANS_PER_UPDATE = 0.06f;
private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
private float m_health = 100f;
protected ulong crossingFromRegion;
@ -604,6 +609,14 @@ namespace OpenSim.Region.Framework.Scenes
}
}
// Used for limited viewer 'fake' user rotations.
private Vector3 m_AngularVelocity = Vector3.Zero;
public Vector3 AngularVelocity
{
get { return m_AngularVelocity; }
}
public bool IsChildAgent { get; set; }
public bool IsLoggingIn { get; set; }
@ -734,6 +747,8 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region Constructor(s)
public ScenePresence(
@ -1223,6 +1238,85 @@ namespace OpenSim.Region.Framework.Scenes
ControllingClient.StopFlying(this);
}
/// <summary>
/// Applies a roll accumulator to the avatar's angular velocity for the avatar fly roll effect.
/// </summary>
/// <param name="amount">Postive or negative roll amount in radians</param>
private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
{
float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
m_AngularVelocity.Z = rollAmount;
// APPLY EXTRA consideration for flying up and flying down during this time.
// if we're turning left
if (amount > 0)
{
// If we're at the max roll and pressing up, we want to swing BACK a bit
// Automatically adds noise
if (PressingUp)
{
if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS - 0.04f)
m_AngularVelocity.Z -= 0.9f;
}
// If we're at the max roll and pressing down, we want to swing MORE a bit
if (PressingDown)
{
if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS && m_AngularVelocity.Z < FLY_ROLL_MAX_RADIANS + 0.6f)
m_AngularVelocity.Z += 0.6f;
}
}
else // we're turning right.
{
// If we're at the max roll and pressing up, we want to swing BACK a bit
// Automatically adds noise
if (PressingUp)
{
if (m_AngularVelocity.Z <= (-FLY_ROLL_MAX_RADIANS))
m_AngularVelocity.Z += 0.6f;
}
// If we're at the max roll and pressing down, we want to swing MORE a bit
if (PressingDown)
{
if (m_AngularVelocity.Z >= -FLY_ROLL_MAX_RADIANS - 0.6f)
m_AngularVelocity.Z -= 0.6f;
}
}
}
/// <summary>
/// incrementally sets roll amount to zero
/// </summary>
/// <param name="amount">Positive roll amount in radians</param>
/// <returns></returns>
private float CalculateFlyingRollResetToZero(float amount)
{
const float rollMinRadians = 0f;
if (m_AngularVelocity.Z > 0)
{
float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return -leftOverToMin;
else
return -amount;
}
else
{
float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
if (amount > leftOverToMin)
return leftOverToMin;
else
return amount;
}
}
// neighbouring regions we have enabled a child agent in
// holds the seed cap for the child agent in that region
private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
@ -1739,6 +1833,33 @@ namespace OpenSim.Region.Framework.Scenes
bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
//m_log.Debug("[CONTROL]: " +flags);
// Applies a satisfying roll effect to the avatar when flying.
if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0))
{
ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
}
else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) &&
((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0))
{
ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
}
else
{
if (m_AngularVelocity.Z != 0)
m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
}
if (Flying && IsColliding && controlland)
{
// nesting this check because LengthSquared() is expensive and we don't

View File

@ -216,6 +216,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return true;
}
// -----------------------------------------------------------------
/// <summary>
///
/// </summary>
// -----------------------------------------------------------------
public bool TestStore(UUID storeID)
{
if (! m_enabled) return false;
lock (m_JsonValueStore)
return m_JsonValueStore.ContainsKey(storeID);
}
// -----------------------------------------------------------------
/// <summary>
///

View File

@ -167,6 +167,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
{
m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
m_comms.RegisterScriptInvocation(this, "JsonTestStore");
m_comms.RegisterScriptInvocation(this, "JsonReadNotecard");
m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard");
@ -243,6 +244,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return m_store.DestroyStore(storeID) ? 1 : 0;
}
// -----------------------------------------------------------------
/// <summary>
///
/// </summary>
// -----------------------------------------------------------------
protected int JsonTestStore(UUID hostID, UUID scriptID, UUID storeID)
{
return m_store.TestStore(storeID) ? 1 : 0;
}
// -----------------------------------------------------------------
/// <summary>
///

View File

@ -48,7 +48,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
/// Tests for inventory functions in LSL
/// </summary>
[TestFixture]
public class LSL_ApiInventoryTests : OpenSimTestCase
public class JsonStoreScriptModuleTests : OpenSimTestCase
{
private Scene m_scene;
private MockScriptEngine m_engine;
@ -59,8 +59,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
{
base.SetUp();
TestHelpers.EnableLogging();
IConfigSource configSource = new IniConfigSource();
IConfig jsonStoreConfig = configSource.AddConfig("JsonStore");
jsonStoreConfig.Set("Enabled", "true");
@ -72,74 +70,129 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
m_scene = new SceneHelpers().SetupScene();
SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, jssm);
try
{
m_smcm.RegisterScriptInvocation(this, "DummyTestMethod");
}
catch (ArgumentException)
{
Assert.Ignore("Ignoring test since running on .NET 3.5 or earlier.");
}
// XXX: Unfortunately, ICommsModule currently has no way of deregistering methods.
}
// [Test]
private object InvokeOp(string name, params object[] args)
{
return m_smcm.InvokeOperation(UUID.Zero, UUID.Zero, name, args);
}
[Test]
public void TestJsonCreateStore()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId = (UUID)m_smcm.InvokeOperation(UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{}" });
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
}
// [Test]
[Test]
public void TestJsonDestroyStore()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
int dsrv = (int)InvokeOp("JsonDestroyStore", storeId);
Assert.That(dsrv, Is.EqualTo(1));
int tprv = (int)InvokeOp("JsonTestPath", storeId, "Hello");
Assert.That(tprv, Is.EqualTo(0));
}
[Test]
public void TestJsonGetValue()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId
= (UUID)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" });
string value
= (string)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" });
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
Assert.That(value, Is.EqualTo("World"));
}
// [Test]
// public void TestJsonTakeValue()
// {
// TestHelpers.InMethod();
//// TestHelpers.EnableLogging();
//
// UUID storeId
// = (UUID)m_smcm.InvokeOperation(
// UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" });
//
// string value
// = (string)m_smcm.InvokeOperation(
// UUID.Zero, UUID.Zero, "JsonTakeValue", new object[] { storeId, "Hello" });
//
// Assert.That(value, Is.EqualTo("World"));
//
// string value2
// = (string)m_smcm.InvokeOperation(
// UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" });
//
// Assert.That(value, Is.Null);
// }
[Test]
public void TestJsonRemoveValue()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
Assert.That(returnValue, Is.EqualTo(1));
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
Assert.That(result, Is.EqualTo(0));
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
Assert.That(returnValue2, Is.EqualTo(""));
}
[Test]
public void TestJsonTestPath()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId
= (UUID)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" });
int result
= (int)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonTestPath", new object[] { storeId, "Hello" });
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
Assert.That(result, Is.EqualTo(1));
}
// [Test]
[Test]
public void TestJsonSetValue()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
UUID storeId
= (UUID)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ }" });
int result
= (int)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonSetValue", new object[] { storeId, "Hello", "World" });
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
int result = (int)InvokeOp("JsonSetValue", storeId, "Hello", "World");
Assert.That(result, Is.EqualTo(1));
string value
= (string)m_smcm.InvokeOperation(
UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" });
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
Assert.That(value, Is.EqualTo("World"));
}
public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; }
}
}

View File

@ -87,7 +87,7 @@ public enum FixedShapeKey : ulong
[StructLayout(LayoutKind.Sequential)]
public struct ShapeData
{
public uint ID;
public UInt32 ID;
public BSPhysicsShapeType Type;
public Vector3 Position;
public Quaternion Rotation;
@ -111,7 +111,7 @@ public struct ShapeData
[StructLayout(LayoutKind.Sequential)]
public struct SweepHit
{
public uint ID;
public UInt32 ID;
public float Fraction;
public Vector3 Normal;
public Vector3 Point;
@ -119,15 +119,15 @@ public struct SweepHit
[StructLayout(LayoutKind.Sequential)]
public struct RaycastHit
{
public uint ID;
public UInt32 ID;
public float Fraction;
public Vector3 Normal;
}
[StructLayout(LayoutKind.Sequential)]
public struct CollisionDesc
{
public uint aID;
public uint bID;
public UInt32 aID;
public UInt32 bID;
public Vector3 point;
public Vector3 normal;
public float penetration;
@ -135,7 +135,7 @@ public struct CollisionDesc
[StructLayout(LayoutKind.Sequential)]
public struct EntityProperties
{
public uint ID;
public UInt32 ID;
public Vector3 Position;
public Quaternion Rotation;
public Vector3 Velocity;
@ -325,7 +325,7 @@ public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParamet
public abstract int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount, out int collidersCount);
public abstract bool UpdateParameter(BulletWorld world, uint localID, String parm, float value);
public abstract bool UpdateParameter(BulletWorld world, UInt32 localID, String parm, float value);
public abstract void Shutdown(BulletWorld sim);
@ -366,24 +366,24 @@ public abstract void UpdateChildTransform(BulletShape pShape, int childIndex, Ve
public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, UInt32 id);
public abstract bool DeleteCollisionShape(BulletWorld world, BulletShape shape);
public abstract CollisionObjectTypes GetBodyType(BulletBody obj);
public abstract BulletBody CreateBodyFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot);
public abstract BulletBody CreateBodyFromShape(BulletWorld sim, BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
public abstract BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot);
public abstract BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
public abstract BulletBody CreateGhostFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot);
public abstract BulletBody CreateGhostFromShape(BulletWorld sim, BulletShape shape, UInt32 id, Vector3 pos, Quaternion rot);
public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
// =====================================================================================
public abstract BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin);
public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
public abstract BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
float scaleFactor, float collisionMargin);
// =====================================================================================
@ -629,7 +629,7 @@ public abstract BulletConstraint GetConstraintRef(BulletBody obj, int index);
public abstract int GetNumConstraintRefs(BulletBody obj);
public abstract bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask);
public abstract bool SetCollisionGroupMask(BulletBody body, UInt32 filter, UInt32 mask);
// =====================================================================================
// btCollisionShape entries

View File

@ -56,7 +56,6 @@ public sealed class BSCharacter : BSPhysObject
private int _physicsActorType;
private bool _isPhysical;
private bool _flying;
private bool _wasWalking; // 'true' if the avatar was walking/moving last frame
private bool _setAlwaysRun;
private bool _throttleUpdates;
private bool _floatOnWater;
@ -84,7 +83,6 @@ public sealed class BSCharacter : BSPhysObject
_position = pos;
_flying = isFlying;
_wasWalking = true; // causes first step to initialize standing
_orientation = OMV.Quaternion.Identity;
_velocity = OMV.Vector3.Zero;
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
@ -220,7 +218,13 @@ public sealed class BSCharacter : BSPhysObject
{
// The avatar shouldn't be moving
_velocityMotor.Zero();
ZeroMotion(true /* inTaintTime */);
// If we are colliding with a stationary object, presume we're standing and don't move around
if (!ColliderIsMoving)
{
DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
ZeroMotion(true /* inTaintTime */);
}
// Standing has more friction on the ground
if (_currentFriction != BSParam.AvatarStandingFriction)
@ -229,8 +233,6 @@ public sealed class BSCharacter : BSPhysObject
PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
}
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1}", LocalID, _velocityMotor.TargetValue);
_wasWalking = false;
}
else
{
@ -260,7 +262,6 @@ public sealed class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
_wasWalking = true;
}
});
}

View File

@ -125,9 +125,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
static readonly float PIOverTwo = ((float)Math.PI) / 2f;
// For debugging, flags to turn on and off individual corrections.
private bool enableAngularVerticalAttraction;
private bool enableAngularDeflection;
private bool enableAngularBanking;
public bool enableAngularVerticalAttraction;
public bool enableAngularDeflection;
public bool enableAngularBanking;
public BSDynamics(BSScene myScene, BSPrim myPrim)
{
@ -146,7 +146,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
enableAngularBanking = false;
if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse)
{
enableAngularVerticalAttraction = false;
enableAngularVerticalAttraction = true;
enableAngularDeflection = false;
enableAngularBanking = false;
}
@ -165,7 +165,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
#region Vehicle parameter setting
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{
VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
switch (pParam)
@ -591,14 +591,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_vehicleMass = Prim.Linkset.LinksetMass;
// Friction affects are handled by this vehicle code
float friction = 0f;
PhysicsScene.PE.SetFriction(Prim.PhysBody, friction);
PhysicsScene.PE.SetFriction(Prim.PhysBody, BSParam.VehicleFriction);
PhysicsScene.PE.SetRestitution(Prim.PhysBody, BSParam.VehicleRestitution);
// Moderate angular movement introduced by Bullet.
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
// Maybe compute linear and angular factor and damping from params.
float angularDamping = BSParam.VehicleAngularDamping;
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, angularDamping);
PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV);
PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV);
// Vehicles report collision events so we know when it's on the ground
PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
@ -613,8 +614,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero);
VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4},grav={5}",
Prim.LocalID, m_vehicleMass, friction, Prim.Inertia, angularDamping, m_VehicleGravity);
VDetailLog("{0},BSDynamics.Refresh,mass={1},inert={2},grav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
Prim.LocalID, m_vehicleMass, Prim.Inertia, m_VehicleGravity,
BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution,
BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor
);
}
else
{
@ -673,13 +677,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private const int m_knownChangedWaterLevel = 1 << 9;
private const int m_knownChangedForwardVelocity = 1 <<10;
private void ForgetKnownVehicleProperties()
public void ForgetKnownVehicleProperties()
{
m_knownHas = 0;
m_knownChanged = 0;
}
// Push all the changed values back into the physics engine
private void PushKnownChanged()
public void PushKnownChanged()
{
if (m_knownChanged != 0)
{
@ -799,7 +803,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_knownVelocity = Prim.ForceVelocity;
m_knownHas |= m_knownChangedVelocity;
}
return (Vector3)m_knownVelocity;
return m_knownVelocity;
}
set
{
@ -898,9 +902,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
if (!IsActive) return;
if (PhysicsScene.VehiclePhysicalLoggingEnabled)
PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
ForgetKnownVehicleProperties();
MoveLinear(pTimestep);
@ -922,6 +923,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity);
}
// Called after the simulation step
internal void PostStep(float pTimestep)
{
if (!IsActive) return;
if (PhysicsScene.VehiclePhysicalLoggingEnabled)
PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
}
// Apply the effect of the linear motor and other linear motions (like hover and float).
private void MoveLinear(float pTimestep)
{
@ -953,10 +963,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// ==================================================================
// Clamp high or low velocities
float newVelocityLengthSq = VehicleVelocity.LengthSquared();
if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocity)
if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocitySq)
{
Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
VehicleVelocity /= VehicleVelocity.Length();
VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
Prim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySq, VehicleVelocity);
}
else if (newVelocityLengthSq < 0.001f)
VehicleVelocity = Vector3.Zero;
@ -968,8 +981,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
public void ComputeLinearVelocity(float pTimestep)
{
// Step the motor from the current value. Get the correction needed this step.
Vector3 currentVel = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVel);
Vector3 origVelW = VehicleVelocity; // DEBUG
Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
// Motor is vehicle coordinates. Rotate it to world coordinates
Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
@ -984,8 +998,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Add this correction to the velocity to make it faster/slower.
VehicleVelocity += linearMotorVelocityW;
VDetailLog("{0}, MoveLinear,velocity,vehVel={1},correction={2},force={3}",
Prim.LocalID, VehicleVelocity, linearMotorCorrectionV, linearMotorVelocityW);
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}",
Prim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity);
}
public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@ -1185,12 +1199,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Hack to reduce downward force if the vehicle is probably sitting on the ground
if (Prim.IsColliding && IsGroundVehicle)
appliedGravity *= 0.2f;
appliedGravity *= BSParam.VehicleGroundGravityFudge;
VehicleAddForce(appliedGravity);
VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},appliedForce-{2}",
Prim.LocalID, m_VehicleGravity, appliedGravity);
VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},appliedForce={3}",
Prim.LocalID, m_VehicleGravity, Prim.IsColliding, appliedGravity);
}
// =======================================================================
@ -1292,6 +1306,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
{
Vector3 vertContributionV = Vector3.Zero;
Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
// Take a vector pointing up and convert it from world to vehicle relative coords.
Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
@ -1319,13 +1334,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
// Correction happens over a number of seconds.
Vector3 unscaledContrib = vertContributionV; // DEBUG DEBUG
Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
vertContributionV /= m_verticalAttractionTimescale;
VehicleRotationalVelocity += vertContributionV * VehicleOrientation;
VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}",
Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
}
}

View File

@ -232,7 +232,7 @@ public sealed class BSLinksetCompound : BSLinkset
newLsi.OffsetFromCenterOfMass,
newLsi.OffsetRot,
true /* shouldRecalculateLocalAabb */);
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1}newLsi={2}",
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
updated.LocalID, whichUpdated, newLsi);
updated.LinksetInfo = newLsi;
updatedChild = true;
@ -377,7 +377,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Constraint linksets are rebuilt every time.
// Note that this works for rebuilding just the root after a linkset is taken apart.
// Called at taint time!!
private bool disableCOM = false; // disable until we get this debugged
private bool disableCOM = true; // disable until we get this debugged
private void RecomputeLinksetCompound()
{
try

View File

@ -82,9 +82,19 @@ public static class BSParam
public static float AvatarStepApproachFactor { get; private set; }
public static float AvatarStepForceFactor { get; private set; }
// Vehicle parameters
public static float VehicleMaxLinearVelocity { get; private set; }
public static float VehicleMaxLinearVelocitySq { get; private set; }
public static float VehicleMaxAngularVelocity { get; private set; }
public static float VehicleMaxAngularVelocitySq { get; private set; }
public static float VehicleAngularDamping { get; private set; }
public static float VehicleFriction { get; private set; }
public static float VehicleRestitution { get; private set; }
public static float VehicleLinearFactor { get; private set; }
public static Vector3 VehicleLinearFactorV { get; private set; }
public static float VehicleAngularFactor { get; private set; }
public static Vector3 VehicleAngularFactorV { get; private set; }
public static float VehicleGroundGravityFudge { get; private set; }
public static float VehicleDebuggingEnabled { get; private set; }
public static float LinksetImplementation { get; private set; }
@ -373,7 +383,7 @@ public static class BSParam
(s) => { return TerrainRestitution; },
(s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
0.04f,
0.08f,
(s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
(s) => { return TerrainCollisionMargin; },
(s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
@ -443,17 +453,42 @@ public static class BSParam
1000.0f,
(s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
(s) => { return (float)VehicleMaxLinearVelocity; },
(s,p,l,v) => { VehicleMaxLinearVelocity = v; } ),
(s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
12.0f,
(s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
(s) => { return (float)VehicleMaxAngularVelocity; },
(s,p,l,v) => { VehicleMaxAngularVelocity = v; } ),
(s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
0.0f,
(s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
(s) => { return VehicleAngularDamping; },
(s,p,l,v) => { VehicleAngularDamping = v; } ),
new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)",
1.0f,
(s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
(s) => { return VehicleLinearFactor; },
(s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ),
new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)",
1.0f,
(s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
(s) => { return VehicleAngularFactor; },
(s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ),
new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
0.0f,
(s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
(s) => { return VehicleFriction; },
(s,p,l,v) => { VehicleFriction = v; } ),
new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
0.0f,
(s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
(s) => { return VehicleRestitution; },
(s,p,l,v) => { VehicleRestitution = v; } ),
new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
0.2f,
(s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
(s) => { return VehicleGroundGravityFudge; },
(s,p,l,v) => { VehicleGroundGravityFudge = v; } ),
new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
ConfigurationParameters.numericFalse,
(s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },

View File

@ -95,12 +95,16 @@ public abstract class BSPhysObject : PhysicsActor
SubscribedEventsMs = 0;
CollidingStep = 0;
CollidingGroundStep = 0;
CollisionAccumulation = 0;
ColliderIsMoving = false;
CollisionScore = 0;
}
// Tell the object to clean up.
public virtual void Destroy()
{
UnRegisterAllPreStepActions();
UnRegisterAllPostStepActions();
}
public BSScene PhysicsScene { get; protected set; }
@ -174,13 +178,14 @@ public abstract class BSPhysObject : PhysicsActor
public abstract OMV.Vector3 RawPosition { get; set; }
public abstract OMV.Vector3 ForcePosition { get; set; }
// Position is what the simulator thinks the positions of the prim is.
// 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is.
// Because Bullet needs the zero coordinate to be the center of mass of the linkset,
// sometimes it is necessary to displace the position the physics engine thinks
// the position is. PositionDisplacement must be added and removed from the
// position as the simulator position is stored and fetched from the physics
// engine.
// engine. Similar to OrientationDisplacement.
public virtual OMV.Vector3 PositionDisplacement { get; set; }
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
public abstract OMV.Quaternion RawOrientation { get; set; }
public abstract OMV.Quaternion ForceOrientation { get; set; }
@ -237,6 +242,12 @@ public abstract class BSPhysObject : PhysicsActor
protected long CollidingObjectStep { get; set; }
// The collision flags we think are set in Bullet
protected CollisionFlags CurrentCollisionFlags { get; set; }
// On a collision, check the collider and remember if the last collider was moving
// Used to modify the standing of avatars (avatars on stationary things stand still)
protected bool ColliderIsMoving;
// Count of collisions for this object
protected long CollisionAccumulation { get; set; }
public override bool IsColliding {
get { return (CollidingStep == PhysicsScene.SimulationStep); }
@ -299,7 +310,12 @@ public abstract class BSPhysObject : PhysicsActor
return ret;
}
// if someone has subscribed for collision events....
CollisionAccumulation++;
// For movement tests, remember if we are colliding with an object that is moving.
ColliderIsMoving = collidee != null ? collidee.RawVelocity != OMV.Vector3.Zero : false;
// If someone has subscribed for collision events log the collision so it will be reported up
if (SubscribedEvents()) {
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
@ -385,6 +401,17 @@ public abstract class BSPhysObject : PhysicsActor
public override bool SubscribedEvents() {
return (SubscribedEventsMs > 0);
}
// Because 'CollisionScore' is called many times while sorting, it should not be recomputed
// each time called. So this is built to be light weight for each collision and to do
// all the processing when the user asks for the info.
public void ComputeCollisionScore()
{
// Scale the collision count by the time since the last collision.
// The "+1" prevents dividing by zero.
long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1;
CollisionScore = CollisionAccumulation / timeAgo;
}
public override float CollisionScore { get; set; }
#endregion // Collisions
@ -393,52 +420,103 @@ public abstract class BSPhysObject : PhysicsActor
// These actions are optional so, rather than scanning all the physical objects and asking them
// if they have anything to do, a physical object registers for an event call before the step is performed.
// This bookkeeping makes it easy to add, remove and clean up after all these registrations.
private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
{
string identifier = op + "-" + id.ToString();
lock (RegisteredActions)
lock (RegisteredPrestepActions)
{
// Clean out any existing action
UnRegisterPreStepAction(op, id);
RegisteredActions[identifier] = actn;
RegisteredPrestepActions[identifier] = actn;
PhysicsScene.BeforeStep += actn;
}
PhysicsScene.BeforeStep += actn;
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
}
// Unregister a pre step action. Safe to call if the action has not been registered.
protected void UnRegisterPreStepAction(string op, uint id)
// Returns 'true' if an action was actually removed
protected bool UnRegisterPreStepAction(string op, uint id)
{
string identifier = op + "-" + id.ToString();
bool removed = false;
lock (RegisteredActions)
lock (RegisteredPrestepActions)
{
if (RegisteredActions.ContainsKey(identifier))
if (RegisteredPrestepActions.ContainsKey(identifier))
{
PhysicsScene.BeforeStep -= RegisteredActions[identifier];
RegisteredActions.Remove(identifier);
PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
RegisteredPrestepActions.Remove(identifier);
removed = true;
}
}
DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
return removed;
}
protected void UnRegisterAllPreStepActions()
{
lock (RegisteredActions)
lock (RegisteredPrestepActions)
{
foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
{
PhysicsScene.BeforeStep -= kvp.Value;
}
RegisteredActions.Clear();
RegisteredPrestepActions.Clear();
}
DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
}
protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
{
string identifier = op + "-" + id.ToString();
lock (RegisteredPoststepActions)
{
// Clean out any existing action
UnRegisterPostStepAction(op, id);
RegisteredPoststepActions[identifier] = actn;
PhysicsScene.AfterStep += actn;
}
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
}
// Unregister a pre step action. Safe to call if the action has not been registered.
// Returns 'true' if an action was actually removed.
protected bool UnRegisterPostStepAction(string op, uint id)
{
string identifier = op + "-" + id.ToString();
bool removed = false;
lock (RegisteredPoststepActions)
{
if (RegisteredPoststepActions.ContainsKey(identifier))
{
PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
RegisteredPoststepActions.Remove(identifier);
removed = true;
}
}
DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
return removed;
}
protected void UnRegisterAllPostStepActions()
{
lock (RegisteredPoststepActions)
{
foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
{
PhysicsScene.AfterStep -= kvp.Value;
}
RegisteredPoststepActions.Clear();
}
DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
}
#endregion // Per Simulation Step actions

View File

@ -59,7 +59,6 @@ public sealed class BSPrim : BSPhysObject
private OMV.Vector3 _force;
private OMV.Vector3 _velocity;
private OMV.Vector3 _torque;
private float _collisionScore;
private OMV.Vector3 _acceleration;
private OMV.Quaternion _orientation;
private int _physicsActorType;
@ -74,7 +73,7 @@ public sealed class BSPrim : BSPhysObject
private bool _kinematic;
private float _buoyancy;
private BSDynamics _vehicle;
public BSDynamics VehicleController { get; private set; }
private BSVMotor _targetMotor;
private OMV.Vector3 _PIDTarget;
@ -108,7 +107,7 @@ public sealed class BSPrim : BSPhysObject
_friction = PhysicsScene.Params.defaultFriction;
_restitution = PhysicsScene.Params.defaultRestitution;
_vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
VehicleController = new BSDynamics(PhysicsScene, this); // add vehicleness
_mass = CalculateMass();
@ -345,6 +344,10 @@ public sealed class BSPrim : BSPhysObject
{
bool ret = false;
// We don't care where non-physical items are placed
if (!IsPhysicallyActive)
return ret;
if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
{
// The physical object is out of the known/simulated area.
@ -513,7 +516,7 @@ public sealed class BSPrim : BSPhysObject
public override int VehicleType {
get {
return (int)_vehicle.Type; // if we are a vehicle, return that type
return (int)VehicleController.Type; // if we are a vehicle, return that type
}
set {
Vehicle type = (Vehicle)value;
@ -522,14 +525,20 @@ public sealed class BSPrim : BSPhysObject
{
// 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);
VehicleController.ProcessTypeChange(type);
ActivateIfPhysical(false);
// If an active vehicle, register the vehicle code to be called before each step
if (_vehicle.Type == Vehicle.TYPE_NONE)
if (VehicleController.Type == Vehicle.TYPE_NONE)
{
UnRegisterPreStepAction("BSPrim.Vehicle", LocalID);
PhysicsScene.AfterStep -= VehicleController.PostStep;
}
else
RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step);
{
RegisterPreStepAction("BSPrim.Vehicle", LocalID, VehicleController.Step);
PhysicsScene.AfterStep += VehicleController.PostStep;
}
});
}
}
@ -537,7 +546,7 @@ public sealed class BSPrim : BSPhysObject
{
PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
{
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
VehicleController.ProcessFloatVehicleParam((Vehicle)param, value);
ActivateIfPhysical(false);
});
}
@ -545,7 +554,7 @@ public sealed class BSPrim : BSPhysObject
{
PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
{
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
VehicleController.ProcessVectorVehicleParam((Vehicle)param, value);
ActivateIfPhysical(false);
});
}
@ -553,7 +562,7 @@ public sealed class BSPrim : BSPhysObject
{
PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
{
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
VehicleController.ProcessRotationVehicleParam((Vehicle)param, rotation);
ActivateIfPhysical(false);
});
}
@ -561,7 +570,7 @@ public sealed class BSPrim : BSPhysObject
{
PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
{
_vehicle.ProcessVehicleFlags(param, remove);
VehicleController.ProcessVehicleFlags(param, remove);
});
}
@ -638,11 +647,6 @@ public sealed class BSPrim : BSPhysObject
// DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
}
}
public override float CollisionScore {
get { return _collisionScore; }
set { _collisionScore = value;
}
}
public override OMV.Vector3 Acceleration {
get { return _acceleration; }
set { _acceleration = value; }
@ -747,7 +751,7 @@ public sealed class BSPrim : BSPhysObject
// isSolid: other objects bounce off of this object
// isVolumeDetect: other objects pass through but can generate collisions
// collisionEvents: whether this object returns collision events
private void UpdatePhysicalParameters()
public void UpdatePhysicalParameters()
{
// DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
@ -759,7 +763,7 @@ public sealed class BSPrim : BSPhysObject
MakeDynamic(IsStatic);
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
_vehicle.Refresh();
VehicleController.Refresh();
// Arrange for collision events if the simulator wants them
EnableCollisions(SubscribedEvents());
@ -1601,7 +1605,7 @@ public sealed class BSPrim : BSPhysObject
// Remove all the physical dependencies on the old body.
// (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
Linkset.RemoveBodyDependencies(this);
_vehicle.RemoveBodyDependencies(this);
VehicleController.RemoveBodyDependencies(this);
});
// Make sure the properties are set on the new object
@ -1618,9 +1622,9 @@ public sealed class BSPrim : BSPhysObject
{
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
// TODO: handle physics introduced by Bullet with computed vehicle physics.
if (_vehicle.IsActive)
if (VehicleController.IsActive)
{
// entprop.RotationalVelocity = OMV.Vector3.Zero;
entprop.RotationalVelocity = OMV.Vector3.Zero;
}
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
@ -1643,7 +1647,7 @@ public sealed class BSPrim : BSPhysObject
// DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG
// The sanity check can change the velocity and/or position.
if (IsPhysical && PositionSanityCheck(true /* inTaintTime */ ))
if (PositionSanityCheck(true /* inTaintTime */ ))
{
entprop.Position = _position;
entprop.Velocity = _velocity;

View File

@ -26,6 +26,7 @@
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
@ -87,7 +88,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public delegate void PreStepAction(float timeStep);
public delegate void PostStepAction(float timeStep);
public event PreStepAction BeforeStep;
public event PreStepAction AfterStep;
public event PostStepAction AfterStep;
// A value of the time now so all the collision and update routines do not have to get their own
// Set to 'now' just before all the prims and actors are called for collisions and updates
@ -697,7 +698,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public override Dictionary<uint, float> GetTopColliders()
{
return new Dictionary<uint, float>();
Dictionary<uint, float> topColliders;
lock (PhysObjects)
{
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
{
kvp.Value.ComputeCollisionScore();
}
List<BSPhysObject> orderedPrims = new List<BSPhysObject>(PhysObjects.Values);
orderedPrims.OrderByDescending(p => p.CollisionScore);
topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
}
return topColliders;
}
public override bool IsThreaded { get { return false; } }
@ -748,7 +763,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
private void TriggerPostStepEvent(float timeStep)
{
PreStepAction actions = AfterStep;
PostStepAction actions = AfterStep;
if (actions != null)
actions(timeStep);
@ -840,7 +855,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{
DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
Util.PrintCallStack(DetailLog);
// Util.PrintCallStack(DetailLog);
}
return InTaintTime;
}

View File

@ -1,8 +1,11 @@
CURRENT PRIORITIES
=================================================
One sided meshes? Should terrain be built into a closed shape?
When meshes get partially wedged into the terrain, they cannot push themselves out.
It is possible that Bullet processes collisions whether entering or leaving a mesh.
Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
Deleting a linkset while standing on the root will leave the physical shape of the root behind.
Not sure if it is because standing on it. Done with large prim linksets.
Child movement in linkset (don't rebuild linkset)
Vehicle angular vertical attraction
vehicle angular banking
Center-of-gravity
@ -12,6 +15,7 @@ when should angular and linear motor targets be zeroed? when selected?
Need a vehicle.clear()? Or an 'else' in prestep if not physical.
Teravus llMoveToTarget script debug
Mixing of hover, buoyancy/gravity, moveToTarget, into one force
Setting hover height to zero disables hover even if hover flags are on (from SL wiki)
Nebadon vehicles turning funny in arena
limitMotorUp calibration (more down?)
llRotLookAt
@ -72,7 +76,11 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
GENERAL TODO LIST:
=================================================
Avatar standing on a moving object should start to move with the object.
llMoveToTarget objects are not effected by gravity until target is removed.
Compute CCD parameters based on body size
Can solver iterations be changed per body/shape? Can be for constraints but what
about regular vehicles?
Implement llSetPhysicalMaterial.
extend it with Center-of-mass, rolling friction, density
Implement llSetForceAndTorque.
@ -321,4 +329,5 @@ Mantis 6040 script http://opensimulator.org/mantis/view.php?id=6040 (DONE)
Boats float low in the water (DONE)
Boats floating at proper level (DONE)
When is force introduced by SetForce removed? The prestep action could go forever. (DONE)
(Resolution: setForce registers a prestep action which keeps applying the force)
(Resolution: setForce registers a prestep action which keeps applying the force)
Child movement in linkset (don't rebuild linkset) (DONE 20130122))

View File

@ -0,0 +1,150 @@
/*
* 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.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using log4net;
using OpenSim.Framework;
using OpenSim.Region.Physics.BulletSPlugin;
using OpenSim.Region.Physics.Manager;
using OpenSim.Tests.Common;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests
{
[TestFixture]
public class BasicVehicles : OpenSimTestCase
{
// Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
// Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
BSScene PhysicsScene { get; set; }
BSPrim TestVehicle { get; set; }
Vector3 TestVehicleInitPosition { get; set; }
float simulationTimeStep = 0.089f;
[TestFixtureSetUp]
public void Init()
{
Dictionary<string, string> engineParams = new Dictionary<string, string>();
PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
Vector3 pos = new Vector3(100.0f, 100.0f, 0f);
pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2f;
TestVehicleInitPosition = pos;
Vector3 size = new Vector3(1f, 1f, 1f);
pbs.Scale = size;
Quaternion rot = Quaternion.Identity;
bool isPhys = false;
uint localID = 123;
PhysicsScene.AddPrimShape("testPrim", pbs, pos, size, rot, isPhys, localID);
TestVehicle = (BSPrim)PhysicsScene.PhysObjects[localID];
// The actual prim shape creation happens at taint time
PhysicsScene.ProcessTaints();
}
[TestFixtureTearDown]
public void TearDown()
{
if (PhysicsScene != null)
{
// The Dispose() will also free any physical objects in the scene
PhysicsScene.Dispose();
PhysicsScene = null;
}
}
[TestCase(2f, 0.2f, 0.25f, 0.25f, 0.25f)]
[TestCase(2f, 0.2f, -0.25f, 0.25f, 0.25f)]
[TestCase(2f, 0.2f, 0.25f, -0.25f, 0.25f)]
[TestCase(2f, 0.2f, -0.25f, -0.25f, 0.25f)]
// [TestCase(2f, 0.2f, 0.785f, 0.0f, 0.25f) /*, "Leaning 45 degrees to the side" */]
// [TestCase(2f, 0.2f, 1.650f, 0.0f, 0.25f) /*, "Leaning more than 90 degrees to the side" */]
// [TestCase(2f, 0.2f, 2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped right" */]
// [TestCase(2f, 0.2f,-2.750f, 0.0f, 0.25f) /*, "Almost upside down, tipped left" */]
// [TestCase(2f, 0.2f, 0.0f, 0.785f, 0.25f) /*, "Tipped back 45 degrees" */]
// [TestCase(2f, 0.2f, 0.0f, 1.650f, 0.25f) /*, "Tipped back more than 90 degrees" */]
// [TestCase(2f, 0.2f, 0.0f, 2.750f, 0.25f) /*, "Almost upside down, tipped back" */]
// [TestCase(2f, 0.2f, 0.0f,-2.750f, 0.25f) /*, "Almost upside down, tipped forward" */]
public void AngularVerticalAttraction(float timeScale, float efficiency, float initRoll, float initPitch, float initYaw)
{
// Enough simulation steps to cover the timescale the operation should take
int simSteps = (int)(timeScale / simulationTimeStep) + 1;
// Tip the vehicle
Quaternion initOrientation = Quaternion.CreateFromEulers(initRoll, initPitch, initYaw);
TestVehicle.Orientation = initOrientation;
TestVehicle.Position = TestVehicleInitPosition;
// The vehicle controller is not enabled directly (by setting a vehicle type).
// Instead the appropriate values are set and calls are made just the parts of the
// controller we want to exercise. Stepping the physics engine then applies
// the actions of that one feature.
TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency);
TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale);
TestVehicle.VehicleController.enableAngularVerticalAttraction = true;
TestVehicle.IsPhysical = true;
PhysicsScene.ProcessTaints();
// Step the simulator a bunch of times and vertical attraction should orient the vehicle up
for (int ii = 0; ii < simSteps; ii++)
{
TestVehicle.VehicleController.ForgetKnownVehicleProperties();
TestVehicle.VehicleController.ComputeAngularVerticalAttraction();
TestVehicle.VehicleController.PushKnownChanged();
PhysicsScene.Simulate(simulationTimeStep);
}
TestVehicle.IsPhysical = false;
PhysicsScene.ProcessTaints();
// After these steps, the vehicle should be upright
/*
float finalRoll, finalPitch, finalYaw;
TestVehicle.Orientation.GetEulerAngles(out finalRoll, out finalPitch, out finalYaw);
Assert.That(finalRoll, Is.InRange(-0.01f, 0.01f));
Assert.That(finalPitch, Is.InRange(-0.01f, 0.01f));
Assert.That(finalYaw, Is.InRange(initYaw - 0.1f, initYaw + 0.1f));
*/
Vector3 upPointer = Vector3.UnitZ * TestVehicle.Orientation;
Assert.That(upPointer.Z, Is.GreaterThan(0.99f));
}
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using log4net;
using OpenSim.Tests.Common;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests
{
[TestFixture]
public class BulletSimTests : OpenSimTestCase
{
// Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
// Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
[TestFixtureSetUp]
public void Init()
{
}
[TestFixtureTearDown]
public void TearDown()
{
}
}
}

View File

@ -0,0 +1,95 @@
/*
* 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.Collections.Generic;
using System.Linq;
using System.Text;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Physics.BulletSPlugin;
using OpenSim.Region.Physics.Meshing;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests
{
// Utility functions for building up and tearing down the sample physics environments
public static class BulletSimTestsUtil
{
// 'engineName' is the Bullet engine to use. Either null (for unmanaged), "BulletUnmanaged" or "BulletXNA"
// 'params' is a set of keyValue pairs to set in the engine's configuration file (override defaults)
// May be 'null' if there are no overrides.
public static BSScene CreateBasicPhysicsEngine(Dictionary<string,string> paramOverrides)
{
IConfigSource openSimINI = new IniConfigSource();
IConfig startupConfig = openSimINI.AddConfig("Startup");
startupConfig.Set("physics", "BulletSim");
startupConfig.Set("meshing", "Meshmerizer");
startupConfig.Set("cacheSculptMaps", "false"); // meshmerizer shouldn't save maps
IConfig bulletSimConfig = openSimINI.AddConfig("BulletSim");
// If the caller cares, specify the bullet engine otherwise it will default to "BulletUnmanaged".
// bulletSimConfig.Set("BulletEngine", "BulletUnmanaged");
// bulletSimConfig.Set("BulletEngine", "BulletXNA");
bulletSimConfig.Set("MeshSculptedPrim", "false");
bulletSimConfig.Set("ForceSimplePrimMeshing", "true");
if (paramOverrides != null)
{
foreach (KeyValuePair<string, string> kvp in paramOverrides)
{
bulletSimConfig.Set(kvp.Key, kvp.Value);
}
}
// If a special directory exists, put detailed logging therein.
// This allows local testing/debugging without having to worry that the build engine will output logs.
if (Directory.Exists("physlogs"))
{
bulletSimConfig.Set("PhysicsLoggingDir","./physlogs");
bulletSimConfig.Set("PhysicsLoggingEnabled","True");
bulletSimConfig.Set("PhysicsLoggingDoFlush","True");
bulletSimConfig.Set("VehicleLoggingEnabled","True");
}
BSPlugin bsPlugin = new BSPlugin();
BSScene bsScene = (BSScene)bsPlugin.GetScene("BSTestRegion");
// Since the asset requestor is not initialized, any mesh or sculptie will be a cube.
// In the future, add a fake asset fetcher to get meshes and sculpts.
// bsScene.RequestAssetMethod = ???;
Meshing.Meshmerizer mesher = new Meshmerizer(openSimINI);
bsScene.Initialise(mesher, openSimINI);
return bsScene;
}
}
}

View File

@ -4096,8 +4096,8 @@ namespace OpenSim.Region.Physics.OdePlugin
lock (_prims)
{
List<OdePrim> orderedPrims = new List<OdePrim>(_prims);
orderedPrims.OrderByDescending(p => p.CollisionScore).Take(25);
topColliders = orderedPrims.ToDictionary(p => p.LocalID, p => p.CollisionScore);
orderedPrims.OrderByDescending(p => p.CollisionScore);
topColliders = orderedPrims.Take(25).ToDictionary(p => p.LocalID, p => p.CollisionScore);
foreach (OdePrim p in _prims)
p.CollisionScore = 0;

View File

@ -31,7 +31,6 @@ using System.Collections.Generic;
using System.Reflection;
using log4net;
using Tools;
using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
@ -479,20 +478,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
string retstr = String.Empty;
bool printSemicolon = true;
retstr += Indent();
bool transformToBlock = false;
if (m_insertCoopTerminationChecks)
{
// We have to check in event functions as well because the user can manually call these.
if (previousSymbol is GlobalFunctionDefinition
|| previousSymbol is WhileStatement
// A non-braced single line do while structure cannot contain multiple statements.
// So to insert the termination check we change this to a braced control structure instead.
if (previousSymbol is WhileStatement
|| previousSymbol is DoWhileStatement
|| previousSymbol is ForLoop
|| previousSymbol is StateEvent)
retstr += Generate(m_coopTerminationCheck);
|| previousSymbol is ForLoop)
{
transformToBlock = true;
// FIXME: This will be wrongly indented because the previous for/while/dowhile will have already indented.
retstr += GenerateIndentedLine("{");
retstr += GenerateIndentedLine(m_coopTerminationCheck);
}
}
retstr += Indent();
if (0 < s.kids.Count)
{
// Jump label prints its own colon, we don't need a semicolon.
@ -508,6 +514,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
if (printSemicolon)
retstr += GenerateLine(";");
if (transformToBlock)
{
// FIXME: This will be wrongly indented because the for/while/dowhile is currently handling the unindent
retstr += GenerateIndentedLine("}");
}
return retstr;
}

View File

@ -55,10 +55,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
private OSChatMessage m_osChatMessageReceived;
/// <summary>
/// Number of chat messages received so far. Reset before each test.
/// </summary>
private int m_chatMessagesReceived;
/// <summary>
/// Number of chat messages expected. m_chatEvent is not fired until this number is reached or exceeded.
/// </summary>
private int m_chatMessagesThreshold;
[SetUp]
public void Init()
{
m_osChatMessageReceived = null;
m_chatMessagesReceived = 0;
m_chatMessagesThreshold = 0;
m_chatEvent = new AutoResetEvent(false);
m_stoppedEvent = new AutoResetEvent(false);
@ -125,6 +137,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
TestStop(script);
}
[Test]
public void TestNoStopOnSingleStatementForLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
for (i = 0; i <= 1; i++) llSay(0, ""Iter "" + (string)i);
}
}";
TestSingleStatementNoStop(script);
}
[Test]
public void TestStopOnLongSingleStatementForLoop()
{
@ -139,8 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
integer i = 0;
llSay(0, ""Thin Lizzy"");
for (i = 0; i < 2147483647; i++)
llSay(0, ""Iter "" + (string)i);
for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i);
}
}";
@ -171,6 +201,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
TestStop(script);
}
[Test]
public void TestNoStopOnSingleStatementWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
while (i < 2) llSay(0, ""Iter "" + (string)i++);
}
}";
TestSingleStatementNoStop(script);
}
[Test]
public void TestStopOnLongSingleStatementWhileLoop()
{
@ -218,7 +267,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
}
[Test]
public void TestStopOnLongDoWhileLoop()
public void TestNoStopOnSingleStatementDoWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
do llSay(0, ""Iter "" + (string)i++);
while (i < 2);
}
}";
TestSingleStatementNoStop(script);
}
[Test]
public void TestStopOnLongSingleStatementDoWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
do llSay(0, ""Iter "" + (string)i++);
while (1 == 1);
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongCompoundStatementDoWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
@ -234,7 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
do
{
llSay(0, ""Iter "" + (string)i++);
} while (1 == 1);
} while (1 == 1);
}
}";
@ -245,7 +337,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
public void TestStopOnInfiniteJumpLoop()
{
TestHelpers.InMethod();
TestHelpers.EnableLogging();
// TestHelpers.EnableLogging();
string script =
@"default
@ -320,14 +412,13 @@ default
TestStop(script);
}
private void TestStop(string script)
private SceneObjectPart CreateScript(string script, string itemName, UUID userId)
{
UUID userId = TestHelpers.ParseTail(0x1);
// UUID objectId = TestHelpers.ParseTail(0x100);
// UUID itemId = TestHelpers.ParseTail(0x3);
string itemName = "TestStop() Item";
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
SceneObjectGroup so
= SceneHelpers.CreateSceneObject(1, userId, string.Format("Object for {0}", itemName), 0x100);
m_scene.AddNewSceneObject(so, true);
InventoryItemBase itemTemplate = new InventoryItemBase();
@ -338,14 +429,57 @@ default
m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
return m_scene.RezNewScript(userId, itemTemplate, script);
}
private void TestSingleStatementNoStop(string script)
{
// In these tests we expect to see at least 2 chat messages to confirm that the loop is working properly.
m_chatMessagesThreshold = 2;
UUID userId = TestHelpers.ParseTail(0x1);
// UUID objectId = TestHelpers.ParseTail(0x100);
// UUID itemId = TestHelpers.ParseTail(0x3);
string itemName = "TestNoStop";
SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
// Wait for the script to start the event before we try stopping it.
m_chatEvent.WaitOne(60000);
Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
if (m_osChatMessageReceived == null)
Assert.Fail("Script did not start");
else
Assert.That(m_chatMessagesReceived, Is.EqualTo(2));
bool running;
TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
Assert.That(
SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
Assert.That(running, Is.True);
}
private void TestStop(string script)
{
// In these tests we're only interested in the first message to confirm that the script has started.
m_chatMessagesThreshold = 1;
UUID userId = TestHelpers.ParseTail(0x1);
// UUID objectId = TestHelpers.ParseTail(0x100);
// UUID itemId = TestHelpers.ParseTail(0x3);
string itemName = "TestStop";
SceneObjectPart partWhereRezzed = CreateScript(script, itemName, userId);
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
// Wait for the script to start the event before we try stopping it.
m_chatEvent.WaitOne(60000);
if (m_osChatMessageReceived != null)
Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
else
Assert.Fail("Script did not start");
// FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
// executes llSay() but has not started the next statement before we try to stop it.
@ -367,11 +501,14 @@ default
private void OnChatFromWorld(object sender, OSChatMessage oscm)
{
m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
Console.WriteLine("Got chat [{0}]", oscm.Message);
m_osChatMessageReceived = oscm;
m_chatEvent.Set();
if (++m_chatMessagesReceived >= m_chatMessagesThreshold)
{
m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
m_chatEvent.Set();
}
}
}
}

View File

@ -49,7 +49,6 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.Shared.CodeTools;
using OpenSim.Region.ScriptEngine.Shared.Instance;
using OpenSim.Region.ScriptEngine.Shared.Api;
@ -698,7 +697,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
}
StringBuilder sb = new StringBuilder();
Queue eq = instance.EventQueue;
sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
sb.AppendFormat("Status : {0}\n", status);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3484,6 +3484,40 @@
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.Physics.BulletSPlugin.Tests" path="OpenSim/Region/Physics/BulletSPlugin/Tests" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="System.Data"/>
<Reference name="Nini" path="../../../../../bin/"/>
<Reference name="log4net" path="../../../../../bin/"/>
<Reference name="nunit.framework" path="../../../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Tests.Common"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Region.Physics.Meshing" path="../../../../../bin/Physics/"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Region.Physics.BulletSPlugin" path="../../../../../bin/Physics/"/>
<Files>
<Match pattern="*.cs" recurse="false"/>
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Server.Handlers.Tests" path="OpenSim/Server/Handlers" type="Library">
<Configuration name="Debug">
<Options>