BulletSim: Convert BSCharacter to use common BSPhysObject code and variables.

Fix avatar height calculation to properly account for the capsule ends.
Rearrange some locking in TerrainManager to eliminate possible race conditions.
Move DetailLog() definition into common BSPhysObject class.
Some variable renaming to make usage clearer (refactor.rename makes this so easy).
connector_plugin
Robert Adams 2012-09-18 11:26:19 -07:00
parent ee7cda261c
commit 91efccabdc
5 changed files with 113 additions and 117 deletions

View File

@ -39,18 +39,16 @@ public class BSCharacter : BSPhysObject
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS CHAR]";
private String _avName;
// private bool _stopped;
private OMV.Vector3 _size;
private OMV.Vector3 _scale;
private PrimitiveBaseShape _pbs;
private uint _localID = 0;
private bool _grabbed;
private bool _selected;
private OMV.Vector3 _position;
private float _mass;
public float _density;
public float _avatarVolume;
private float _avatarDensity;
private float _avatarVolume;
private OMV.Vector3 _force;
private OMV.Vector3 _velocity;
private OMV.Vector3 _torque;
@ -63,18 +61,12 @@ public class BSCharacter : BSPhysObject
private bool _setAlwaysRun;
private bool _throttleUpdates;
private bool _isColliding;
private long _collidingStep;
private bool _collidingGround;
private long _collidingGroundStep;
private bool _collidingObj;
private bool _floatOnWater;
private OMV.Vector3 _rotationalVelocity;
private bool _kinematic;
private float _buoyancy;
private int _subscribedEventsMs = 0;
private int _nextCollisionOkTime = 0;
private OMV.Vector3 _PIDTarget;
private bool _usePID;
private float _PIDTau;
@ -85,9 +77,7 @@ public class BSCharacter : BSPhysObject
public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
{
base.BaseInitialize(parent_scene);
_localID = localID;
_avName = avName;
base.BaseInitialize(parent_scene, localID, avName);
_physicsActorType = (int)ActorTypes.Agent;
_position = pos;
_size = size;
@ -95,14 +85,15 @@ public class BSCharacter : BSPhysObject
_orientation = OMV.Quaternion.Identity;
_velocity = OMV.Vector3.Zero;
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
// The dimensions of the avatar capsule are kept in the scale.
// Physics creates a unit capsule which is scaled by the physics engine.
_scale = new OMV.Vector3(PhysicsScene.Params.avatarCapsuleRadius, PhysicsScene.Params.avatarCapsuleRadius, size.Z);
_density = PhysicsScene.Params.avatarDensity;
ComputeAvatarScale(_size);
_avatarDensity = PhysicsScene.Params.avatarDensity;
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
ShapeData shapeData = new ShapeData();
shapeData.ID = _localID;
shapeData.ID = LocalID;
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
shapeData.Position = _position;
shapeData.Rotation = _orientation;
@ -117,7 +108,7 @@ public class BSCharacter : BSPhysObject
// do actual create at taint time
PhysicsScene.TaintedObject("BSCharacter.create", delegate()
{
DetailLog("{0},BSCharacter.create", _localID);
DetailLog("{0},BSCharacter.create,taint", LocalID);
BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData);
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
@ -135,7 +126,7 @@ public class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.Destroy", LocalID);
PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
{
BulletSimAPI.DestroyObject(PhysicsScene.WorldID, _localID);
BulletSimAPI.DestroyObject(PhysicsScene.WorldID, LocalID);
});
}
@ -158,7 +149,7 @@ public class BSCharacter : BSPhysObject
// When an avatar's size is set, only the height is changed
// and that really only depends on the radius.
_size = value;
_scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
ComputeAvatarScale(_size);
// TODO: something has to be done with the avatar's vertical position
@ -175,11 +166,6 @@ public class BSCharacter : BSPhysObject
set { _pbs = value;
}
}
public override uint LocalID {
set { _localID = value;
}
get { return _localID; }
}
public override bool Grabbed {
set { _grabbed = value;
}
@ -223,7 +209,7 @@ public class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
{
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
});
}
}
@ -261,7 +247,7 @@ public class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
{
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
});
ret = true;
}
@ -312,7 +298,7 @@ public class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
{
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, _localID, _velocity);
BulletSimAPI.SetObjectVelocity(PhysicsScene.WorldID, LocalID, _velocity);
});
}
}
@ -338,7 +324,7 @@ public class BSCharacter : BSPhysObject
PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
{
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, _localID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(PhysicsScene.WorldID, LocalID, _position, _orientation);
});
}
}
@ -375,12 +361,12 @@ public class BSCharacter : BSPhysObject
set { _throttleUpdates = value; }
}
public override bool IsColliding {
get { return (_collidingStep == PhysicsScene.SimulationStep); }
get { return (CollidingStep == PhysicsScene.SimulationStep); }
set { _isColliding = value; }
}
public override bool CollidingGround {
get { return (_collidingGroundStep == PhysicsScene.SimulationStep); }
set { _collidingGround = value; }
get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
set { CollidingGround = value; }
}
public override bool CollidingObj {
get { return _collidingObj; }
@ -466,6 +452,16 @@ public class BSCharacter : BSPhysObject
public override void SetMomentum(OMV.Vector3 momentum) {
}
private void ComputeAvatarScale(OMV.Vector3 size)
{
_scale.X = PhysicsScene.Params.avatarCapsuleRadius;
_scale.Y = PhysicsScene.Params.avatarCapsuleRadius;
// The 1.15 came from ODE but it seems to cause the avatar to float off the ground
// _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
_scale.Z = (_size.Z) - (_scale.X + _scale.Y);
}
// set _avatarVolume and _mass based on capsule size, _density and _scale
private void ComputeAvatarVolumeAndMass()
{
@ -480,7 +476,7 @@ public class BSCharacter : BSPhysObject
* Math.Min(_scale.X, _scale.Y)
* _scale.Y // plus the volume of the capsule end caps
);
_mass = _density * _avatarVolume;
_mass = _avatarDensity * _avatarVolume;
}
// The physics engine says that properties have updated. Update same and inform
@ -502,11 +498,5 @@ public class BSCharacter : BSPhysObject
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
}
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
PhysicsScene.PhysicsLogging.Write(msg, args);
}
}
}

