Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
avinationmerge
Melanie 2012-08-16 02:46:48 +01:00
commit 90ad98370a
19 changed files with 485 additions and 237 deletions

View File

@ -97,6 +97,32 @@ namespace OpenSim.Framework.Monitoring
/// /summary> /// /summary>
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout; public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
/// <summary>
/// Is this watchdog active?
/// </summary>
public static bool Enabled
{
get { return m_enabled; }
set
{
// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value);
if (value == m_enabled)
return;
m_enabled = value;
if (m_enabled)
{
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
}
m_watchdogTimer.Enabled = m_enabled;
}
}
private static bool m_enabled;
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<int, ThreadWatchdogInfo> m_threads; private static Dictionary<int, ThreadWatchdogInfo> m_threads;
private static System.Timers.Timer m_watchdogTimer; private static System.Timers.Timer m_watchdogTimer;
@ -115,11 +141,6 @@ namespace OpenSim.Framework.Monitoring
m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
m_watchdogTimer.AutoReset = false; m_watchdogTimer.AutoReset = false;
m_watchdogTimer.Elapsed += WatchdogTimerElapsed; m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
m_watchdogTimer.Start();
} }
/// <summary> /// <summary>

View File

@ -320,8 +320,13 @@ namespace OpenSim
m_httpServerPort = m_networkServersInfo.HttpListenerPort; m_httpServerPort = m_networkServersInfo.HttpListenerPort;
SceneManager.OnRestartSim += handleRestartRegion; SceneManager.OnRestartSim += handleRestartRegion;
// Only start the memory watchdog once all regions are ready // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; // heavily used during initial startup.
//
// FIXME: It's also possible that region ready status should be flipped during an OAR load since this
// also makes heavy use of the CPU.
SceneManager.OnRegionsReadyStatusChange
+= sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
} }
/// <summary> /// <summary>

View File

@ -37,7 +37,8 @@ public class BS6DofConstraint : BSConstraint
// Create a btGeneric6DofConstraint // Create a btGeneric6DofConstraint
public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot, Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot ) Vector3 frame2, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{ {
m_world = world; m_world = world;
m_body1 = obj1; m_body1 = obj1;
@ -46,16 +47,45 @@ public class BS6DofConstraint : BSConstraint
BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
frame1, frame1rot, frame1, frame1rot,
frame2, frame2rot, frame2, frame2rot,
true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true; m_enabled = true;
} }
public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 joinPoint,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(
BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
joinPoint,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true;
}
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
{
bool ret = false;
if (m_enabled)
{
BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot);
ret = true;
}
return ret;
}
public bool SetCFMAndERP(float cfm, float erp) public bool SetCFMAndERP(float cfm, float erp)
{ {
bool ret = true; bool ret = false;
if (m_enabled)
{
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
ret = true;
}
return ret; return ret;
} }
@ -76,5 +106,13 @@ public class BS6DofConstraint : BSConstraint
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
return ret; return ret;
} }
public bool SetBreakingImpulseThreshold(float threshold)
{
bool ret = false;
if (m_enabled)
ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
return ret;
}
} }
} }

View File

