Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

sedebug
Diva Canto 2015-01-02 09:18:05 -08:00
commit 63e771b593
10 changed files with 869 additions and 110 deletions

View File

@ -307,7 +307,7 @@ namespace OpenSim.Framework.Monitoring
if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
if (request.ContainsKey("stat")) pStatName = request["stat"].ToString();
string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();

View File

@ -66,6 +66,7 @@ public class ExtendedPhysics : INonSharedRegionModule
public const string PhysFunctChangeLinkType = "BulletSim.ChangeLinkType";
public const string PhysFunctGetLinkType = "BulletSim.GetLinkType";
public const string PhysFunctChangeLinkParams = "BulletSim.ChangeLinkParams";
public const string PhysFunctAxisLockLimits = "BulletSim.AxisLockLimits";
// =============================================================
@ -176,6 +177,71 @@ public class ExtendedPhysics : INonSharedRegionModule
return ret;
}
// Code for specifying params.
// The choice if 14700 is arbitrary and only serves to catch parameter code misuse.
[ScriptConstant]
public const int PHYS_AXIS_LOCK_LINEAR = 14700;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_LINEAR_X = 14701;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_LINEAR_X = 14702;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_LINEAR_Y = 14703;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_LINEAR_Y = 14704;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_LINEAR_Z = 14705;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_LINEAR_Z = 14706;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_ANGULAR = 14707;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_ANGULAR_X = 14708;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_ANGULAR_X = 14709;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_ANGULAR_Y = 14710;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_ANGULAR_Y = 14711;
[ScriptConstant]
public const int PHYS_AXIS_LOCK_ANGULAR_Z = 14712;
[ScriptConstant]
public const int PHYS_AXIS_LIMIT_ANGULAR_Z = 14713;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_LINEAR = 14714;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_LINEAR_X = 14715;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_LINEAR_Y = 14716;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_LINEAR_Z = 14717;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_ANGULAR = 14718;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_ANGULAR_X = 14719;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_ANGULAR_Y = 14720;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK_ANGULAR_Z = 14721;
[ScriptConstant]
public const int PHYS_AXIS_UNLOCK = 14722;
// physAxisLockLimits()
[ScriptInvocation]
public int physAxisLock(UUID hostID, UUID scriptID, object[] parms)
{
int ret = -1;
if (!Enabled) return ret;
PhysicsActor rootPhysActor;
if (GetRootPhysActor(hostID, out rootPhysActor))
{
object[] parms2 = AddToBeginningOfArray(rootPhysActor, null, parms);
ret = MakeIntError(rootPhysActor.Extension(PhysFunctAxisLockLimits, parms2));
}
return ret;
}
[ScriptConstant]
public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
[ScriptConstant]
@ -187,7 +253,6 @@ public class ExtendedPhysics : INonSharedRegionModule
public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
{
int ret = -1;
if (!Enabled) return ret;
// The part that is requesting the change.
@ -259,34 +324,11 @@ public class ExtendedPhysics : INonSharedRegionModule
int ret = -1;
if (!Enabled) return ret;
// The part that is requesting the change.
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
if (requestingPart != null)
PhysicsActor rootPhysActor;
if (GetRootPhysActor(hostID, out rootPhysActor))
{
// The type is is always on the root of a linkset.
SceneObjectGroup containingGroup = requestingPart.ParentGroup;
SceneObjectPart rootPart = containingGroup.RootPart;
if (rootPart != null)
{
PhysicsActor rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
object[] parms2 = { rootPhysActor, null };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
}
else
{
m_log.WarnFormat("{0} physGetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
LogHeader, rootPart.Name, hostID);
}
}
else
{
m_log.WarnFormat("{0} physGetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
LogHeader, requestingPart.Name, hostID);
}
object[] parms2 = { rootPhysActor, null };
ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
}
else
{

View File

@ -37,12 +37,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
public class BSActorLockAxis : BSActor
{
BSConstraint LockAxisConstraint = null;
// The lock access flags (which axises were locked) when the contraint was built.
// Used to see if locking has changed since when the constraint was built.
OMV.Vector3 LockAxisLinearFlags;
OMV.Vector3 LockAxisAngularFlags;
public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
: base(physicsScene, pObj, actorName)
{
m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
LockAxisConstraint = null;
// we place our constraint just before the simulation step to make sure the linkset is complete
m_physicsScene.BeforeStep += PhysicsScene_BeforeStep;
}
// BSActor.isActive
@ -55,6 +62,7 @@ public class BSActorLockAxis : BSActor
// BSActor.Dispose()
public override void Dispose()
{
m_physicsScene.BeforeStep -= PhysicsScene_BeforeStep;
RemoveAxisLockConstraint();
}
@ -63,10 +71,18 @@ public class BSActorLockAxis : BSActor
// BSActor.Refresh()
public override void Refresh()
{
m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}",
m_controllingPrim.LocalID, m_controllingPrim.LockedAngularAxis, Enabled, m_controllingPrim.IsPhysicallyActive);
// Since the axis logging is done with a constraint, Refresh() time is good for
// changing parameters but this needs to wait until the prim/linkset is physically
// constructed. Therefore, the constraint itself is placed at pre-step time.
/*
m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedLinear={1},lockedAngular={2},enabled={3},pActive={4}",
m_controllingPrim.LocalID,
m_controllingPrim.LockedLinearAxis,
m_controllingPrim.LockedAngularAxis,
Enabled, m_controllingPrim.IsPhysicallyActive);
// If all the axis are free, we don't need to exist
if (m_controllingPrim.LockedAngularAxis == m_controllingPrim.LockedAxisFree)
if (m_controllingPrim.LockedAngularAxis == m_controllingPrim.LockedAxisFree
&& m_controllingPrim.LockedLinearAxis == m_controllingPrim.LockedAxisFree)
{
Enabled = false;
}
@ -74,12 +90,21 @@ public class BSActorLockAxis : BSActor
// If the object is physically active, add the axis locking constraint
if (isActive)
{
// Check to see if the locking parameters have changed
if (m_controllingPrim.LockedLinearAxis != this.LockAxisLinearFlags
|| m_controllingPrim.LockedAngularAxis != this.LockAxisAngularFlags)
{
// The locking has changed. Remove the old constraint and build a new one
RemoveAxisLockConstraint();
}
AddAxisLockConstraint();
}
else
{
RemoveAxisLockConstraint();
}
*/
}
// The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
@ -88,15 +113,35 @@ public class BSActorLockAxis : BSActor
// BSActor.RemoveDependencies()
public override void RemoveDependencies()
{
if (LockAxisConstraint != null)
RemoveAxisLockConstraint();
// The pre-step action will restore the constraint of needed
}
private void PhysicsScene_BeforeStep(float timestep)
{
// If all the axis are free, we don't need to exist
if (m_controllingPrim.LockedAngularAxis == m_controllingPrim.LockedAxisFree
&& m_controllingPrim.LockedLinearAxis == m_controllingPrim.LockedAxisFree)
{
// If a constraint is set up, remove it from the physical scene
RemoveAxisLockConstraint();
// Schedule a call before the next simulation step to restore the constraint.
m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate()
Enabled = false;
}
// If the object is physically active, add the axis locking constraint
if (isActive)
{
// Check to see if the locking parameters have changed
if (m_controllingPrim.LockedLinearAxis != this.LockAxisLinearFlags
|| m_controllingPrim.LockedAngularAxis != this.LockAxisAngularFlags)
{
Refresh();
});
// The locking has changed. Remove the old constraint and build a new one
RemoveAxisLockConstraint();
}
AddAxisLockConstraint();
}
else
{
RemoveAxisLockConstraint();
}
}
@ -118,56 +163,30 @@ public class BSActorLockAxis : BSActor
LockAxisConstraint = axisConstrainer;
m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
// Remember the clocking being inforced so we can notice if they have changed
LockAxisLinearFlags = m_controllingPrim.LockedLinearAxis;
LockAxisAngularFlags = m_controllingPrim.LockedAngularAxis;
// The constraint is tied to the world and oriented to the prim.
// Free to move linearly in the region
// OMV.Vector3 linearLow = OMV.Vector3.Zero;
// OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
OMV.Vector3 linearLow = new OMV.Vector3(-10000f, -10000f, -10000f);
OMV.Vector3 linearHigh = new OMV.Vector3(10000f, 10000f, 10000f);
if (m_controllingPrim.LockedLinearAxis.X != BSPhysObject.FreeAxis)
if (!axisConstrainer.SetLinearLimits(m_controllingPrim.LockedLinearAxisLow, m_controllingPrim.LockedLinearAxisHigh))
{
linearLow.X = m_controllingPrim.RawPosition.X;
linearHigh.X = m_controllingPrim.RawPosition.X;
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetLinearLimits",
m_controllingPrim.LocalID);
}
if (m_controllingPrim.LockedLinearAxis.Y != BSPhysObject.FreeAxis)
{
linearLow.Y = m_controllingPrim.RawPosition.Y;
linearHigh.Y = m_controllingPrim.RawPosition.Y;
}
if (m_controllingPrim.LockedLinearAxis.Z != BSPhysObject.FreeAxis)
{
linearLow.Z = m_controllingPrim.RawPosition.Z;
linearHigh.Z = m_controllingPrim.RawPosition.Z;
}
axisConstrainer.SetLinearLimits(linearLow, linearHigh);
// Angular with some axis locked
float fPI = (float)Math.PI;
OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
if (m_controllingPrim.LockedAngularAxis.X != BSPhysObject.FreeAxis)
if (!axisConstrainer.SetAngularLimits(m_controllingPrim.LockedAngularAxisLow, m_controllingPrim.LockedAngularAxisHigh))
{
angularLow.X = 0f;
angularHigh.X = 0f;
}
if (m_controllingPrim.LockedAngularAxis.Y != BSPhysObject.FreeAxis)
{
angularLow.Y = 0f;
angularHigh.Y = 0f;
}
if (m_controllingPrim.LockedAngularAxis.Z != BSPhysObject.FreeAxis)
{
angularLow.Z = 0f;
angularHigh.Z = 0f;
}
if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
{
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits",
m_controllingPrim.LocalID);
}
m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
m_controllingPrim.LocalID,
m_controllingPrim.LockedLinearAxisLow,
m_controllingPrim.LockedLinearAxisHigh,
m_controllingPrim.LockedAngularAxisLow,
m_controllingPrim.LockedAngularAxisHigh);
// Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);