View File

@ -77,7 +77,7 @@ public class BSLinkset
// A simple linkset of one (no children)
LinksetID = m_nextLinksetID++;
// We create LOTS of linksets.
if (m_nextLinksetID < 0)
if (m_nextLinksetID <= 0)
m_nextLinksetID = 1;
PhysicsScene = scene;
LinksetRoot = parent;
@ -157,21 +157,26 @@ public class BSLinkset
private float ComputeLinksetMass()
{
float mass = LinksetRoot.MassRaw;
foreach (BSPhysObject bp in m_children)
float mass;
lock (m_linksetActivityLock)
{
mass += bp.MassRaw;
mass = LinksetRoot.MassRaw;
foreach (BSPhysObject bp in m_children)
{
mass += bp.MassRaw;
}
}
return mass;
}
private OMV.Vector3 ComputeLinksetCenterOfMass()
{
OMV.Vector3 com = LinksetRoot.Position * LinksetRoot.MassRaw;
float totalMass = LinksetRoot.MassRaw;
OMV.Vector3 com;
lock (m_linksetActivityLock)
{
com = LinksetRoot.Position * LinksetRoot.MassRaw;
float totalMass = LinksetRoot.MassRaw;
foreach (BSPhysObject bp in m_children)
{
com += bp.Position * bp.MassRaw;
@ -186,10 +191,11 @@ public class BSLinkset
private OMV.Vector3 ComputeLinksetGeometricCenter()
{
OMV.Vector3 com = LinksetRoot.Position;
OMV.Vector3 com;
lock (m_linksetActivityLock)
{
com = LinksetRoot.Position;
foreach (BSPhysObject bp in m_children)
{
com += bp.Position * bp.MassRaw;
@ -208,8 +214,8 @@ public class BSLinkset
// Called at taint-time!
public bool MakeDynamic(BSPhysObject child)
{
bool ret = false;
return ret;
// What is done for each object in BSPrim is what we want.
return false;
}
// The object is going static (non-physical). Do any setup necessary

View File

@ -39,9 +39,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// unless the difference is significant.
public abstract class BSPhysObject : PhysicsActor
{
protected void BaseInitialize(BSScene parentScene)
protected void BaseInitialize(BSScene parentScene, uint localID, string name)
{
PhysicsScene = parentScene;
LocalID = localID;
PhysObjectName = name;
Linkset = new BSLinkset(PhysicsScene, this);
CollisionCollection = new CollisionEventUpdate();
@ -51,6 +54,8 @@ public abstract class BSPhysObject : PhysicsActor
}
public BSScene PhysicsScene { get; protected set; }
// public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
public string PhysObjectName { get; protected set; }
public BSLinkset Linkset { get; set; }
@ -111,13 +116,13 @@ public abstract class BSPhysObject : PhysicsActor
return ret;
}
PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith);
DetailLog("{0},BSPhysObject.Collison,call,with={1}", LocalID, collidingWith);
// if someone has subscribed for collision events....
if (SubscribedEvents()) {
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
PhysicsScene.PhysicsLogging.Write("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4},next={5}",
LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff"));
DetailLog("{0},BSPhysObject.Collison.AddCollider,call,with={1},point={2},normal={3},depth={4}",
LocalID, collidingWith, contactPoint, contactNormal, pentrationDepth);
ret = true;
}
return ret;
@ -127,6 +132,8 @@ public abstract class BSPhysObject : PhysicsActor
// Also handles removal of this from the collection of objects with collisions if
// there are no collisions from this object. Mechanism is create one last
// collision event to make collision_end work.
// Called at taint time from within the Step() function thus no locking problems
// with CollisionCollection and ObjectsWithNoMoreCollisions.
public virtual void SendCollisions()
{
// throttle the collisions to the number of milliseconds specified in the subscription
@ -140,10 +147,11 @@ public abstract class BSPhysObject : PhysicsActor
if (CollisionCollection.Count == 0)
PhysicsScene.ObjectsWithNoMoreCollisions.Add(this);
DetailLog("{0},SendCollisions.SendCollisionUpdate,call,numCollisions={1}", LocalID, CollisionCollection.Count);
base.SendCollisionUpdate(CollisionCollection);
// The collisionCollection structure is passed around in the simulator.
// Make sure we don't have a handle to that one and that a new one is used next time.
// Make sure we don't have a handle to that one and that a new one is used for next time.
CollisionCollection = new CollisionEventUpdate();
}
}
@ -156,8 +164,7 @@ public abstract class BSPhysObject : PhysicsActor
{
// make sure first collision happens
NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
PhysicsScene.PhysicsLogging.Write("{0},SubscribeEvents,call,ms={1},nextOKTime={2}",
LocalID, SubscribedEventsMs, NextCollisionOkTime.ToString("yyyyMMddHHmmssfff"));
DetailLog("{0},SubscribeEvents,call,ms={1}", LocalID, SubscribedEventsMs);
PhysicsScene.TaintedObject("BSPhysObject.SubscribeEvents", delegate()
{
@ -172,7 +179,7 @@ public abstract class BSPhysObject : PhysicsActor
}
public override void UnSubscribeEvents() {
SubscribedEventsMs = 0;
PhysicsScene.PhysicsLogging.Write("{0},UnSubscribeEvents,call", LocalID);
DetailLog("{0},UnSubscribeEvents,call", LocalID);
PhysicsScene.TaintedObject("BSPhysObject.UnSubscribeEvents", delegate()
{
CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
@ -184,5 +191,11 @@ public abstract class BSPhysObject : PhysicsActor
}
#endregion // Collisions
// High performance detailed logging routine used by the physical objects.
protected void DetailLog(string msg, params Object[] args)
{
PhysicsScene.PhysicsLogging.Write(msg, args);
}
}
}

View File

@ -49,9 +49,6 @@ public sealed class BSPrim : BSPhysObject
private ulong _hullKey;
private List<ConvexResult> _hulls;
private String _avName;
private uint _localID = 0;
// _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
// Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
@ -99,9 +96,7 @@ public sealed class BSPrim : BSPhysObject
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
{
// m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
base.BaseInitialize(parent_scene);
_localID = localID;
_avName = primName;
base.BaseInitialize(parent_scene, localID, primName);
_physicsActorType = (int)ActorTypes.Prim;
_position = pos;
_size = size;
@ -187,10 +182,6 @@ public sealed class BSPrim : BSPhysObject
});
}
}
public override uint LocalID {
set { _localID = value; }
get { return _localID; }
}
public override bool Grabbed {
set { _grabbed = value;
}
@ -267,7 +258,7 @@ public sealed class BSPrim : BSPhysObject
_position = BulletSimAPI.GetPosition2(BSBody.Ptr);
// don't do the GetObjectPosition for root elements because this function is called a zillion times
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID);
return _position;
}
set {
@ -425,7 +416,7 @@ public sealed class BSPrim : BSPhysObject
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
{
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID);
DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetTranslation2(BSBody.Ptr, _position, _orientation);
});
@ -666,7 +657,7 @@ public sealed class BSPrim : BSPhysObject
// Buoyancy is faked by changing the gravity applied to the object
float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
BulletSimAPI.SetGravity2(BSBody.Ptr, new OMV.Vector3(0f, 0f, grav));
// BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, _localID, _buoyancy);
// BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
});
}
}
@ -1127,7 +1118,7 @@ public sealed class BSPrim : BSPhysObject
lod = PhysicsScene.MeshMegaPrimLOD;
ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
// m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
// m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey);
// if this new shape is the same as last time, don't recreate the mesh
if (_meshKey == newMeshKey) return false;
@ -1136,7 +1127,7 @@ public sealed class BSPrim : BSPhysObject
// Since we're recreating new, get rid of any previously generated shape
if (_meshKey != 0)
{
// m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
// m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, LocalID, _meshKey);
DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(PhysicsScene.WorldID, _meshKey);
_mesh = null;
@ -1145,7 +1136,7 @@ public sealed class BSPrim : BSPhysObject
_meshKey = newMeshKey;
// always pass false for physicalness as this creates some sort of bounding box which we don't need
_mesh = PhysicsScene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
_mesh = PhysicsScene.mesher.CreateMesh(PhysObjectName, _pbs, _size, lod, false);
int[] indices = _mesh.getIndexListAsInt();
List<OMV.Vector3> vertices = _mesh.getVertexList();
@ -1160,7 +1151,7 @@ public sealed class BSPrim : BSPhysObject
}
// m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
// LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
// LogHeader, LocalID, _meshKey, indices.Length, vertices.Count);
BulletSimAPI.CreateMesh(PhysicsScene.WorldID, _meshKey, indices.GetLength(0), indices,
vertices.Count, verticesAsFloats);
@ -1176,7 +1167,7 @@ public sealed class BSPrim : BSPhysObject
{
float lod = _pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD;
ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
// m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
// m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey);
// if the hull hasn't changed, don't rebuild it
if (newHullKey == _hullKey) return false;
@ -1276,7 +1267,7 @@ public sealed class BSPrim : BSPhysObject
}
// create the hull definition in Bullet
// m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
// m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount);
BulletSimAPI.CreateHull(PhysicsScene.WorldID, _hullKey, hullCount, convHulls);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
// meshes are already scaled by the meshmerizer
@ -1316,7 +1307,7 @@ public sealed class BSPrim : BSPhysObject
// the mesh or hull must have already been created in Bullet
ShapeData shape;
FillShapeInfo(out shape);
// m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
// m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type);
bool ret = BulletSimAPI.CreateObject(PhysicsScene.WorldID, shape);
// the CreateObject() may have recreated the rigid body. Make sure we have the latest address.
@ -1329,7 +1320,7 @@ public sealed class BSPrim : BSPhysObject
// Copy prim's info into the BulletSim shape description structure
public void FillShapeInfo(out ShapeData shape)
{
shape.ID = _localID;
shape.ID = LocalID;
shape.Type = _shapeType;
shape.Position = _position;
shape.Rotation = _orientation;
@ -1350,7 +1341,7 @@ public sealed class BSPrim : BSPhysObject
// No locking here because this is done when the physics engine is not simulating
private void CreateGeomAndObject(bool forceRebuild)
{
// m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, _localID, forceRebuild);
// m_log.DebugFormat("{0}: CreateGeomAndObject. lID={1}, force={2}", LogHeader, LocalID, forceRebuild);
// Create the geometry that will make up the object
if (CreateGeom(forceRebuild))
{
@ -1453,10 +1444,5 @@ public sealed class BSPrim : BSPhysObject
}
*/
}
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
PhysicsScene.PhysicsLogging.Write(msg, args);
}
}
}

