From 9e914f5c321d5588b196221343e3bc9ed9735f64 Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Thu, 26 Jul 2012 16:03:15 -0700
Subject: Add check so Ode does not try to simulate after it has been
Dispose()'ed. Fixes exception that happens when shutting down region
(improvements from last patch)
---
OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 9 +++++++++
1 file changed, 9 insertions(+)
(limited to 'OpenSim/Region/Physics')
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 32e81e2..0db936f 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -489,6 +489,8 @@ namespace OpenSim.Region.Physics.OdePlugin
///
internal Object OdeLock = new Object();
+ private bool _worldInitialized = false;
+
public IMesher mesher;
private IConfigSource m_config;
@@ -875,6 +877,8 @@ namespace OpenSim.Region.Physics.OdePlugin
staticPrimspace[i, j] = IntPtr.Zero;
}
}
+
+ _worldInitialized = true;
}
// internal void waitForSpaceUnlock(IntPtr space)
@@ -2896,6 +2900,8 @@ namespace OpenSim.Region.Physics.OdePlugin
/// The number of frames simulated over that period.
public override float Simulate(float timeStep)
{
+ if (!_worldInitialized) return 11f;
+
int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
int tempTick = 0, tempTick2 = 0;
@@ -4017,6 +4023,8 @@ namespace OpenSim.Region.Physics.OdePlugin
public override void Dispose()
{
+ _worldInitialized = false;
+
m_rayCastManager.Dispose();
m_rayCastManager = null;
@@ -4037,6 +4045,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.WorldDestroy(world);
//d.CloseODE();
}
+
}
public override Dictionary GetTopColliders()
--
cgit v1.1
From 7d30637d51c64a582cc55d41546af8f0cfc889ba Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Thu, 26 Jul 2012 14:54:57 -0700
Subject: BulletSim: refactor all the linkset logic out of the prim class and
into its own class. The BulletSim data structures track individual prims as
linksets of 1 so most of the prim code is not different between a linked and
unlinked object.
---
OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 308 +++++++++++++++++++
OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 327 ++++++---------------
OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 +-
.../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +-
4 files changed, 409 insertions(+), 235 deletions(-)
create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
(limited to 'OpenSim/Region/Physics')
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
new file mode 100755
index 0000000..a1027ee
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -0,0 +1,308 @@
+/*
+ * 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;
+
+namespace OpenSim.Region.Physics.BulletSPlugin
+{
+public class BSLinkset
+{
+ private static string LogHeader = "[BULLETSIM LINKSET]";
+
+ private BSPrim m_linksetRoot;
+ public BSPrim Root { get { return m_linksetRoot; } }
+
+ private BSScene m_scene;
+
+ 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
+ // to the physical representation is done via the tainting mechenism.
+ private object m_linksetActivityLock = new Object();
+
+ // We keep the prim's mass in the linkset structure since it could be dependent on other prims
+ private float m_mass;
+ public float Mass
+ {
+ get
+ {
+ m_mass = ComputeLinksetMass();
+ return m_mass;
+ }
+ }
+
+ public OMV.Vector3 CenterOfMass
+ {
+ get { return ComputeLinksetCenterOfMass(); }
+ }
+
+ public OMV.Vector3 GeometricCenter
+ {
+ get { return ComputeLinksetGeometricCenter(); }
+ }
+
+ public BSLinkset(BSScene scene, BSPrim parent)
+ {
+ // A simple linkset of one (no children)
+ m_scene = scene;
+ m_linksetRoot = parent;
+ 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 it's membership.
+ public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
+ {
+ lock (m_linksetActivityLock)
+ {
+ parent.Linkset.AddChildToLinkset(child);
+ }
+ return parent.Linkset;
+ }
+
+ public BSLinkset RemoveMeFromLinkset(BSPrim child)
+ {
+ lock (m_linksetActivityLock)
+ {
+ if (IsRoot(child))
+ {
+ // if root of linkset, take the linkset apart
+ while (m_children.Count > 0)
+ {
+ // Note that we don't do a foreach because the remove routine
+ // takes it out of the list.
+ RemoveChildFromLinkset(m_children[0]);
+ }
+ m_children.Clear(); // just to make sure
+ }
+ else
+ {
+ // Just removing a child from an existing linkset
+ RemoveChildFromLinkset(child);
+ }
+ }
+
+ // The child is down to a linkset of just itself
+ return new BSLinkset(m_scene, child);
+ }
+
+ // An existing linkset had one of its members rebuilt or something.
+ // Undo all the physical linking and rebuild the physical linkset.
+ public bool RefreshLinkset(BSPrim requestor)
+ {
+ return true;
+ }
+
+
+ // Return 'true' if the passed object is the root object of this linkset
+ public bool IsRoot(BSPrim requestor)
+ {
+ return (requestor.LocalID == m_linksetRoot.LocalID);
+ }
+
+ // Return 'true' if this linkset has any children (more than the root member)
+ public bool HasAnyChildren { get { return (m_children.Count > 0); } }
+
+ // Return 'true' if this child is in this linkset
+ public bool HasChild(BSPrim child)
+ {
+ bool ret = false;
+ foreach (BSPrim bp in m_children)
+ {
+ if (child.LocalID == bp.LocalID)
+ {
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+ }
+
+ private float ComputeLinksetMass()
+ {
+ float mass = m_linksetRoot.Mass;
+ foreach (BSPrim bp in m_children)
+ {
+ mass += bp.Mass;
+ }
+ return mass;
+ }
+
+ private OMV.Vector3 ComputeLinksetCenterOfMass()
+ {
+ OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
+ float totalMass = m_linksetRoot.MassRaw;
+
+ foreach (BSPrim bp in m_children)
+ {
+ com += bp.Position * bp.MassRaw;
+ totalMass += bp.MassRaw;
+ }
+ com /= totalMass;
+
+ return com;
+ }
+
+ private OMV.Vector3 ComputeLinksetGeometricCenter()
+ {
+ OMV.Vector3 com = m_linksetRoot.Position;
+
+ foreach (BSPrim bp in m_children)
+ {
+ com += bp.Position * bp.MassRaw;
+ }
+ com /= m_children.Count + 1;
+
+ return com;
+ }
+
+ // I am the root of a linkset and a new child is being added
+ public void AddChildToLinkset(BSPrim pchild)
+ {
+ BSPrim child = pchild;
+ if (!HasChild(child))
+ {
+ m_children.Add(child);
+
+ m_scene.TaintedObject(delegate()
+ {
+ DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
+ DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
+ PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
+ });
+ }
+ return;
+ }
+
+ // 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.
+ public void RemoveChildFromLinkset(BSPrim pchild)
+ {
+ BSPrim child = pchild;
+
+ if (m_children.Remove(child))
+ {
+ m_scene.TaintedObject(delegate()
+ {
+ DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
+ DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
+
+ if (m_children.Count == 0)
+ {
+ // if the linkset is empty, make sure all linkages have been removed
+ PhysicallyUnlinkAllChildrenFromRoot();
+ }
+ else
+ {
+ PhysicallyUnlinkAChildFromRoot(pchild);
+ }
+ });
+ }
+ else
+ {
+ // This will happen if we remove the root of the linkset first. Non-fatal occurance.
+ // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
+ }
+ return;
+ }
+
+ // Create a constraint between me (root of linkset) and the passed prim (the child).
+ // Called at taint time!
+ private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
+ {
+ // Zero motion for children so they don't interpolate
+ childPrim.ZeroMotion();
+
+ // relative position normalized to the root prim
+ OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
+ OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
+
+ // relative rotation of the child to the parent
+ OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
+
+ // create a constraint that allows no freedom of movement between the two objects
+ // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
+ // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
+ DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
+ BSConstraint constrain = m_scene.Constraints.CreateConstraint(
+ m_scene.World, m_linksetRoot.Body, childPrim.Body,
+ childRelativePosition,
+ childRelativeRotation,
+ OMV.Vector3.Zero,
+ OMV.Quaternion.Identity);
+ constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
+ constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
+
+ // tweek the constraint to increase stability
+ constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
+ constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
+ m_scene.Params.linkConstraintTransMotorMaxVel,
+ m_scene.Params.linkConstraintTransMotorMaxForce);
+
+ }
+
+ // Remove linkage between myself and a particular child
+ // Called at taint time!
+ private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
+ {
+ DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
+ LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
+ DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
+ // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
+ m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
+ }
+
+ // Remove linkage between myself and any possible children I might have
+ // Called at taint time!
+ private void PhysicallyUnlinkAllChildrenFromRoot()
+ {
+ // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
+ DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
+ m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
+ // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
+ }
+
+ // Invoke the detailed logger and output something if it's enabled.
+ private void DebugLog(string msg, params Object[] args)
+ {
+ m_scene.Logger.DebugFormat(msg, args);
+ }
+
+ // Invoke the detailed logger and output something if it's enabled.
+ private void DetailLog(string msg, params Object[] args)
+ {
+ m_scene.PhysicsLogging.Write(msg, args);
+ }
+
+}
+}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 3be28e3..d604f9c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -66,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
private bool _isSelected;
private bool _isVolumeDetect;
private OMV.Vector3 _position;
- private float _mass;
+ private float _mass; // the mass of this object
private float _density;
private OMV.Vector3 _force;
private OMV.Vector3 _velocity;
@@ -89,8 +89,13 @@ public sealed class BSPrim : PhysicsActor
private bool _kinematic;
private float _buoyancy;
- private BSPrim _parentPrim;
- private List _childrenPrims;
+ // Membership in a linkset is controlled by this class.
+ private BSLinkset _linkset;
+ public BSLinkset Linkset
+ {
+ get { return _linkset; }
+ set { _linkset = value; }
+ }
private int _subscribedEventsMs = 0;
private int _nextCollisionOkTime = 0;
@@ -133,9 +138,8 @@ 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;
- _parentPrim = null; // not a child or a parent
+ _linkset = new BSLinkset(_scene, this); // a linkset of one
_vehicle = new BSDynamics(this); // add vehicleness
- _childrenPrims = new List();
_mass = CalculateMass();
// do the actual object creation at taint time
_scene.TaintedObject(delegate()
@@ -161,16 +165,8 @@ public sealed class BSPrim : PhysicsActor
_scene.TaintedObject(delegate()
{
- // undo any dependance with/on other objects
- if (_parentPrim != null)
- {
- // If I'm someone's child, tell them to forget about me.
- _parentPrim.RemoveChildFromLinkset(this);
- _parentPrim = null;
- }
-
- // make sure there are no other prims linked to me
- UnlinkAllChildren();
+ // Undo any links between me and any other object
+ _linkset = _linkset.RemoveMeFromLinkset(this);
// everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
@@ -187,7 +183,7 @@ public sealed class BSPrim : PhysicsActor
_scene.TaintedObject(delegate()
{
_mass = CalculateMass(); // changing size changes the mass
- BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, Mass, IsPhysical);
+ BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
RecreateGeomAndObject();
});
}
@@ -226,32 +222,8 @@ public sealed class BSPrim : PhysicsActor
BSPrim parent = obj as BSPrim;
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
- // TODO: decide if this parent checking needs to happen at taint time
- if (_parentPrim == null)
- {
- if (parent != null)
- {
- // I don't have a parent so I am joining a linkset
- parent.AddChildToLinkset(this);
- }
- }
- else
- {
- // I already have a parent, is parenting changing?
- if (parent != _parentPrim)
- {
- if (parent == null)
- {
- // we are being removed from a linkset
- _parentPrim.RemoveChildFromLinkset(this);
- }
- else
- {
- // asking to reparent a prim should not happen
- m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader);
- }
- }
- }
+
+ _linkset = _linkset.AddMeToLinkset(this, parent);
return;
}
@@ -260,81 +232,18 @@ 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
DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
- (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString()));
- DetailLog("{0},delink,parent={1}", LocalID, (_parentPrim==null ? "NULL" : _parentPrim.LocalID.ToString()));
- if (_parentPrim != null)
- {
- _parentPrim.RemoveChildFromLinkset(this);
- }
- return;
- }
+ _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
+ DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
- // I am the root of a linkset and a new child is being added
- public void AddChildToLinkset(BSPrim pchild)
- {
- BSPrim child = pchild;
- _scene.TaintedObject(delegate()
- {
- if (!_childrenPrims.Contains(child))
- {
- DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID);
- DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID);
- _childrenPrims.Add(child);
- child._parentPrim = this; // the child has gained a parent
- // RecreateGeomAndObject(); // rebuild my shape with the new child added
- LinkAChildToMe(pchild); // build the physical binding between me and the child
-
- _mass = CalculateMass();
- }
- });
- return;
- }
-
- // 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.
- public void RemoveChildFromLinkset(BSPrim pchild)
- {
- BSPrim child = pchild;
- _scene.TaintedObject(delegate()
- {
- if (_childrenPrims.Contains(child))
- {
- DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
- DetailLog("{0},RemoveChildFromLinkset,child={1}", LocalID, pchild.LocalID);
- _childrenPrims.Remove(child);
- child._parentPrim = null; // the child has lost its parent
- if (_childrenPrims.Count == 0)
- {
- // if the linkset is empty, make sure all linkages have been removed
- UnlinkAllChildren();
- }
- else
- {
- // RecreateGeomAndObject(); // rebuild my shape with the child removed
- UnlinkAChildFromMe(pchild);
- }
-
- _mass = CalculateMass();
- }
- else
- {
- m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
- }
- });
- return;
- }
-
- // return true if we are the root of a linkset (there are children to manage)
- public bool IsRootOfLinkset
- {
- get { return (_parentPrim == null && _childrenPrims.Count != 0); }
+ _linkset.RemoveMeFromLinkset(this);
+ return;
}
// Set motion values to zero.
// 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!
- private void ZeroMotion()
+ public void ZeroMotion()
{
_velocity = OMV.Vector3.Zero;
_acceleration = OMV.Vector3.Zero;
@@ -355,9 +264,10 @@ public sealed class BSPrim : PhysicsActor
public override OMV.Vector3 Position {
get {
- // child prims move around based on their parent. Need to get the latest location
- if (_parentPrim != null)
+ if (!_linkset.IsRoot(this))
+ // child prims move around based on their parent. Need to get the latest location
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
+
// don't do the GetObjectPosition for root elements because this function is called a zillion times
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
return _position;
@@ -373,16 +283,31 @@ public sealed class BSPrim : PhysicsActor
}
}
- // Return the effective mass of the object. Non-physical objects do not have mass.
- public override float Mass {
- get {
- if (IsPhysical)
- return _mass;
- else
- return 0f;
+ // Return the effective mass of the object.
+ // If there are multiple items in the linkset, add them together for the root
+ public override float Mass
+ {
+ get
+ {
+ return _linkset.Mass;
}
}
+ // used when we only want this prim's mass and not the linkset thing
+ public float MassRaw { get { return _mass; } }
+
+ // Is this used?
+ public override OMV.Vector3 CenterOfMass
+ {
+ get { return _linkset.CenterOfMass; }
+ }
+
+ // Is this used?
+ public override OMV.Vector3 GeometricCenter
+ {
+ get { return _linkset.GeometricCenter; }
+ }
+
public override OMV.Vector3 Force {
get { return _force; }
set {
@@ -473,8 +398,6 @@ public sealed class BSPrim : PhysicsActor
return;
}
- public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
- public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
public override OMV.Vector3 Velocity {
get { return _velocity; }
set {
@@ -503,9 +426,9 @@ public sealed class BSPrim : PhysicsActor
}
public override OMV.Quaternion Orientation {
get {
- if (_parentPrim != null)
+ 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);
}
return _orientation;
@@ -555,14 +478,16 @@ public sealed class BSPrim : PhysicsActor
private void SetObjectDynamic()
{
// m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
- // non-physical things work best with a mass of zero
- if (!IsStatic)
- {
- _mass = CalculateMass();
- RecreateGeomAndObject();
- }
- DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, Mass);
- BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), Mass);
+
+ RecreateGeomAndObject();
+
+ float mass = _mass;
+ // Bullet wants static objects have a mass of zero
+ if (IsStatic)
+ mass = 0f;
+
+ DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
+ BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
}
// prims don't fly
@@ -1004,6 +929,9 @@ public sealed class BSPrim : PhysicsActor
returnMass = _density * volume;
+ /*
+ * This change means each object keeps its own mass and the Mass property
+ * will return the sum if we're part of a linkset.
if (IsRootOfLinkset)
{
foreach (BSPrim prim in _childrenPrims)
@@ -1011,6 +939,7 @@ public sealed class BSPrim : PhysicsActor
returnMass += prim.CalculateMass();
}
}
+ */
if (returnMass <= 0)
returnMass = 0.0001f;
@@ -1026,9 +955,11 @@ public sealed class BSPrim : PhysicsActor
// The objects needs a hull if it's physical otherwise a mesh is enough
// No locking here because this is done when we know physics is not simulating
// if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
- private void CreateGeom(bool forceRebuild)
+ // Returns 'true' if the geometry was rebuilt
+ private bool CreateGeom(bool forceRebuild)
{
// the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
+ bool ret = false;
if (!_scene.NeedsMeshing(_pbs))
{
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -1036,18 +967,26 @@ public sealed class BSPrim : PhysicsActor
if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
{
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
- _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
- DetailLog("{0},CreateGeom,sphere", LocalID);
- // Bullet native objects are scaled by the Bullet engine so pass the size in
- _scale = _size;
+ if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)
+ {
+ DetailLog("{0},CreateGeom,sphere", LocalID);
+ _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
+ ret = true;
+ // Bullet native objects are scaled by the Bullet engine so pass the size in
+ _scale = _size;
+ }
}
}
else
{
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
- DetailLog("{0},CreateGeom,box", LocalID);
- _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
- _scale = _size;
+ if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)
+ {
+ DetailLog("{0},CreateGeom,box", LocalID);
+ _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
+ ret = true;
+ _scale = _size;
+ }
}
}
else
@@ -1059,6 +998,7 @@ public sealed class BSPrim : PhysicsActor
// physical objects require a hull for interaction.
// This will create the mesh if it doesn't already exist
CreateGeomHull();
+ ret = true;
}
}
else
@@ -1067,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor
{
// Static (non-physical) objects only need a mesh for bumping into
CreateGeomMesh();
+ ret = true;
}
}
}
+ return ret;
}
// No locking here because this is done when we know physics is not simulating
@@ -1254,20 +1196,18 @@ public sealed class BSPrim : PhysicsActor
// No locking here because this is done when the physics engine is not simulating
private void CreateObject()
{
- if (IsRootOfLinkset)
- {
- // Create a linkset around this object
- CreateLinkset();
- }
- else
- {
- // simple object
- // 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);
- BulletSimAPI.CreateObject(_scene.WorldID, shape);
- }
+ // this routine is called when objects are rebuilt.
+
+ // 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);
+ BulletSimAPI.CreateObject(_scene.WorldID, shape);
+ // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
+ m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
+
+ // The root object could have been recreated. Make sure everything linksety is up to date.
+ _linkset.RefreshLinkset(this);
}
// Copy prim's info into the BulletSim shape description structure
@@ -1279,7 +1219,7 @@ public sealed class BSPrim : PhysicsActor
shape.Rotation = _orientation;
shape.Velocity = _velocity;
shape.Scale = _scale;
- shape.Mass = Mass;
+ shape.Mass = _isPhysical ? _mass : 0f;
shape.Buoyancy = _buoyancy;
shape.HullKey = _hullKey;
shape.MeshKey = _meshKey;
@@ -1289,83 +1229,6 @@ public sealed class BSPrim : PhysicsActor
shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
}
- #region Linkset creation and destruction
-
- // Create the linkset by putting constraints between the objects of the set so they cannot move
- // relative to each other.
- void CreateLinkset()
- {
- // DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
-
- // remove any constraints that might be in place
- UnlinkAllChildren();
-
- // create constraints between the root prim and each of the children
- foreach (BSPrim prim in _childrenPrims)
- {
- LinkAChildToMe(prim);
- }
- }
-
- // Create a constraint between me (root of linkset) and the passed prim (the child).
- // Called at taint time!
- private void LinkAChildToMe(BSPrim childPrim)
- {
- // Zero motion for children so they don't interpolate
- childPrim.ZeroMotion();
-
- // relative position normalized to the root prim
- OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation);
- OMV.Vector3 childRelativePosition = (childPrim._position - this._position) * invThisOrientation;
-
- // relative rotation of the child to the parent
- OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim._orientation;
-
- // create a constraint that allows no freedom of movement between the two objects
- // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
- // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
- DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
- BSConstraint constrain = _scene.Constraints.CreateConstraint(
- _scene.World, this.Body, childPrim.Body,
- childRelativePosition,
- childRelativeRotation,
- OMV.Vector3.Zero,
- OMV.Quaternion.Identity);
- constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
- constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
-
- // tweek the constraint to increase stability
- constrain.UseFrameOffset(_scene.BoolNumeric(_scene.Params.linkConstraintUseFrameOffset));
- if (_scene.BoolNumeric(_scene.Params.linkConstraintEnableTransMotor))
- {
- constrain.TranslationalLimitMotor(true,
- _scene.Params.linkConstraintTransMotorMaxVel,
- _scene.Params.linkConstraintTransMotorMaxForce);
- }
- }
-
- // Remove linkage between myself and a particular child
- // Called at taint time!
- private void UnlinkAChildFromMe(BSPrim childPrim)
- {
- DebugLog("{0}: UnlinkAChildFromMe: RemoveConstraint between root prim {1} and child prim {2}",
- LogHeader, LocalID, childPrim.LocalID);
- DetailLog("{0},UnlinkAChildFromMe,taint,root={1},child={2}", LocalID, LocalID, childPrim.LocalID);
- // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
- _scene.Constraints.RemoveAndDestroyConstraint(this.Body, childPrim.Body);
- }
-
- // Remove linkage between myself and any possible children I might have
- // Called at taint time!
- private void UnlinkAllChildren()
- {
- DebugLog("{0}: UnlinkAllChildren:", LogHeader);
- DetailLog("{0},UnlinkAllChildren,taint", LocalID);
- _scene.Constraints.RemoveAndDestroyConstraint(this.Body);
- // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
- }
-
- #endregion // Linkset creation and destruction
// Rebuild the geometry and object.
// This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1443,7 +1306,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 (_parentPrim == null)
+ if (_linkset.IsRoot(this))
{
// Assign to the local variables so the normal set action does not happen
_position = entprop.Position;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index a1587a8..c6d622b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS SCENE]";
- private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
+ public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
public string BulletSimVersion = "?";
@@ -87,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private uint m_worldID;
public uint WorldID { get { return m_worldID; } }
+ // let my minuions use my logger
+ public ILog Logger { get { return m_log; } }
+
private bool m_initialized = false;
private int m_detailedStatsStep = 0;
@@ -1026,7 +1029,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
- ConfigurationParameters.numericTrue,
+ ConfigurationParameters.numericFalse,
(s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
(s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
(s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 89fd9b7..65e3145 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -239,10 +239,10 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CreateObject(uint worldID, ShapeData shapeData);
+/* Remove old functionality
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
-/* Remove old functionality
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void AddConstraint(uint worldID, uint id1, uint id2,
Vector3 frame1, Quaternion frame1rot,
--
cgit v1.1
From ce812c88ccc9226167b049e49296892943409e3f Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Thu, 26 Jul 2012 15:24:53 -0700
Subject: BulletSim: fix a recursive loop when fetching the mass of the root of
a linkset.
---
OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 6 +++---
OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
(limited to 'OpenSim/Region/Physics')
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index a1027ee..3bc2100 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -50,7 +50,7 @@ public class BSLinkset
// We keep the prim's mass in the linkset structure since it could be dependent on other prims
private float m_mass;
- public float Mass
+ public float LinksetMass
{
get
{
@@ -150,10 +150,10 @@ public class BSLinkset
private float ComputeLinksetMass()
{
- float mass = m_linksetRoot.Mass;
+ float mass = m_linksetRoot.MassRaw;
foreach (BSPrim bp in m_children)
{
- mass += bp.Mass;
+ mass += bp.MassRaw;
}
return mass;
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index d604f9c..7590d93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -289,7 +289,7 @@ public sealed class BSPrim : PhysicsActor
{
get
{
- return _linkset.Mass;
+ return _linkset.LinksetMass;
}
}
--
cgit v1.1