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

0.7.4.1
Justin Clark-Casey (justincc) 2012-03-27 02:10:02 +01:00
commit 09c85a6a6c
15 changed files with 532 additions and 139 deletions

View File

@ -26,12 +26,12 @@
*/ */
using System; using System;
using System.Reflection;
using OpenMetaverse; using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces namespace OpenSim.Region.Framework.Interfaces
{ {
public delegate void ScriptCommand(UUID script, string id, string module, string command, string k); public delegate void ScriptCommand(UUID script, string id, string module, string command, string k);
public delegate object ScriptInvocation(UUID script, object[] parms);
/// <summary> /// <summary>
/// Interface for communication between OpenSim modules and in-world scripts /// Interface for communication between OpenSim modules and in-world scripts
@ -46,14 +46,17 @@ namespace OpenSim.Region.Framework.Interfaces
/// </summary> /// </summary>
event ScriptCommand OnScriptCommand; event ScriptCommand OnScriptCommand;
void RegisterScriptInvocation(string name, ScriptInvocation fn, Type[] csig, Type rsig); void RegisterScriptInvocation(object target, string method);
void RegisterScriptInvocation(object target, MethodInfo method);
void RegisterScriptInvocation(object target, string[] methods);
Delegate[] GetScriptInvocationList();
ScriptInvocation LookupScriptInvocation(string fname); Delegate LookupScriptInvocation(string fname);
string LookupModInvocation(string fname); string LookupModInvocation(string fname);
Type[] LookupTypeSignature(string fname); Type[] LookupTypeSignature(string fname);
Type LookupReturnType(string fname); Type LookupReturnType(string fname);
object InvokeOperation(UUID scriptId, string fname, params object[] parms); object InvokeOperation(UUID hostId, UUID scriptId, string fname, params object[] parms);
/// <summary> /// <summary>
/// Send a link_message event to an in-world script /// Send a link_message event to an in-world script

View File

@ -35,6 +35,8 @@ using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using Mono.Addins; using Mono.Addins;
using OpenMetaverse; using OpenMetaverse;
using System.Linq;
using System.Linq.Expressions;
namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
{ {
@ -47,15 +49,15 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
#region ScriptInvocation #region ScriptInvocation
protected class ScriptInvocationData protected class ScriptInvocationData
{ {
public ScriptInvocation ScriptInvocationFn { get; private set; } public Delegate ScriptInvocationDelegate { get; private set; }
public string FunctionName { get; private set; } public string FunctionName { get; private set; }
public Type[] TypeSignature { get; private set; } public Type[] TypeSignature { get; private set; }
public Type ReturnType { get; private set; } public Type ReturnType { get; private set; }
public ScriptInvocationData(string fname, ScriptInvocation fn, Type[] callsig, Type returnsig) public ScriptInvocationData(string fname, Delegate fn, Type[] callsig, Type returnsig)
{ {
FunctionName = fname; FunctionName = fname;
ScriptInvocationFn = fn; ScriptInvocationDelegate = fn;
TypeSignature = callsig; TypeSignature = callsig;
ReturnType = returnsig; ReturnType = returnsig;
} }
@ -126,14 +128,72 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
m_scriptModule.PostScriptEvent(script, "link_message", args); m_scriptModule.PostScriptEvent(script, "link_message", args);
} }
public void RegisterScriptInvocation(string fname, ScriptInvocation fcall, Type[] csig, Type rsig) public void RegisterScriptInvocation(object target, string meth)
{ {
MethodInfo mi = target.GetType().GetMethod(meth,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (mi == null)
{
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth);
return;
}
RegisterScriptInvocation(target, mi);
}
public void RegisterScriptInvocation(object target, string[] meth)
{
foreach (string m in meth)
RegisterScriptInvocation(target, m);
}
public void RegisterScriptInvocation(object target, MethodInfo mi)
{
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name);
Type delegateType;
var typeArgs = mi.GetParameters()
.Select(p => p.ParameterType)
.ToList();
if (mi.ReturnType == typeof(void))
{
delegateType = Expression.GetActionType(typeArgs.ToArray());
}
else
{
typeArgs.Add(mi.ReturnType);
delegateType = Expression.GetFuncType(typeArgs.ToArray());
}
Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi);
lock (m_scriptInvocation) lock (m_scriptInvocation)
{ {
m_scriptInvocation[fname] = new ScriptInvocationData(fname,fcall,csig,rsig); ParameterInfo[] parameters = fcall.Method.GetParameters ();
if (parameters.Length < 2) // Must have two UUID params
return;
// Hide the first two parameters
Type[] parmTypes = new Type[parameters.Length - 2];
for (int i = 2 ; i < parameters.Length ; i++)
parmTypes[i - 2] = parameters[i].ParameterType;
m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
} }
} }
public Delegate[] GetScriptInvocationList()
{
List<Delegate> ret = new List<Delegate>();
lock (m_scriptInvocation)
{
foreach (ScriptInvocationData d in m_scriptInvocation.Values)
ret.Add(d.ScriptInvocationDelegate);
}
return ret.ToArray();
}
public string LookupModInvocation(string fname) public string LookupModInvocation(string fname)
{ {
lock (m_scriptInvocation) lock (m_scriptInvocation)
@ -147,19 +207,29 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
return "modInvokeI"; return "modInvokeI";
else if (sid.ReturnType == typeof(float)) else if (sid.ReturnType == typeof(float))
return "modInvokeF"; return "modInvokeF";
else if (sid.ReturnType == typeof(UUID))
return "modInvokeK";
else if (sid.ReturnType == typeof(OpenMetaverse.Vector3))
return "modInvokeV";
else if (sid.ReturnType == typeof(OpenMetaverse.Quaternion))
return "modInvokeR";
else if (sid.ReturnType == typeof(object[]))
return "modInvokeL";
m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
} }
} }
return null; return null;
} }
public ScriptInvocation LookupScriptInvocation(string fname) public Delegate LookupScriptInvocation(string fname)
{ {
lock (m_scriptInvocation) lock (m_scriptInvocation)
{ {
ScriptInvocationData sid; ScriptInvocationData sid;
if (m_scriptInvocation.TryGetValue(fname,out sid)) if (m_scriptInvocation.TryGetValue(fname,out sid))
return sid.ScriptInvocationFn; return sid.ScriptInvocationDelegate;
} }
return null; return null;
@ -189,10 +259,15 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
return null; return null;
} }
public object InvokeOperation(UUID scriptid, string fname, params object[] parms) public object InvokeOperation(UUID hostid, UUID scriptid, string fname, params object[] parms)
{ {
ScriptInvocation fn = LookupScriptInvocation(fname); List<object> olist = new List<object>();
return fn(scriptid,parms); olist.Add(hostid);
olist.Add(scriptid);
foreach (object o in parms)
olist.Add(o);
Delegate fn = LookupScriptInvocation(fname);
return fn.DynamicInvoke(olist.ToArray());
} }
#endregion #endregion

