BulletSim: complete movement of BulletSimAPI functions to BSAPITemplate.

Update BulletSim DLLs and SOs with simplier step function interface.
0.7.5-pf-bulletsim
Robert Adams 2012-12-31 16:22:45 -08:00
parent c2a7af18b6
commit 3d0fc70864
14 changed files with 312 additions and 195 deletions

View File

@ -111,10 +111,6 @@ public sealed class BSPrim : BSPhysObject
_mass = CalculateMass(); _mass = CalculateMass();
// No body or shape yet
PhysBody = new BulletBody(LocalID);
PhysShape = new BulletShape();
Linkset.Refresh(this); Linkset.Refresh(this);
DetailLog("{0},BSPrim.constructor,call", LocalID); DetailLog("{0},BSPrim.constructor,call", LocalID);

View File

@ -26,6 +26,7 @@
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using System.Text; using System.Text;
@ -36,31 +37,102 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public sealed class BSAPIUnman : BSAPITemplate public sealed class BSAPIUnman : BSAPITemplate
{ {
/*
// We pin the memory passed between the managed and unmanaged code.
GCHandle m_paramsHandle;
private GCHandle m_collisionArrayPinnedHandle;
private GCHandle m_updateArrayPinnedHandle;
// Handle to the callback used by the unmanaged code to call into the managed code.
// Used for debug logging.
// Need to store the handle in a persistant variable so it won't be freed.
private BSAPICPP.DebugLogCallback m_DebugLogCallbackHandle;
private BSScene PhysicsScene { get; set; }
public override string BulletEngineName { get { return "BulletUnmanaged"; } }
public override string BulletEngineVersion { get; protected set; }
public BSAPIUnman(string paramName, BSScene physScene)
{
PhysicsScene = physScene;
// Do something fancy with the paramName to get the right DLL implementation
// like "Bullet-2.80-OpenCL-Intel" loading the version for Intel based OpenCL implementation, etc.
}
// Initialization and simulation // Initialization and simulation
public BulletWorld Initialize(Vector3 maxPosition, IntPtr parms, public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
int maxCollisions, IntPtr collisionArray, int maxCollisions, ref CollisionDesc[] collisionArray,
int maxUpdates, IntPtr updateArray int maxUpdates, ref EntityProperties[] updateArray
); )
{
// Pin down the memory that will be used to pass object collisions and updates back from unmanaged code
m_paramsHandle = GCHandle.Alloc(parms, GCHandleType.Pinned);
m_collisionArrayPinnedHandle = GCHandle.Alloc(collisionArray, GCHandleType.Pinned);
m_updateArrayPinnedHandle = GCHandle.Alloc(updateArray, GCHandleType.Pinned);
public bool UpdateParameter(BulletWorld world, uint localID, String parm, float value); // If Debug logging level, enable logging from the unmanaged code
m_DebugLogCallbackHandle = null;
if (BSScene.m_log.IsDebugEnabled || PhysicsScene.PhysicsLogging.Enabled)
{
BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader);
if (PhysicsScene.PhysicsLogging.Enabled)
// The handle is saved in a variable to make sure it doesn't get freed after this call
m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLoggerPhysLog);
else
m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLogger);
}
// Get the version of the DLL
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
// BulletEngineVersion = BulletSimAPI.GetVersion2();
BulletEngineVersion = "";
// Call the unmanaged code with the buffers and other information
return new BulletWorld(0, PhysicsScene, BSAPICPP.Initialize2(maxPosition, m_paramsHandle.AddrOfPinnedObject(),
maxCollisions, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
maxUpdates, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
m_DebugLogCallbackHandle));
}
// Called directly from unmanaged code so don't do much
private void BulletLogger(string msg)
{
BSScene.m_log.Debug("[BULLETS UNMANAGED]:" + msg);
}
// Called directly from unmanaged code so don't do much
private void BulletLoggerPhysLog(string msg)
{
PhysicsScene.DetailLog("[BULLETS UNMANAGED]:" + msg);
}
/*
public void SetHeightMap(BulletWorld world, float[] heightmap); public void SetHeightMap(BulletWorld world, float[] heightmap);
public void Shutdown(BulletWorld sim);
public int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount,
out IntPtr updatedEntitiesPtr,
out int collidersCount,
out IntPtr collidersPtr);
*/ */
public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount, out int collidersCount)
{
return BSAPICPP.PhysicsStep2(world.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount);
}
public override void Shutdown(BulletWorld sim)
{
BSAPICPP.Shutdown2(sim.ptr);
}
public override bool PushUpdate(BulletBody obj) public override bool PushUpdate(BulletBody obj)
{ {
return BSAPICPP.PushUpdate2(obj.ptr); return BSAPICPP.PushUpdate2(obj.ptr);
} }
public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value)
{
return BSAPICPP.UpdateParameter2(world.ptr, localID, parm, value);
}
// ===================================================================================== // =====================================================================================
// Mesh, hull, shape and body creation helper routines // Mesh, hull, shape and body creation helper routines
public override BulletShape CreateMeshShape(BulletWorld world, public override BulletShape CreateMeshShape(BulletWorld world,
@ -893,11 +965,81 @@ public override float GetMargin(BulletShape shape)
return BSAPICPP.GetMargin2(shape.ptr); return BSAPICPP.GetMargin2(shape.ptr);
} }
// =====================================================================================
// Debugging
public override void DumpRigidBody(BulletWorld sim, BulletBody collisionObject)
{
BSAPICPP.DumpRigidBody2(sim.ptr, collisionObject.ptr);
}
public override void DumpCollisionShape(BulletWorld sim, BulletShape collisionShape)
{
BSAPICPP.DumpCollisionShape2(sim.ptr, collisionShape.ptr);
}
public override void DumpMapInfo(BulletWorld sim, BulletHMapInfo mapInfo)
{
BSAPICPP.DumpMapInfo2(sim.ptr, mapInfo.ptr);
}
public override void DumpConstraint(BulletWorld sim, BulletConstraint constrain)
{
BSAPICPP.DumpConstraint2(sim.ptr, constrain.ptr);
}
public override void DumpActivationInfo(BulletWorld sim)
{
BSAPICPP.DumpActivationInfo2(sim.ptr);
}
public override void DumpAllInfo(BulletWorld sim)
{
BSAPICPP.DumpAllInfo2(sim.ptr);
}
public override void DumpPhysicsStatistics(BulletWorld sim)
{
BSAPICPP.DumpPhysicsStatistics2(sim.ptr);
}
// =====================================================================================
// =====================================================================================
// =====================================================================================
// =====================================================================================
// =====================================================================================
// The actual interface to the unmanaged code
static class BSAPICPP static class BSAPICPP
{ {
// ===============================================================================
// Link back to the managed code for outputting log messages
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
// ===============================================================================
// Initialization and simulation
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
int maxCollisions, IntPtr collisionArray,
int maxUpdates, IntPtr updateArray,
DebugLogCallback logRoutine);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount, out int collidersCount);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void Shutdown2(IntPtr sim);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool PushUpdate2(IntPtr obj); public static extern bool PushUpdate2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
// ===================================================================================== // =====================================================================================
// Mesh, hull, shape and body creation helper routines // Mesh, hull, shape and body creation helper routines
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@ -1431,52 +1573,6 @@ public static extern void SetMargin2(IntPtr shape, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern float GetMargin2(IntPtr shape); public static extern float GetMargin2(IntPtr shape);
}
}
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
// ===============================================================================
static class BulletSimAPI {
// ===============================================================================
// Link back to the managed code for outputting log messages
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
// ===============================================================================
// Initialization and simulation
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
int maxCollisions, IntPtr collisionArray,
int maxUpdates, IntPtr updateArray,
DebugLogCallback logRoutine);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void Shutdown2(IntPtr sim);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount,
out IntPtr updatedEntitiesPtr,
out int collidersCount,
out IntPtr collidersPtr);
// ===================================================================================== // =====================================================================================
// Debugging // Debugging
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@ -1501,4 +1597,7 @@ public static extern void DumpAllInfo2(IntPtr sim);
public static extern void DumpPhysicsStatistics2(IntPtr sim); public static extern void DumpPhysicsStatistics2(IntPtr sim);
} }
}
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -32,7 +32,7 @@ using System.Text;
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
/* /*
public sealed class BSAPIXNA : BulletSimAPITemplate public sealed class BSAPIXNA : BSAPITemplate
{ {
} }
*/ */