View File

@ -201,7 +201,10 @@ public sealed class BSLinksetCompound : BSLinkset
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
{
// Find the physical instance of the child
if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
if (!RebuildScheduled // if rebuilding, let the rebuild do it
&& !LinksetRoot.IsIncomplete // if waiting for assets or whatever, don't change
&& LinksetRoot.PhysShape.HasPhysicalShape // there must be a physical shape assigned
&& m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
{
// It is possible that the linkset is still under construction and the child is not yet
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will

View File

@ -309,11 +309,20 @@ public abstract class BSPhysObject : PhysicsActor
// Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
public OMV.Vector3 LockedLinearAxis; // zero means locked. one means free.
public OMV.Vector3 LockedAngularAxis; // zero means locked. one means free.
public const float FreeAxis = 1f;
public const float LockedAxis = 0f;
public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
// If an axis is locked (flagged above) then the limits of that axis are specified here.
// Linear axis limits are relative to the object's starting coordinates.
// Angular limits are limited to -PI to +PI
public OMV.Vector3 LockedLinearAxisLow;
public OMV.Vector3 LockedLinearAxisHigh;
public OMV.Vector3 LockedAngularAxisLow;
public OMV.Vector3 LockedAngularAxisHigh;
// Enable physical actions. Bullet will keep sleeping non-moving physical objects so
// they need waking up when parameters are changed.
// Called in taint-time!!

View File

@ -34,6 +34,7 @@ using OMV = OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.ConvexDecompositionDotNet;
using OpenSim.Region.OptionalModules.Scripting; // for ExtendedPhysics
namespace OpenSim.Region.Physics.BulletSPlugin
{
@ -95,11 +96,9 @@ public class BSPrim : BSPhysObject
_isPhysical = pisPhysical;
_isVolumeDetect = false;
// Add a dynamic vehicle to our set of actors that can move this prim.
// PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName));
_mass = CalculateMass();
DetailLog("{0},BSPrim.constructor,pbs={1}", LocalID, BSScene.PrimitiveBaseShapeToString(pbs));
// DetailLog("{0},BSPrim.constructor,call", LocalID);
// do the actual object creation at taint time
PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
@ -167,6 +166,7 @@ public class BSPrim : BSPhysObject
public override PrimitiveBaseShape Shape {
set {
BaseShape = value;
DetailLog("{0},BSPrim.changeShape,pbs={1}", LocalID, BSScene.PrimitiveBaseShapeToString(BaseShape));
PrimAssetState = PrimAssetCondition.Unknown;
ForceBodyShapeRebuild(false);
}
@ -285,23 +285,21 @@ public class BSPrim : BSPhysObject
{
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
// "1" means free, "0" means locked
OMV.Vector3 locking = LockedAxisFree;
if (axis.X != 1) locking.X = 0f;
if (axis.Y != 1) locking.Y = 0f;
if (axis.Z != 1) locking.Z = 0f;
LockedAngularAxis = locking;
EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate()
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f);
if (axis.X != 1)
{
return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
});
// Update parameters so the new actor's Refresh() action is called at the right time.
PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f);
}
if (axis.Y != 1)
{
UpdatePhysicalParameters();
});
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f);
}
if (axis.Z != 1)
{
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f);
}
InitializeAxisActor();
return;
}
@ -533,6 +531,12 @@ public class BSPrim : BSPhysObject
{
return new BSActorSetForce(PhysScene, this, SetForceActorName);
});
// Call update so actor Refresh() is called to start things off
PhysScene.TaintedObject(LocalID, "BSPrim.setForce", delegate()
{
UpdatePhysicalParameters();
});
}
}
@ -766,6 +770,12 @@ public class BSPrim : BSPhysObject
return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
});
DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
// Call update so actor Refresh() is called to start things off
PhysScene.TaintedObject(LocalID, "BSPrim.setTorque", delegate()
{
UpdatePhysicalParameters();
});
}
}
public override OMV.Vector3 Acceleration {
@ -1138,6 +1148,12 @@ public class BSPrim : BSPhysObject
{
return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
});
// Call update so actor Refresh() is called to start things off
PhysScene.TaintedObject(LocalID, "BSPrim.PIDActive", delegate()
{
UpdatePhysicalParameters();
});
}
}
@ -1164,6 +1180,12 @@ public class BSPrim : BSPhysObject
{
return new BSActorHover(PhysScene, this, HoverActorName);
});
// Call update so actor Refresh() is called to start things off
PhysScene.TaintedObject(LocalID, "BSPrim.PIDHoverActive", delegate()
{
UpdatePhysicalParameters();
});
}
}
@ -1601,12 +1623,293 @@ public class BSPrim : BSPhysObject
object ret = null;
switch (pFunct)
{
case ExtendedPhysics.PhysFunctAxisLockLimits:
ret = SetAxisLockLimitsExtension(pParams);
break;
default:
ret = base.Extension(pFunct, pParams);
break;
}
return ret;
}
private void InitializeAxisActor()
{
EnableActor(LockedAngularAxis != LockedAxisFree || LockedLinearAxis != LockedAxisFree,
LockedAxisActorName, delegate()
{
return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
});
// Update parameters so the new actor's Refresh() action is called at the right time.
PhysScene.TaintedObject(LocalID, "BSPrim.LockAxis", delegate()
{
UpdatePhysicalParameters();
});
}
// Passed an array of an array of parameters, set the axis locking.
// This expects an int (PHYS_AXIS_*) followed by none or two limit floats
// followed by another int and floats, etc.
private object SetAxisLockLimitsExtension(object[] pParams)
{
DetailLog("{0} SetAxisLockLimitsExtension. parmlen={1}", LocalID, pParams.GetLength(0));
object ret = null;
try
{
if (pParams.GetLength(0) > 1)
{
int index = 2;
while (index < pParams.GetLength(0))
{
var funct = pParams[index];
DetailLog("{0} SetAxisLockLimitsExtension. op={1}, index={2}", LocalID, funct, index);
if (funct is Int32 || funct is Int64)
{
switch ((int)funct)
{
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_X, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_X, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Y, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Y, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Z, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Z, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_X, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Y, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Z, (float)pParams[index + 1], (float)pParams[index + 2]);
index += 3;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_X, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Y, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Z, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_X:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_X, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Y:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Y, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Z:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Z, 0f, 0f);
index += 1;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK, 0f, 0f);
index += 1;
break;
default:
m_log.WarnFormat("{0} SetSxisLockLimitsExtension. Unknown op={1}", LogHeader, funct);
index += 1;
break;
}
}
}
InitializeAxisActor();
ret = (object)index;
}
}
catch (Exception e)
{
m_log.WarnFormat("{0} SetSxisLockLimitsExtension exception in object {1}: {2}", LogHeader, this.Name, e);
ret = null;
}
return ret; // not implemented yet
}
// Set the locking parameters.
// If an axis is locked, the limits for the axis are set to zero,
// If the axis is being constrained, the high and low value are passed and set.
// When done here, LockedXXXAxis flags are set and LockedXXXAxixLow/High are set to the range.
protected void ApplyAxisLimits(int funct, float low, float high)
{
DetailLog("{0} ApplyAxisLimits. op={1}, low={2}, high={3}", LocalID, funct, low, high);
float linearMax = 23000f;
float angularMax = (float)Math.PI;
switch ((int)funct)
{
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR:
this.LockedLinearAxis = new OMV.Vector3(LockedAxis, LockedAxis, LockedAxis);
this.LockedLinearAxisLow = OMV.Vector3.Zero;
this.LockedLinearAxisHigh = OMV.Vector3.Zero;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_X:
this.LockedLinearAxis.X = LockedAxis;
this.LockedLinearAxisLow.X = 0f;
this.LockedLinearAxisHigh.X = 0f;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_X:
this.LockedLinearAxis.X = LockedAxis;
this.LockedLinearAxisLow.X = Util.Clip(low, -linearMax, linearMax);
this.LockedLinearAxisHigh.X = Util.Clip(high, -linearMax, linearMax);
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Y:
this.LockedLinearAxis.Y = LockedAxis;
this.LockedLinearAxisLow.Y = 0f;
this.LockedLinearAxisHigh.Y = 0f;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Y:
this.LockedLinearAxis.Y = LockedAxis;
this.LockedLinearAxisLow.Y = Util.Clip(low, -linearMax, linearMax);
this.LockedLinearAxisHigh.Y = Util.Clip(high, -linearMax, linearMax);
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_LINEAR_Z:
this.LockedLinearAxis.Z = LockedAxis;
this.LockedLinearAxisLow.Z = 0f;
this.LockedLinearAxisHigh.Z = 0f;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_LINEAR_Z:
this.LockedLinearAxis.Z = LockedAxis;
this.LockedLinearAxisLow.Z = Util.Clip(low, -linearMax, linearMax);
this.LockedLinearAxisHigh.Z = Util.Clip(high, -linearMax, linearMax);
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR:
this.LockedAngularAxis = new OMV.Vector3(LockedAxis, LockedAxis, LockedAxis);
this.LockedAngularAxisLow = OMV.Vector3.Zero;
this.LockedAngularAxisHigh = OMV.Vector3.Zero;
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X:
this.LockedAngularAxis.X = LockedAxis;
this.LockedAngularAxisLow.X = 0;
this.LockedAngularAxisHigh.X = 0;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_X:
this.LockedAngularAxis.X = LockedAxis;
this.LockedAngularAxisLow.X = Util.Clip(low, -angularMax, angularMax);
this.LockedAngularAxisHigh.X = Util.Clip(high, -angularMax, angularMax);
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y:
this.LockedAngularAxis.Y = LockedAxis;
this.LockedAngularAxisLow.Y = 0;
this.LockedAngularAxisHigh.Y = 0;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Y:
this.LockedAngularAxis.Y = LockedAxis;
this.LockedAngularAxisLow.Y = Util.Clip(low, -angularMax, angularMax);
this.LockedAngularAxisHigh.Y = Util.Clip(high, -angularMax, angularMax);
break;
case ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z:
this.LockedAngularAxis.Z = LockedAxis;
this.LockedAngularAxisLow.Z = 0;
this.LockedAngularAxisHigh.Z = 0;
break;
case ExtendedPhysics.PHYS_AXIS_LIMIT_ANGULAR_Z:
this.LockedAngularAxis.Z = LockedAxis;
this.LockedAngularAxisLow.Z = Util.Clip(low, -angularMax, angularMax);
this.LockedAngularAxisHigh.Z = Util.Clip(high, -angularMax, angularMax);
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR:
this.LockedLinearAxis = LockedAxisFree;
this.LockedLinearAxisLow = new OMV.Vector3(-linearMax, -linearMax, -linearMax);
this.LockedLinearAxisHigh = new OMV.Vector3(linearMax, linearMax, linearMax);
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_X:
this.LockedLinearAxis.X = FreeAxis;
this.LockedLinearAxisLow.X = -linearMax;
this.LockedLinearAxisHigh.X = linearMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Y:
this.LockedLinearAxis.Y = FreeAxis;
this.LockedLinearAxisLow.Y = -linearMax;
this.LockedLinearAxisHigh.Y = linearMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR_Z:
this.LockedLinearAxis.Z = FreeAxis;
this.LockedLinearAxisLow.Z = -linearMax;
this.LockedLinearAxisHigh.Z = linearMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR:
this.LockedAngularAxis = LockedAxisFree;
this.LockedAngularAxisLow = new OMV.Vector3(-angularMax, -angularMax, -angularMax);
this.LockedAngularAxisHigh = new OMV.Vector3(angularMax, angularMax, angularMax);
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_X:
this.LockedAngularAxis.X = FreeAxis;
this.LockedAngularAxisLow.X = -angularMax;
this.LockedAngularAxisHigh.X = angularMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Y:
this.LockedAngularAxis.Y = FreeAxis;
this.LockedAngularAxisLow.Y = -angularMax;
this.LockedAngularAxisHigh.Y = angularMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR_Z:
this.LockedAngularAxis.Z = FreeAxis;
this.LockedAngularAxisLow.Z = -angularMax;
this.LockedAngularAxisHigh.Z = angularMax;
break;
case ExtendedPhysics.PHYS_AXIS_UNLOCK:
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_LINEAR, 0f, 0f);
ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f);
break;
default:
break;
}
return;
}
#endregion // Extension
// The physics engine says that properties have updated. Update same and inform