View File

@ -94,7 +94,7 @@ public class BSCharacter : PhysicsActor
_flying = isFlying; _flying = isFlying;
_orientation = Quaternion.Identity; _orientation = Quaternion.Identity;
_velocity = Vector3.Zero; _velocity = Vector3.Zero;
_buoyancy = isFlying ? 1f : 0f; _buoyancy = ComputeBuoyancyFromFlying(isFlying);
_scale = new Vector3(1f, 1f, 1f); _scale = new Vector3(1f, 1f, 1f);
_density = _scene.Params.avatarDensity; _density = _scene.Params.avatarDensity;
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
@ -110,7 +110,7 @@ public class BSCharacter : PhysicsActor
shapeData.Buoyancy = _buoyancy; shapeData.Buoyancy = _buoyancy;
shapeData.Static = ShapeData.numericFalse; shapeData.Static = ShapeData.numericFalse;
shapeData.Friction = _scene.Params.avatarFriction; shapeData.Friction = _scene.Params.avatarFriction;
shapeData.Restitution = _scene.Params.defaultRestitution; shapeData.Restitution = _scene.Params.avatarRestitution;
// do actual create at taint time // do actual create at taint time
_scene.TaintedObject(delegate() _scene.TaintedObject(delegate()
@ -260,13 +260,13 @@ public class BSCharacter : PhysicsActor
get { return _flying; } get { return _flying; }
set { set {
_flying = value; _flying = value;
_scene.TaintedObject(delegate() // simulate flying by changing the effect of gravity
{ this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
// simulate flying by changing the effect of gravity
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _flying ? 1f : 0f);
});
} }
} }
private float ComputeBuoyancyFromFlying(bool ifFlying) {
return ifFlying ? 1f : 0f;
}
public override bool public override bool
SetAlwaysRun { SetAlwaysRun {
get { return _setAlwaysRun; } get { return _setAlwaysRun; }
@ -299,6 +299,7 @@ public class BSCharacter : PhysicsActor
get { return _kinematic; } get { return _kinematic; }
set { _kinematic = value; } set { _kinematic = value; }
} }
// neg=fall quickly, 0=1g, 1=0g, pos=float up
public override float Buoyancy { public override float Buoyancy {
get { return _buoyancy; } get { return _buoyancy; }
set { _buoyancy = value; set { _buoyancy = value;
@ -355,7 +356,7 @@ public class BSCharacter : PhysicsActor
} }
else else
{ {
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); m_log.ErrorFormat("{0}: Got a NaN force applied to a Character", LogHeader);
} }
//m_lastUpdateSent = false; //m_lastUpdateSent = false;
} }
@ -425,6 +426,8 @@ public class BSCharacter : PhysicsActor
} }
} }
// Called by the scene when a collision with this object is reported
CollisionEventUpdate collisionCollection = null;
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
{ {
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@ -442,10 +445,24 @@ public class BSCharacter : PhysicsActor
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
_lastCollisionTime = nowTime; _lastCollisionTime = nowTime;
Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>(); if (collisionCollection == null)
contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); collisionCollection = new CollisionEventUpdate();
CollisionEventUpdate args = new CollisionEventUpdate(contactPoints); collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
base.SendCollisionUpdate(args); }
public void SendCollisions()
{
// if (collisionCollection != null)
// {
// base.SendCollisionUpdate(collisionCollection);
// collisionCollection = null;
// }
// Kludge to make a collision call even if there are no collisions.
// This causes the avatar animation to get updated.
if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate();
base.SendCollisionUpdate(collisionCollection);
collisionCollection = null;
} }
} }

