From 7b6987ce83d16871f6070f3cc7d56280ad3d5dbe Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 24 Aug 2012 12:58:42 -0700 Subject: BulletSim: unify physical objects under BSPhysObjects. Now BSScene and BSLinkset only know of BSPhysObject's and there is only one list to search in BSScene. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 31 +++-- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 50 ++++---- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 58 +++++++++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 84 ++++++------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 137 +++++++++------------ 5 files changed, 200 insertions(+), 160 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs (limited to 'OpenSim/Region/Physics') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 1b23a36..784076d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.Manager; 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 string LogHeader = "[BULLETS CHAR]"; @@ -74,11 +74,8 @@ public class BSCharacter : PhysicsActor private bool _kinematic; private float _buoyancy; - private BulletBody m_body; - public BulletBody Body { - get { return m_body; } - set { m_body = value; } - } + public override BulletBody Body { get; set; } + public override BSLinkset Linkset { get; set; } private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; @@ -108,6 +105,8 @@ public class BSCharacter : PhysicsActor _density = _scene.Params.avatarDensity; ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + Linkset = new BSLinkset(_scene, this); + ShapeData shapeData = new ShapeData(); shapeData.ID = _localID; shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; @@ -130,7 +129,7 @@ public class BSCharacter : PhysicsActor // Set the buoyancy for flying. This will be refactored when all the settings happen in C# 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) BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -139,7 +138,7 @@ public class BSCharacter : PhysicsActor } // 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); _scene.TaintedObject("BSCharacter.destroy", delegate() @@ -245,6 +244,10 @@ public class BSCharacter : PhysicsActor 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 { get { return _force; } set { @@ -448,6 +451,12 @@ public class BSCharacter : PhysicsActor }); } } + + public override void ZeroMotion() + { + return; + } + // Stop collision events public override void UnSubscribeEvents() { _subscribedEventsMs = 0; @@ -481,7 +490,7 @@ public class BSCharacter : PhysicsActor // The physics engine says that properties have updated. Update same and inform // the world that things have changed. - public void UpdateProperties(EntityProperties entprop) + public override void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; @@ -500,7 +509,7 @@ public class BSCharacter : PhysicsActor // 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. 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); @@ -525,7 +534,7 @@ public class BSCharacter : PhysicsActor } } - public void SendCollisions() + public override void SendCollisions() { /* if (collisionCollection != null && collisionCollection.Count > 0) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e3f0db..b04e1b6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -36,8 +36,8 @@ public class BSLinkset { private static string LogHeader = "[BULLETSIM LINKSET]"; - private BSPrim m_linksetRoot; - public BSPrim LinksetRoot { get { return m_linksetRoot; } } + private BSPhysObject m_linksetRoot; + public BSPhysObject LinksetRoot { get { return m_linksetRoot; } } private BSScene m_physicsScene; public BSScene PhysicsScene { get { return m_physicsScene; } } @@ -46,7 +46,7 @@ public class BSLinkset public int LinksetID { get; private set; } // The children under the root in this linkset - private List m_children; + private List m_children; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -74,7 +74,7 @@ public class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - public BSLinkset(BSScene scene, BSPrim parent) + public BSLinkset(BSScene scene, BSPhysObject parent) { // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; @@ -83,14 +83,14 @@ public class BSLinkset m_nextLinksetID = 1; m_physicsScene = scene; m_linksetRoot = parent; - m_children = new List(); + m_children = new List(); m_mass = parent.MassRaw; } // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // 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) { @@ -102,7 +102,7 @@ public class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). - public BSLinkset RemoveMeFromLinkset(BSPrim child) + public BSLinkset RemoveMeFromLinkset(BSPhysObject child) { lock (m_linksetActivityLock) { @@ -129,7 +129,7 @@ public class BSLinkset } // 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); } @@ -140,12 +140,12 @@ public class BSLinkset public bool HasAnyChildren { get { return (m_children.Count > 0); } } // Return 'true' if this child is in this linkset - public bool HasChild(BSPrim child) + public bool HasChild(BSPhysObject child) { bool ret = false; lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) { @@ -160,7 +160,7 @@ public class BSLinkset private float ComputeLinksetMass() { float mass = m_linksetRoot.MassRaw; - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { mass += bp.MassRaw; } @@ -174,7 +174,7 @@ public class BSLinkset lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; totalMass += bp.MassRaw; @@ -192,7 +192,7 @@ public class BSLinkset lock (m_linksetActivityLock) { - foreach (BSPrim bp in m_children) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; } @@ -204,7 +204,7 @@ public class BSLinkset // When physical properties are changed the linkset needs to recalculate // 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 (!HasAnyChildren) @@ -230,7 +230,7 @@ public class BSLinkset float linksetMass = LinksetMass; lock (m_linksetActivityLock) { - foreach (BSPrim child in m_children) + foreach (BSPhysObject child in m_children) { BSConstraint 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 // Called while LinkActivity is locked. - private void AddChildToLinkset(BSPrim child) + private void AddChildToLinkset(BSPhysObject child) { if (!HasChild(child)) { m_children.Add(child); - BSPrim rootx = LinksetRoot; // capture the root as of now - BSPrim childx = child; + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { 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. // Normal OpenSimulator operation will never do this because other SceneObjectPart information // 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); RemoveChildFromLinkset(pchild); @@ -285,12 +285,12 @@ public class BSLinkset // 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. - private void RemoveChildFromLinkset(BSPrim child) + private void RemoveChildFromLinkset(BSPhysObject child) { if (m_children.Remove(child)) { - BSPrim rootx = LinksetRoot; // capture the root as of now - BSPrim childx = child; + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { 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). // 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 childPrim.ZeroMotion(); @@ -383,7 +383,7 @@ public class BSLinkset // Remove linkage between myself and a particular child // 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); @@ -396,7 +396,7 @@ public class BSLinkset // Remove linkage between myself and any possible children I might have // Called at taint time! - private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) + private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs new file mode 100755 index 0000000..6e205a9 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -0,0 +1,58 @@ +/* + * 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 abstract void UpdateProperties(EntityProperties entprop); + + public abstract void Destroy(); +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index d3f1e9c..036fd4f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { [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 string LogHeader = "[BULLETS PRIM]"; @@ -88,23 +88,14 @@ public sealed class BSPrim : PhysicsActor private float _buoyancy; // Membership in a linkset is controlled by this class. - private BSLinkset _linkset; - public BSLinkset Linkset - { - get { return _linkset; } - set { _linkset = value; } - } + public override BSLinkset Linkset { get; set; } private int _subscribedEventsMs = 0; private int _nextCollisionOkTime = 0; long _collidingStep; long _collidingGroundStep; - private BulletBody m_body; - public BulletBody Body { - get { return m_body; } - set { m_body = value; } - } + public override BulletBody Body { get; set; } private BSDynamics _vehicle; @@ -139,7 +130,7 @@ public sealed class BSPrim : PhysicsActor _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _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 _mass = CalculateMass(); // 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. // 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. - 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 - public void Destroy() + public override void Destroy() { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any links between me and any other object - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + 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}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; @@ -230,13 +221,13 @@ public sealed class BSPrim : PhysicsActor BSPrim parent = obj as BSPrim; if (parent != null) { - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + 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}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); } return; } @@ -246,13 +237,13 @@ public sealed class BSPrim : PhysicsActor // 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 - BSPrim parentBefore = _linkset.LinksetRoot; - int childrenBefore = _linkset.NumberOfChildren; + BSPhysObject parentBefore = Linkset.LinksetRoot; + int childrenBefore = Linkset.NumberOfChildren; - _linkset = _linkset.RemoveMeFromLinkset(this); + Linkset = Linkset.RemoveMeFromLinkset(this); 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; } @@ -260,7 +251,7 @@ public sealed class BSPrim : PhysicsActor // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public void ZeroMotion() + public override void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; @@ -281,7 +272,7 @@ public sealed class BSPrim : PhysicsActor public override OMV.Vector3 Position { get { - if (!_linkset.IsRoot(this)) + if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); @@ -306,23 +297,23 @@ public sealed class BSPrim : PhysicsActor { get { - return _linkset.LinksetMass; + return Linkset.LinksetMass; } } // 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? public override OMV.Vector3 CenterOfMass { - get { return _linkset.CenterOfMass; } + get { return Linkset.CenterOfMass; } } // Is this used? public override OMV.Vector3 GeometricCenter { - get { return _linkset.GeometricCenter; } + get { return Linkset.GeometricCenter; } } public override OMV.Vector3 Force { @@ -431,7 +422,7 @@ public sealed class BSPrim : PhysicsActor } public override OMV.Quaternion Orientation { get { - if (!_linkset.IsRoot(this)) + if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); @@ -490,7 +481,7 @@ public sealed class BSPrim : PhysicsActor BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); // recompute any linkset parameters - _linkset.Refresh(this); + Linkset.Refresh(this); CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 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 ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - public void UpdateProperties(EntityProperties entprop) + public override void UpdateProperties(EntityProperties entprop) { /* 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. // 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 _position = entprop.Position; @@ -1375,7 +1366,7 @@ public sealed class BSPrim : PhysicsActor // I've collided with something // Called at taint time from within the Step() function 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); @@ -1387,18 +1378,15 @@ public sealed class BSPrim : PhysicsActor } // 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 + if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) { - // prims in the same linkset cannot collide with each other - if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID) - { - return; - } + return; } - // if someone is subscribed to collision events.... - if (_subscribedEventsMs != 0) { + // if someone has subscribed for collision events.... + if (SubscribedEvents()) { // throttle the collisions to the number of milliseconds specified in the subscription int nowTime = _scene.SimulationNowTime; 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 - public void SendCollisions() + public override void SendCollisions() { if (collisionCollection != null && collisionCollection.Count > 0) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 56924aa..ce64b9b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -78,14 +78,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters public string BulletSimVersion = "?"; - private Dictionary m_avatars = new Dictionary(); - public Dictionary Characters { get { return m_avatars; } } - - private Dictionary m_prims = new Dictionary(); - public Dictionary Prims { get { return m_prims; } } + public Dictionary PhysObjects = new Dictionary(); + private HashSet m_objectsWithCollisions = new HashSet(); + // Following is a kludge and can be removed when avatar animation updating is + // moved to a better place. private HashSet m_avatarsWithCollisions = new HashSet(); - private HashSet m_primsWithCollisions = new HashSet(); private List m_vehicles = new List(); @@ -235,7 +233,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // BulletSimVersion = BulletSimAPI.GetVersion(); // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - // if Debug, enable logging from the unmanaged code + // If Debug logging level, enable logging from the unmanaged code if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) { m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); @@ -243,13 +241,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters 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 + // 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(); mesher = meshmerizer; + // The bounding box for the simulated world Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); @@ -337,7 +336,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (m_avatars) m_avatars.Add(localID, actor); + lock (PhysObjects) PhysObjects.Add(localID, actor); + + // Remove kludge someday + lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor); + return actor; } @@ -352,7 +355,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters { 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) { @@ -374,7 +379,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { - lock (m_prims) m_prims.Remove(bsprim.LocalID); + lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); } catch (Exception e) { @@ -399,7 +404,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters DetailLog("{0},AddPrimShape,call", localID); 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; } @@ -470,19 +475,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - foreach (BSPrim bsp in m_primsWithCollisions) + foreach (BSPhysObject bsp in m_objectsWithCollisions) bsp.SendCollisions(); - m_primsWithCollisions.Clear(); + m_objectsWithCollisions.Clear(); // 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 // avatar animations and stuff. - // foreach (BSCharacter bsc in m_avatarsWithCollisions) - // bsc.SendCollisions(); - foreach (KeyValuePair kvp in m_avatars) - kvp.Value.SendCollisions(); - m_avatarsWithCollisions.Clear(); + foreach (BSPhysObject bpo in m_avatarsWithCollisions) + bpo.SendCollisions(); + // m_avatarsWithCollisions.Clear(); // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) @@ -490,16 +492,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; - BSPrim prim; - if (m_prims.TryGetValue(entprop.ID, out prim)) - { - prim.UpdateProperties(entprop); - continue; - } - BSCharacter actor; - if (m_avatars.TryGetValue(entprop.ID, out actor)) + BSPhysObject pobj; + if (PhysObjects.TryGetValue(entprop.ID, out pobj)) { - actor.UpdateProperties(entprop); + pobj.UpdateProperties(entprop); continue; } } @@ -529,33 +525,36 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // 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) { 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; if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) + { type = ActorTypes.Ground; - else if (m_avatars.ContainsKey(collidingWith)) - type = ActorTypes.Agent; + } + else + { + collidee = PhysObjects[collidingWith]; + if (collidee is BSCharacter) + type = ActorTypes.Agent; + } // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - BSPrim prim; - if (m_prims.TryGetValue(localID, out prim)) { - 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; - } + collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration); + m_objectsWithCollisions.Add(collider); + return; } @@ -605,17 +604,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters // make sure no stepping happens while we're deleting stuff m_initialized = false; - foreach (KeyValuePair kvp in m_avatars) - { - kvp.Value.Destroy(); - } - m_avatars.Clear(); - - foreach (KeyValuePair kvp in m_prims) + foreach (KeyValuePair kvp in PhysObjects) { kvp.Value.Destroy(); } - m_prims.Clear(); + PhysObjects.Clear(); // Now that the prims are all cleaned up, there should be no constraints left if (m_constraintCollection != null) @@ -996,42 +989,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (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)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (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", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (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", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (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", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (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)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (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" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (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" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (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" , 0.5f, @@ -1052,32 +1045,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters 0.5f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (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.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, (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.", 0f, (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (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", 0.37f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, (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", 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (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", 0.1f, (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, (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)", @@ -1264,18 +1257,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // 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) - { - List operateOn; - lock (m_prims) operateOn = new List(m_prims.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) + protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val) { List operateOn; - lock (m_avatars) operateOn = new List(m_avatars.Keys); + lock (PhysObjects) operateOn = new List(PhysObjects.Keys); UpdateParameterSet(operateOn, ref loc, parm, localID, val); } -- cgit v1.1