View File

@ -292,26 +292,27 @@ public enum ConstraintParamAxis : int
public abstract class BSAPITemplate public abstract class BSAPITemplate
{ {
/* // Returns the name of the underlying Bullet engine
public abstract string BulletEngineName { get; }
public abstract string BulletEngineVersion { get; protected set;}
// Initialization and simulation // Initialization and simulation
public abstract BulletWorld Initialize(Vector3 maxPosition, IntPtr parms, public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
int maxCollisions, IntPtr collisionArray, int maxCollisions, ref CollisionDesc[] collisionArray,
int maxUpdates, IntPtr updateArray int maxUpdates, ref EntityProperties[] updateArray
); );
/*
public abstract void SetHeightMap(BulletWorld world, float[] heightmap);
*/
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, uint localID, String parm, float value);
public abstract void SetHeightMap(BulletWorld world, float[] heightmap);
public abstract void Shutdown(BulletWorld sim); public abstract void Shutdown(BulletWorld sim);
public abstract int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount,
out IntPtr updatedEntitiesPtr,
out int collidersCount,
out IntPtr collidersPtr);
*/
public abstract bool PushUpdate(BulletBody obj); public abstract bool PushUpdate(BulletBody obj);
// ===================================================================================== // =====================================================================================
@ -660,5 +661,21 @@ public abstract void SetMargin(BulletShape shape, float val);
public abstract float GetMargin(BulletShape shape); public abstract float GetMargin(BulletShape shape);
// =====================================================================================
// Debugging
public abstract void DumpRigidBody(BulletWorld sim, BulletBody collisionObject);
public abstract void DumpCollisionShape(BulletWorld sim, BulletShape collisionShape);
public abstract void DumpMapInfo(BulletWorld sim, BulletHMapInfo mapInfo);
public abstract void DumpConstraint(BulletWorld sim, BulletConstraint constrain);
public abstract void DumpActivationInfo(BulletWorld sim);
public abstract void DumpAllInfo(BulletWorld sim);
public abstract void DumpPhysicsStatistics(BulletWorld sim);
}; };
} }