@ -137,7 +137,7 @@ public class BSCharacter : PhysicsActor
// called when this character is being destroyed and the resources should be released // called when this character is being destroyed and the resources should be released
public void Destroy() public void Destroy()
{ {
// DetailLog("{0},Destroy", LocalID); // DetailLog("{0},BSCharacter.Destroy", LocalID);
_scene.TaintedObject("BSCharacter.destroy", delegate() _scene.TaintedObject("BSCharacter.destroy", delegate()
{ {
BulletSimAPI.DestroyObject(_scene.WorldID, _localID); BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
@ -209,7 +209,7 @@ public class BSCharacter : PhysicsActor
_scene.TaintedObject("BSCharacter.setPosition", delegate() _scene.TaintedObject("BSCharacter.setPosition", delegate()
{ {
DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -226,7 +226,7 @@ public class BSCharacter : PhysicsActor
float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
if (_position.Z < terrainHeight) if (_position.Z < terrainHeight)
{ {
DetailLog("{0},PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
_position.Z = terrainHeight + 2.0f; _position.Z = terrainHeight + 2.0f;
ret = true; ret = true;
} }
@ -368,7 +368,7 @@ public class BSCharacter : PhysicsActor
set { _buoyancy = value; set { _buoyancy = value;
_scene.TaintedObject("BSCharacter.setBuoyancy", delegate() _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
{ {
DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
}); });
} }
@ -415,7 +415,7 @@ public class BSCharacter : PhysicsActor
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
_scene.TaintedObject("BSCharacter.AddForce", delegate() _scene.TaintedObject("BSCharacter.AddForce", delegate()
{ {
DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force); DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
BulletSimAPI.AddObjectForce2(Body.Ptr, _force); BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
}); });
} }
@ -488,9 +488,11 @@ public class BSCharacter : PhysicsActor
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate(); // base.RequestPhysicsterseUpdate();
/*
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity); entprop.Acceleration, entprop.RotationalVelocity);
*/
} }
// Called by the scene when a collision with this object is reported // Called by the scene when a collision with this object is reported
@ -507,6 +509,7 @@ public class BSCharacter : PhysicsActor
{ {
_collidingGroundStep = _scene.SimulationStep; _collidingGroundStep = _scene.SimulationStep;
} }
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
// throttle collisions to the rate specified in the subscription // throttle collisions to the rate specified in the subscription
if (_subscribedEventsMs != 0) { if (_subscribedEventsMs != 0) {
@ -535,7 +538,10 @@ public class BSCharacter : PhysicsActor
if (collisionCollection == null) if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate(); collisionCollection = new CollisionEventUpdate();
base.SendCollisionUpdate(collisionCollection); base.SendCollisionUpdate(collisionCollection);
collisionCollection.Clear(); // If there were any collisions in the collection, make sure we don't use the
// same instance next time.
if (collisionCollection.Count > 0)
collisionCollection = null;
// End kludge // End kludge
} }

View File

@ -80,10 +80,33 @@ public abstract class BSConstraint : IDisposable
bool ret = false; bool ret = false;
if (m_enabled) if (m_enabled)
{ {
// Recompute the internal transforms
BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
ret = true; ret = true;
} }
return ret; return ret;
} }
// Reset this constraint making sure it has all its internal structures
// recomputed and is enabled and ready to go.
public virtual bool RecomputeConstraintVariables(float mass)
{
bool ret = false;
if (m_enabled)
{
ret = CalculateTransforms();
if (ret)
{
// m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
// BSScene.DetailLogZero, Body1.ID, Body2.ID);
BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
}
else
{
m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID);
}
}
return ret;
}
} }
} }

View File

@ -55,6 +55,8 @@ public class BSConstraintCollection : IDisposable
} }
public void Clear() public void Clear()
{
lock (m_constraints)
{ {
foreach (BSConstraint cons in m_constraints) foreach (BSConstraint cons in m_constraints)
{ {
@ -62,15 +64,17 @@ public class BSConstraintCollection : IDisposable
} }
m_constraints.Clear(); m_constraints.Clear();
} }
}
public bool AddConstraint(BSConstraint cons) public bool AddConstraint(BSConstraint cons)
{
lock (m_constraints)
{ {
// There is only one constraint between any bodies. Remove any old just to make sure. // There is only one constraint between any bodies. Remove any old just to make sure.
RemoveAndDestroyConstraint(cons.Body1, cons.Body2); RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID);
m_constraints.Add(cons); m_constraints.Add(cons);
}
return true; return true;
} }
@ -84,16 +88,19 @@ public class BSConstraintCollection : IDisposable
uint lookingID1 = body1.ID; uint lookingID1 = body1.ID;
uint lookingID2 = body2.ID; uint lookingID2 = body2.ID;
ForEachConstraint(delegate(BSConstraint constrain) lock (m_constraints)
{
foreach (BSConstraint constrain in m_constraints)
{ {
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
{ {
foundConstraint = constrain; foundConstraint = constrain;
found = true; found = true;
break;
}
}
} }
return found;
});
returnConstraint = foundConstraint; returnConstraint = foundConstraint;
return found; return found;
} }
@ -103,25 +110,35 @@ public class BSConstraintCollection : IDisposable
// Return 'true' if a constraint was found and destroyed. // Return 'true' if a constraint was found and destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
{ {
// return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
bool ret = false; bool ret = false;
lock (m_constraints)
{
BSConstraint constrain; BSConstraint constrain;
if (this.TryGetConstraint(body1, body2, out constrain)) if (this.TryGetConstraint(body1, body2, out constrain))
{ {
m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID);
// remove the constraint from our collection // remove the constraint from our collection
m_constraints.Remove(constrain); RemoveAndDestroyConstraint(constrain);
// tell the engine that all its structures need to be freed
constrain.Dispose();
// we destroyed something
ret = true; ret = true;
} }
}
return ret; return ret;
} }
// The constraint MUST exist in the collection
public bool RemoveAndDestroyConstraint(BSConstraint constrain)
{
lock (m_constraints)
{
// remove the constraint from our collection
m_constraints.Remove(constrain);
}
// tell the engine that all its structures need to be freed
constrain.Dispose();
// we destroyed something
return true;
}
// Remove all constraints that reference the passed body. // Remove all constraints that reference the passed body.
// Return 'true' if any constraints were destroyed. // Return 'true' if any constraints were destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1) public bool RemoveAndDestroyConstraint(BulletBody body1)
@ -130,16 +147,15 @@ public class BSConstraintCollection : IDisposable
List<BSConstraint> toRemove = new List<BSConstraint>(); List<BSConstraint> toRemove = new List<BSConstraint>();
uint lookingID = body1.ID; uint lookingID = body1.ID;
ForEachConstraint(delegate(BSConstraint constrain) lock (m_constraints)
{
foreach (BSConstraint constrain in m_constraints)
{ {
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
{ {
toRemove.Add(constrain); toRemove.Add(constrain);
} }
return false; }
});
lock (m_constraints)
{
foreach (BSConstraint constrain in toRemove) foreach (BSConstraint constrain in toRemove)
{ {
m_constraints.Remove(constrain); m_constraints.Remove(constrain);
@ -151,28 +167,16 @@ public class BSConstraintCollection : IDisposable
public bool RecalculateAllConstraints() public bool RecalculateAllConstraints()
{ {
ForEachConstraint(delegate(BSConstraint constrain) bool ret = false;
{
constrain.CalculateTransforms();
return false;
});
return true;
}
// Lock the constraint list and loop through it.
// The constraint action returns 'true' if it wants the loop aborted.
private void ForEachConstraint(ConstraintAction action)
{
lock (m_constraints) lock (m_constraints)
{ {
foreach (BSConstraint constrain in m_constraints) foreach (BSConstraint constrain in m_constraints)
{ {
if (action(constrain)) constrain.CalculateTransforms();
break; ret = true;
} }
} }
return ret;
} }
} }
} }

