Merge branch 'master' into careminster
commit
e2e8b09059
|
@ -34,13 +34,12 @@ using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSCharacter : PhysicsActor
|
public class BSCharacter : BSPhysObject
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static readonly string LogHeader = "[BULLETS CHAR]";
|
private static readonly string LogHeader = "[BULLETS CHAR]";
|
||||||
|
|
||||||
private BSScene _scene;
|
public BSScene Scene { get; private set; }
|
||||||
public BSScene Scene { get { return _scene; } }
|
|
||||||
private String _avName;
|
private String _avName;
|
||||||
// private bool _stopped;
|
// private bool _stopped;
|
||||||
private Vector3 _size;
|
private Vector3 _size;
|
||||||
|
@ -74,11 +73,8 @@ public class BSCharacter : PhysicsActor
|
||||||
private bool _kinematic;
|
private bool _kinematic;
|
||||||
private float _buoyancy;
|
private float _buoyancy;
|
||||||
|
|
||||||
private BulletBody m_body;
|
public override BulletBody Body { get; set; }
|
||||||
public BulletBody Body {
|
public override BSLinkset Linkset { get; set; }
|
||||||
get { return m_body; }
|
|
||||||
set { m_body = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _subscribedEventsMs = 0;
|
private int _subscribedEventsMs = 0;
|
||||||
private int _nextCollisionOkTime = 0;
|
private int _nextCollisionOkTime = 0;
|
||||||
|
@ -95,7 +91,7 @@ public class BSCharacter : PhysicsActor
|
||||||
{
|
{
|
||||||
_localID = localID;
|
_localID = localID;
|
||||||
_avName = avName;
|
_avName = avName;
|
||||||
_scene = parent_scene;
|
Scene = parent_scene;
|
||||||
_position = pos;
|
_position = pos;
|
||||||
_size = size;
|
_size = size;
|
||||||
_flying = isFlying;
|
_flying = isFlying;
|
||||||
|
@ -104,10 +100,12 @@ public class BSCharacter : PhysicsActor
|
||||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||||
// The dimensions of the avatar capsule are kept in the scale.
|
// The dimensions of the avatar capsule are kept in the scale.
|
||||||
// Physics creates a unit capsule which is scaled by the physics engine.
|
// Physics creates a unit capsule which is scaled by the physics engine.
|
||||||
_scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
|
_scale = new Vector3(Scene.Params.avatarCapsuleRadius, Scene.Params.avatarCapsuleRadius, size.Z);
|
||||||
_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
|
||||||
|
|
||||||
|
Linkset = new BSLinkset(Scene, this);
|
||||||
|
|
||||||
ShapeData shapeData = new ShapeData();
|
ShapeData shapeData = new ShapeData();
|
||||||
shapeData.ID = _localID;
|
shapeData.ID = _localID;
|
||||||
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
|
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
|
||||||
|
@ -118,19 +116,19 @@ public class BSCharacter : PhysicsActor
|
||||||
shapeData.Mass = _mass;
|
shapeData.Mass = _mass;
|
||||||
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.avatarRestitution;
|
shapeData.Restitution = Scene.Params.avatarRestitution;
|
||||||
|
|
||||||
// do actual create at taint time
|
// do actual create at taint time
|
||||||
_scene.TaintedObject("BSCharacter.create", delegate()
|
Scene.TaintedObject("BSCharacter.create", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.create", _localID);
|
DetailLog("{0},BSCharacter.create", _localID);
|
||||||
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
|
BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
|
||||||
|
|
||||||
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
||||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||||
|
|
||||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||||
});
|
});
|
||||||
|
@ -139,12 +137,12 @@ public class BSCharacter : PhysicsActor
|
||||||
}
|
}
|
||||||
|
|
||||||
// called when this character is being destroyed and the resources should be released
|
// called when this character is being destroyed and the resources should be released
|
||||||
public void Destroy()
|
public override void Destroy()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.Destroy", LocalID);
|
DetailLog("{0},BSCharacter.Destroy", LocalID);
|
||||||
_scene.TaintedObject("BSCharacter.destroy", delegate()
|
Scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||||
{
|
{
|
||||||
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
|
BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,9 +171,9 @@ public class BSCharacter : PhysicsActor
|
||||||
|
|
||||||
ComputeAvatarVolumeAndMass();
|
ComputeAvatarVolumeAndMass();
|
||||||
|
|
||||||
_scene.TaintedObject("BSCharacter.setSize", delegate()
|
Scene.TaintedObject("BSCharacter.setSize", delegate()
|
||||||
{
|
{
|
||||||
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
|
BulletSimAPI.SetObjectScaleMass(Scene.WorldID, LocalID, _scale, _mass, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -204,17 +202,17 @@ public class BSCharacter : PhysicsActor
|
||||||
|
|
||||||
public override Vector3 Position {
|
public override Vector3 Position {
|
||||||
get {
|
get {
|
||||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||||
return _position;
|
return _position;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
_position = value;
|
_position = value;
|
||||||
PositionSanityCheck();
|
PositionSanityCheck();
|
||||||
|
|
||||||
_scene.TaintedObject("BSCharacter.setPosition", delegate()
|
Scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,16 +225,35 @@ public class BSCharacter : PhysicsActor
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
// If below the ground, move the avatar up
|
// If below the ground, move the avatar up
|
||||||
float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
|
float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||||
if (_position.Z < terrainHeight)
|
if (Position.Z < terrainHeight)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||||
_position.Z = terrainHeight + 2.0f;
|
_position.Z = terrainHeight + 2.0f;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for out of bounds
|
// TODO: check for out of bounds
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A version of the sanity check that also makes sure a new position value is
|
||||||
|
// pushed back to the physics engine. This routine would be used by anyone
|
||||||
|
// who is not already pushing the value.
|
||||||
|
private bool PositionSanityCheck2()
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
if (PositionSanityCheck())
|
||||||
|
{
|
||||||
|
// The new position value must be pushed into the physics engine but we can't
|
||||||
|
// just assign to "Position" because of potential call loops.
|
||||||
|
Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||||
|
});
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +262,10 @@ public class BSCharacter : PhysicsActor
|
||||||
return _mass;
|
return _mass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// used when we only want this prim's mass and not the linkset thing
|
||||||
|
public override float MassRaw { get {return _mass; } }
|
||||||
|
|
||||||
public override Vector3 Force {
|
public override Vector3 Force {
|
||||||
get { return _force; }
|
get { return _force; }
|
||||||
set {
|
set {
|
||||||
|
@ -277,10 +298,10 @@ public class BSCharacter : PhysicsActor
|
||||||
set {
|
set {
|
||||||
_velocity = value;
|
_velocity = value;
|
||||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
||||||
_scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
Scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||||
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
|
BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,10 +324,10 @@ public class BSCharacter : PhysicsActor
|
||||||
set {
|
set {
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||||
_scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
Scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||||
{
|
{
|
||||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,11 +364,11 @@ public class BSCharacter : PhysicsActor
|
||||||
set { _throttleUpdates = value; }
|
set { _throttleUpdates = value; }
|
||||||
}
|
}
|
||||||
public override bool IsColliding {
|
public override bool IsColliding {
|
||||||
get { return (_collidingStep == _scene.SimulationStep); }
|
get { return (_collidingStep == Scene.SimulationStep); }
|
||||||
set { _isColliding = value; }
|
set { _isColliding = value; }
|
||||||
}
|
}
|
||||||
public override bool CollidingGround {
|
public override bool CollidingGround {
|
||||||
get { return (_collidingGroundStep == _scene.SimulationStep); }
|
get { return (_collidingGroundStep == Scene.SimulationStep); }
|
||||||
set { _collidingGround = value; }
|
set { _collidingGround = value; }
|
||||||
}
|
}
|
||||||
public override bool CollidingObj {
|
public override bool CollidingObj {
|
||||||
|
@ -369,10 +390,10 @@ public class BSCharacter : PhysicsActor
|
||||||
public override float Buoyancy {
|
public override float Buoyancy {
|
||||||
get { return _buoyancy; }
|
get { return _buoyancy; }
|
||||||
set { _buoyancy = value;
|
set { _buoyancy = value;
|
||||||
_scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +437,7 @@ public class BSCharacter : PhysicsActor
|
||||||
_force.Y += force.Y;
|
_force.Y += force.Y;
|
||||||
_force.Z += force.Z;
|
_force.Z += force.Z;
|
||||||
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
|
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
|
||||||
_scene.TaintedObject("BSCharacter.AddForce", delegate()
|
Scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||||
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
||||||
|
@ -448,6 +469,12 @@ public class BSCharacter : PhysicsActor
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ZeroMotion()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Stop collision events
|
// Stop collision events
|
||||||
public override void UnSubscribeEvents() {
|
public override void UnSubscribeEvents() {
|
||||||
_subscribedEventsMs = 0;
|
_subscribedEventsMs = 0;
|
||||||
|
@ -481,7 +508,7 @@ public class BSCharacter : PhysicsActor
|
||||||
|
|
||||||
// The physics engine says that properties have updated. Update same and inform
|
// The physics engine says that properties have updated. Update same and inform
|
||||||
// the world that things have changed.
|
// the world that things have changed.
|
||||||
public void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
_position = entprop.Position;
|
_position = entprop.Position;
|
||||||
_orientation = entprop.Rotation;
|
_orientation = entprop.Rotation;
|
||||||
|
@ -491,30 +518,33 @@ public class BSCharacter : PhysicsActor
|
||||||
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
||||||
// base.RequestPhysicsterseUpdate();
|
// base.RequestPhysicsterseUpdate();
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
|
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
||||||
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
|
PositionSanityCheck2();
|
||||||
entprop.Acceleration, entprop.RotationalVelocity);
|
|
||||||
|
float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
|
||||||
|
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
|
||||||
|
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the scene when a collision with this object is reported
|
// Called by the scene when a collision with this object is reported
|
||||||
// The collision, if it should be reported to the character, is placed in a collection
|
// The collision, if it should be reported to the character, is placed in a collection
|
||||||
// that will later be sent to the simulator when SendCollisions() is called.
|
// that will later be sent to the simulator when SendCollisions() is called.
|
||||||
CollisionEventUpdate collisionCollection = null;
|
CollisionEventUpdate collisionCollection = null;
|
||||||
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
public override void Collide(uint collidingWith, BSPhysObject collidee, 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);
|
||||||
|
|
||||||
// The following makes IsColliding() and IsCollidingGround() work
|
// The following makes IsColliding() and IsCollidingGround() work
|
||||||
_collidingStep = _scene.SimulationStep;
|
_collidingStep = Scene.SimulationStep;
|
||||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||||
{
|
{
|
||||||
_collidingGroundStep = _scene.SimulationStep;
|
_collidingGroundStep = Scene.SimulationStep;
|
||||||
}
|
}
|
||||||
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
||||||
|
|
||||||
// throttle collisions to the rate specified in the subscription
|
// throttle collisions to the rate specified in the subscription
|
||||||
if (_subscribedEventsMs != 0) {
|
if (_subscribedEventsMs != 0) {
|
||||||
int nowTime = _scene.SimulationNowTime;
|
int nowTime = Scene.SimulationNowTime;
|
||||||
if (nowTime >= _nextCollisionOkTime) {
|
if (nowTime >= _nextCollisionOkTime) {
|
||||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||||
|
|
||||||
|
@ -525,7 +555,7 @@ public class BSCharacter : PhysicsActor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SendCollisions()
|
public override void SendCollisions()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||||
|
|
|
@ -48,11 +48,10 @@ public abstract class BSConstraint : IDisposable
|
||||||
{
|
{
|
||||||
if (m_enabled)
|
if (m_enabled)
|
||||||
{
|
{
|
||||||
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
|
m_enabled = false;
|
||||||
bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
|
bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
|
||||||
m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
|
m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
|
||||||
m_constraint.Ptr = System.IntPtr.Zero;
|
m_constraint.Ptr = System.IntPtr.Zero;
|
||||||
m_enabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -465,6 +465,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
}//end SetDefaultsForType
|
}//end SetDefaultsForType
|
||||||
|
|
||||||
|
// One step of the vehicle properties for the next 'pTimestep' seconds.
|
||||||
internal void Step(float pTimestep)
|
internal void Step(float pTimestep)
|
||||||
{
|
{
|
||||||
if (m_type == Vehicle.TYPE_NONE) return;
|
if (m_type == Vehicle.TYPE_NONE) return;
|
||||||
|
@ -592,9 +593,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
// If below the terrain, move us above the ground a little.
|
// If below the terrain, move us above the ground a little.
|
||||||
if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
|
if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
|
||||||
{
|
{
|
||||||
pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
|
pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
|
||||||
m_prim.Position = pos;
|
m_prim.Position = pos;
|
||||||
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
||||||
}
|
}
|
||||||
|
@ -609,7 +610,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
}
|
}
|
||||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||||
{
|
{
|
||||||
m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||||
}
|
}
|
||||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||||
{
|
{
|
||||||
|
@ -673,7 +674,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
grav.Z = (float)(grav.Z * 1.125);
|
grav.Z = (float)(grav.Z * 1.125);
|
||||||
}
|
}
|
||||||
float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
|
float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||||
float postemp = (pos.Z - terraintemp);
|
float postemp = (pos.Z - terraintemp);
|
||||||
if (postemp > 2.5f)
|
if (postemp > 2.5f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,8 +36,8 @@ public class BSLinkset
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM LINKSET]";
|
private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||||
|
|
||||||
private BSPrim m_linksetRoot;
|
private BSPhysObject m_linksetRoot;
|
||||||
public BSPrim LinksetRoot { get { return m_linksetRoot; } }
|
public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
|
||||||
|
|
||||||
private BSScene m_physicsScene;
|
private BSScene m_physicsScene;
|
||||||
public BSScene PhysicsScene { get { return m_physicsScene; } }
|
public BSScene PhysicsScene { get { return m_physicsScene; } }
|
||||||
|
@ -46,7 +46,7 @@ public class BSLinkset
|
||||||
public int LinksetID { get; private set; }
|
public int LinksetID { get; private set; }
|
||||||
|
|
||||||
// The children under the root in this linkset
|
// The children under the root in this linkset
|
||||||
private List<BSPrim> m_children;
|
private List<BSPhysObject> m_children;
|
||||||
|
|
||||||
// We lock the diddling of linkset classes to prevent any badness.
|
// We lock the diddling of linkset classes to prevent any badness.
|
||||||
// This locks the modification of the instances of this class. Changes
|
// This locks the modification of the instances of this class. Changes
|
||||||
|
@ -74,7 +74,7 @@ public class BSLinkset
|
||||||
get { return ComputeLinksetGeometricCenter(); }
|
get { return ComputeLinksetGeometricCenter(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public BSLinkset(BSScene scene, BSPrim parent)
|
public BSLinkset(BSScene scene, BSPhysObject parent)
|
||||||
{
|
{
|
||||||
// A simple linkset of one (no children)
|
// A simple linkset of one (no children)
|
||||||
LinksetID = m_nextLinksetID++;
|
LinksetID = m_nextLinksetID++;
|
||||||
|
@ -83,14 +83,14 @@ public class BSLinkset
|
||||||
m_nextLinksetID = 1;
|
m_nextLinksetID = 1;
|
||||||
m_physicsScene = scene;
|
m_physicsScene = scene;
|
||||||
m_linksetRoot = parent;
|
m_linksetRoot = parent;
|
||||||
m_children = new List<BSPrim>();
|
m_children = new List<BSPhysObject>();
|
||||||
m_mass = parent.MassRaw;
|
m_mass = parent.MassRaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link to a linkset where the child knows the parent.
|
// Link to a linkset where the child knows the parent.
|
||||||
// Parent changing should not happen so do some sanity checking.
|
// Parent changing should not happen so do some sanity checking.
|
||||||
// We return the parent's linkset so the child can track its membership.
|
// We return the parent's linkset so the child can track its membership.
|
||||||
public BSLinkset AddMeToLinkset(BSPrim child)
|
public BSLinkset AddMeToLinkset(BSPhysObject child)
|
||||||
{
|
{
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
|
@ -102,7 +102,7 @@ public class BSLinkset
|
||||||
// Remove a child from a linkset.
|
// Remove a child from a linkset.
|
||||||
// Returns a new linkset for the child which is a linkset of one (just the
|
// Returns a new linkset for the child which is a linkset of one (just the
|
||||||
// orphened child).
|
// orphened child).
|
||||||
public BSLinkset RemoveMeFromLinkset(BSPrim child)
|
public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
|
||||||
{
|
{
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +129,7 @@ public class BSLinkset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 'true' if the passed object is the root object of this linkset
|
// Return 'true' if the passed object is the root object of this linkset
|
||||||
public bool IsRoot(BSPrim requestor)
|
public bool IsRoot(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
return (requestor.LocalID == m_linksetRoot.LocalID);
|
return (requestor.LocalID == m_linksetRoot.LocalID);
|
||||||
}
|
}
|
||||||
|
@ -140,12 +140,12 @@ public class BSLinkset
|
||||||
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
|
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
|
||||||
|
|
||||||
// Return 'true' if this child is in this linkset
|
// Return 'true' if this child is in this linkset
|
||||||
public bool HasChild(BSPrim child)
|
public bool HasChild(BSPhysObject child)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
foreach (BSPrim bp in m_children)
|
foreach (BSPhysObject bp in m_children)
|
||||||
{
|
{
|
||||||
if (child.LocalID == bp.LocalID)
|
if (child.LocalID == bp.LocalID)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ public class BSLinkset
|
||||||
private float ComputeLinksetMass()
|
private float ComputeLinksetMass()
|
||||||
{
|
{
|
||||||
float mass = m_linksetRoot.MassRaw;
|
float mass = m_linksetRoot.MassRaw;
|
||||||
foreach (BSPrim bp in m_children)
|
foreach (BSPhysObject bp in m_children)
|
||||||
{
|
{
|
||||||
mass += bp.MassRaw;
|
mass += bp.MassRaw;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public class BSLinkset
|
||||||
|
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
foreach (BSPrim bp in m_children)
|
foreach (BSPhysObject bp in m_children)
|
||||||
{
|
{
|
||||||
com += bp.Position * bp.MassRaw;
|
com += bp.Position * bp.MassRaw;
|
||||||
totalMass += bp.MassRaw;
|
totalMass += bp.MassRaw;
|
||||||
|
@ -192,7 +192,7 @@ public class BSLinkset
|
||||||
|
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
foreach (BSPrim bp in m_children)
|
foreach (BSPhysObject bp in m_children)
|
||||||
{
|
{
|
||||||
com += bp.Position * bp.MassRaw;
|
com += bp.Position * bp.MassRaw;
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
public void Refresh(BSPrim requestor)
|
public void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
// If there are no children, there aren't any constraints to recompute
|
// If there are no children, there aren't any constraints to recompute
|
||||||
if (!HasAnyChildren)
|
if (!HasAnyChildren)
|
||||||
|
@ -230,7 +230,7 @@ public class BSLinkset
|
||||||
float linksetMass = LinksetMass;
|
float linksetMass = LinksetMass;
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
foreach (BSPrim child in m_children)
|
foreach (BSPhysObject child in m_children)
|
||||||
{
|
{
|
||||||
BSConstraint constrain;
|
BSConstraint constrain;
|
||||||
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
|
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
|
||||||
|
@ -255,14 +255,14 @@ public class BSLinkset
|
||||||
|
|
||||||
// I am the root of a linkset and a new child is being added
|
// I am the root of a linkset and a new child is being added
|
||||||
// Called while LinkActivity is locked.
|
// Called while LinkActivity is locked.
|
||||||
private void AddChildToLinkset(BSPrim child)
|
private void AddChildToLinkset(BSPhysObject child)
|
||||||
{
|
{
|
||||||
if (!HasChild(child))
|
if (!HasChild(child))
|
||||||
{
|
{
|
||||||
m_children.Add(child);
|
m_children.Add(child);
|
||||||
|
|
||||||
BSPrim rootx = LinksetRoot; // capture the root as of now
|
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||||
BSPrim childx = child;
|
BSPhysObject childx = child;
|
||||||
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
|
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||||
|
@ -277,7 +277,7 @@ public class BSLinkset
|
||||||
// it's still connected to the linkset.
|
// it's still connected to the linkset.
|
||||||
// Normal OpenSimulator operation will never do this because other SceneObjectPart information
|
// Normal OpenSimulator operation will never do this because other SceneObjectPart information
|
||||||
// has to be updated also (like pointer to prim's parent).
|
// has to be updated also (like pointer to prim's parent).
|
||||||
private void RemoveChildFromOtherLinkset(BSPrim pchild)
|
private void RemoveChildFromOtherLinkset(BSPhysObject pchild)
|
||||||
{
|
{
|
||||||
pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
|
pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
|
||||||
RemoveChildFromLinkset(pchild);
|
RemoveChildFromLinkset(pchild);
|
||||||
|
@ -285,12 +285,12 @@ public class BSLinkset
|
||||||
|
|
||||||
// I am the root of a linkset and one of my children is being removed.
|
// I am the root of a linkset and one of my children is being removed.
|
||||||
// Safe to call even if the child is not really in my linkset.
|
// Safe to call even if the child is not really in my linkset.
|
||||||
private void RemoveChildFromLinkset(BSPrim child)
|
private void RemoveChildFromLinkset(BSPhysObject child)
|
||||||
{
|
{
|
||||||
if (m_children.Remove(child))
|
if (m_children.Remove(child))
|
||||||
{
|
{
|
||||||
BSPrim rootx = LinksetRoot; // capture the root as of now
|
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||||
BSPrim childx = child;
|
BSPhysObject childx = child;
|
||||||
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||||
|
@ -310,7 +310,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
|
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
{
|
{
|
||||||
// Zero motion for children so they don't interpolate
|
// Zero motion for children so they don't interpolate
|
||||||
childPrim.ZeroMotion();
|
childPrim.ZeroMotion();
|
||||||
|
@ -383,7 +383,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// Remove linkage between myself and a particular child
|
// Remove linkage between myself and a particular child
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
|
private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ public class BSLinkset
|
||||||
|
|
||||||
// Remove linkage between myself and any possible children I might have
|
// Remove linkage between myself and any possible children I might have
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
|
private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||||
{
|
{
|
||||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OMV = OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
// Class to wrap all objects.
|
||||||
|
// The rest of BulletSim doesn't need to keep checking for avatars or prims
|
||||||
|
// unless the difference is significant.
|
||||||
|
public abstract class BSPhysObject : PhysicsActor
|
||||||
|
{
|
||||||
|
public abstract BSLinkset Linkset { get; set; }
|
||||||
|
|
||||||
|
public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
|
||||||
|
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
|
||||||
|
public abstract void SendCollisions();
|
||||||
|
|
||||||
|
// Return the object mass without calculating it or side effects
|
||||||
|
public abstract float MassRaw { get; }
|
||||||
|
|
||||||
|
public abstract BulletBody Body { get; set; }
|
||||||
|
public abstract void ZeroMotion();
|
||||||
|
|
||||||
|
public virtual void StepVehicle(float timeStep) { }
|
||||||
|
|
||||||
|
public abstract void UpdateProperties(EntityProperties entprop);
|
||||||
|
|
||||||
|
public abstract void Destroy();
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public sealed class BSPrim : PhysicsActor
|
public sealed class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||||
|
@ -88,23 +88,14 @@ public sealed class BSPrim : PhysicsActor
|
||||||
private float _buoyancy;
|
private float _buoyancy;
|
||||||
|
|
||||||
// Membership in a linkset is controlled by this class.
|
// Membership in a linkset is controlled by this class.
|
||||||
private BSLinkset _linkset;
|
public override BSLinkset Linkset { get; set; }
|
||||||
public BSLinkset Linkset
|
|
||||||
{
|
|
||||||
get { return _linkset; }
|
|
||||||
set { _linkset = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _subscribedEventsMs = 0;
|
private int _subscribedEventsMs = 0;
|
||||||
private int _nextCollisionOkTime = 0;
|
private int _nextCollisionOkTime = 0;
|
||||||
long _collidingStep;
|
long _collidingStep;
|
||||||
long _collidingGroundStep;
|
long _collidingGroundStep;
|
||||||
|
|
||||||
private BulletBody m_body;
|
public override BulletBody Body { get; set; }
|
||||||
public BulletBody Body {
|
|
||||||
get { return m_body; }
|
|
||||||
set { m_body = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private BSDynamics _vehicle;
|
private BSDynamics _vehicle;
|
||||||
|
|
||||||
|
@ -139,7 +130,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
|
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
|
||||||
_density = _scene.Params.defaultDensity; // TODO: compute based on object material
|
_density = _scene.Params.defaultDensity; // TODO: compute based on object material
|
||||||
_restitution = _scene.Params.defaultRestitution;
|
_restitution = _scene.Params.defaultRestitution;
|
||||||
_linkset = new BSLinkset(Scene, this); // a linkset of one
|
Linkset = new BSLinkset(Scene, this); // a linkset of one
|
||||||
_vehicle = new BSDynamics(Scene, this); // add vehicleness
|
_vehicle = new BSDynamics(Scene, this); // add vehicleness
|
||||||
_mass = CalculateMass();
|
_mass = CalculateMass();
|
||||||
// do the actual object creation at taint time
|
// do the actual object creation at taint time
|
||||||
|
@ -151,23 +142,23 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// Get the pointer to the physical body for this object.
|
// Get the pointer to the physical body for this object.
|
||||||
// At the moment, we're still letting BulletSim manage the creation and destruction
|
// At the moment, we're still letting BulletSim manage the creation and destruction
|
||||||
// of the object. Someday we'll move that into the C# code.
|
// of the object. Someday we'll move that into the C# code.
|
||||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 override void Destroy()
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
|
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
|
||||||
|
|
||||||
// Undo any links between me and any other object
|
// Undo any links between me and any other object
|
||||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||||
int childrenBefore = _linkset.NumberOfChildren;
|
int childrenBefore = Linkset.NumberOfChildren;
|
||||||
|
|
||||||
_linkset = _linkset.RemoveMeFromLinkset(this);
|
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
|
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
|
||||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||||
|
|
||||||
// Undo any vehicle properties
|
// Undo any vehicle properties
|
||||||
this.VehicleType = (int)Vehicle.TYPE_NONE;
|
this.VehicleType = (int)Vehicle.TYPE_NONE;
|
||||||
|
@ -230,13 +221,13 @@ public sealed class BSPrim : PhysicsActor
|
||||||
BSPrim parent = obj as BSPrim;
|
BSPrim parent = obj as BSPrim;
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||||
int childrenBefore = _linkset.NumberOfChildren;
|
int childrenBefore = Linkset.NumberOfChildren;
|
||||||
|
|
||||||
_linkset = parent.Linkset.AddMeToLinkset(this);
|
Linkset = parent.Linkset.AddMeToLinkset(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
|
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
|
||||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -246,13 +237,13 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// TODO: decide if this parent checking needs to happen at taint time
|
// TODO: decide if this parent checking needs to happen at taint time
|
||||||
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen
|
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen
|
||||||
|
|
||||||
BSPrim parentBefore = _linkset.LinksetRoot;
|
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||||
int childrenBefore = _linkset.NumberOfChildren;
|
int childrenBefore = Linkset.NumberOfChildren;
|
||||||
|
|
||||||
_linkset = _linkset.RemoveMeFromLinkset(this);
|
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||||
|
|
||||||
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
||||||
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
|
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +251,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// Do it to the properties so the values get set in the physics engine.
|
// Do it to the properties so the values get set in the physics engine.
|
||||||
// Push the setting of the values to the viewer.
|
// Push the setting of the values to the viewer.
|
||||||
// Called at taint time!
|
// Called at taint time!
|
||||||
public void ZeroMotion()
|
public override void ZeroMotion()
|
||||||
{
|
{
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
_acceleration = OMV.Vector3.Zero;
|
_acceleration = OMV.Vector3.Zero;
|
||||||
|
@ -281,7 +272,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
|
|
||||||
public override OMV.Vector3 Position {
|
public override OMV.Vector3 Position {
|
||||||
get {
|
get {
|
||||||
if (!_linkset.IsRoot(this))
|
if (!Linkset.IsRoot(this))
|
||||||
// child prims move around based on their parent. Need to get the latest location
|
// child prims move around based on their parent. Need to get the latest location
|
||||||
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||||
|
|
||||||
|
@ -306,23 +297,23 @@ public sealed class BSPrim : PhysicsActor
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _linkset.LinksetMass;
|
return Linkset.LinksetMass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// used when we only want this prim's mass and not the linkset thing
|
// used when we only want this prim's mass and not the linkset thing
|
||||||
public float MassRaw { get { return _mass; } }
|
public override float MassRaw { get { return _mass; } }
|
||||||
|
|
||||||
// Is this used?
|
// Is this used?
|
||||||
public override OMV.Vector3 CenterOfMass
|
public override OMV.Vector3 CenterOfMass
|
||||||
{
|
{
|
||||||
get { return _linkset.CenterOfMass; }
|
get { return Linkset.CenterOfMass; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this used?
|
// Is this used?
|
||||||
public override OMV.Vector3 GeometricCenter
|
public override OMV.Vector3 GeometricCenter
|
||||||
{
|
{
|
||||||
get { return _linkset.GeometricCenter; }
|
get { return Linkset.GeometricCenter; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override OMV.Vector3 Force {
|
public override OMV.Vector3 Force {
|
||||||
|
@ -386,7 +377,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
|
|
||||||
// Called each simulation step to advance vehicle characteristics.
|
// Called each simulation step to advance vehicle characteristics.
|
||||||
// Called from Scene when doing simulation step so we're in taint processing time.
|
// Called from Scene when doing simulation step so we're in taint processing time.
|
||||||
public void StepVehicle(float timeStep)
|
public override void StepVehicle(float timeStep)
|
||||||
{
|
{
|
||||||
if (IsPhysical)
|
if (IsPhysical)
|
||||||
_vehicle.Step(timeStep);
|
_vehicle.Step(timeStep);
|
||||||
|
@ -431,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
public override OMV.Quaternion Orientation {
|
public override OMV.Quaternion Orientation {
|
||||||
get {
|
get {
|
||||||
if (!_linkset.IsRoot(this))
|
if (!Linkset.IsRoot(this))
|
||||||
{
|
{
|
||||||
// Children move around because tied to parent. Get a fresh value.
|
// Children move around because tied to parent. Get a fresh value.
|
||||||
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
|
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
|
||||||
|
@ -490,7 +481,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
|
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
|
||||||
|
|
||||||
// recompute any linkset parameters
|
// recompute any linkset parameters
|
||||||
_linkset.Refresh(this);
|
Linkset.Refresh(this);
|
||||||
|
|
||||||
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
|
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
|
||||||
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
|
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
|
||||||
|
@ -1299,7 +1290,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
const float ACCELERATION_TOLERANCE = 0.01f;
|
const float ACCELERATION_TOLERANCE = 0.01f;
|
||||||
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
|
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
|
||||||
|
|
||||||
public void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
UpdatedProperties changed = 0;
|
UpdatedProperties changed = 0;
|
||||||
|
@ -1347,7 +1338,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
||||||
|
|
||||||
// Updates only for individual prims and for the root object of a linkset.
|
// Updates only for individual prims and for the root object of a linkset.
|
||||||
if (_linkset.IsRoot(this))
|
if (Linkset.IsRoot(this))
|
||||||
{
|
{
|
||||||
// Assign to the local variables so the normal set action does not happen
|
// Assign to the local variables so the normal set action does not happen
|
||||||
_position = entprop.Position;
|
_position = entprop.Position;
|
||||||
|
@ -1375,7 +1366,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
// I've collided with something
|
// I've collided with something
|
||||||
// Called at taint time from within the Step() function
|
// Called at taint time from within the Step() function
|
||||||
CollisionEventUpdate collisionCollection;
|
CollisionEventUpdate collisionCollection;
|
||||||
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
public override void Collide(uint collidingWith, BSPhysObject collidee, 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);
|
||||||
|
|
||||||
|
@ -1387,18 +1378,15 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
|
|
||||||
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
|
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
|
||||||
BSPrim collidingWithPrim;
|
|
||||||
if (_scene.Prims.TryGetValue(collidingWith, out collidingWithPrim))
|
|
||||||
{
|
|
||||||
// prims in the same linkset cannot collide with each other
|
// prims in the same linkset cannot collide with each other
|
||||||
if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID)
|
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// if someone is subscribed to collision events....
|
// if someone has subscribed for collision events....
|
||||||
if (_subscribedEventsMs != 0) {
|
if (SubscribedEvents()) {
|
||||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||||
int nowTime = _scene.SimulationNowTime;
|
int nowTime = _scene.SimulationNowTime;
|
||||||
if (nowTime >= _nextCollisionOkTime) {
|
if (nowTime >= _nextCollisionOkTime) {
|
||||||
|
@ -1412,7 +1400,7 @@ public sealed class BSPrim : PhysicsActor
|
||||||
}
|
}
|
||||||
|
|
||||||
// The scene is telling us it's time to pass our collected collisions into the simulator
|
// The scene is telling us it's time to pass our collected collisions into the simulator
|
||||||
public void SendCollisions()
|
public override void SendCollisions()
|
||||||
{
|
{
|
||||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,8 +39,6 @@ using log4net;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -54,10 +52,8 @@ using OpenMetaverse;
|
||||||
// Use collision masks for collision with terrain and phantom objects
|
// Use collision masks for collision with terrain and phantom objects
|
||||||
// Check out llVolumeDetect. Must do something for that.
|
// 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?
|
||||||
// changing the position and orientation of a linked prim must rebuild the constraint with the root.
|
|
||||||
// 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
|
||||||
// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
|
|
||||||
// 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?
|
||||||
|
@ -78,27 +74,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
public string BulletSimVersion = "?";
|
public string BulletSimVersion = "?";
|
||||||
|
|
||||||
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
|
public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
|
||||||
public Dictionary<uint, BSCharacter> Characters { get { return m_avatars; } }
|
|
||||||
|
|
||||||
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
|
|
||||||
public Dictionary<uint, BSPrim> Prims { get { return m_prims; } }
|
|
||||||
|
|
||||||
|
private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
|
||||||
|
// Following is a kludge and can be removed when avatar animation updating is
|
||||||
|
// moved to a better place.
|
||||||
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
|
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
|
||||||
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
|
|
||||||
|
|
||||||
private List<BSPrim> m_vehicles = new List<BSPrim>();
|
// List of all the objects that have vehicle properties and should be called
|
||||||
|
// to update each physics step.
|
||||||
private float[] m_heightMap;
|
private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
|
||||||
private float m_waterLevel;
|
|
||||||
private uint m_worldID;
|
|
||||||
public uint WorldID { get { return m_worldID; } }
|
|
||||||
|
|
||||||
// let my minuions use my logger
|
// let my minuions use my logger
|
||||||
public ILog Logger { get { return m_log; } }
|
public ILog Logger { get { return m_log; } }
|
||||||
|
|
||||||
private bool m_initialized = false;
|
// If non-zero, the number of simulation steps between calls to the physics
|
||||||
|
// engine to output detailed physics stats. Debug logging level must be on also.
|
||||||
private int m_detailedStatsStep = 0;
|
private int m_detailedStatsStep = 0;
|
||||||
|
|
||||||
public IMesher mesher;
|
public IMesher mesher;
|
||||||
|
@ -108,29 +99,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
public float MeshMegaPrimThreshold { get; private set; }
|
public float MeshMegaPrimThreshold { get; private set; }
|
||||||
public float SculptLOD { get; private set; }
|
public float SculptLOD { get; private set; }
|
||||||
|
|
||||||
private BulletSim m_worldSim;
|
public uint WorldID { get; private set; }
|
||||||
public BulletSim World
|
public BulletSim World { get; private set; }
|
||||||
{
|
|
||||||
get { return m_worldSim; }
|
|
||||||
}
|
|
||||||
private BSConstraintCollection m_constraintCollection;
|
|
||||||
public BSConstraintCollection Constraints
|
|
||||||
{
|
|
||||||
get { return m_constraintCollection; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// All the constraints that have been allocated in this instance.
|
||||||
|
public BSConstraintCollection Constraints { get; private set; }
|
||||||
|
|
||||||
|
// Simulation parameters
|
||||||
private int m_maxSubSteps;
|
private int m_maxSubSteps;
|
||||||
private float m_fixedTimeStep;
|
private float m_fixedTimeStep;
|
||||||
private long m_simulationStep = 0;
|
private long m_simulationStep = 0;
|
||||||
public long SimulationStep { get { return m_simulationStep; } }
|
public long SimulationStep { get { return m_simulationStep; } }
|
||||||
|
|
||||||
|
// The length of the last timestep we were asked to simulate.
|
||||||
|
// This is used by the vehicle code. Since the vehicle code is called
|
||||||
|
// once per simulation step, its constants need to be scaled by this.
|
||||||
public float LastSimulatedTimestep { get; private set; }
|
public float LastSimulatedTimestep { get; private set; }
|
||||||
|
|
||||||
// A value of the time now so all the collision and update routines do not have to get their own
|
// 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
|
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||||
private int m_simulationNowTime;
|
public int SimulationNowTime { get; private set; }
|
||||||
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
|
||||||
|
|
||||||
|
// True if initialized and ready to do simulation steps
|
||||||
|
private bool m_initialized = false;
|
||||||
|
|
||||||
|
// Pinned memory used to pass step information between managed and unmanaged
|
||||||
private int m_maxCollisionsPerFrame;
|
private int m_maxCollisionsPerFrame;
|
||||||
private CollisionDesc[] m_collisionArray;
|
private CollisionDesc[] m_collisionArray;
|
||||||
private GCHandle m_collisionArrayPinnedHandle;
|
private GCHandle m_collisionArrayPinnedHandle;
|
||||||
|
@ -147,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
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;
|
||||||
|
public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
|
||||||
|
|
||||||
|
private float m_waterLevel;
|
||||||
|
public BSTerrainManager TerrainManager { get; private set; }
|
||||||
|
|
||||||
public ConfigurationParameters Params
|
public ConfigurationParameters Params
|
||||||
{
|
{
|
||||||
|
@ -157,12 +154,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
get { return new Vector3(0f, 0f, Params.gravity); }
|
get { return new Vector3(0f, 0f, Params.gravity); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private float m_maximumObjectMass;
|
public float MaximumObjectMass { get; private set; }
|
||||||
public float MaximumObjectMass
|
|
||||||
{
|
|
||||||
get { return m_maximumObjectMass; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// When functions in the unmanaged code must be called, it is only
|
||||||
|
// done at a known time just before the simulation step. The taint
|
||||||
|
// system saves all these function calls and executes them in
|
||||||
|
// order before the simulation.
|
||||||
public delegate void TaintCallback();
|
public delegate void TaintCallback();
|
||||||
private struct TaintCallbackEntry
|
private struct TaintCallbackEntry
|
||||||
{
|
{
|
||||||
|
@ -178,6 +175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
private Object _taintLock = new Object();
|
private Object _taintLock = new Object();
|
||||||
|
|
||||||
// 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.
|
||||||
ConfigurationParameters[] m_params;
|
ConfigurationParameters[] m_params;
|
||||||
GCHandle m_paramsHandle;
|
GCHandle m_paramsHandle;
|
||||||
|
|
||||||
|
@ -192,10 +190,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
private string m_physicsLoggingDir;
|
private string m_physicsLoggingDir;
|
||||||
private string m_physicsLoggingPrefix;
|
private string m_physicsLoggingPrefix;
|
||||||
private int m_physicsLoggingFileMinutes;
|
private int m_physicsLoggingFileMinutes;
|
||||||
|
// 'true' of the vehicle code is to log lots of details
|
||||||
|
public bool VehicleLoggingEnabled { get; private set; }
|
||||||
|
|
||||||
private bool m_vehicleLoggingEnabled;
|
#region Construction and Initialization
|
||||||
public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
|
|
||||||
|
|
||||||
public BSScene(string identifier)
|
public BSScene(string identifier)
|
||||||
{
|
{
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
|
@ -218,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
||||||
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
||||||
|
|
||||||
|
mesher = meshmerizer;
|
||||||
|
_taintedObjects = new List<TaintCallbackEntry>();
|
||||||
|
|
||||||
// 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
|
||||||
// can be left in and every call doesn't have to check for null.
|
// can be left in and every call doesn't have to check for null.
|
||||||
|
@ -230,38 +231,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
PhysicsLogging = new Logging.LogWriter();
|
PhysicsLogging = new Logging.LogWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If Debug logging level, enable logging from the unmanaged code
|
||||||
|
m_DebugLogCallbackHandle = null;
|
||||||
|
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||||
|
{
|
||||||
|
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
|
// Get the version of the DLL
|
||||||
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
|
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
|
||||||
// BulletSimVersion = BulletSimAPI.GetVersion();
|
// BulletSimVersion = BulletSimAPI.GetVersion();
|
||||||
// m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
|
// m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
|
||||||
|
|
||||||
// if Debug, enable logging from the unmanaged code
|
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
||||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
// a child in a mega-region.
|
||||||
{
|
// Turns out that Bullet really doesn't care about the extents of the simulated
|
||||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
// area. It tracks active objects no matter where they are.
|
||||||
if (PhysicsLogging.Enabled)
|
|
||||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
|
||||||
else
|
|
||||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
|
||||||
// the handle is saved in a variable to make sure it doesn't get freed after this call
|
|
||||||
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
_taintedObjects = new List<TaintCallbackEntry>();
|
|
||||||
|
|
||||||
mesher = meshmerizer;
|
|
||||||
// The bounding box for the simulated world
|
|
||||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
|
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(),
|
WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
|
||||||
|
m_DebugLogCallbackHandle);
|
||||||
|
|
||||||
// Initialization to support the transition to a new API which puts most of the logic
|
// Initialization to support the transition to a new API which puts most of the logic
|
||||||
// into the C# code so it is easier to modify and add to.
|
// into the C# code so it is easier to modify and add to.
|
||||||
m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
|
World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
|
||||||
m_constraintCollection = new BSConstraintCollection(World);
|
|
||||||
|
Constraints = new BSConstraintCollection(World);
|
||||||
|
|
||||||
|
TerrainManager = new BSTerrainManager(this);
|
||||||
|
TerrainManager.CreateInitialGroundPlaneAndTerrain();
|
||||||
|
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +295,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
|
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
|
||||||
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
|
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
|
||||||
// Very detailed logging for vehicle debugging
|
// Very detailed logging for vehicle debugging
|
||||||
m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||||
|
|
||||||
// Do any replacements in the parameters
|
// Do any replacements in the parameters
|
||||||
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
||||||
|
@ -324,6 +330,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||||
|
|
||||||
|
// make sure no stepping happens while we're deleting stuff
|
||||||
|
m_initialized = false;
|
||||||
|
|
||||||
|
TerrainManager.ReleaseGroundPlaneAndTerrain();
|
||||||
|
|
||||||
|
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
|
||||||
|
{
|
||||||
|
kvp.Value.Destroy();
|
||||||
|
}
|
||||||
|
PhysObjects.Clear();
|
||||||
|
|
||||||
|
// Now that the prims are all cleaned up, there should be no constraints left
|
||||||
|
if (Constraints != null)
|
||||||
|
{
|
||||||
|
Constraints.Dispose();
|
||||||
|
Constraints = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anything left in the unmanaged code should be cleaned out
|
||||||
|
BulletSimAPI.Shutdown(WorldID);
|
||||||
|
|
||||||
|
// Not logging any more
|
||||||
|
PhysicsLogging.Close();
|
||||||
|
}
|
||||||
|
#endregion // Construction and Initialization
|
||||||
|
|
||||||
|
#region Prim and Avatar addition and removal
|
||||||
|
|
||||||
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||||
{
|
{
|
||||||
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
|
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||||
|
@ -337,7 +375,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
if (!m_initialized) return null;
|
if (!m_initialized) return null;
|
||||||
|
|
||||||
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
||||||
lock (m_avatars) m_avatars.Add(localID, actor);
|
lock (PhysObjects) PhysObjects.Add(localID, actor);
|
||||||
|
|
||||||
|
// TODO: Remove kludge someday.
|
||||||
|
// We must generate a collision for avatars whether they collide or not.
|
||||||
|
// This is required by OpenSim to update avatar animations, etc.
|
||||||
|
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
|
||||||
|
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +396,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (m_avatars) m_avatars.Remove(actor.LocalID);
|
lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
|
||||||
|
// Remove kludge someday
|
||||||
|
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -374,7 +420,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
|
// m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (m_prims) m_prims.Remove(bsprim.LocalID);
|
lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -399,7 +445,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
DetailLog("{0},AddPrimShape,call", localID);
|
DetailLog("{0},AddPrimShape,call", localID);
|
||||||
|
|
||||||
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||||
lock (m_prims) m_prims.Add(localID, prim);
|
lock (PhysObjects) PhysObjects.Add(localID, prim);
|
||||||
return prim;
|
return prim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +454,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// information call is not needed.
|
// information call is not needed.
|
||||||
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||||
|
|
||||||
|
#endregion // Prim and Avatar addition and removal
|
||||||
|
|
||||||
|
#region Simulation
|
||||||
// Simulate one timestep
|
// Simulate one timestep
|
||||||
public override float Simulate(float timeStep)
|
public override float Simulate(float timeStep)
|
||||||
{
|
{
|
||||||
|
@ -424,6 +473,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
int simulateStartTime = Util.EnvironmentTickCount();
|
int simulateStartTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
// update the prim states while we know the physics engine is not busy
|
// update the prim states while we know the physics engine is not busy
|
||||||
|
int numTaints = _taintedObjects.Count;
|
||||||
ProcessTaints();
|
ProcessTaints();
|
||||||
|
|
||||||
// Some of the prims operate with special vehicle properties
|
// Some of the prims operate with special vehicle properties
|
||||||
|
@ -435,14 +485,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
int numSubSteps = 0;
|
int numSubSteps = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||||
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||||
DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
|
DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
|
||||||
|
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
|
m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
|
||||||
// DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
|
LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
|
||||||
|
DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
|
||||||
|
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||||
updatedEntityCount = 0;
|
updatedEntityCount = 0;
|
||||||
collidersCount = 0;
|
collidersCount = 0;
|
||||||
}
|
}
|
||||||
|
@ -451,7 +504,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
|
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
|
||||||
|
|
||||||
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
||||||
m_simulationNowTime = Util.EnvironmentTickCount();
|
SimulationNowTime = Util.EnvironmentTickCount();
|
||||||
|
|
||||||
// If there were collisions, process them by sending the event to the prim.
|
// If there were collisions, process them by sending the event to the prim.
|
||||||
// Collisions must be processed before updates.
|
// Collisions must be processed before updates.
|
||||||
|
@ -470,19 +523,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// The above SendCollision's batch up the collisions on the objects.
|
// The above SendCollision's batch up the collisions on the objects.
|
||||||
// Now push the collisions into the simulator.
|
// Now push the collisions into the simulator.
|
||||||
foreach (BSPrim bsp in m_primsWithCollisions)
|
foreach (BSPhysObject bsp in m_objectsWithCollisions)
|
||||||
bsp.SendCollisions();
|
bsp.SendCollisions();
|
||||||
m_primsWithCollisions.Clear();
|
m_objectsWithCollisions.Clear();
|
||||||
|
|
||||||
// This is a kludge to get avatar movement updated.
|
// This is a kludge to get avatar movement updated.
|
||||||
// Don't send collisions only if there were collisions -- send everytime.
|
|
||||||
// ODE sends collisions even if there are none and this is used to update
|
// ODE sends collisions even if there are none and this is used to update
|
||||||
// avatar animations and stuff.
|
// avatar animations and stuff.
|
||||||
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
|
foreach (BSPhysObject bpo in m_avatarsWithCollisions)
|
||||||
// bsc.SendCollisions();
|
bpo.SendCollisions();
|
||||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
// m_avatarsWithCollisions.Clear();
|
||||||
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)
|
||||||
|
@ -490,16 +540,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
for (int ii = 0; ii < updatedEntityCount; ii++)
|
for (int ii = 0; ii < updatedEntityCount; ii++)
|
||||||
{
|
{
|
||||||
EntityProperties entprop = m_updateArray[ii];
|
EntityProperties entprop = m_updateArray[ii];
|
||||||
BSPrim prim;
|
BSPhysObject pobj;
|
||||||
if (m_prims.TryGetValue(entprop.ID, out prim))
|
if (PhysObjects.TryGetValue(entprop.ID, out pobj))
|
||||||
{
|
{
|
||||||
prim.UpdateProperties(entprop);
|
pobj.UpdateProperties(entprop);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
BSCharacter actor;
|
|
||||||
if (m_avatars.TryGetValue(entprop.ID, out actor))
|
|
||||||
{
|
|
||||||
actor.UpdateProperties(entprop);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,58 +573,47 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something has collided
|
// Something has collided
|
||||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration)
|
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
|
||||||
{
|
{
|
||||||
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
if (localID <= TerrainManager.HighestTerrainID)
|
||||||
{
|
{
|
||||||
return; // don't send collisions to the terrain
|
return; // don't send collisions to the terrain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BSPhysObject collider = PhysObjects[localID];
|
||||||
|
// TODO: as of this code, terrain was not in the physical object list.
|
||||||
|
// When BSTerrain is created and it will be in the list, we can remove
|
||||||
|
// the possibility that it's not there and just fetch the collidee.
|
||||||
|
BSPhysObject collidee = null;
|
||||||
|
|
||||||
ActorTypes type = ActorTypes.Prim;
|
ActorTypes type = ActorTypes.Prim;
|
||||||
if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
|
if (collidingWith <= TerrainManager.HighestTerrainID)
|
||||||
|
{
|
||||||
type = ActorTypes.Ground;
|
type = ActorTypes.Ground;
|
||||||
else if (m_avatars.ContainsKey(collidingWith))
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
collidee = PhysObjects[collidingWith];
|
||||||
|
if (collidee is BSCharacter)
|
||||||
type = ActorTypes.Agent;
|
type = ActorTypes.Agent;
|
||||||
|
}
|
||||||
|
|
||||||
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
||||||
|
|
||||||
BSPrim prim;
|
collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
|
||||||
if (m_prims.TryGetValue(localID, out prim)) {
|
m_objectsWithCollisions.Add(collider);
|
||||||
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
|
||||||
m_primsWithCollisions.Add(prim);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BSCharacter actor;
|
|
||||||
if (m_avatars.TryGetValue(localID, out actor)) {
|
|
||||||
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
|
||||||
m_avatarsWithCollisions.Add(actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion // Simulation
|
||||||
|
|
||||||
public override void GetResults() { }
|
public override void GetResults() { }
|
||||||
|
|
||||||
|
#region Terrain
|
||||||
|
|
||||||
public override void SetTerrain(float[] heightMap) {
|
public override void SetTerrain(float[] heightMap) {
|
||||||
m_heightMap = heightMap;
|
TerrainManager.SetTerrain(heightMap);
|
||||||
this.TaintedObject("BSScene.SetTerrain", delegate()
|
|
||||||
{
|
|
||||||
BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Someday we will have complex terrain with caves and tunnels
|
|
||||||
// For the moment, it's flat and convex
|
|
||||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
|
||||||
{
|
|
||||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
|
||||||
{
|
|
||||||
if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
|
|
||||||
return 30;
|
|
||||||
return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetWaterLevel(float baseheight)
|
public override void SetWaterLevel(float baseheight)
|
||||||
|
@ -598,39 +631,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
|
// m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
// Although no one seems to check this, I do support combining.
|
||||||
|
public override bool SupportsCombining()
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
return TerrainManager.SupportsCombining();
|
||||||
|
|
||||||
// make sure no stepping happens while we're deleting stuff
|
|
||||||
m_initialized = false;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
|
||||||
{
|
|
||||||
kvp.Value.Destroy();
|
|
||||||
}
|
}
|
||||||
m_avatars.Clear();
|
// This call says I am a child to region zero in a mega-region. 'pScene' is that
|
||||||
|
// of region zero, 'offset' is my offset from regions zero's origin, and
|
||||||
foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
|
// 'extents' is the largest XY that is handled in my region.
|
||||||
|
public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||||
{
|
{
|
||||||
kvp.Value.Destroy();
|
TerrainManager.Combine(pScene, offset, extents);
|
||||||
}
|
|
||||||
m_prims.Clear();
|
|
||||||
|
|
||||||
// Now that the prims are all cleaned up, there should be no constraints left
|
|
||||||
if (m_constraintCollection != null)
|
|
||||||
{
|
|
||||||
m_constraintCollection.Dispose();
|
|
||||||
m_constraintCollection = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything left in the unmanaged code should be cleaned out
|
// Unhook all the combining that I know about.
|
||||||
BulletSimAPI.Shutdown(WorldID);
|
public override void UnCombine(PhysicsScene pScene)
|
||||||
|
{
|
||||||
// Not logging any more
|
TerrainManager.UnCombine(pScene);
|
||||||
PhysicsLogging.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion // Terrain
|
||||||
|
|
||||||
public override Dictionary<uint, float> GetTopColliders()
|
public override Dictionary<uint, float> GetTopColliders()
|
||||||
{
|
{
|
||||||
return new Dictionary<uint, float>();
|
return new Dictionary<uint, float>();
|
||||||
|
@ -840,14 +861,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// no locking because only called when physics engine is not busy
|
// no locking because only called when physics engine is not busy
|
||||||
private void ProcessVehicles(float timeStep)
|
private void ProcessVehicles(float timeStep)
|
||||||
{
|
{
|
||||||
foreach (BSPrim prim in m_vehicles)
|
foreach (BSPhysObject pobj in m_vehicles)
|
||||||
{
|
{
|
||||||
prim.StepVehicle(timeStep);
|
pobj.StepVehicle(timeStep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion Vehicles
|
#endregion Vehicles
|
||||||
|
|
||||||
#region Parameters
|
#region INI and command line parameter processing
|
||||||
|
|
||||||
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
|
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
|
||||||
delegate float ParamGet(BSScene scene);
|
delegate float ParamGet(BSScene scene);
|
||||||
|
@ -950,9 +971,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
||||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||||
10000.01f,
|
10000.01f,
|
||||||
(s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)s.m_maximumObjectMass; },
|
(s) => { return (float)s.MaximumObjectMass; },
|
||||||
(s,p,l,v) => { s.m_maximumObjectMass = v; } ),
|
(s,p,l,v) => { s.MaximumObjectMass = v; } ),
|
||||||
|
|
||||||
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
||||||
2200f,
|
2200f,
|
||||||
|
@ -996,42 +1017,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].linearDamping; },
|
(s) => { return s.m_params[0].linearDamping; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||||
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].angularDamping; },
|
(s) => { return s.m_params[0].angularDamping; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
|
||||||
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
||||||
0.2f,
|
0.2f,
|
||||||
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].deactivationTime; },
|
(s) => { return s.m_params[0].deactivationTime; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
||||||
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||||
0.8f,
|
0.8f,
|
||||||
(s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].linearSleepingThreshold; },
|
(s) => { return s.m_params[0].linearSleepingThreshold; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
||||||
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||||
1.0f,
|
1.0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].angularSleepingThreshold; },
|
(s) => { return s.m_params[0].angularSleepingThreshold; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
||||||
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||||
0f, // set to zero to disable
|
0f, // set to zero to disable
|
||||||
(s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].ccdMotionThreshold; },
|
(s) => { return s.m_params[0].ccdMotionThreshold; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
||||||
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].ccdSweptSphereRadius; },
|
(s) => { return s.m_params[0].ccdSweptSphereRadius; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
||||||
new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
|
new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].contactProcessingThreshold; },
|
(s) => { return s.m_params[0].contactProcessingThreshold; },
|
||||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||||
|
|
||||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||||
0.5f,
|
0.5f,
|
||||||
|
@ -1049,35 +1070,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
(s) => { return s.m_params[0].terrainRestitution; },
|
(s) => { return s.m_params[0].terrainRestitution; },
|
||||||
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
|
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
|
||||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||||
0.5f,
|
0.2f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarFriction; },
|
(s) => { return s.m_params[0].avatarFriction; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||||
60f,
|
60f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarDensity; },
|
(s) => { return s.m_params[0].avatarDensity; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
||||||
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||||
0f,
|
0f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarRestitution; },
|
(s) => { return s.m_params[0].avatarRestitution; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||||
new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
|
new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
|
||||||
0.37f,
|
0.37f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarCapsuleRadius; },
|
(s) => { return s.m_params[0].avatarCapsuleRadius; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
||||||
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||||
1.5f,
|
1.5f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarCapsuleHeight; },
|
(s) => { return s.m_params[0].avatarCapsuleHeight; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
||||||
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||||
0.1f,
|
0.1f,
|
||||||
(s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||||
(s) => { return s.m_params[0].avatarContactProcessingThreshold; },
|
(s) => { return s.m_params[0].avatarContactProcessingThreshold; },
|
||||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
||||||
|
|
||||||
|
|
||||||
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
|
||||||
|
@ -1214,6 +1235,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
|
private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
|
||||||
|
|
||||||
|
// This creates an array in the correct format for returning the list of
|
||||||
|
// parameters. This is used by the 'list' option of the 'physics' command.
|
||||||
private void BuildParameterTable()
|
private void BuildParameterTable()
|
||||||
{
|
{
|
||||||
if (SettableParameters.Length < ParameterDefinitions.Length)
|
if (SettableParameters.Length < ParameterDefinitions.Length)
|
||||||
|
@ -1264,18 +1287,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if we are updating a parameter for a particular or all of the prims
|
// check to see if we are updating a parameter for a particular or all of the prims
|
||||||
protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
|
protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
|
||||||
{
|
{
|
||||||
List<uint> operateOn;
|
List<uint> operateOn;
|
||||||
lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
|
lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
|
||||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if we are updating a parameter for a particular or all of the avatars
|
|
||||||
protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
|
|
||||||
{
|
|
||||||
List<uint> operateOn;
|
|
||||||
lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
|
|
||||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1298,7 +1313,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
||||||
foreach (uint lID in objectIDs)
|
foreach (uint lID in objectIDs)
|
||||||
{
|
{
|
||||||
BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
|
BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -1316,7 +1331,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
string xparm = parm.ToLower();
|
string xparm = parm.ToLower();
|
||||||
float xval = val;
|
float xval = val;
|
||||||
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
|
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
|
||||||
BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
|
BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,464 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyrightD
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Framework;
|
||||||
|
using OpenSim.Region.CoreModules;
|
||||||
|
using OpenSim.Region.Physics.Manager;
|
||||||
|
|
||||||
|
using Nini.Config;
|
||||||
|
using log4net;
|
||||||
|
|
||||||
|
using OpenMetaverse;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
{
|
||||||
|
public class BSTerrainManager
|
||||||
|
{
|
||||||
|
static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
|
||||||
|
|
||||||
|
// These height values are fractional so the odd values will be
|
||||||
|
// noticable when debugging.
|
||||||
|
public const float HEIGHT_INITIALIZATION = 24.987f;
|
||||||
|
public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
|
||||||
|
public const float HEIGHT_GETHEIGHT_RET = 24.765f;
|
||||||
|
|
||||||
|
// If the min and max height are equal, we reduce the min by this
|
||||||
|
// amount to make sure that a bounding box is built for the terrain.
|
||||||
|
public const float HEIGHT_EQUAL_FUDGE = 0.2f;
|
||||||
|
|
||||||
|
public const float TERRAIN_COLLISION_MARGIN = 0.0f;
|
||||||
|
|
||||||
|
// Until the whole simulator is changed to pass us the region size, we rely on constants.
|
||||||
|
public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
|
||||||
|
|
||||||
|
// The scene that I am part of
|
||||||
|
private BSScene m_physicsScene;
|
||||||
|
|
||||||
|
// The ground plane created to keep thing from falling to infinity.
|
||||||
|
private BulletBody m_groundPlane;
|
||||||
|
|
||||||
|
// If doing mega-regions, if we're region zero we will be managing multiple
|
||||||
|
// region terrains since region zero does the physics for the whole mega-region.
|
||||||
|
private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
|
||||||
|
|
||||||
|
// True of the terrain has been modified.
|
||||||
|
// Used to force recalculation of terrain height after terrain has been modified
|
||||||
|
private bool m_terrainModified;
|
||||||
|
|
||||||
|
// If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
|
||||||
|
// This is incremented before assigning to new region so it is the last ID allocated.
|
||||||
|
private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
|
||||||
|
public uint HighestTerrainID { get {return m_terrainCount; } }
|
||||||
|
|
||||||
|
// If doing mega-regions, this holds our offset from region zero of
|
||||||
|
// the mega-regions. "parentScene" points to the PhysicsScene of region zero.
|
||||||
|
private Vector3 m_worldOffset;
|
||||||
|
// If the parent region (region 0), this is the extent of the combined regions
|
||||||
|
// relative to the origin of region zero
|
||||||
|
private Vector3 m_worldMax;
|
||||||
|
private PhysicsScene m_parentScene;
|
||||||
|
|
||||||
|
public BSTerrainManager(BSScene physicsScene)
|
||||||
|
{
|
||||||
|
m_physicsScene = physicsScene;
|
||||||
|
m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
|
||||||
|
m_terrainModified = false;
|
||||||
|
|
||||||
|
// Assume one region of default size
|
||||||
|
m_worldOffset = Vector3.Zero;
|
||||||
|
m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
|
||||||
|
m_parentScene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the initial instance of terrain and the underlying ground plane.
|
||||||
|
// The objects are allocated in the unmanaged space and the pointers are tracked
|
||||||
|
// by the managed code.
|
||||||
|
// The terrains and the groundPlane are not added to the list of PhysObjects.
|
||||||
|
// This is called from the initialization routine so we presume it is
|
||||||
|
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
||||||
|
public void CreateInitialGroundPlaneAndTerrain()
|
||||||
|
{
|
||||||
|
// The ground plane is here to catch things that are trying to drop to negative infinity
|
||||||
|
BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
|
||||||
|
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
||||||
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
|
||||||
|
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||||
|
|
||||||
|
Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
|
||||||
|
Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
|
||||||
|
int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
|
||||||
|
float[] initialMap = new float[totalHeights];
|
||||||
|
for (int ii = 0; ii < totalHeights; ii++)
|
||||||
|
{
|
||||||
|
initialMap[ii] = HEIGHT_INITIALIZATION;
|
||||||
|
}
|
||||||
|
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release all the terrain structures we might have allocated
|
||||||
|
public void ReleaseGroundPlaneAndTerrain()
|
||||||
|
{
|
||||||
|
if (m_groundPlane.Ptr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
|
||||||
|
{
|
||||||
|
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||||
|
}
|
||||||
|
m_groundPlane.Ptr = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseTerrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release all the terrain we have allocated
|
||||||
|
public void ReleaseTerrain()
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
|
||||||
|
{
|
||||||
|
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
|
||||||
|
{
|
||||||
|
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
|
||||||
|
BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_heightMaps.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The simulator wants to set a new heightmap for the terrain.
|
||||||
|
public void SetTerrain(float[] heightMap) {
|
||||||
|
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||||
|
{
|
||||||
|
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||||
|
ReleaseGroundPlaneAndTerrain();
|
||||||
|
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||||
|
// the terrain is added to our parent
|
||||||
|
if (m_parentScene is BSScene)
|
||||||
|
{
|
||||||
|
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||||
|
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||||
|
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||||
|
heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If not doing the mega-prim thing, just change the terrain
|
||||||
|
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||||
|
|
||||||
|
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
||||||
|
// based on the passed information. The 'id' should be either the terrain id or
|
||||||
|
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
||||||
|
// The latter feature is for creating child terrains for mega-regions.
|
||||||
|
// If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
|
||||||
|
// then a new body and shape is created and the mapInfo is filled.
|
||||||
|
// This call is used for doing the initial terrain creation.
|
||||||
|
// If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
|
||||||
|
// terrain shape is created and added to the body.
|
||||||
|
// This call is most often used to update the heightMap and parameters of the terrain.
|
||||||
|
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
||||||
|
// calling this routine from initialization or taint-time routines) or whether to delay
|
||||||
|
// all the unmanaged activities to taint-time.
|
||||||
|
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
|
||||||
|
{
|
||||||
|
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
|
||||||
|
BSScene.DetailLogZero, minCoords, maxCoords, doNow);
|
||||||
|
|
||||||
|
float minZ = float.MaxValue;
|
||||||
|
float maxZ = float.MinValue;
|
||||||
|
Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
|
||||||
|
|
||||||
|
int heightMapSize = heightMap.Length;
|
||||||
|
for (int ii = 0; ii < heightMapSize; ii++)
|
||||||
|
{
|
||||||
|
float height = heightMap[ii];
|
||||||
|
if (height < minZ) minZ = height;
|
||||||
|
if (height > maxZ) maxZ = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The shape of the terrain is from its base to its extents.
|
||||||
|
minCoords.Z = minZ;
|
||||||
|
maxCoords.Z = maxZ;
|
||||||
|
|
||||||
|
BulletHeightMapInfo mapInfo;
|
||||||
|
if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
|
||||||
|
{
|
||||||
|
// If this is terrain we know about, it's easy to update
|
||||||
|
|
||||||
|
mapInfo.heightMap = heightMap;
|
||||||
|
mapInfo.minCoords = minCoords;
|
||||||
|
mapInfo.maxCoords = maxCoords;
|
||||||
|
mapInfo.minZ = minZ;
|
||||||
|
mapInfo.maxZ = maxZ;
|
||||||
|
mapInfo.sizeX = maxCoords.X - minCoords.X;
|
||||||
|
mapInfo.sizeY = maxCoords.Y - minCoords.Y;
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||||
|
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||||
|
|
||||||
|
BSScene.TaintCallback rebuildOperation = delegate()
|
||||||
|
{
|
||||||
|
if (m_parentScene != null)
|
||||||
|
{
|
||||||
|
// It's possible that Combine() was called after this code was queued.
|
||||||
|
// If we are a child of combined regions, we don't create any terrain for us.
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
|
||||||
|
|
||||||
|
// Get rid of any terrain that may have been allocated for us.
|
||||||
|
ReleaseGroundPlaneAndTerrain();
|
||||||
|
|
||||||
|
// I hate doing this, but just bail
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
// Updating an existing terrain.
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||||
|
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||||
|
|
||||||
|
// Remove from the dynamics world because we're going to mangle this object
|
||||||
|
BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||||
|
|
||||||
|
// Get rid of the old terrain
|
||||||
|
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||||
|
BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
|
||||||
|
mapInfo.Ptr = IntPtr.Zero;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// NOTE: This routine is half here because I can't get the terrain shape replacement
|
||||||
|
// to work. In the short term, the above three lines completely delete the old
|
||||||
|
// terrain and the code below recreates one from scratch.
|
||||||
|
// Hopefully the Bullet community will help me out on this one.
|
||||||
|
|
||||||
|
// First, release the old collision shape (there is only one terrain)
|
||||||
|
BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
|
||||||
|
|
||||||
|
// Fill the existing height map info with the new location and size information
|
||||||
|
BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
|
||||||
|
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||||
|
|
||||||
|
// Create a terrain shape based on the new info
|
||||||
|
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||||
|
|
||||||
|
// Stuff the shape into the existing terrain body
|
||||||
|
BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
{
|
||||||
|
// Creating a new terrain.
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
|
||||||
|
BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
|
||||||
|
|
||||||
|
mapInfo.ID = id;
|
||||||
|
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
|
||||||
|
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||||
|
|
||||||
|
// The terrain object initial position is at the center of the object
|
||||||
|
Vector3 centerPos;
|
||||||
|
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
||||||
|
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
||||||
|
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
||||||
|
|
||||||
|
// Create the terrain shape from the mapInfo
|
||||||
|
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||||
|
|
||||||
|
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
||||||
|
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
|
||||||
|
centerPos, Quaternion.Identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the entry is in the heightmap table
|
||||||
|
m_heightMaps[terrainRegionBase] = mapInfo;
|
||||||
|
|
||||||
|
// Set current terrain attributes
|
||||||
|
BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
|
||||||
|
BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
|
||||||
|
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
|
||||||
|
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||||
|
|
||||||
|
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
|
||||||
|
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
|
||||||
|
|
||||||
|
// Return the new terrain to the world of physical objects
|
||||||
|
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||||
|
|
||||||
|
// redo its bounding box now that it is in the world
|
||||||
|
BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||||
|
|
||||||
|
// Make sure the new shape is processed.
|
||||||
|
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||||
|
// to do the Bullet operations later.
|
||||||
|
if (doNow)
|
||||||
|
rebuildOperation();
|
||||||
|
else
|
||||||
|
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We don't know about this terrain so either we are creating a new terrain or
|
||||||
|
// our mega-prim child is giving us a new terrain to add to the phys world
|
||||||
|
|
||||||
|
// if this is a child terrain, calculate a unique terrain id
|
||||||
|
uint newTerrainID = id;
|
||||||
|
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||||
|
newTerrainID = ++m_terrainCount;
|
||||||
|
|
||||||
|
float[] heightMapX = heightMap;
|
||||||
|
Vector3 minCoordsX = minCoords;
|
||||||
|
Vector3 maxCoordsX = maxCoords;
|
||||||
|
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
|
||||||
|
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||||
|
|
||||||
|
// Code that must happen at taint-time
|
||||||
|
BSScene.TaintCallback createOperation = delegate()
|
||||||
|
{
|
||||||
|
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
|
||||||
|
// Create a new mapInfo that will be filled with the new info
|
||||||
|
mapInfo = new BulletHeightMapInfo(id, heightMapX,
|
||||||
|
BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
|
||||||
|
minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
|
||||||
|
// Put the unfilled heightmap info into the collection of same
|
||||||
|
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||||
|
// Build the terrain
|
||||||
|
UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||||
|
if (doNow)
|
||||||
|
createOperation();
|
||||||
|
else
|
||||||
|
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Someday we will have complex terrain with caves and tunnels
|
||||||
|
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||||
|
{
|
||||||
|
// For the moment, it's flat and convex
|
||||||
|
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given an X and Y, find the height of the terrain.
|
||||||
|
// Since we could be handling multiple terrains for a mega-region,
|
||||||
|
// the base of the region is calcuated assuming all regions are
|
||||||
|
// the same size and that is the default.
|
||||||
|
// Once the heightMapInfo is found, we have all the information to
|
||||||
|
// compute the offset into the array.
|
||||||
|
private float lastHeightTX = 999999f;
|
||||||
|
private float lastHeightTY = 999999f;
|
||||||
|
private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
|
||||||
|
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||||
|
{
|
||||||
|
// You'd be surprized at the number of times this routine is called
|
||||||
|
// with the same parameters as last time.
|
||||||
|
if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
|
||||||
|
return lastHeight;
|
||||||
|
|
||||||
|
lastHeightTX = tX;
|
||||||
|
lastHeightTY = tY;
|
||||||
|
float ret = HEIGHT_GETHEIGHT_RET;
|
||||||
|
|
||||||
|
int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
|
||||||
|
int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
|
||||||
|
Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
|
||||||
|
|
||||||
|
BulletHeightMapInfo mapInfo;
|
||||||
|
if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
|
||||||
|
{
|
||||||
|
float regionX = tX - offsetX;
|
||||||
|
float regionY = tY - offsetY;
|
||||||
|
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||||
|
if (regionY > mapInfo.sizeY) regionY = 0;
|
||||||
|
int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
|
||||||
|
ret = mapInfo.heightMap[mapIndex];
|
||||||
|
m_terrainModified = false;
|
||||||
|
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||||
|
BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||||
|
LogHeader, m_physicsScene.RegionName, tX, tY);
|
||||||
|
}
|
||||||
|
lastHeight = ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Although no one seems to check this, I do support combining.
|
||||||
|
public bool SupportsCombining()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This routine is called two ways:
|
||||||
|
// One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
|
||||||
|
// extent of the combined regions. This is to inform the parent of the size
|
||||||
|
// of the combined regions.
|
||||||
|
// and one with 'offset' as the offset of the child region to the base region,
|
||||||
|
// 'pScene' pointing to the parent and 'extents' of zero. This informs the
|
||||||
|
// child of its relative base and new parent.
|
||||||
|
public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||||
|
{
|
||||||
|
m_worldOffset = offset;
|
||||||
|
m_worldMax = extents;
|
||||||
|
m_parentScene = pScene;
|
||||||
|
if (pScene != null)
|
||||||
|
{
|
||||||
|
// We are a child.
|
||||||
|
// We want m_worldMax to be the highest coordinate of our piece of terrain.
|
||||||
|
m_worldMax = offset + DefaultRegionSize;
|
||||||
|
}
|
||||||
|
DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
|
||||||
|
BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unhook all the combining that I know about.
|
||||||
|
public void UnCombine(PhysicsScene pScene)
|
||||||
|
{
|
||||||
|
// Just like ODE, for the moment a NOP
|
||||||
|
DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DetailLog(string msg, params Object[] args)
|
||||||
|
{
|
||||||
|
m_physicsScene.PhysicsLogging.Write(msg, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,15 +33,25 @@ using OpenMetaverse;
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||||
|
|
||||||
// Classes to allow some type checking for the API
|
// Classes to allow some type checking for the API
|
||||||
|
// These hold pointers to allocated objects in the unmanaged space.
|
||||||
|
|
||||||
|
// The physics engine controller class created at initialization
|
||||||
public struct BulletSim
|
public struct BulletSim
|
||||||
{
|
{
|
||||||
public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
|
public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
|
||||||
public uint ID;
|
public uint worldID;
|
||||||
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
// The scene is only in here so very low level routines have a handle to print debug/error messages
|
||||||
public BSScene scene;
|
public BSScene scene;
|
||||||
public IntPtr Ptr;
|
public IntPtr Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct BulletShape
|
||||||
|
{
|
||||||
|
public BulletShape(IntPtr xx) { Ptr = xx; }
|
||||||
|
public IntPtr Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An allocated Bullet btRigidBody
|
||||||
public struct BulletBody
|
public struct BulletBody
|
||||||
{
|
{
|
||||||
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||||
|
@ -49,12 +59,41 @@ public struct BulletBody
|
||||||
public uint ID;
|
public uint ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An allocated Bullet btConstraint
|
||||||
public struct BulletConstraint
|
public struct BulletConstraint
|
||||||
{
|
{
|
||||||
public BulletConstraint(IntPtr xx) { Ptr = xx; }
|
public BulletConstraint(IntPtr xx) { Ptr = xx; }
|
||||||
public IntPtr Ptr;
|
public IntPtr Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An allocated HeightMapThing which hold various heightmap info
|
||||||
|
// Made a class rather than a struct so there would be only one
|
||||||
|
// instance of this and C# will pass around pointers rather
|
||||||
|
// than making copies.
|
||||||
|
public class BulletHeightMapInfo
|
||||||
|
{
|
||||||
|
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
||||||
|
ID = id;
|
||||||
|
Ptr = xx;
|
||||||
|
heightMap = hm;
|
||||||
|
terrainRegionBase = new Vector2(0f, 0f);
|
||||||
|
minCoords = new Vector3(100f, 100f, 25f);
|
||||||
|
maxCoords = new Vector3(101f, 101f, 26f);
|
||||||
|
minZ = maxZ = 0f;
|
||||||
|
sizeX = sizeY = 256f;
|
||||||
|
}
|
||||||
|
public uint ID;
|
||||||
|
public IntPtr Ptr;
|
||||||
|
public float[] heightMap;
|
||||||
|
public Vector2 terrainRegionBase;
|
||||||
|
public Vector3 minCoords;
|
||||||
|
public Vector3 maxCoords;
|
||||||
|
public float sizeX, sizeY;
|
||||||
|
public float minZ, maxZ;
|
||||||
|
public BulletShape terrainShape;
|
||||||
|
public BulletBody terrainBody;
|
||||||
|
}
|
||||||
|
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct ConvexHull
|
public struct ConvexHull
|
||||||
|
@ -221,6 +260,10 @@ public enum ConstraintParamAxis : int
|
||||||
// ===============================================================================
|
// ===============================================================================
|
||||||
static class BulletSimAPI {
|
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);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||||
public static extern string GetVersion();
|
public static extern string GetVersion();
|
||||||
|
@ -228,7 +271,11 @@ public static extern string GetVersion();
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
|
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,
|
||||||
|
DebugLogCallback logRoutine);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
|
||||||
|
|
||||||
[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);
|
||||||
|
@ -342,8 +389,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
|
||||||
public static extern void DumpBulletStatistics();
|
public static extern void DumpBulletStatistics();
|
||||||
|
|
||||||
// Log a debug message
|
// Log a debug message
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||||
|
|
||||||
|
@ -377,7 +422,7 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
|
||||||
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
|
public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
|
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void Shutdown2(IntPtr sim);
|
public static extern void Shutdown2(IntPtr sim);
|
||||||
|
@ -392,23 +437,53 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
|
||||||
[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]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
|
public static extern IntPtr CreateMeshShape2(IntPtr world,
|
||||||
|
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
|
||||||
|
int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
|
public static extern IntPtr CreateHullShape2(IntPtr world,
|
||||||
|
int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
|
public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
|
public static extern IntPtr BuildNativeShape2(IntPtr world,
|
||||||
|
float shapeType, float collisionMargin, Vector3 scale);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
|
public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||||
*/
|
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||||
|
// =====================================================================================
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||||
|
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||||
|
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
|
||||||
|
|
||||||
|
// =====================================================================================
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||||
Vector3 frame1loc, Quaternion frame1rot,
|
Vector3 frame1loc, Quaternion frame1rot,
|
||||||
|
@ -460,11 +535,16 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
|
public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
|
||||||
|
|
||||||
|
// =====================================================================================
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
|
public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
|
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
|
||||||
|
|
||||||
|
// =====================================================================================
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern void Activate2(IntPtr obj, bool forceActivation);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern Vector3 GetPosition2(IntPtr obj);
|
public static extern Vector3 GetPosition2(IntPtr obj);
|
||||||
|
@ -508,6 +588,9 @@ public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool SetFriction2(IntPtr obj, float val);
|
public static extern bool SetFriction2(IntPtr obj, float val);
|
||||||
|
|
||||||
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
|
public static extern bool SetHitFraction2(IntPtr obj, float val);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool SetRestitution2(IntPtr obj, float val);
|
public static extern bool SetRestitution2(IntPtr obj, float val);
|
||||||
|
|
||||||
|
@ -551,7 +634,7 @@ public static extern bool SetMargin2(IntPtr obj, float val);
|
||||||
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
|
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern bool DestroyObject2(IntPtr world, uint id);
|
public static extern bool DestroyObject2(IntPtr world, IntPtr obj);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
Json.NET
|
|
||||||
License: The MIT License
|
|
||||||
Copyright (c) 2007 James Newton-King
|
|
||||||
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3385,6 +3385,7 @@
|
||||||
|
|
||||||
<ReferencePath>../../../bin/</ReferencePath>
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
<Reference name="System"/>
|
<Reference name="System"/>
|
||||||
|
<Reference name="System.Core"/>
|
||||||
<Reference name="System.Xml"/>
|
<Reference name="System.Xml"/>
|
||||||
<Reference name="System.Data"/>
|
<Reference name="System.Data"/>
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
|
Loading…
Reference in New Issue