View File

@ -821,7 +821,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
*/ */
// Get what the body is doing, this includes 'external' influences // Get what the body is doing, this includes 'external' influences
Vector3 angularVelocity = m_prim.AngularVelocity; Vector3 angularVelocity = m_prim.RotationalVelocity;
// Vector3 angularVelocity = Vector3.Zero; // Vector3 angularVelocity = Vector3.Zero;
if (m_angularMotorApply > 0) if (m_angularMotorApply > 0)
@ -910,7 +910,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
// Apply to the body // Apply to the body
m_prim.AngularVelocity = m_lastAngularVelocity; m_prim.RotationalVelocity = m_lastAngularVelocity;
} //end MoveAngular } //end MoveAngular
internal void LimitRotation(float timestep) internal void LimitRotation(float timestep)

View File

@ -85,7 +85,6 @@ public sealed class BSPrim : PhysicsActor
private OMV.Vector3 _rotationalVelocity; private OMV.Vector3 _rotationalVelocity;
private bool _kinematic; private bool _kinematic;
private float _buoyancy; private float _buoyancy;
private OMV.Vector3 _angularVelocity;
private List<BSPrim> _childrenPrims; private List<BSPrim> _childrenPrims;
private BSPrim _parentPrim; private BSPrim _parentPrim;
@ -119,7 +118,6 @@ public sealed class BSPrim : PhysicsActor
_buoyancy = 1f; _buoyancy = 1f;
_velocity = OMV.Vector3.Zero; _velocity = OMV.Vector3.Zero;
_rotationalVelocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero;
_angularVelocity = OMV.Vector3.Zero;
_hullKey = 0; _hullKey = 0;
_meshKey = 0; _meshKey = 0;
_pbs = pbs; _pbs = pbs;
@ -146,7 +144,7 @@ public sealed class BSPrim : PhysicsActor
// called when this prim is being destroyed and we should free all the resources // called when this prim is being destroyed and we should free all the resources
public void Destroy() public void Destroy()
{ {
// m_log.DebugFormat("{0}: Destroy", LogHeader); // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
// Undo any vehicle properties // Undo any vehicle properties
_vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
_scene.RemoveVehiclePrim(this); // just to make sure _scene.RemoveVehiclePrim(this); // just to make sure
@ -203,7 +201,7 @@ public sealed class BSPrim : PhysicsActor
// link me to the specified parent // link me to the specified parent
public override void link(PhysicsActor obj) { public override void link(PhysicsActor obj) {
BSPrim parent = (BSPrim)obj; BSPrim parent = obj as BSPrim;
// m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
// TODO: decide if this parent checking needs to happen at taint time // TODO: decide if this parent checking needs to happen at taint time
if (_parentPrim == null) if (_parentPrim == null)
@ -527,10 +525,6 @@ public sealed class BSPrim : PhysicsActor
}); });
} }
} }
public OMV.Vector3 AngularVelocity {
get { return _angularVelocity; }
set { _angularVelocity = value; }
}
public override bool Kinematic { public override bool Kinematic {
get { return _kinematic; } get { return _kinematic; }
set { _kinematic = value; set { _kinematic = value;
@ -993,7 +987,7 @@ public sealed class BSPrim : PhysicsActor
} }
// m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
// LogHeader, _localID, _meshKey, indices.Length, vertices.Count); // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices,
vertices.Count, verticesAsFloats); vertices.Count, verticesAsFloats);
@ -1127,7 +1121,7 @@ public sealed class BSPrim : PhysicsActor
return; return;
} }
// Create an object in Bullet // Create an object in Bullet if it has not already been created
// No locking here because this is done when the physics engine is not simulating // No locking here because this is done when the physics engine is not simulating
private void CreateObject() private void CreateObject()
{ {
@ -1324,13 +1318,15 @@ public sealed class BSPrim : PhysicsActor
_velocity = entprop.Velocity; _velocity = entprop.Velocity;
_acceleration = entprop.Acceleration; _acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity; _rotationalVelocity = entprop.RotationalVelocity;
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
// LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
base.RequestPhysicsterseUpdate(); base.RequestPhysicsterseUpdate();
} }
} }
} }
// I've collided with something // I've collided with something
CollisionEventUpdate collisionCollection = null;
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
{ {
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@ -1348,11 +1344,18 @@ public sealed class BSPrim : PhysicsActor
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return; if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
_lastCollisionTime = nowTime; _lastCollisionTime = nowTime;
// create the event for the collision if (collisionCollection == null)
Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>(); collisionCollection = new CollisionEventUpdate();
contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
CollisionEventUpdate args = new CollisionEventUpdate(contactPoints); }
base.SendCollisionUpdate(args);
public void SendCollisions()
{
if (collisionCollection != null)
{
base.SendCollisionUpdate(collisionCollection);
collisionCollection = null;
}
} }
} }
} }