View File

@ -947,6 +947,73 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
}
#endregion // Extensions
public static string PrimitiveBaseShapeToString(PrimitiveBaseShape pbs)
{
float pathShearX = pbs.PathShearX < 128 ? (float)pbs.PathShearX * 0.01f : (float)(pbs.PathShearX - 256) * 0.01f;
float pathShearY = pbs.PathShearY < 128 ? (float)pbs.PathShearY * 0.01f : (float)(pbs.PathShearY - 256) * 0.01f;
float pathBegin = (float)pbs.PathBegin * 2.0e-5f;
float pathEnd = 1.0f - (float)pbs.PathEnd * 2.0e-5f;
float pathScaleX = (float)(pbs.PathScaleX - 100) * 0.01f;
float pathScaleY = (float)(pbs.PathScaleY - 100) * 0.01f;
float profileBegin = (float)pbs.ProfileBegin * 2.0e-5f;
float profileEnd = 1.0f - (float)pbs.ProfileEnd * 2.0e-5f;
float profileHollow = (float)pbs.ProfileHollow * 2.0e-5f;
if (profileHollow > 0.95f)
profileHollow = 0.95f;
StringBuilder buff = new StringBuilder();
buff.Append("shape=");
buff.Append(((ProfileShape)pbs.ProfileShape).ToString());
buff.Append(",");
buff.Append("hollow=");
buff.Append(((HollowShape)pbs.HollowShape).ToString());
buff.Append(",");
buff.Append("pathCurve=");
buff.Append(((Extrusion)pbs.PathCurve).ToString());
buff.Append(",");
buff.Append("profCurve=");
buff.Append(((Extrusion)pbs.ProfileCurve).ToString());
buff.Append(",");
buff.Append("profHollow=");
buff.Append(profileHollow.ToString());
buff.Append(",");
buff.Append("pathBegEnd=");
buff.Append(pathBegin.ToString());
buff.Append("/");
buff.Append(pathEnd.ToString());
buff.Append(",");
buff.Append("profileBegEnd=");
buff.Append(profileBegin.ToString());
buff.Append("/");
buff.Append(profileEnd.ToString());
buff.Append(",");
buff.Append("scaleXY=");
buff.Append(pathScaleX.ToString());
buff.Append("/");
buff.Append(pathScaleY.ToString());
buff.Append(",");
buff.Append("shearXY=");
buff.Append(pathShearX.ToString());
buff.Append("/");
buff.Append(pathShearY.ToString());
buff.Append(",");
buff.Append("taperXY=");
buff.Append(pbs.PathTaperX.ToString());
buff.Append("/");
buff.Append(pbs.PathTaperY.ToString());
buff.Append(",");
buff.Append("skew=");
buff.Append(pbs.PathSkew.ToString());
buff.Append(",");
buff.Append("twist/Beg=");
buff.Append(pbs.PathTwist.ToString());
buff.Append("/");
buff.Append(pbs.PathTwistBegin.ToString());
return buff.ToString();
}
#region Taints
// The simulation execution order is:
// Simulate()