View File

@ -613,7 +613,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
MoveAngular(pTimestep); MoveAngular(pTimestep);
LimitRotation(pTimestep); LimitRotation(pTimestep);
DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
}// end Step }// end Step

View File

@ -0,0 +1,55 @@
/*
* 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 OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
class BSHingeConstraint : BSConstraint
{
public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 pivotInA, Vector3 pivotInB,
Vector3 axisInA, Vector3 axisInB,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(
BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
pivotInA, pivotInB,
axisInA, axisInB,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true;
}
}
}

View File

@ -37,11 +37,12 @@ public class BSLinkset
private static string LogHeader = "[BULLETSIM LINKSET]"; private static string LogHeader = "[BULLETSIM LINKSET]";
private BSPrim m_linksetRoot; private BSPrim m_linksetRoot;
public BSPrim Root { get { return m_linksetRoot; } } public BSPrim LinksetRoot { get { return m_linksetRoot; } }
private BSScene m_scene; private BSScene m_physicsScene;
public BSScene Scene { get { return m_scene; } } public BSScene PhysicsScene { get { return m_physicsScene; } }
// The children under the root in this linkset
private List<BSPrim> m_children; private List<BSPrim> m_children;
// We lock the diddling of linkset classes to prevent any badness. // We lock the diddling of linkset classes to prevent any badness.
@ -73,7 +74,7 @@ public class BSLinkset
public BSLinkset(BSScene scene, BSPrim parent) public BSLinkset(BSScene scene, BSPrim parent)
{ {
// A simple linkset of one (no children) // A simple linkset of one (no children)
m_scene = scene; m_physicsScene = scene;
m_linksetRoot = parent; m_linksetRoot = parent;
m_children = new List<BSPrim>(); m_children = new List<BSPrim>();
m_mass = parent.MassRaw; m_mass = parent.MassRaw;
@ -91,6 +92,9 @@ public class BSLinkset
return this; return this;
} }
// 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(BSPrim child)
{ {
lock (m_linksetActivityLock) lock (m_linksetActivityLock)
@ -114,60 +118,9 @@ public class BSLinkset
} }
// The child is down to a linkset of just itself // The child is down to a linkset of just itself
return new BSLinkset(Scene, child); return new BSLinkset(PhysicsScene, child);
} }
/* DEPRECATED: this is really bad in that it trys to unlink other prims.
// An existing linkset had one of its members rebuilt or something.
// Go through the linkset and rebuild the pointers to the bodies of the linkset members.
public BSLinkset RefreshLinkset(BSPrim requestor)
{
BSLinkset ret = requestor.Linkset;
lock (m_linksetActivityLock)
{
// The body pointer is refetched in case anything has moved.
System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
if (aPtr == System.IntPtr.Zero)
{
// That's odd. We can't find the root of the linkset.
// The linkset is somehow dead. The requestor is now a member of a linkset of one.
DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID);
ret = RemoveMeFromLinkset(m_linksetRoot);
}
else
{
// Reconstruct the pointer to the body of the linkset root.
DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr);
m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr);
List<BSPrim> toRemove = new List<BSPrim>();
foreach (BSPrim bsp in m_children)
{
aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID);
if (aPtr == System.IntPtr.Zero)
{
toRemove.Add(bsp);
}
else
{
// Reconstruct the pointer to the body of the linkset root.
DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr);
bsp.Body = new BulletBody(bsp.LocalID, aPtr);
}
}
foreach (BSPrim bsp in toRemove)
{
RemoveChildFromOtherLinkset(bsp);
}
}
}
return ret;
}
*/
// Return 'true' if the passed object is the root object of this linkset // Return 'true' if the passed object is the root object of this linkset
public bool IsRoot(BSPrim requestor) public bool IsRoot(BSPrim requestor)
{ {
@ -183,6 +136,8 @@ public class BSLinkset
public bool HasChild(BSPrim child) public bool HasChild(BSPrim child)
{ {
bool ret = false; bool ret = false;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
if (child.LocalID == bp.LocalID) if (child.LocalID == bp.LocalID)
@ -191,6 +146,7 @@ public class BSLinkset
break; break;
} }
} }
}
return ret; return ret;
} }
@ -209,6 +165,8 @@ public class BSLinkset
OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
float totalMass = m_linksetRoot.MassRaw; float totalMass = m_linksetRoot.MassRaw;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
com += bp.Position * bp.MassRaw; com += bp.Position * bp.MassRaw;
@ -216,6 +174,7 @@ public class BSLinkset
} }
if (totalMass != 0f) if (totalMass != 0f)
com /= totalMass; com /= totalMass;
}
return com; return com;
} }
@ -224,29 +183,84 @@ public class BSLinkset
{ {
OMV.Vector3 com = m_linksetRoot.Position; OMV.Vector3 com = m_linksetRoot.Position;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
com += bp.Position * bp.MassRaw; com += bp.Position * bp.MassRaw;
} }
com /= (m_children.Count + 1); com /= (m_children.Count + 1);
}
return com; return com;
} }
// When physical properties are changed the linkset needs to recalculate
// its internal properties.
public void Refresh(BSPrim requestor)
{
// If there are no children, there aren't any constraints to recompute
if (!HasAnyChildren)
return;
// Only the root does the recomputation
if (IsRoot(requestor))
{
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
{
RecomputeLinksetConstraintVariables();
});
}
}
// Call each of the constraints that make up this linkset and recompute the
// various transforms and variables. Used when objects are added or removed
// from a linkset to make sure the constraints know about the new mass and
// geometry.
// Must only be called at taint time!!
private bool RecomputeLinksetConstraintVariables()
{
float linksetMass = LinksetMass;
lock (m_linksetActivityLock)
{
foreach (BSPrim child in m_children)
{
BSConstraint constrain;
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
{
// DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
// LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
constrain.RecomputeConstraintVariables(linksetMass);
}
else
{
// Non-fatal error that can happen when children are being added to the linkset but
// their constraints have not been created yet.
// Caused by the fact that m_children is built at run time but building constraints
// happens at taint time.
// m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
// m_linksetRoot.Body.ID, child.Body.ID);
}
}
}
return false;
}
// I am the root of a linkset and a new child is being added // I am the root of a linkset and a new child is being added
// Called while LinkActivity is locked. // Called while LinkActivity is locked.
public void AddChildToLinkset(BSPrim child) private void AddChildToLinkset(BSPrim child)
{ {
if (!HasChild(child)) if (!HasChild(child))
{ {
m_children.Add(child); m_children.Add(child);
BSPrim root = Root; // capture the root as of now BSPrim rootx = LinksetRoot; // capture the root as of now
m_scene.TaintedObject("AddChildToLinkset", delegate() BSPrim childx = child;
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
{ {
DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
}); });
} }
return; return;
@ -257,31 +271,34 @@ public class BSLinkset
// it's still connected to the linkset. // it's still connected to the linkset.
// Normal OpenSimulator operation will never do this because other SceneObjectPart information // Normal OpenSimulator operation will never do this because other SceneObjectPart information
// has to be updated also (like pointer to prim's parent). // has to be updated also (like pointer to prim's parent).
public void RemoveChildFromOtherLinkset(BSPrim pchild) private void RemoveChildFromOtherLinkset(BSPrim pchild)
{ {
pchild.Linkset = new BSLinkset(m_scene, pchild); pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
RemoveChildFromLinkset(pchild); RemoveChildFromLinkset(pchild);
} }
// I am the root of a linkset and one of my children is being removed. // I am the root of a linkset and one of my children is being removed.
// Safe to call even if the child is not really in my linkset. // Safe to call even if the child is not really in my linkset.
public void RemoveChildFromLinkset(BSPrim child) private void RemoveChildFromLinkset(BSPrim child)
{ {
if (m_children.Remove(child)) if (m_children.Remove(child))
{ {
BSPrim root = Root; // capture the root as of now BSPrim rootx = LinksetRoot; // capture the root as of now
m_scene.TaintedObject("RemoveChildFromLinkset", delegate() BSPrim childx = child;
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
{ {
DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
PhysicallyUnlinkAChildFromRoot(root, child); PhysicallyUnlinkAChildFromRoot(rootx, childx);
}); });
RecomputeLinksetConstraintVariables();
} }
else else
{ {
// This will happen if we remove the root of the linkset first. Non-fatal occurance. // 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); // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
} }
return; return;
} }
@ -293,37 +310,72 @@ public class BSLinkset
// Zero motion for children so they don't interpolate // Zero motion for children so they don't interpolate
childPrim.ZeroMotion(); childPrim.ZeroMotion();
// Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of childPrim
OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
// real world coordinate of midpoint between the two objects
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
// 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},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
BS6DofConstraint constrain = new BS6DofConstraint(
m_physicsScene.World, rootPrim.Body, childPrim.Body,
midPoint,
true,
true
);
/* NOTE: attempt to build constraint with full frame computation, etc.
* Using the midpoint is easier since it lets the Bullet code use the transforms
* of the objects.
* Code left here as an example.
// ==================================================================================
// relative position normalized to the root prim // relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
// relative rotation of the child to the parent // relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
// create a constraint that allows no freedom of movement between the two objects // create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 // 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); // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
BS6DofConstraint constrain = new BS6DofConstraint( BS6DofConstraint constrain = new BS6DofConstraint(
m_scene.World, rootPrim.Body, childPrim.Body, PhysicsScene.World, rootPrim.Body, childPrim.Body,
childRelativePosition,
childRelativeRotation,
OMV.Vector3.Zero, OMV.Vector3.Zero,
-childRelativeRotation OMV.Quaternion.Inverse(rootPrim.Orientation),
OMV.Vector3.Zero,
OMV.Quaternion.Inverse(childPrim.Orientation),
// A point half way between the parent and child
// childRelativePosition/2,
// childRelativeRotation,
// childRelativePosition/2,
// inverseChildRelativeRotation,
true,
true
); );
m_scene.Constraints.AddConstraint(constrain); // ==================================================================================
*/
m_physicsScene.Constraints.AddConstraint(constrain);
// zero linear and angular limits makes the objects unable to move in relation to each other // zero linear and angular limits makes the objects unable to move in relation to each other
constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
// tweek the constraint to increase stability // tweek the constraint to increase stability
constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
m_scene.Params.linkConstraintTransMotorMaxVel, PhysicsScene.Params.linkConstraintTransMotorMaxVel,
m_scene.Params.linkConstraintTransMotorMaxForce); PhysicsScene.Params.linkConstraintTransMotorMaxForce);
constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
RecomputeLinksetConstraintVariables();
} }
// Remove linkage between myself and a particular child // Remove linkage between myself and a particular child
@ -334,7 +386,9 @@ public class BSLinkset
// LogHeader, rootPrim.LocalID, childPrim.LocalID); // LogHeader, rootPrim.LocalID, childPrim.LocalID);
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); // Find the constraint for this link and get rid of it from the overall collection and from my list
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
// Make the child refresh its location // Make the child refresh its location
BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
} }
@ -346,20 +400,20 @@ public class BSLinkset
// DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
} }
// Invoke the detailed logger and output something if it's enabled. // Invoke the detailed logger and output something if it's enabled.
private void DebugLog(string msg, params Object[] args) private void DebugLog(string msg, params Object[] args)
{ {
if (m_scene.ShouldDebugLog) if (m_physicsScene.ShouldDebugLog)
m_scene.Logger.DebugFormat(msg, args); m_physicsScene.Logger.DebugFormat(msg, args);
} }
// Invoke the detailed logger and output something if it's enabled. // Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args) private void DetailLog(string msg, params Object[] args)
{ {
m_scene.PhysicsLogging.Write(msg, args); m_physicsScene.PhysicsLogging.Write(msg, args);
} }
} }