View File

@ -37,14 +37,18 @@ using OpenMetaverse;
using OpenSim.Region.Framework; using OpenSim.Region.Framework;
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
// Debug linkset
// Test with multiple regions in one simulator
// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) // Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
// Test sculpties // Test sculpties
// Compute physics FPS reasonably // Compute physics FPS reasonably
// Based on material, set density and friction // Based on material, set density and friction
// More efficient memory usage in passing hull information from BSPrim to BulletSim // More efficient memory usage when passing hull information from BSPrim to BulletSim
// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
// At the moment, physical and phantom causes object to drop through the terrain // At the moment, physical and phantom causes object to drop through the terrain
// Physical phantom objects and related typing (collision options )
// Check out llVolumeDetect. Must do something for that.
// Should prim.link() and prim.delink() membership checking happen at taint time? // Should prim.link() and prim.delink() membership checking happen at taint time?
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
@ -52,6 +56,16 @@ using OpenSim.Region.Framework;
// Implement LockAngularMotion // Implement LockAngularMotion
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
// Does NeedsMeshing() really need to exclude all the different shapes? // Does NeedsMeshing() really need to exclude all the different shapes?
// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
// Add PID movement operations. What does ScenePresence.MoveToTarget do?
// Check terrain size. 128 or 127?
// Multiple contact points on collision?
// See code in ode::near... calls to collision_accounting_events()
// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
// Use collision masks for collision with terrain and phantom objects
// Figure out how to not allocate a new Dictionary and List for every collision
// in BSPrim.Collide() and BSCharacter.Collide(). Can the same ones be reused?
// Raycast
// //
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
@ -64,6 +78,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
private List<BSPrim> m_vehicles = new List<BSPrim>(); private List<BSPrim> m_vehicles = new List<BSPrim>();
private float[] m_heightMap; private float[] m_heightMap;
private float m_waterLevel; private float m_waterLevel;
@ -164,6 +180,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
if (m_log.IsDebugEnabled) if (m_log.IsDebugEnabled)
{ {
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
// the handle is saved to it doesn't get freed after this call
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
} }
@ -172,7 +189,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
mesher = meshmerizer; mesher = meshmerizer;
// The bounding box for the simulated world // The bounding box for the simulated world
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f); Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
@ -220,10 +237,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
parms.terrainFriction = 0.5f; parms.terrainFriction = 0.5f;
parms.terrainHitFraction = 0.8f; parms.terrainHitFraction = 0.8f;
parms.terrainRestitution = 0f; parms.terrainRestitution = 0f;
parms.avatarFriction = 0.0f; parms.avatarFriction = 0.5f;
parms.avatarRestitution = 0.0f;
parms.avatarDensity = 60f; parms.avatarDensity = 60f;
parms.avatarCapsuleRadius = 0.37f; parms.avatarCapsuleRadius = 0.37f;
parms.avatarCapsuleHeight = 1.5f; // 2.140599f parms.avatarCapsuleHeight = 1.5f; // 2.140599f
parms.avatarContactProcessingThreshold = 0.1f;
parms.maxPersistantManifoldPoolSize = 0f;
parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
parms.numberOfSolverIterations = 0f; // means use default
if (config != null) if (config != null)
{ {
@ -265,14 +292,40 @@ public class BSScene : PhysicsScene, IPhysicsParameters
parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution); parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction); parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity); parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius); parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight); parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
} }
} }
m_params[0] = parms; m_params[0] = parms;
} }
// A helper function that handles a true/false parameter and returns the proper float number encoding
float ParamBoolean(IConfig config, string parmName, float deflt)
{
float ret = deflt;
if (config.Contains(parmName))
{
ret = ConfigurationParameters.numericFalse;
if (config.GetBoolean(parmName, false))
{
ret = ConfigurationParameters.numericTrue;
}
}
return ret;
}
// Called directly from unmanaged code so don't do much // Called directly from unmanaged code so don't do much
private void BulletLogger(string msg) private void BulletLogger(string msg)
{ {
@ -384,6 +437,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
} }
// The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator.
foreach (BSPrim bsp in m_primsWithCollisions)
bsp.SendCollisions();
m_primsWithCollisions.Clear();
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
// bsc.SendCollisions();
// This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
kvp.Value.SendCollisions();
m_avatarsWithCollisions.Clear();
// If any of the objects had updated properties, tell the object it has been changed by the physics engine // If any of the objects had updated properties, tell the object it has been changed by the physics engine
if (updatedEntityCount > 0) if (updatedEntityCount > 0)
{ {
@ -391,16 +455,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
{ {
EntityProperties entprop = m_updateArray[ii]; EntityProperties entprop = m_updateArray[ii];
// m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position);
BSCharacter actor;
if (m_avatars.TryGetValue(entprop.ID, out actor))
{
actor.UpdateProperties(entprop);
continue;
}
BSPrim prim; BSPrim prim;
if (m_prims.TryGetValue(entprop.ID, out prim)) if (m_prims.TryGetValue(entprop.ID, out prim))
{ {
prim.UpdateProperties(entprop); prim.UpdateProperties(entprop);
continue;
}
BSCharacter actor;
if (m_avatars.TryGetValue(entprop.ID, out actor))
{
actor.UpdateProperties(entprop);
} }
} }
} }
@ -434,11 +498,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BSPrim prim; BSPrim prim;
if (m_prims.TryGetValue(localID, out prim)) { if (m_prims.TryGetValue(localID, out prim)) {
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
m_primsWithCollisions.Add(prim);
return; return;
} }
BSCharacter actor; BSCharacter actor;
if (m_avatars.TryGetValue(localID, out actor)) { if (m_avatars.TryGetValue(localID, out actor)) {
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
m_avatarsWithCollisions.Add(actor);
return; return;
} }
return; return;
@ -470,12 +536,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public override void DeleteTerrain() public override void DeleteTerrain()
{ {
m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
} }
public override void Dispose() public override void Dispose()
{ {
m_log.DebugFormat("{0}: Dispose()", LogHeader); // m_log.DebugFormat("{0}: Dispose()", LogHeader);
} }
public override Dictionary<uint, float> GetTopColliders() public override Dictionary<uint, float> GetTopColliders()
@ -699,9 +765,23 @@ public class BSScene : PhysicsScene, IPhysicsParameters
new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ),
new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ),
new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ),
// new PhysParameterEntry("CcdMotionThreshold", "" ), new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ),
// new PhysParameterEntry("CcdSweptSphereRadius", "" ), new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ),
new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ),
// Can only change the following at initialization time. Change the INI file and reboot.
new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"),
new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"),
new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"),
new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"),
new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"),
new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"),
new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"),
new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ),
new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ),
new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ),
new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ),
new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ),
new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ),
@ -710,7 +790,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ),
new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ),
new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ),
new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ) new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ),
new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions")
}; };
#region IPhysicsParameters #region IPhysicsParameters
@ -733,6 +815,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
switch (lparm) switch (lparm)
{ {
case "detailedstats": m_detailedStatsStep = (int)val; break; case "detailedstats": m_detailedStatsStep = (int)val; break;
case "meshlod": m_meshLOD = (int)val; break; case "meshlod": m_meshLOD = (int)val; break;
case "sculptlod": m_sculptLOD = (int)val; break; case "sculptlod": m_sculptLOD = (int)val; break;
case "maxsubstep": m_maxSubSteps = (int)val; break; case "maxsubstep": m_maxSubSteps = (int)val; break;
@ -743,7 +826,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
case "defaultdensity": m_params[0].defaultDensity = val; break; case "defaultdensity": m_params[0].defaultDensity = val; break;
case "defaultrestitution": m_params[0].defaultRestitution = val; break; case "defaultrestitution": m_params[0].defaultRestitution = val; break;
case "collisionmargin": m_params[0].collisionMargin = val; break; case "collisionmargin": m_params[0].collisionMargin = val; break;
case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
@ -753,6 +836,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
// the following are used only at initialization time so setting them makes no sense
// case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
// case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
// case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
// case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
// case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
// case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
// case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
case "friction": TaintedUpdateParameter(lparm, localID, val); break;
case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
// set a terrain physical feature and cause terrain to be recalculated // set a terrain physical feature and cause terrain to be recalculated
case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
@ -764,6 +858,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
default: ret = false; break; default: ret = false; break;
} }
@ -856,6 +951,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
case "terrainfriction": val = m_params[0].terrainFriction; break; case "terrainfriction": val = m_params[0].terrainFriction; break;
case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
@ -866,6 +968,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
case "avatarrestitution": val = m_params[0].avatarRestitution; break; case "avatarrestitution": val = m_params[0].avatarRestitution; break;
case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break; case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break; case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
default: ret = false; break; default: ret = false; break;
} }