View File

@ -38,6 +38,76 @@ using OMV = OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
{
// Information class that holds stats for the shape. Which values mean
// something depends on the type of shape.
// This information is used for debugging and stats and is not used
// for operational things.
public class ShapeInfoInfo
{
public int Vertices { get; set; }
private int m_hullCount;
private int[] m_verticesPerHull;
public ShapeInfoInfo()
{
Vertices = 0;
m_hullCount = 0;
m_verticesPerHull = null;
}
public int HullCount
{
set
{
m_hullCount = value;
m_verticesPerHull = new int[m_hullCount];
Array.Clear(m_verticesPerHull, 0, m_hullCount);
}
get { return m_hullCount; }
}
public void SetVerticesPerHull(int hullNum, int vertices)
{
if (m_verticesPerHull != null && hullNum < m_verticesPerHull.Length)
{
m_verticesPerHull[hullNum] = vertices;
}
}
public int GetVerticesPerHull(int hullNum)
{
if (m_verticesPerHull != null && hullNum < m_verticesPerHull.Length)
{
return m_verticesPerHull[hullNum];
}
return 0;
}
public override string ToString()
{
StringBuilder buff = new StringBuilder();
// buff.Append("ShapeInfo=<");
buff.Append("<");
if (Vertices > 0)
{
buff.Append("verts=");
buff.Append(Vertices.ToString());
}
if (Vertices > 0 && HullCount > 0) buff.Append(",");
if (HullCount > 0)
{
buff.Append("nHulls=");
buff.Append(HullCount.ToString());
buff.Append(",");
buff.Append("hullVerts=");
for (int ii = 0; ii < HullCount; ii++)
{
if (ii != 0) buff.Append(",");
buff.Append(GetVerticesPerHull(ii).ToString());
}
}
buff.Append(">");
return buff.ToString();
}
}
public abstract class BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE]";
@ -45,18 +115,21 @@ public abstract class BSShape
public int referenceCount { get; set; }
public DateTime lastReferenced { get; set; }
public BulletShape physShapeInfo { get; set; }
public ShapeInfoInfo shapeInfo { get; private set; }
public BSShape()
{
referenceCount = 1;
lastReferenced = DateTime.Now;
physShapeInfo = new BulletShape();
shapeInfo = new ShapeInfoInfo();
}
public BSShape(BulletShape pShape)
{
referenceCount = 1;
lastReferenced = DateTime.Now;
physShapeInfo = pShape;
shapeInfo = new ShapeInfoInfo();
}
// Get another reference to this shape.
@ -283,6 +356,9 @@ public class BSShapeNull : BSShape
}
// ============================================================================================================
// BSShapeNative is a wrapper for a Bullet 'native' shape -- cube and sphere.
// They are odd in that they don't allocate meshes but are computated/procedural.
// This means allocation and freeing is different than meshes.
public class BSShapeNative : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
@ -361,6 +437,7 @@ public class BSShapeNative : BSShape
}
// ============================================================================================================
// BSShapeMesh is a simple mesh.
public class BSShapeMesh : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE MESH]";
@ -457,7 +534,11 @@ public class BSShapeMesh : BSShape
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
(w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) );
(w, iC, i, vC, v) =>
{
shapeInfo.Vertices = vC;
return physicsScene.PE.CreateMeshShape(w, iC, i, vC, v);
});
}
// Code that uses the mesher to create the index/vertices info for a trimesh shape.
@ -545,6 +626,9 @@ public class BSShapeMesh : BSShape
}
// ============================================================================================================
// BSShapeHull is a physical shape representation htat is made up of many convex hulls.
// The convex hulls are either supplied with the asset or are approximated by one of the
// convex hull creation routines (in OpenSim or in Bullet).
public class BSShapeHull : BSShape
{
#pragma warning disable 414
@ -553,6 +637,7 @@ public class BSShapeHull : BSShape
public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
public BSShapeHull(BulletShape pShape) : base(pShape)
{
}
@ -615,6 +700,7 @@ public class BSShapeHull : BSShape
// TODO: schedule aging and destruction of unused meshes.
}
}
List<ConvexResult> m_hulls;
private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
@ -647,6 +733,7 @@ public class BSShapeHull : BSShape
if (allHulls != null && BSParam.ShouldUseAssetHulls)
{
int hullCount = allHulls.Count;
shapeInfo.HullCount = hullCount;
int totalVertices = 1; // include one for the count of the hulls
// Using the structure described for HACD hulls, create the memory sturcture
// to pass the hull data to the creater.
@ -659,6 +746,7 @@ public class BSShapeHull : BSShape
convHulls[0] = (float)hullCount;
int jj = 1;
int hullIndex = 0;
foreach (List<OMV.Vector3> hullVerts in allHulls)
{
convHulls[jj + 0] = hullVerts.Count;
@ -673,6 +761,8 @@ public class BSShapeHull : BSShape
convHulls[jj + 2] = oneVert.Z;
jj += 3;
}
shapeInfo.SetVerticesPerHull(hullIndex, hullVerts.Count);
hullIndex++;
}
// create the hull data structure in Bullet
@ -708,6 +798,10 @@ public class BSShapeHull : BSShape
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);
// Now done with the mesh shape.
shapeInfo.HullCount = 1;
BSShapeMesh maybeMesh = meshShape as BSShapeMesh;
if (maybeMesh != null)
shapeInfo.SetVerticesPerHull(0, maybeMesh.shapeInfo.Vertices);
meshShape.Dereference(physicsScene);
}
physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
@ -857,6 +951,8 @@ public class BSShapeHull : BSShape
}
// ============================================================================================================
// BSShapeCompound is a wrapper for the Bullet compound shape which is built from multiple, separate
// meshes. Used by BulletSim for complex shapes like linksets.
public class BSShapeCompound : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
@ -999,6 +1095,9 @@ public class BSShapeCompound : BSShape
}
// ============================================================================================================
// BSShapeConvexHull is a wrapper for a Bullet single convex hull. A BSShapeHull contains multiple convex
// hull shapes. This is used for simple prims that are convex and thus can be made into a simple
// collision shape (a single hull). More complex physical shapes will be BSShapeHull's.
public class BSShapeConvexHull : BSShape
{
#pragma warning disable 414
@ -1098,6 +1197,9 @@ public class BSShapeConvexHull : BSShape
}
}
// ============================================================================================================
// BSShapeGImpact is a wrapper for the Bullet GImpact shape which is a collision mesh shape that
// can handle concave as well as convex shapes. Much slower computationally but creates smoother
// shapes than multiple convex hull approximations.
public class BSShapeGImpact : BSShape
{
#pragma warning disable 414
@ -1151,7 +1253,11 @@ public class BSShapeGImpact : BSShape
PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
{
return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
(w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) );
(w, iC, i, vC, v) =>
{
shapeInfo.Vertices = vC;
return physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v);
});
}
public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
@ -1206,6 +1312,7 @@ public class BSShapeGImpact : BSShape
}
// ============================================================================================================
// BSShapeAvatar is a specialized mesh shape for avatars.
public class BSShapeAvatar : BSShape
{
#pragma warning disable 414

View File

@ -28,15 +28,16 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Physics.BulletSPlugin;
using OpenSim.Region.Physics.Manager;
using OpenSim.Region.Physics.Meshing;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests
{
// Utility functions for building up and tearing down the sample physics environments
@ -77,17 +78,21 @@ public static class BulletSimTestsUtil
bulletSimConfig.Set("VehicleLoggingEnabled","True");
}
BSPlugin bsPlugin = new BSPlugin();
PhysicsPluginManager physicsPluginManager;
physicsPluginManager = new PhysicsPluginManager();
physicsPluginManager.LoadPluginsFromAssemblies("Physics");
BSScene bsScene = (BSScene)bsPlugin.GetScene("BSTestRegion");
Vector3 regionExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
PhysicsScene pScene = physicsPluginManager.GetPhysicsScene(
"BulletSim", "Meshmerizer", openSimINI, "BSTestRegion", regionExtent);
BSScene bsScene = pScene as BSScene;
// Since the asset requestor is not initialized, any mesh or sculptie will be a cube.
// In the future, add a fake asset fetcher to get meshes and sculpts.
// bsScene.RequestAssetMethod = ???;
Meshing.Meshmerizer mesher = new Meshmerizer(openSimINI);
bsScene.Initialise(mesher, openSimINI);
return bsScene;
}