View File

@ -163,13 +163,13 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
// Undo any links between me and any other object // Undo any links between me and any other object
BSPrim parentBefore = _linkset.Root; BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren; int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this); _linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
// Undo any vehicle properties // Undo any vehicle properties
this.VehicleType = (int)Vehicle.TYPE_NONE; this.VehicleType = (int)Vehicle.TYPE_NONE;
@ -233,13 +233,13 @@ public sealed class BSPrim : PhysicsActor
if (parent != null) if (parent != null)
{ {
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
BSPrim parentBefore = _linkset.Root; BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren; int childrenBefore = _linkset.NumberOfChildren;
_linkset = parent.Linkset.AddMeToLinkset(this); _linkset = parent.Linkset.AddMeToLinkset(this);
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
} }
return; return;
} }
@ -249,15 +249,15 @@ public sealed class BSPrim : PhysicsActor
// TODO: decide if this parent checking needs to happen at taint time // TODO: decide if this parent checking needs to happen at taint time
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
_linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
BSPrim parentBefore = _linkset.Root; BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren; int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this); _linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
return; return;
} }
@ -280,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
public override void LockAngularMotion(OMV.Vector3 axis) public override void LockAngularMotion(OMV.Vector3 axis)
{ {
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
return; return;
} }
@ -299,7 +299,7 @@ public sealed class BSPrim : PhysicsActor
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
_scene.TaintedObject("BSPrim.setPosition", delegate() _scene.TaintedObject("BSPrim.setPosition", delegate()
{ {
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -336,7 +336,7 @@ public sealed class BSPrim : PhysicsActor
_force = value; _force = value;
_scene.TaintedObject("BSPrim.setForce", delegate() _scene.TaintedObject("BSPrim.setForce", delegate()
{ {
DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
// BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
BulletSimAPI.SetObjectForce2(Body.Ptr, _force); BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
}); });
@ -414,7 +414,7 @@ public sealed class BSPrim : PhysicsActor
_velocity = value; _velocity = value;
_scene.TaintedObject("BSPrim.setVelocity", delegate() _scene.TaintedObject("BSPrim.setVelocity", delegate()
{ {
DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
}); });
} }
@ -422,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
public override OMV.Vector3 Torque { public override OMV.Vector3 Torque {
get { return _torque; } get { return _torque; }
set { _torque = value; set { _torque = value;
DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
} }
} }
public override float CollisionScore { public override float CollisionScore {
@ -449,7 +449,7 @@ public sealed class BSPrim : PhysicsActor
_scene.TaintedObject("BSPrim.setOrientation", delegate() _scene.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); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -497,8 +497,11 @@ public sealed class BSPrim : PhysicsActor
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
// recompute any linkset parameters
_linkset.Refresh(this);
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
} }
// prims don't fly // prims don't fly
@ -555,7 +558,7 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
_scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
{ {
DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
}); });
} }
@ -572,7 +575,7 @@ public sealed class BSPrim : PhysicsActor
_buoyancy = value; _buoyancy = value;
_scene.TaintedObject("BSPrim.setBuoyancy", delegate() _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
{ {
DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
}); });
} }
@ -635,17 +638,17 @@ public sealed class BSPrim : PhysicsActor
} }
m_accumulatedForces.Clear(); m_accumulatedForces.Clear();
} }
DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
}); });
} }
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
// m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
} }
public override void SetMomentum(OMV.Vector3 momentum) { public override void SetMomentum(OMV.Vector3 momentum) {
DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
} }
public override void SubscribeEvents(int ms) { public override void SubscribeEvents(int ms) {
_subscribedEventsMs = ms; _subscribedEventsMs = ms;
@ -989,7 +992,7 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
{ {
DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
// Bullet native objects are scaled by the Bullet engine so pass the size in // Bullet native objects are scaled by the Bullet engine so pass the size in
_scale = _size; _scale = _size;
@ -1003,7 +1006,7 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
{ {
DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
_scale = _size; _scale = _size;
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before? // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@ -1046,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor
// if this new shape is the same as last time, don't recreate the mesh // if this new shape is the same as last time, don't recreate the mesh
if (_meshKey == newMeshKey) return; if (_meshKey == newMeshKey) return;
DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
// Since we're recreating new, get rid of any previously generated shape // Since we're recreating new, get rid of any previously generated shape
if (_meshKey != 0) 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); // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
_mesh = null; _mesh = null;
_meshKey = 0; _meshKey = 0;
@ -1081,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
// meshes are already scaled by the meshmerizer // meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f); _scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
return; return;
} }
@ -1095,28 +1098,21 @@ public sealed class BSPrim : PhysicsActor
// if the hull hasn't changed, don't rebuild it // if the hull hasn't changed, don't rebuild it
if (newHullKey == _hullKey) return; if (newHullKey == _hullKey) return;
DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey); // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
// Since we're recreating new, get rid of any previously generated shape // Since we're recreating new, get rid of any previously generated shape
if (_hullKey != 0) if (_hullKey != 0)
{ {
// m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
_hullKey = 0; _hullKey = 0;
_hulls.Clear();
DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
_mesh = null; // the mesh cannot match either
_meshKey = 0;
} }
_hullKey = newHullKey; _hullKey = newHullKey;
if (_meshKey != _hullKey)
{ // Make sure the underlying mesh exists and is correct
// if the underlying mesh has changed, rebuild it
CreateGeomMesh(); CreateGeomMesh();
}
int[] indices = _mesh.getIndexListAsInt(); int[] indices = _mesh.getIndexListAsInt();
List<OMV.Vector3> vertices = _mesh.getVertexList(); List<OMV.Vector3> vertices = _mesh.getVertexList();
@ -1142,7 +1138,7 @@ public sealed class BSPrim : PhysicsActor
// create the hull into the _hulls variable // create the hull into the _hulls variable
convexBuilder.process(dcomp); convexBuilder.process(dcomp);
// Convert the vertices and indices for passing to unmanaged // Convert the vertices and indices for passing to unmanaged.
// The hull information is passed as a large floating point array. // The hull information is passed as a large floating point array.
// The format is: // The format is:
// convHulls[0] = number of hulls // convHulls[0] = number of hulls
@ -1202,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
// meshes are already scaled by the meshmerizer // meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f); _scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
return; return;
} }
@ -1340,11 +1336,12 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
// LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
base.RequestPhysicsterseUpdate(); base.RequestPhysicsterseUpdate();
} }
/*
else else
{ {
// For debugging, we also report the movement of children // For debugging, we also report the movement of children
@ -1352,10 +1349,11 @@ public sealed class BSPrim : PhysicsActor
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity); entprop.Acceleration, entprop.RotationalVelocity);
} }
*/
} }
// I've collided with something // I've collided with something
CollisionEventUpdate collisionCollection = null; CollisionEventUpdate collisionCollection;
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
{ {
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@ -1367,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor
_collidingGroundStep = _scene.SimulationStep; _collidingGroundStep = _scene.SimulationStep;
} }
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
// if someone is subscribed to collision events.... // if someone is subscribed to collision events....
if (_subscribedEventsMs != 0) { if (_subscribedEventsMs != 0) {
// throttle the collisions to the number of milliseconds specified in the subscription // throttle the collisions to the number of milliseconds specified in the subscription
@ -1387,7 +1387,9 @@ public sealed class BSPrim : PhysicsActor
if (collisionCollection != null && collisionCollection.Count > 0) if (collisionCollection != null && collisionCollection.Count > 0)
{ {
base.SendCollisionUpdate(collisionCollection); base.SendCollisionUpdate(collisionCollection);
collisionCollection.Clear(); // 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.
collisionCollection = null;
} }
} }