View File

@ -132,6 +132,15 @@ public struct ConfigurationParameters
public float avatarRestitution; public float avatarRestitution;
public float avatarCapsuleRadius; public float avatarCapsuleRadius;
public float avatarCapsuleHeight; public float avatarCapsuleHeight;
public float avatarContactProcessingThreshold;
public float maxPersistantManifoldPoolSize;
public float shouldDisableContactPoolDynamicAllocation;
public float shouldForceUpdateAllAabbs;
public float shouldRandomizeSolverOrder;
public float shouldSplitSimulationIslands;
public float shouldEnableFrictionCaching;
public float numberOfSolverIterations;
public const float numericTrue = 1f; public const float numericTrue = 1f;
public const float numericFalse = 0f; public const float numericFalse = 0f;
@ -148,17 +157,17 @@ public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
int maxCollisions, IntPtr collisionArray, int maxCollisions, IntPtr collisionArray,
int maxUpdates, IntPtr updateArray); int maxUpdates, IntPtr updateArray);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter(uint worldID, uint localID,
[MarshalAs(UnmanagedType.LPStr)]string paramCode, float value);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void Shutdown(uint worldID); public static extern void Shutdown(uint worldID);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter(uint worldID, uint localID,
[MarshalAs(UnmanagedType.LPStr)]string paramCode, float value);
// ===============================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount, out int updatedEntityCount,
@ -240,6 +249,7 @@ public static extern bool HasObject(uint worldID, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyObject(uint worldID, uint id); public static extern bool DestroyObject(uint worldID, uint id);
// ===============================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin); public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin);
@ -249,6 +259,7 @@ public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vec
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
// ===============================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void DumpBulletStatistics(); public static extern void DumpBulletStatistics();

View File

@ -120,33 +120,110 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// ///
/// </summary> /// </summary>
/// <param name="fname">The name of the function to invoke</param> /// <param name="fname">The name of the function to invoke</param>
/// <param name="fname">List of parameters</param> /// <param name="parms">List of parameters</param>
/// <returns>string result of the invocation</returns> /// <returns>string result of the invocation</returns>
public string modInvokeS(string fname, params object[] parms) public void modInvokeN(string fname, params object[] parms)
{ {
Type returntype = m_comms.LookupReturnType(fname); Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(string)) if (returntype != typeof(string))
MODError(String.Format("return type mismatch for {0}",fname)); MODError(String.Format("return type mismatch for {0}",fname));
return (string)modInvoke(fname,parms); modInvoke(fname,parms);
} }
public int modInvokeI(string fname, params object[] parms) public LSL_String modInvokeS(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(string))
MODError(String.Format("return type mismatch for {0}",fname));
string result = (string)modInvoke(fname,parms);
return new LSL_String(result);
}
public LSL_Integer modInvokeI(string fname, params object[] parms)
{ {
Type returntype = m_comms.LookupReturnType(fname); Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(int)) if (returntype != typeof(int))
MODError(String.Format("return type mismatch for {0}",fname)); MODError(String.Format("return type mismatch for {0}",fname));
return (int)modInvoke(fname,parms); int result = (int)modInvoke(fname,parms);
return new LSL_Integer(result);
} }
public float modInvokeF(string fname, params object[] parms) public LSL_Float modInvokeF(string fname, params object[] parms)
{ {
Type returntype = m_comms.LookupReturnType(fname); Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(float)) if (returntype != typeof(float))
MODError(String.Format("return type mismatch for {0}",fname)); MODError(String.Format("return type mismatch for {0}",fname));
return (float)modInvoke(fname,parms); float result = (float)modInvoke(fname,parms);
return new LSL_Float(result);
}
public LSL_Key modInvokeK(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(UUID))
MODError(String.Format("return type mismatch for {0}",fname));
UUID result = (UUID)modInvoke(fname,parms);
return new LSL_Key(result.ToString());
}
public LSL_Vector modInvokeV(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(OpenMetaverse.Vector3))
MODError(String.Format("return type mismatch for {0}",fname));
OpenMetaverse.Vector3 result = (OpenMetaverse.Vector3)modInvoke(fname,parms);
return new LSL_Vector(result.X,result.Y,result.Z);
}
public LSL_Rotation modInvokeR(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(OpenMetaverse.Quaternion))
MODError(String.Format("return type mismatch for {0}",fname));
OpenMetaverse.Quaternion result = (OpenMetaverse.Quaternion)modInvoke(fname,parms);
return new LSL_Rotation(result.X,result.Y,result.Z,result.W);
}
public LSL_List modInvokeL(string fname, params object[] parms)
{
Type returntype = m_comms.LookupReturnType(fname);
if (returntype != typeof(object[]))
MODError(String.Format("return type mismatch for {0}",fname));
object[] result = (object[])modInvoke(fname,parms);
object[] llist = new object[result.Length];
for (int i = 0; i < result.Length; i++)
{
if (result[i] is string)
llist[i] = new LSL_String((string)result[i]);
else if (result[i] is int)
llist[i] = new LSL_Integer((int)result[i]);
else if (result[i] is float)
llist[i] = new LSL_Float((float)result[i]);
else if (result[i] is OpenMetaverse.Vector3)
{
OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i];
llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z);
}
else if (result[i] is OpenMetaverse.Quaternion)
{
OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i];
llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W);
}
else
{
MODError(String.Format("unknown list element returned by {0}",fname));
}
}
return new LSL_List(llist);
} }
/// <summary> /// <summary>
@ -168,63 +245,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
MODError(String.Format("wrong number of parameters to function {0}",fname)); MODError(String.Format("wrong number of parameters to function {0}",fname));
object[] convertedParms = new object[parms.Length]; object[] convertedParms = new object[parms.Length];
for (int i = 0; i < parms.Length; i++) for (int i = 0; i < parms.Length; i++)
convertedParms[i] = ConvertFromLSL(parms[i],signature[i]);
// now call the function, the contract with the function is that it will always return
// non-null but don't trust it completely
try
{ {
if (parms[i] is LSL_String) object result = m_comms.InvokeOperation(m_host.UUID, m_itemID, fname, convertedParms);
{ if (result != null)
if (signature[i] != typeof(string)) return result;
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (string)(LSL_String)parms[i]; MODError(String.Format("Invocation of {0} failed; null return value",fname));
} }
else if (parms[i] is LSL_Integer) catch (Exception e)
{ {
if (signature[i] != typeof(int)) MODError(String.Format("Invocation of {0} failed; {1}",fname,e.Message));
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (int)(LSL_Integer)parms[i];
}
else if (parms[i] is LSL_Float)
{
if (signature[i] != typeof(float))
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (float)(LSL_Float)parms[i];
}
else if (parms[i] is LSL_Key)
{
if (signature[i] != typeof(string))
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (string)(LSL_Key)parms[i];
}
else if (parms[i] is LSL_Rotation)
{
if (signature[i] != typeof(string))
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (string)(LSL_Rotation)parms[i];
}
else if (parms[i] is LSL_Vector)
{
if (signature[i] != typeof(string))
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = (string)(LSL_Vector)parms[i];
}
else
{
if (signature[i] != parms[i].GetType())
MODError(String.Format("parameter type mismatch in {0}; expecting {1}",fname,signature[i].Name));
convertedParms[i] = parms[i];
}
} }
return m_comms.InvokeOperation(m_itemID,fname,convertedParms); return null;
} }
/// <summary>
/// Send a command to functions registered on an event
/// </summary>
public string modSendCommand(string module, string command, string k) public string modSendCommand(string module, string command, string k)
{ {
if (!m_MODFunctionsEnabled) if (!m_MODFunctionsEnabled)
@ -239,5 +283,101 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return req.ToString(); return req.ToString();
} }
/// <summary>
/// </summary>
protected object ConvertFromLSL(object lslparm, Type type)
{
// ---------- String ----------
if (lslparm is LSL_String)
{
if (type == typeof(string))
return (string)(LSL_String)lslparm;
// Need to check for UUID since keys are often treated as strings
if (type == typeof(UUID))
return new UUID((string)(LSL_String)lslparm);
}
// ---------- Integer ----------
else if (lslparm is LSL_Integer)
{
if (type == typeof(int))
return (int)(LSL_Integer)lslparm;
}
// ---------- Float ----------
else if (lslparm is LSL_Float)
{
if (type == typeof(float))
return (float)(LSL_Float)lslparm;
}
// ---------- Key ----------
else if (lslparm is LSL_Key)
{
if (type == typeof(UUID))
return new UUID((LSL_Key)lslparm);
}
// ---------- Rotation ----------
else if (lslparm is LSL_Rotation)
{
if (type == typeof(OpenMetaverse.Quaternion))
{
LSL_Rotation rot = (LSL_Rotation)lslparm;
return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
}
}
// ---------- Vector ----------
else if (lslparm is LSL_Vector)
{
if (type == typeof(OpenMetaverse.Vector3))
{
LSL_Vector vect = (LSL_Vector)lslparm;
return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
}
}
// ---------- List ----------
else if (lslparm is LSL_List)
{
if (type == typeof(object[]))
{
object[] plist = (lslparm as LSL_List).Data;
object[] result = new object[plist.Length];
for (int i = 0; i < plist.Length; i++)
{
if (plist[i] is LSL_String)
result[i] = (string)(LSL_String)plist[i];
else if (plist[i] is LSL_Integer)
result[i] = (int)(LSL_Integer)plist[i];
else if (plist[i] is LSL_Float)
result[i] = (float)(LSL_Float)plist[i];
else if (plist[i] is LSL_Key)
result[i] = new UUID((LSL_Key)plist[i]);
else if (plist[i] is LSL_Rotation)
{
LSL_Rotation rot = (LSL_Rotation)plist[i];
result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
}
else if (plist[i] is LSL_Vector)
{
LSL_Vector vect = (LSL_Vector)plist[i];
result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
}
else
MODError("unknown LSL list element type");
}
return result;
}
}
MODError(String.Format("parameter type mismatch; expecting {0}",type.Name));
return null;
}
} }
} }

