Pass collisions and updates in pinned memory (saves marshaling).
Fix folding feet by using collision normals. Add constraint specification.bulletsim
parent
4cbc912375
commit
5ffec1cd64
|
@ -185,7 +185,7 @@ public class BSCharacter : PhysicsActor
|
|||
get { return _force; }
|
||||
set {
|
||||
_force = value;
|
||||
m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||
_scene.TaintedObject(delegate()
|
||||
{
|
||||
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
|
||||
|
@ -411,8 +411,9 @@ public class BSCharacter : PhysicsActor
|
|||
_collidingGroundStep = _scene.SimulationStep;
|
||||
}
|
||||
|
||||
// throttle collisions to the rate specified in the subscription
|
||||
if (_subscribedEventsMs == 0) return; // don't want collisions
|
||||
int nowTime = Util.EnvironmentTickCount();
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
|
||||
_lastCollisionTime = nowTime;
|
||||
|
||||
|
|
|
@ -261,6 +261,7 @@ public sealed class BSPrim : PhysicsActor
|
|||
{
|
||||
if (_childrenPrims.Contains(child))
|
||||
{
|
||||
BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID);
|
||||
_childrenPrims.Remove(child);
|
||||
child.ParentPrim = null; // the child has lost its parent
|
||||
RecreateGeomAndObject(); // rebuild my shape with the child removed
|
||||
|
@ -1018,47 +1019,8 @@ public sealed class BSPrim : PhysicsActor
|
|||
if (IsRootOfLinkset)
|
||||
{
|
||||
// Create a linkset around this object
|
||||
/*
|
||||
* NOTE: the original way of creating a linkset was to create a compound hull in the
|
||||
* root which consisted of the hulls of all the children. This didn't work well because
|
||||
* OpenSimulator needs updates and collisions for all the children and the physics
|
||||
* engine didn't create events for the children when the root hull was moved.
|
||||
* This code creates the compound hull.
|
||||
// If I am the root prim of a linkset, replace my physical shape with all the
|
||||
// pieces of the children.
|
||||
// All of the children should have called CreateGeom so they have a hull
|
||||
// in the physics engine already. Here we pull together all of those hulls
|
||||
// into one shape.
|
||||
int totalPrimsInLinkset = _childrenPrims.Count + 1;
|
||||
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
|
||||
ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
|
||||
FillShapeInfo(out shapes[0]);
|
||||
int ii = 1;
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
|
||||
prim.FillShapeInfo(out shapes[ii]);
|
||||
ii++;
|
||||
}
|
||||
BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
|
||||
*/
|
||||
// Create the linkset by putting constraints between the objects of the set so they cannot move
|
||||
// relative to each other.
|
||||
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
||||
|
||||
// remove any constraints that might be in place
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
|
||||
}
|
||||
// create constraints between the root prim and each of the children
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
// this is a constraint that allows no freedom of movement between the two objects
|
||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, OMV.Vector3.Zero, OMV.Vector3.Zero,
|
||||
OMV.Vector3.Zero, OMV.Vector3.Zero, OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
}
|
||||
CreateLinksetWithCompoundHull();
|
||||
// CreateLinksetWithConstraints();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1070,6 +1032,73 @@ public sealed class BSPrim : PhysicsActor
|
|||
}
|
||||
}
|
||||
|
||||
// Create a linkset by creating a compound hull at the root prim that consists of all
|
||||
// the children.
|
||||
void CreateLinksetWithCompoundHull()
|
||||
{
|
||||
// If I am the root prim of a linkset, replace my physical shape with all the
|
||||
// pieces of the children.
|
||||
// All of the children should have called CreateGeom so they have a hull
|
||||
// in the physics engine already. Here we pull together all of those hulls
|
||||
// into one shape.
|
||||
int totalPrimsInLinkset = _childrenPrims.Count + 1;
|
||||
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
|
||||
ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
|
||||
FillShapeInfo(out shapes[0]);
|
||||
int ii = 1;
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
|
||||
prim.FillShapeInfo(out shapes[ii]);
|
||||
ii++;
|
||||
}
|
||||
BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
|
||||
}
|
||||
|
||||
// Create the linkset by putting constraints between the objects of the set so they cannot move
|
||||
// relative to each other.
|
||||
void CreateLinksetWithConstraints()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
|
||||
|
||||
// remove any constraints that might be in place
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: CreateObject: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
|
||||
BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
|
||||
}
|
||||
// create constraints between the root prim and each of the children
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
// this is a constraint that allows no freedom of movement between the two objects
|
||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||
// m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
|
||||
|
||||
// relative position normalized to the root prim
|
||||
OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
|
||||
// OMV.Quaternion relativeRotation = OMV.Quaternion.Identity;
|
||||
|
||||
// rotation is pointing up the vector between the object centers
|
||||
OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromAxisAngle(childRelativePosition, 0f);
|
||||
|
||||
/* // the logic for relative rotation from http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6391
|
||||
OMV.Vector3 rrn = childRelativePosition;
|
||||
rrn.Normalize();
|
||||
rrn /= rrn.X;
|
||||
OMV.Matrix4 rotmat = new OMV.Matrix4(rrn.X, rrn.Y, rrn.Z, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromRotationMatrix(rotmat);
|
||||
*/
|
||||
|
||||
BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
|
||||
childRelativePosition / 2,
|
||||
relativeRotation,
|
||||
-childRelativePosition / 2,
|
||||
relativeRotation,
|
||||
OMV.Vector3.Zero, OMV.Vector3.Zero,
|
||||
OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy prim's info into the BulletSim shape description structure
|
||||
public void FillShapeInfo(out ShapeData shape)
|
||||
{
|
||||
|
@ -1118,50 +1147,53 @@ public sealed class BSPrim : PhysicsActor
|
|||
// The physics engine says that properties have updated. Update same and inform
|
||||
// the world that things have changed.
|
||||
// TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
|
||||
private int UpPropPosition = 1 << 0;
|
||||
private int UpPropRotation = 1 << 1;
|
||||
private int UpPropVelocity = 1 << 2;
|
||||
private int UpPropAcceleration = 1 << 3;
|
||||
private int UpPropAngularVel = 1 << 4;
|
||||
enum UpdatedProperties {
|
||||
Position = 1 << 0,
|
||||
Rotation = 1 << 1,
|
||||
Velocity = 1 << 2,
|
||||
Acceleration = 1 << 3,
|
||||
AngularVel = 1 << 4
|
||||
}
|
||||
|
||||
public void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
int changed = 0;
|
||||
UpdatedProperties changed = 0;
|
||||
// assign to the local variables so the normal set action does not happen
|
||||
if (_position != entprop.Position)
|
||||
{
|
||||
_position = entprop.Position;
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: position = {1}", LogHeader, _position);
|
||||
changed |= UpPropPosition;
|
||||
changed |= UpdatedProperties.Position;
|
||||
}
|
||||
if (_orientation != entprop.Rotation)
|
||||
{
|
||||
_orientation = entprop.Rotation;
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: rotation = {1}", LogHeader, _orientation);
|
||||
changed |= UpPropRotation;
|
||||
changed |= UpdatedProperties.Rotation;
|
||||
}
|
||||
if (_velocity != entprop.Velocity)
|
||||
{
|
||||
_velocity = entprop.Velocity;
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
|
||||
changed |= UpPropVelocity;
|
||||
changed |= UpdatedProperties.Velocity;
|
||||
}
|
||||
if (_acceleration != entprop.Acceleration)
|
||||
{
|
||||
_acceleration = entprop.Acceleration;
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
|
||||
changed |= UpPropAcceleration;
|
||||
changed |= UpdatedProperties.Acceleration;
|
||||
}
|
||||
if (_rotationalVelocity != entprop.AngularVelocity)
|
||||
{
|
||||
_rotationalVelocity = entprop.AngularVelocity;
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
|
||||
changed |= UpPropAngularVel;
|
||||
changed |= UpdatedProperties.AngularVel;
|
||||
}
|
||||
if (changed != 0)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
|
||||
base.RequestPhysicsterseUpdate();
|
||||
if (this._parentPrim == null)
|
||||
base.RequestPhysicsterseUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1210,7 @@ public sealed class BSPrim : PhysicsActor
|
|||
|
||||
if (_subscribedEventsMs == 0) return; // nothing in the object is waiting for collision events
|
||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||
int nowTime = Util.EnvironmentTickCount();
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
|
||||
_lastCollisionTime = nowTime;
|
||||
|
||||
|
|
|
@ -38,9 +38,7 @@ using OpenSim.Region.Framework;
|
|||
|
||||
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
|
||||
// Fix folding up feet
|
||||
// Fix terrain. Only flat terrain works. Terrain with shape is oriented wrong? Origined wrong?
|
||||
// Parameterize BulletSim. Pass a structure of parameters to the C++ code. Capsule size, friction, ...
|
||||
// Shift drag duplication of objects does not work
|
||||
// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
|
||||
// Test sculpties
|
||||
// Compute physics FPS reasonably
|
||||
|
@ -82,6 +80,19 @@ public class BSScene : PhysicsScene
|
|||
private long m_simulationStep = 0;
|
||||
public long SimulationStep { get { return m_simulationStep; } }
|
||||
|
||||
// A value of the time now so all the collision and update routines do not have to get their own
|
||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||
private int m_simulationNowTime;
|
||||
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
||||
|
||||
private int m_maxCollisionsPerFrame = 2048;
|
||||
private CollisionDesc[] m_collisionArray;
|
||||
private GCHandle m_collisionArrayPinnedHandle;
|
||||
|
||||
private int m_maxUpdatesPerFrame = 2048;
|
||||
private EntityProperties[] m_updateArray;
|
||||
private GCHandle m_updateArrayPinnedHandle;
|
||||
|
||||
private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
|
||||
private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
|
||||
public float maximumMassObject = 10000.01f;
|
||||
|
@ -129,8 +140,19 @@ public class BSScene : PhysicsScene
|
|||
_taintedObjects = new List<TaintCallback>();
|
||||
|
||||
mesher = meshmerizer;
|
||||
// The bounding box for the simulated world
|
||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f);
|
||||
|
||||
// Allocate pinned memory to pass back object property updates and collisions from simulation step
|
||||
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);
|
||||
|
||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||
m_worldID = BulletSimAPI.Initialize(new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f));
|
||||
m_worldID = BulletSimAPI.Initialize(worldExtent,
|
||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||
}
|
||||
|
||||
// Called directly from unmanaged code so don't do much
|
||||
|
@ -188,19 +210,7 @@ public class BSScene : PhysicsScene
|
|||
}
|
||||
|
||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation) // deprecated
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation, bool isPhysical)
|
||||
{
|
||||
m_log.ErrorFormat("{0}: CALL TO AddPrimShape in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||
return null;
|
||||
}
|
||||
|
||||
public override PhysicsActor AddPrimShape(uint localID, string primName, PrimitiveBaseShape pbs, Vector3 position,
|
||||
Vector3 size, Quaternion rotation, bool isPhysical)
|
||||
Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
|
||||
IMesh mesh = null;
|
||||
|
@ -225,10 +235,8 @@ public class BSScene : PhysicsScene
|
|||
{
|
||||
int updatedEntityCount;
|
||||
IntPtr updatedEntitiesPtr;
|
||||
IntPtr[] updatedEntities;
|
||||
int collidersCount;
|
||||
IntPtr collidersPtr;
|
||||
int[] colliders; // should be uint but Marshal.Copy does not have that overload
|
||||
|
||||
// update the prim states while we know the physics engine is not busy
|
||||
ProcessTaints();
|
||||
|
@ -242,32 +250,33 @@ public class BSScene : PhysicsScene
|
|||
int numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||
|
||||
// if there were collisions, they show up here
|
||||
// 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
|
||||
m_simulationNowTime = Util.EnvironmentTickCount();
|
||||
|
||||
// If there were collisions, process them by sending the event to the prim.
|
||||
// Collisions must be processed before updates.
|
||||
if (collidersCount > 0)
|
||||
{
|
||||
colliders = new int[collidersCount];
|
||||
Marshal.Copy(collidersPtr, colliders, 0, collidersCount);
|
||||
for (int ii = 0; ii < collidersCount; ii+=2)
|
||||
for (int ii = 0; ii < collidersCount; ii++)
|
||||
{
|
||||
uint cA = (uint)colliders[ii];
|
||||
uint cB = (uint)colliders[ii+1];
|
||||
SendCollision(cA, cB);
|
||||
SendCollision(cB, cA);
|
||||
uint cA = m_collisionArray[ii].aID;
|
||||
uint cB = m_collisionArray[ii].bID;
|
||||
Vector3 point = m_collisionArray[ii].point;
|
||||
Vector3 normal = m_collisionArray[ii].normal;
|
||||
SendCollision(cA, cB, point, normal, 0.01f);
|
||||
SendCollision(cB, cA, point, -normal, 0.01f);
|
||||
}
|
||||
}
|
||||
|
||||
// if any of the objects had updated properties, they are returned in the updatedEntity structure
|
||||
// TODO: figure out how to pass all of the EntityProperties structures in one marshal call.
|
||||
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
|
||||
if (updatedEntityCount > 0)
|
||||
{
|
||||
updatedEntities = new IntPtr[updatedEntityCount];
|
||||
// fetch all the pointers to all the EntityProperties structures for these updates
|
||||
Marshal.Copy(updatedEntitiesPtr, updatedEntities, 0, updatedEntityCount);
|
||||
for (int ii = 0; ii < updatedEntityCount; ii++)
|
||||
{
|
||||
IntPtr updatePointer = updatedEntities[ii];
|
||||
EntityProperties entprop = (EntityProperties)Marshal.PtrToStructure(updatePointer, typeof(EntityProperties));
|
||||
// m_log.DebugFormat("{0}: entprop: id={1}, pos={2}", LogHeader, entprop.ID, entprop.Position);
|
||||
EntityProperties entprop = m_updateArray[ii];
|
||||
// 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))
|
||||
{
|
||||
|
@ -282,12 +291,12 @@ public class BSScene : PhysicsScene
|
|||
}
|
||||
}
|
||||
|
||||
// fps calculation wrong. This calculation returns about 1 in normal operation.
|
||||
// fps calculation wrong. This calculation always returns about 1 in normal operation.
|
||||
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
||||
}
|
||||
|
||||
// Something has collided
|
||||
private void SendCollision(uint localID, uint collidingWith)
|
||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration)
|
||||
{
|
||||
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
||||
{
|
||||
|
@ -303,12 +312,12 @@ public class BSScene : PhysicsScene
|
|||
|
||||
BSPrim prim;
|
||||
if (m_prims.TryGetValue(localID, out prim)) {
|
||||
prim.Collide(collidingWith, type, Vector3.Zero, Vector3.UnitZ, 0.01f);
|
||||
prim.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f);
|
||||
return;
|
||||
}
|
||||
BSCharacter actor;
|
||||
if (m_avatars.TryGetValue(localID, out actor)) {
|
||||
actor.Collide(collidingWith, type, Vector3.Zero, Vector3.UnitZ, 0.01f);
|
||||
actor.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
@ -317,7 +326,6 @@ public class BSScene : PhysicsScene
|
|||
public override void GetResults() { }
|
||||
|
||||
public override void SetTerrain(float[] heightMap) {
|
||||
m_log.DebugFormat("{0}: SetTerrain", LogHeader);
|
||||
m_heightMap = heightMap;
|
||||
this.TaintedObject(delegate()
|
||||
{
|
||||
|
|
|
@ -78,7 +78,13 @@ public struct RaycastHit
|
|||
public float Fraction;
|
||||
public Vector3 Normal;
|
||||
}
|
||||
|
||||
public struct CollisionDesc
|
||||
{
|
||||
public uint aID;
|
||||
public uint bID;
|
||||
public Vector3 point;
|
||||
public Vector3 normal;
|
||||
}
|
||||
public struct EntityProperties
|
||||
{
|
||||
public uint ID;
|
||||
|
@ -92,7 +98,8 @@ public struct EntityProperties
|
|||
static class BulletSimAPI {
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern uint Initialize(Vector3 maxPosition);
|
||||
public static extern uint Initialize(Vector3 maxPosition, int maxCollisions, IntPtr collisionArray,
|
||||
int maxUpdates, IntPtr updateArray);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||
|
@ -124,7 +131,12 @@ public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData
|
|||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void AddConstraint(uint worldID, uint id1, uint id2,
|
||||
Vector3 frame1, Vector3 frame2, Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
Vector3 frame2, Quaternion frame2rot,
|
||||
Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraintByID(uint worldID, uint id1);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
<configuration>
|
||||
<dllmap os="windows" cpu="x86" dll="BulletSim" target="BulletSim" />
|
||||
<dllmap os="windows" cpu="x86-64,ia64" dll="BulletSim" target="BulletSim-x86_64" />
|
||||
<dllmap os="!windows,osx" cpu="x86" dll="BulletSim" target="libBulletSim" />
|
||||
<dllmap os="!windows,osx" cpu="x86-64,ia64" dll="BulletSim" target="libBulletSim-x86_64" />
|
||||
</configuration>
|
Binary file not shown.
Loading…
Reference in New Issue