View File

@ -57,10 +57,10 @@ public class BSTerrainManager
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);
public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
// The scene that I am part of
private BSScene m_physicsScene;
private BSScene PhysicsScene { get; set; }
// The ground plane created to keep thing from falling to infinity.
private BulletBody m_groundPlane;
@ -84,18 +84,18 @@ public class BSTerrainManager
// 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;
private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
public BSTerrainManager(BSScene physicsScene)
{
m_physicsScene = physicsScene;
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;
m_worldMax = new Vector3(DefaultRegionSize);
MegaRegionParentPhysicsScene = null;
}
// Create the initial instance of terrain and the underlying ground plane.
@ -110,7 +110,7 @@ public class BSTerrainManager
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);
BulletSimAPI.AddObjectToWorld2(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);
@ -128,9 +128,9 @@ public class BSTerrainManager
{
if (m_groundPlane.Ptr != IntPtr.Zero)
{
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr))
{
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, m_groundPlane.Ptr);
}
m_groundPlane.Ptr = IntPtr.Zero;
}
@ -143,9 +143,9 @@ public class BSTerrainManager
{
foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
{
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
{
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
}
}
@ -155,19 +155,19 @@ public class BSTerrainManager
// The simulator wants to set a new heightmap for the terrain.
public void SetTerrain(float[] heightMap) {
float[] localHeightMap = heightMap;
m_physicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
{
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != 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)
if (MegaRegionParentPhysicsScene is BSScene)
{
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
}
}
@ -176,7 +176,8 @@ public class BSTerrainManager
// If not doing the mega-prim thing, just change the terrain
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap,
m_worldOffset, m_worldOffset + DefaultRegionSize, true);
}
});
}
@ -232,7 +233,7 @@ public class BSTerrainManager
BSScene.TaintCallback rebuildOperation = delegate()
{
if (m_parentScene != null)
if (MegaRegionParentPhysicsScene != 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.
@ -252,10 +253,10 @@ public class BSTerrainManager
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);
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
// Get rid of the old terrain
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
mapInfo.Ptr = IntPtr.Zero;
@ -286,7 +287,7 @@ public class BSTerrainManager
BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
mapInfo.ID = id;
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(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
@ -307,19 +308,19 @@ public class BSTerrainManager
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.SetFriction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainFriction);
BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, PhysicsScene.Params.terrainHitFraction);
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, 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);
BulletSimAPI.AddObjectToWorld2(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);
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
// Make sure the new shape is processed.
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
@ -332,7 +333,7 @@ public class BSTerrainManager
if (doNow)
rebuildOperation();
else
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
}
else
{
@ -357,7 +358,7 @@ public class BSTerrainManager
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,
BulletSimAPI.CreateHeightMapInfo2(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);
@ -371,7 +372,7 @@ public class BSTerrainManager
if (doNow)
createOperation();
else
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
}
}
@ -419,7 +420,7 @@ public class BSTerrainManager
catch
{
// Sometimes they give us wonky values of X and Y. Give a warning and return something.
m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
LogHeader, terrainBaseXY, regionX, regionY);
ret = HEIGHT_GETHEIGHT_RET;
}
@ -428,8 +429,8 @@ public class BSTerrainManager
}
else
{
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
LogHeader, m_physicsScene.RegionName, tX, tY);
PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
LogHeader, PhysicsScene.RegionName, tX, tY);
}
m_terrainModified = false;
lastHeight = ret;
@ -453,7 +454,7 @@ public class BSTerrainManager
{
m_worldOffset = offset;
m_worldMax = extents;
m_parentScene = pScene;
MegaRegionParentPhysicsScene = pScene;
if (pScene != null)
{
// We are a child.
@ -474,7 +475,7 @@ public class BSTerrainManager
private void DetailLog(string msg, params Object[] args)
{
m_physicsScene.PhysicsLogging.Write(msg, args);
PhysicsScene.PhysicsLogging.Write(msg, args);
}
}
}