View File

@ -28,26 +28,27 @@
using System.Collections; using System.Collections;
using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces;
using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{ {
public interface IMOD_Api public interface IMOD_Api
{ {
// Invocation functions // Invocation functions
string modInvokeS(string fname, params object[] parms); void modInvokeN(string fname, params object[] parms);
int modInvokeI(string fname, params object[] parms); LSL_String modInvokeS(string fname, params object[] parms);
float modInvokeF(string fname, params object[] parms); LSL_Integer modInvokeI(string fname, params object[] parms);
// vector modInvokeV(string fname, params object[] parms); LSL_Float modInvokeF(string fname, params object[] parms);
// rotation modInvokeV(string fname, params object[] parms); LSL_Key modInvokeK(string fname, params object[] parms);
// key modInvokeK(string fname, params object[] parms); LSL_Vector modInvokeV(string fname, params object[] parms);
// list modInvokeL(string fname, params object[] parms); LSL_Rotation modInvokeR(string fname, params object[] parms);
LSL_List modInvokeL(string fname, params object[] parms);
//Module functions //Module functions
string modSendCommand(string modules, string command, string k); string modSendCommand(string modules, string command, string k);

View File

@ -39,10 +39,14 @@ using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{ {
@ -58,21 +62,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
m_MOD_Functions = (IMOD_Api)api; m_MOD_Functions = (IMOD_Api)api;
} }
public string modInvokeS(string fname, params object[] parms) public void modInvokeN(string fname, params object[] parms)
{
m_MOD_Functions.modInvokeN(fname, parms);
}
public LSL_String modInvokeS(string fname, params object[] parms)
{ {
return m_MOD_Functions.modInvokeS(fname, parms); return m_MOD_Functions.modInvokeS(fname, parms);
} }
public int modInvokeI(string fname, params object[] parms) public LSL_Integer modInvokeI(string fname, params object[] parms)
{ {
return m_MOD_Functions.modInvokeI(fname, parms); return m_MOD_Functions.modInvokeI(fname, parms);
} }
public float modInvokeF(string fname, params object[] parms) public LSL_Float modInvokeF(string fname, params object[] parms)
{ {
return m_MOD_Functions.modInvokeF(fname, parms); return m_MOD_Functions.modInvokeF(fname, parms);
} }
public LSL_Key modInvokeK(string fname, params object[] parms)
{
return m_MOD_Functions.modInvokeK(fname, parms);
}
public LSL_Vector modInvokeV(string fname, params object[] parms)
{
return m_MOD_Functions.modInvokeV(fname, parms);
}
public LSL_Rotation modInvokeR(string fname, params object[] parms)
{
return m_MOD_Functions.modInvokeR(fname, parms);
}
public LSL_List modInvokeL(string fname, params object[] parms)
{
return m_MOD_Functions.modInvokeL(fname, parms);
}
public string modSendCommand(string module, string command, string k) public string modSendCommand(string module, string command, string k)
{ {
return m_MOD_Functions.modSendCommand(module, command, k); return m_MOD_Functions.modSendCommand(module, command, k);

View File

@ -846,10 +846,12 @@
TerrainFriction = 0.50 TerrainFriction = 0.50
TerrainHitFriction = 0.8 TerrainHitFriction = 0.8
TerrainRestitution = 0 TerrainRestitution = 0
AvatarFriction = 0 AvatarFriction = 0.2
AvatarRestitution = 0.0
AvatarDensity = 60.0 AvatarDensity = 60.0
AvatarCapsuleRadius = 0.37 AvatarCapsuleRadius = 0.37
AvatarCapsuleHeight = 1.5 AvatarCapsuleHeight = 1.5
AvatarContactProcessingThreshold = 0.1;
MaxObjectMass = 10000.01 MaxObjectMass = 10000.01
@ -862,6 +864,15 @@
CcdMotionThreshold = 0.0 CcdMotionThreshold = 0.0
CcdSweptSphereRadius = 0.0 CcdSweptSphereRadius = 0.0
ContactProcessingThreshold = 0.1 ContactProcessingThreshold = 0.1
; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc)
MaxPersistantManifoldPoolSize = 0;
ShouldDisableContactPoolDynamicAllocation = False;
ShouldForceUpdateAllAabbs = False;
ShouldRandomizeSolverOrder = False;
ShouldSplitSimulationIslands = False;
ShouldEnableFrictionCaching = False;
NumberOfSolverIterations = 0;
; Whether to mesh sculpties ; Whether to mesh sculpties
MeshSculptedPrim = true MeshSculptedPrim = true

Binary file not shown.

BIN
bin/lib32/libBulletSim.so Executable file

Binary file not shown.

Binary file not shown.

BIN
bin/lib64/libBulletSim.so Executable file

Binary file not shown.