View File

@ -362,7 +362,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BSPrim bsprim = prim as BSPrim; BSPrim bsprim = prim as BSPrim;
if (bsprim != null) if (bsprim != null)
{ {
DetailLog("{0},RemovePrim,call", bsprim.LocalID); // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
// m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
try try
{ {
@ -388,7 +388,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
if (!m_initialized) return null; if (!m_initialized) return null;
DetailLog("{0},AddPrimShape,call", localID); // DetailLog("{0},AddPrimShape,call", localID);
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
lock (m_prims) m_prims.Add(localID, prim); lock (m_prims) m_prims.Add(localID, prim);
@ -413,7 +413,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// prevent simulation until we've been initialized // prevent simulation until we've been initialized
if (!m_initialized) return 10.0f; if (!m_initialized) return 10.0f;
long simulateStartTime = Util.EnvironmentTickCount(); int simulateStartTime = Util.EnvironmentTickCount();
// update the prim states while we know the physics engine is not busy // update the prim states while we know the physics engine is not busy
ProcessTaints(); ProcessTaints();
@ -429,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
{ {
numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
// updatedEntityCount = 0; // updatedEntityCount = 0;
collidersCount = 0; collidersCount = 0;
} }
@ -511,8 +511,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
// return (timeStep * (float)simulateTotalTime); // return (timeStep * (float)simulateTotalTime);
// TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. // TODO: FIX THIS: fps calculation possibly wrong.
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; // This calculation says 1/timeStep is the ideal frame rate. Any time added to
// that by the physics simulation gives a slower frame rate.
long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
if (totalSimulationTime >= timeStep)
return 0;
return 1f / (timeStep + totalSimulationTime);
} }
// Something has collided // Something has collided
@ -590,12 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// make sure no stepping happens while we're deleting stuff // make sure no stepping happens while we're deleting stuff
m_initialized = false; m_initialized = false;
if (m_constraintCollection != null)
{
m_constraintCollection.Dispose();
m_constraintCollection = null;
}
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
{ {
kvp.Value.Destroy(); kvp.Value.Destroy();
@ -608,6 +607,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
m_prims.Clear(); m_prims.Clear();
// Now that the prims are all cleaned up, there should be no constraints left
if (m_constraintCollection != null)
{
m_constraintCollection.Dispose();
m_constraintCollection = null;
}
// Anything left in the unmanaged code should be cleaned out // Anything left in the unmanaged code should be cleaned out
BulletSimAPI.Shutdown(WorldID); BulletSimAPI.Shutdown(WorldID);

View File

@ -415,6 +415,27 @@ public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, Int
Vector3 frame2loc, Quaternion frame2rot, Vector3 frame2loc, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
Vector3 joinPoint,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
Vector3 pivotinA, Vector3 pivotinB,
Vector3 axisInA, Vector3 axisInB,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetFrames2(IntPtr constrain,
Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
@ -427,6 +448,9 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CalculateTransforms2(IntPtr constrain); public static extern bool CalculateTransforms2(IntPtr constrain);
@ -517,6 +541,9 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ClearForces2(IntPtr obj); public static extern IntPtr ClearForces2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ClearAllForces2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetMargin2(IntPtr obj, float val); public static extern bool SetMargin2(IntPtr obj, float val);

View File

@ -12124,7 +12124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_List remaining = SetPrimParams(obj, rules); LSL_List remaining = SetPrimParams(obj, rules);
while (remaining != null && remaining.Length > 2) while ((object)remaining != null && remaining.Length > 2)
{ {
LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
LSL_List newrules = remaining.GetSublist(1, -1); LSL_List newrules = remaining.GetSublist(1, -1);

View File

@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int ATTACH_BELLY = 28; public const int ATTACH_BELLY = 28;
public const int ATTACH_RPEC = 29; public const int ATTACH_RPEC = 29;
public const int ATTACH_LPEC = 30; public const int ATTACH_LPEC = 30;
public const int ATTACH_LEFT_PEC = 29; // Same value as ATTACH_RPEC, see https://jira.secondlife.com/browse/SVC-580
public const int ATTACH_RIGHT_PEC = 30; // Same value as ATTACH_LPEC, see https://jira.secondlife.com/browse/SVC-580
public const int ATTACH_HUD_CENTER_2 = 31; public const int ATTACH_HUD_CENTER_2 = 31;
public const int ATTACH_HUD_TOP_RIGHT = 32; public const int ATTACH_HUD_TOP_RIGHT = 32;
public const int ATTACH_HUD_TOP_CENTER = 33; public const int ATTACH_HUD_TOP_CENTER = 33;

View File

@ -894,7 +894,7 @@
AvatarDensity = 60.0 AvatarDensity = 60.0
AvatarCapsuleRadius = 0.37 AvatarCapsuleRadius = 0.37
AvatarCapsuleHeight = 1.5 AvatarCapsuleHeight = 1.5
AvatarContactProcessingThreshold = 0.1; AvatarContactProcessingThreshold = 0.1
MaxObjectMass = 10000.01 MaxObjectMass = 10000.01
@ -908,19 +908,19 @@
CcdSweptSphereRadius = 0.0 CcdSweptSphereRadius = 0.0
ContactProcessingThreshold = 0.1 ContactProcessingThreshold = 0.1
; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc) ; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc)
MaxPersistantManifoldPoolSize = 0; MaxPersistantManifoldPoolSize = 0
ShouldDisableContactPoolDynamicAllocation = False; ShouldDisableContactPoolDynamicAllocation = False
ShouldForceUpdateAllAabbs = False; ShouldForceUpdateAllAabbs = False
ShouldRandomizeSolverOrder = False; ShouldRandomizeSolverOrder = False
ShouldSplitSimulationIslands = False; ShouldSplitSimulationIslands = False
ShouldEnableFrictionCaching = False; ShouldEnableFrictionCaching = False
NumberOfSolverIterations = 0; NumberOfSolverIterations = 0;
; Linkset constraint parameters ; Linkset constraint parameters
LinkConstraintUseFrameOffset = False; LinkConstraintUseFrameOffset = False
LinkConstraintEnableTransMotor = True; LinkConstraintEnableTransMotor = True
LinkConstraintTransMotorMaxVel = 5.0; LinkConstraintTransMotorMaxVel = 5.0
LinkConstraintTransMotorMaxForce = 0.1; LinkConstraintTransMotorMaxForce = 0.1
; Whether to mesh sculpties ; Whether to mesh sculpties
@ -935,12 +935,17 @@
SculptLevelOfDetail = 32 SculptLevelOfDetail = 32
; Bullet step parameters ; Bullet step parameters
MaxSubSteps = 10; MaxSubSteps = 10
FixedTimeStep = .01667 FixedTimeStep = .01667
MaxCollisionsPerFrame = 2048 MaxCollisionsPerFrame = 2048
MaxUpdatesPerFrame = 8192 MaxUpdatesPerFrame = 8192
; Detailed physics debug logging
PhysicsLoggingEnabled = False
PhysicsLoggingDir = "."
VehicleLoggingEnabled = False
[RemoteAdmin] [RemoteAdmin]
enabled = false enabled = false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.