View File

@ -823,7 +823,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (!IsActive) return; if (!IsActive) return;
if (PhysicsScene.VehiclePhysicalLoggingEnabled) if (PhysicsScene.VehiclePhysicalLoggingEnabled)
BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, Prim.PhysBody.ptr); PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
ForgetKnownVehicleProperties(); ForgetKnownVehicleProperties();
@ -840,7 +840,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
PushKnownChanged(); PushKnownChanged();
if (PhysicsScene.VehiclePhysicalLoggingEnabled) if (PhysicsScene.VehiclePhysicalLoggingEnabled)
BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, Prim.PhysBody.ptr); PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);

View File

@ -26,6 +26,7 @@
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -42,8 +43,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public sealed class BSScene : PhysicsScene, IPhysicsParameters public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); internal static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS SCENE]"; internal static readonly string LogHeader = "[BULLETS SCENE]";
// The name of the region we're working for. // The name of the region we're working for.
public string RegionName { get; private set; } public string RegionName { get; private set; }
@ -51,6 +52,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public string BulletSimVersion = "?"; public string BulletSimVersion = "?";
// The handle to the underlying managed or unmanaged version of Bullet being used. // The handle to the underlying managed or unmanaged version of Bullet being used.
public string BulletEngineName { get; private set; }
public BSAPITemplate PE; public BSAPITemplate PE;
public Dictionary<uint, BSPhysObject> PhysObjects; public Dictionary<uint, BSPhysObject> PhysObjects;
@ -102,11 +104,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Pinned memory used to pass step information between managed and unmanaged // Pinned memory used to pass step information between managed and unmanaged
internal int m_maxCollisionsPerFrame; internal int m_maxCollisionsPerFrame;
internal CollisionDesc[] m_collisionArray; internal CollisionDesc[] m_collisionArray;
internal GCHandle m_collisionArrayPinnedHandle;
internal int m_maxUpdatesPerFrame; internal int m_maxUpdatesPerFrame;
internal EntityProperties[] m_updateArray; internal EntityProperties[] m_updateArray;
internal GCHandle m_updateArrayPinnedHandle;
public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
public const uint GROUNDPLANE_ID = 1; public const uint GROUNDPLANE_ID = 1;
@ -152,12 +152,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// A pointer to an instance if this structure is passed to the C++ code // A pointer to an instance if this structure is passed to the C++ code
// Used to pass basic configuration values to the unmanaged code. // Used to pass basic configuration values to the unmanaged code.
internal ConfigurationParameters[] UnmanagedParams; internal ConfigurationParameters[] UnmanagedParams;
GCHandle m_paramsHandle;
// Handle to the callback used by the unmanaged code to call into the managed code.
// Used for debug logging.
// Need to store the handle in a persistant variable so it won't be freed.
private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
// Sometimes you just have to log everything. // Sometimes you just have to log everything.
public Logging.LogWriter PhysicsLogging; public Logging.LogWriter PhysicsLogging;
@ -194,15 +188,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Set default values for physics parameters plus any overrides from the ini file // Set default values for physics parameters plus any overrides from the ini file
GetInitialParameterValues(config); GetInitialParameterValues(config);
// For the moment, only one version of the interface // Get the connection to the physics engine (could be native or one of many DLLs)
PE = new BSAPIUnman(); PE = SelectUnderlyingBulletEngine(BulletEngineName);
// Allocate more pinned memory. Do this early to try and get all pinned memory close together.
m_paramsHandle = GCHandle.Alloc(UnmanagedParams, GCHandleType.Pinned);
m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned);
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
// Enable very detailed logging. // Enable very detailed logging.
// By creating an empty logger when not logging, the log message invocation code // By creating an empty logger when not logging, the log message invocation code
@ -217,22 +204,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
PhysicsLogging = new Logging.LogWriter(); PhysicsLogging = new Logging.LogWriter();
} }
// If Debug logging level, enable logging from the unmanaged code // Allocate memory for returning of the updates and collisions from the physics engine
m_DebugLogCallbackHandle = null; m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
{
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
if (PhysicsLogging.Enabled)
// The handle is saved in a variable to make sure it doesn't get freed after this call
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
else
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
}
// Get the version of the DLL
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
// BulletSimVersion = BulletSimAPI.GetVersion();
// m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
// The bounding box for the simulated world. The origin is 0,0,0 unless we're // The bounding box for the simulated world. The origin is 0,0,0 unless we're
// a child in a mega-region. // a child in a mega-region.
@ -240,11 +214,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// area. It tracks active objects no matter where they are. // area. It tracks active objects no matter where they are.
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
World = new BulletWorld(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
m_DebugLogCallbackHandle));
Constraints = new BSConstraintCollection(World); Constraints = new BSConstraintCollection(World);
@ -274,6 +244,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
BSParam.SetParameterConfigurationValues(this, pConfig); BSParam.SetParameterConfigurationValues(this, pConfig);
// There are two Bullet implementations to choose from
BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
// Very detailed logging for physics debugging // Very detailed logging for physics debugging
// TODO: the boolean values can be moved to the normal parameter processing. // TODO: the boolean values can be moved to the normal parameter processing.
m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
@ -315,16 +288,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
return ret; return ret;
} }
// Called directly from unmanaged code so don't do much // Select the connection to the actual Bullet implementation.
private void BulletLogger(string msg) // The main engine selection is the engineName up to the first hypen.
// So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name
// is passed to the engine to do its special selection, etc.
private BSAPITemplate SelectUnderlyingBulletEngine(string engineName)
{ {
m_log.Debug("[BULLETS UNMANAGED]:" + msg); // For the moment, do a simple switch statement.
} // Someday do fancyness with looking up the interfaces in the assembly.
BSAPITemplate ret = null;
// Called directly from unmanaged code so don't do much string selectionName = engineName.ToLower();
private void BulletLoggerPhysLog(string msg) int hyphenIndex = engineName.IndexOf("-");
{ if (hyphenIndex > 0)
DetailLog("[BULLETS UNMANAGED]:" + msg); selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1);
switch (selectionName)
{
case "bulletunmanaged":
ret = new BSAPIUnman(engineName, this);
break;
case "bulletxna":
// ret = new BSAPIXNA(engineName, this);
break;
}
if (ret == null)
{
m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader);
}
else
{
m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
}
return ret;
} }
public override void Dispose() public override void Dispose()
@ -361,7 +359,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
} }
// Anything left in the unmanaged code should be cleaned out // Anything left in the unmanaged code should be cleaned out
BulletSimAPI.Shutdown2(World.ptr); PE.Shutdown(World);
// Not logging any more // Not logging any more
PhysicsLogging.Close(); PhysicsLogging.Close();
@ -474,9 +472,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
LastTimeStep = timeStep; LastTimeStep = timeStep;
int updatedEntityCount = 0; int updatedEntityCount = 0;
IntPtr updatedEntitiesPtr;
int collidersCount = 0; int collidersCount = 0;
IntPtr collidersPtr;
int beforeTime = 0; int beforeTime = 0;
int simTime = 0; int simTime = 0;
@ -492,6 +488,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
TriggerPreStepEvent(timeStep); TriggerPreStepEvent(timeStep);
// the prestep actions might have added taints // the prestep actions might have added taints
numTaints += _taintOperations.Count;
ProcessTaints(); ProcessTaints();
InTaintTime = false; // Only used for debugging so locking is not necessary. InTaintTime = false; // Only used for debugging so locking is not necessary.
@ -499,23 +496,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
// Only enable this in a limited test world with few objects. // Only enable this in a limited test world with few objects.
if (m_physicsPhysicalDumpEnabled) if (m_physicsPhysicalDumpEnabled)
BulletSimAPI.DumpAllInfo2(World.ptr); PE.DumpAllInfo(World);
// step the physical world one interval // step the physical world one interval
m_simulationStep++; m_simulationStep++;
int numSubSteps = 0; int numSubSteps = 0;
try try
{ {
if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); if (PhysicsLogging.Enabled)
beforeTime = Util.EnvironmentTickCount();
numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); if (PhysicsLogging.Enabled)
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}", {
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, simTime = Util.EnvironmentTickCountSubtract(beforeTime);
updatedEntityCount, collidersCount, ObjectsWithCollisions.Count); DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -527,8 +526,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
collidersCount = 0; collidersCount = 0;
} }
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
// Get a value for 'now' so all the collision and update routines don't have to get their own. // Get a value for 'now' so all the collision and update routines don't have to get their own.
SimulationNowTime = Util.EnvironmentTickCount(); SimulationNowTime = Util.EnvironmentTickCount();
@ -570,7 +567,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Objects that are done colliding are removed from the ObjectsWithCollisions list. // Objects that are done colliding are removed from the ObjectsWithCollisions list.
// Not done above because it is inside an iteration of ObjectWithCollisions. // Not done above because it is inside an iteration of ObjectWithCollisions.
// This complex collision processing is required to create an empty collision // This complex collision processing is required to create an empty collision
// event call after all collisions have happened on an object. This enables // event call after all real collisions have happened on an object. This enables
// the simulator to generate the 'collision end' event. // the simulator to generate the 'collision end' event.
if (ObjectsWithNoMoreCollisions.Count > 0) if (ObjectsWithNoMoreCollisions.Count > 0)
{ {
@ -599,11 +596,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
// Only enable this in a limited test world with few objects. // Only enable this in a limited test world with few objects.
if (m_physicsPhysicalDumpEnabled) if (m_physicsPhysicalDumpEnabled)
BulletSimAPI.DumpAllInfo2(World.ptr); PE.DumpAllInfo(World);
// The physics engine returns the number of milliseconds it simulated this call. // The physics engine returns the number of milliseconds it simulated this call.
// These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
// Multiply by 55 to give a nominal frame rate of 55. // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
} }