View File

@ -0,0 +1,204 @@
/*
* 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 copyright
* 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.Linq;
using System.Text;
using NUnit.Framework;
using log4net;
using OpenSim.Framework;
using OpenSim.Region.Physics.BulletSPlugin;
using OpenSim.Region.Physics.Manager;
using OpenSim.Tests.Common;
using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests
{
[TestFixture]
public class HullCreation : OpenSimTestCase
{
// Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
// Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
BSScene PhysicsScene { get; set; }
Vector3 ObjectInitPosition;
float simulationTimeStep = 0.089f;
[TestFixtureSetUp]
public void Init()
{
}
[TestFixtureTearDown]
public void TearDown()
{
if (PhysicsScene != null)
{
// The Dispose() will also free any physical objects in the scene
PhysicsScene.Dispose();
PhysicsScene = null;
}
}
[TestCase(7, 2, 5f, 5f, 32, 0f)] /* default hull parameters */
public void GeomHullConvexDecomp( int maxDepthSplit,
int maxDepthSplitForSimpleShapes,
float concavityThresholdPercent,
float volumeConservationThresholdPercent,
int maxVertices,
float maxSkinWidth)
{
// Setup the physics engine to use the C# version of convex decomp
Dictionary<string, string> engineParams = new Dictionary<string, string>();
engineParams.Add("MeshSculptedPrim", "true"); // ShouldMeshSculptedPrim
engineParams.Add("ForceSimplePrimMeshing", "false"); // ShouldForceSimplePrimMeshing
engineParams.Add("UseHullsForPhysicalObjects", "true"); // ShouldUseHullsForPhysicalObjects
engineParams.Add("ShouldRemoveZeroWidthTriangles", "true");
engineParams.Add("ShouldUseBulletHACD", "false");
engineParams.Add("ShouldUseSingleConvexHullForPrims", "true");
engineParams.Add("ShouldUseGImpactShapeForPrims", "false");
engineParams.Add("ShouldUseAssetHulls", "true");
engineParams.Add("CSHullMaxDepthSplit", maxDepthSplit.ToString());
engineParams.Add("CSHullMaxDepthSplitForSimpleShapes", maxDepthSplitForSimpleShapes.ToString());
engineParams.Add("CSHullConcavityThresholdPercent", concavityThresholdPercent.ToString());
engineParams.Add("CSHullVolumeConservationThresholdPercent", volumeConservationThresholdPercent.ToString());
engineParams.Add("CSHullMaxVertices", maxVertices.ToString());
engineParams.Add("CSHullMaxSkinWidth", maxSkinWidth.ToString());
PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
PrimitiveBaseShape pbs;
Vector3 pos;
Vector3 size;
Quaternion rot;
bool isPhys;
// Cylinder
pbs = PrimitiveBaseShape.CreateCylinder();
pos = new Vector3(100.0f, 100.0f, 0f);
pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f;
ObjectInitPosition = pos;
size = new Vector3(2f, 2f, 2f);
pbs.Scale = size;
rot = Quaternion.Identity;
isPhys = true;
uint cylinderLocalID = 123;
PhysicsScene.AddPrimShape("testCylinder", pbs, pos, size, rot, isPhys, cylinderLocalID);
BSPrim primTypeCylinder = (BSPrim)PhysicsScene.PhysObjects[cylinderLocalID];
// Hollow Cylinder
pbs = PrimitiveBaseShape.CreateCylinder();
pbs.ProfileHollow = (ushort)(0.70f * 50000);
pos = new Vector3(110.0f, 110.0f, 0f);
pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f;
ObjectInitPosition = pos;
size = new Vector3(2f, 2f, 2f);
pbs.Scale = size;
rot = Quaternion.Identity;
isPhys = true;
uint hollowCylinderLocalID = 124;
PhysicsScene.AddPrimShape("testHollowCylinder", pbs, pos, size, rot, isPhys, hollowCylinderLocalID);
BSPrim primTypeHollowCylinder = (BSPrim)PhysicsScene.PhysObjects[hollowCylinderLocalID];
// Torus
// ProfileCurve = Circle, PathCurve = Curve1
pbs = PrimitiveBaseShape.CreateSphere();
pbs.ProfileShape = (byte)ProfileShape.Circle;
pbs.PathCurve = (byte)Extrusion.Curve1;
pos = new Vector3(120.0f, 120.0f, 0f);
pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 10f;
ObjectInitPosition = pos;
size = new Vector3(2f, 4f, 4f);
pbs.Scale = size;
rot = Quaternion.Identity;
isPhys = true;
uint torusLocalID = 125;
PhysicsScene.AddPrimShape("testTorus", pbs, pos, size, rot, isPhys, torusLocalID);
BSPrim primTypeTorus = (BSPrim)PhysicsScene.PhysObjects[torusLocalID];
// The actual prim shape creation happens at taint time
PhysicsScene.ProcessTaints();
// Check out the created hull shapes and report their characteristics
ReportShapeGeom(primTypeCylinder);
ReportShapeGeom(primTypeHollowCylinder);
ReportShapeGeom(primTypeTorus);
}
[TestCase]
public void GeomHullBulletHACD()
{
// Cylinder
// Hollow Cylinder
// Torus
}
private void ReportShapeGeom(BSPrim prim)
{
if (prim != null)
{
if (prim.PhysShape.HasPhysicalShape)
{
BSShape physShape = prim.PhysShape;
string shapeType = physShape.GetType().ToString();
switch (shapeType)
{
case "OpenSim.Region.Physics.BulletSPlugin.BSShapeNative":
BSShapeNative nShape = physShape as BSShapeNative;
prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
break;
case "OpenSim.Region.Physics.BulletSPlugin.BSShapeMesh":
BSShapeMesh mShape = physShape as BSShapeMesh;
prim.PhysScene.DetailLog("{0}, mesh, shapeInfo={1}", prim.Name, mShape.shapeInfo);
break;
case "OpenSim.Region.Physics.BulletSPlugin.BSShapeHull":
// BSShapeHull hShape = physShape as BSShapeHull;
// prim.PhysScene.DetailLog("{0}, hull, shapeInfo={1}", prim.Name, hShape.shapeInfo);
break;
case "OpenSim.Region.Physics.BulletSPlugin.BSShapeConvexHull":
BSShapeConvexHull chShape = physShape as BSShapeConvexHull;
prim.PhysScene.DetailLog("{0}, convexHull, shapeInfo={1}", prim.Name, chShape.shapeInfo);
break;
case "OpenSim.Region.Physics.BulletSPlugin.BSShapeCompound":
BSShapeCompound cShape = physShape as BSShapeCompound;
prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
break;
default:
prim.PhysScene.DetailLog("{0}, type={1}", prim.Name, shapeType);
break;
}
}
}
}
}
}