View File

@ -44,7 +44,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
{ {
static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
BulletHeightMapInfo m_mapInfo = null; BulletHMapInfo m_mapInfo = null;
// Constructor to build a default, flat heightmap terrain. // Constructor to build a default, flat heightmap terrain.
public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
@ -58,7 +58,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
{ {
initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
} }
m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo = new BulletHMapInfo(id, initialMap, IntPtr.Zero);
m_mapInfo.minCoords = minTerrainCoords; m_mapInfo.minCoords = minTerrainCoords;
m_mapInfo.maxCoords = maxTerrainCoords; m_mapInfo.maxCoords = maxTerrainCoords;
m_mapInfo.terrainRegionBase = TerrainBase; m_mapInfo.terrainRegionBase = TerrainBase;
@ -72,7 +72,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
Vector3 minCoords, Vector3 maxCoords) Vector3 minCoords, Vector3 maxCoords)
: base(physicsScene, regionBase, id) : base(physicsScene, regionBase, id)
{ {
m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo = new BulletHMapInfo(id, initialMap, IntPtr.Zero);
m_mapInfo.minCoords = minCoords; m_mapInfo.minCoords = minCoords;
m_mapInfo.maxCoords = maxCoords; m_mapInfo.maxCoords = maxCoords;
m_mapInfo.minZ = minCoords.Z; m_mapInfo.minZ = minCoords.Z;
@ -91,12 +91,12 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
// Using the information in m_mapInfo, create the physical representation of the heightmap. // Using the information in m_mapInfo, create the physical representation of the heightmap.
private void BuildHeightmapTerrain() private void BuildHeightmapTerrain()
{ {
m_mapInfo.Ptr = PhysicsScene.PE.CreateHeightMapInfo(PhysicsScene.World, m_mapInfo.ID, m_mapInfo.ptr = PhysicsScene.PE.CreateHeightMapInfo(PhysicsScene.World, m_mapInfo.ID,
m_mapInfo.minCoords, m_mapInfo.maxCoords, m_mapInfo.minCoords, m_mapInfo.maxCoords,
m_mapInfo.heightMap, BSParam.TerrainCollisionMargin); m_mapInfo.heightMap, BSParam.TerrainCollisionMargin);
// Create the terrain shape from the mapInfo // Create the terrain shape from the mapInfo
m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape(m_mapInfo.Ptr); m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape(m_mapInfo.ptr);
// The terrain object initial position is at the center of the object // The terrain object initial position is at the center of the object
Vector3 centerPos; Vector3 centerPos;
@ -138,7 +138,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody);
// Frees both the body and the shape. // Frees both the body and the shape.
PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody);
PhysicsScene.PE.ReleaseHeightMapInfo(m_mapInfo.Ptr); PhysicsScene.PE.ReleaseHeightMapInfo(m_mapInfo.ptr);
} }
} }
m_mapInfo = null; m_mapInfo = null;

View File

@ -187,11 +187,11 @@ public class BulletConstraint
// Made a class rather than a struct so there would be only one // Made a class rather than a struct so there would be only one
// instance of this and C# will pass around pointers rather // instance of this and C# will pass around pointers rather
// than making copies. // than making copies.
public class BulletHeightMapInfo public class BulletHMapInfo
{ {
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { public BulletHMapInfo(uint id, float[] hm, IntPtr xx) {
ID = id; ID = id;
Ptr = xx; ptr = xx;
heightMap = hm; heightMap = hm;
terrainRegionBase = OMV.Vector3.Zero; terrainRegionBase = OMV.Vector3.Zero;
minCoords = new OMV.Vector3(100f, 100f, 25f); minCoords = new OMV.Vector3(100f, 100f, 25f);
@ -200,7 +200,7 @@ public class BulletHeightMapInfo
sizeX = sizeY = 256f; sizeX = sizeY = 256f;
} }
public uint ID; public uint ID;
public IntPtr Ptr; public IntPtr ptr;
public float[] heightMap; public float[] heightMap;
public OMV.Vector3 terrainRegionBase; public OMV.Vector3 terrainRegionBase;
public OMV.Vector3 minCoords; public OMV.Vector3 minCoords;

View File

@ -61,7 +61,8 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
BULLETSIM TODO LIST: BULLETSIM TODO LIST:
================================================= =================================================
Avatar density is WAY off. Compare and calibrate with what's in SL. Implement an avatar mesh shape. The Bullet capsule is way too limited.
Consider just hand creating a vertex/index array in a new BSShapeAvatar.
Revisit CollisionMargin. Builders notice the 0.04 spacing between prims. Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
Duplicating a physical prim causes old prim to jump away Duplicating a physical prim causes old prim to jump away
Dup a phys prim and the original become unselected and thus interacts w/ selected prim. Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
@ -170,6 +171,9 @@ Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/3179
INTERNAL IMPROVEMENT/CLEANUP INTERNAL IMPROVEMENT/CLEANUP
================================================= =================================================
Create the physical wrapper classes (BulletBody, BulletShape) by methods on
BSAPITemplate and make their actual implementation Bullet engine specific.
For the short term, just call the existing functions in ShapeCollection.
Consider moving prim/character body and shape destruction in destroy() Consider moving prim/character body and shape destruction in destroy()
to postTimeTime rather than protecting all the potential sets that to postTimeTime rather than protecting all the potential sets that
might have been queued up. might have been queued up.
@ -204,6 +208,8 @@ Should taints check for existance or activeness of target?
Possibly have and 'active' flag that is checked by the taint processor? Possibly have and 'active' flag that is checked by the taint processor?
Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones) Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'? Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
There are TOO MANY interfaces from BulletSim core to Bullet itself
Think of something to eliminate one or more of the layers
THREADING THREADING
================================================= =================================================
@ -262,3 +268,5 @@ llApplyImpulse()
(Resolution: tested on SL and OS. AddForce scales the force for timestep) (Resolution: tested on SL and OS. AddForce scales the force for timestep)
llSetBuoyancy() (DONE) llSetBuoyancy() (DONE)
(Resolution: Bullet resets object gravity when added to world. Moved set gravity) (Resolution: Bullet resets object gravity when added to world. Moved set gravity)
Avatar density is WAY off. Compare and calibrate with what's in SL. (DONE)
(Resolution: set default density to 3.5 (from 60) which is closer to SL)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.