diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 77e8b009bd..7b823ba8f0 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
// search the local cache
foreach (UserData data in m_UserCache.Values)
if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
- (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query)))
+ (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
users.Add(data);
AddAdditionalUsers(avatarID, query, users);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index 018357adf1..c48e58585e 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -375,11 +375,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
scene.GetRootAgentCount(), scene.RegionInfo.RegionName,
scene.RegionInfo.RegionID,
DateTime.UtcNow.ToString("s")));
+
scene.ForEachRootScenePresence(delegate(ScenePresence sp)
{
- list.Append(String.Format(" \n", sp.Name, sp.UUID));
- list.Append("");
+ list.Append(String.Format(" \n", sp.Name, sp.UUID));
});
+
+ list.Append("");
string payload = list.ToString();
// post via REST to broker
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index f5b84d4ca4..fdf2cb98f4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -268,6 +268,25 @@ public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShap
BSPhysicsShapeType.SHAPE_HULL);
}
+public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
+{
+ BulletWorldUnman worldu = world as BulletWorldUnman;
+ BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
+ return new BulletShapeUnman(
+ BSAPICPP.BuildConvexHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
+ BSPhysicsShapeType.SHAPE_CONVEXHULL);
+}
+
+public override BulletShape CreateConvexHullShape(BulletWorld world,
+ int indicesCount, int[] indices,
+ int verticesCount, float[] vertices)
+{
+ BulletWorldUnman worldu = world as BulletWorldUnman;
+ return new BulletShapeUnman(
+ BSAPICPP.CreateConvexHullShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
+ BSPhysicsShapeType.SHAPE_CONVEXHULL);
+}
+
public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
{
BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1413,6 +1432,14 @@ public static extern IntPtr CreateHullShape2(IntPtr world,
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms);
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern IntPtr BuildConvexHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern IntPtr CreateConvexHullShape2(IntPtr world,
+ int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
+ int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
+
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index f6b4359572..b37265a46f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1778,6 +1778,16 @@ private sealed class BulletConstraintXNA : BulletConstraint
/* TODO */ return null;
}
+ public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
+ {
+ /* TODO */ return null;
+ }
+
+ public override BulletShape CreateConvexHullShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
+ {
+ /* TODO */ return null;
+ }
+
public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
{
//DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index 8416740ada..bd5ee0b17f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -40,10 +40,16 @@ public class BSActorAvatarMove : BSActor
{
BSVMotor m_velocityMotor;
+ // Set to true if we think we're going up stairs.
+ // This state is remembered because collisions will turn on and off as we go up stairs.
+ int m_walkingUpStairs;
+ float m_lastStepUp;
+
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
: base(physicsScene, pObj, actorName)
{
m_velocityMotor = null;
+ m_walkingUpStairs = 0;
m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
}
@@ -119,6 +125,8 @@ public class BSActorAvatarMove : BSActor
SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
m_physicsScene.BeforeStep += Mover;
+
+ m_walkingUpStairs = 0;
}
}
@@ -216,8 +224,6 @@ public class BSActorAvatarMove : BSActor
// 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
- // Should we check for move force being small and forcing velocity to zero?
-
// Add special movement force to allow avatars to walk up stepped surfaces.
moveForce += WalkUpStairs();
@@ -233,24 +239,33 @@ public class BSActorAvatarMove : BSActor
{
OMV.Vector3 ret = OMV.Vector3.Zero;
+ m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
+ m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
+ m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
// This test is done if moving forward, not flying and is colliding with something.
- // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
- // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
- if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
+ // Check for stairs climbing if colliding, not flying and moving forward
+ if ( m_controllingPrim.IsColliding
+ && !m_controllingPrim.Flying
+ && m_controllingPrim.TargetVelocitySpeed > 0.1f )
{
// The range near the character's feet where we will consider stairs
- float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
+ // float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
+ // Note: there is a problem with the computation of the capsule height. Thus RawPosition is off
+ // from the height. Revisit size and this computation when height is scaled properly.
+ float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - 0.05f;
float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
- // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
+ // Look for a collision point that is near the character's feet and is oriented the same as the charactor is.
+ // Find the highest 'good' collision.
+ OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero;
foreach (KeyValuePair kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
{
// Don't care about collisions with the terrain
if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
{
OMV.Vector3 touchPosition = kvp.Value.Position;
- // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
- // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
+ m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
+ m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
{
// This contact is within the 'near the feet' range.
@@ -261,24 +276,76 @@ public class BSActorAvatarMove : BSActor
float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
if (diff < BSParam.AvatarStepApproachFactor)
{
- // Found the stairs contact point. Push up a little to raise the character.
- float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
- ret = new OMV.Vector3(0f, 0f, upForce);
-
- // Also move the avatar up for the new height
- OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
- m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
+ if (highestTouchPosition.Z < touchPosition.Z)
+ highestTouchPosition = touchPosition;
}
- m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
- m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
}
}
}
+ m_walkingUpStairs = 0;
+ // If there is a good step sensing, move the avatar over the step.
+ if (highestTouchPosition != OMV.Vector3.Zero)
+ {
+ // Remember that we are going up stairs. This is needed because collisions
+ // will stop when we move up so this smoothes out that effect.
+ m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps;
+
+ m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin;
+ ret = ComputeStairCorrection(m_lastStepUp);
+ m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}",
+ m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret);
+ }
+ }
+ else
+ {
+ // If we used to be going up stairs but are not now, smooth the case where collision goes away while
+ // we are bouncing up the stairs.
+ if (m_walkingUpStairs > 0)
+ {
+ m_walkingUpStairs--;
+ ret = ComputeStairCorrection(m_lastStepUp);
+ }
}
return ret;
}
+ private OMV.Vector3 ComputeStairCorrection(float stepUp)
+ {
+ OMV.Vector3 ret = OMV.Vector3.Zero;
+ OMV.Vector3 displacement = OMV.Vector3.Zero;
+
+ if (stepUp > 0f)
+ {
+ // Found the stairs contact point. Push up a little to raise the character.
+ if (BSParam.AvatarStepForceFactor > 0f)
+ {
+ float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
+ ret = new OMV.Vector3(0f, 0f, upForce);
+ }
+
+ // Also move the avatar up for the new height
+ if (BSParam.AvatarStepUpCorrectionFactor > 0f)
+ {
+ // Move the avatar up related to the height of the collision
+ displacement = new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor);
+ m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
+ }
+ else
+ {
+ if (BSParam.AvatarStepUpCorrectionFactor < 0f)
+ {
+ // Move the avatar up about the specified step height
+ displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight);
+ m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
+ }
+ }
+ m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,disp={1},force={2}",
+ m_controllingPrim.LocalID, displacement, ret);
+
+ }
+ return ret;
+ }
}
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index d0d9f34ae8..bfeec24419 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -70,6 +70,7 @@ public enum BSPhysicsShapeType
SHAPE_COMPOUND = 22,
SHAPE_HEIGHTMAP = 23,
SHAPE_AVATAR = 24,
+ SHAPE_CONVEXHULL= 25,
};
// The native shapes have predefined shape hash keys
@@ -325,6 +326,12 @@ public abstract BulletShape CreateHullShape(BulletWorld world,
public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms);
+public abstract BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
+
+public abstract BulletShape CreateConvexHullShape(BulletWorld world,
+ int indicesCount, int[] indices,
+ int verticesCount, float[] vertices );
+
public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
public abstract bool IsNativeShape(BulletShape shape);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 06df85e1e1..980d40587b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -128,6 +128,8 @@ public static class BSParam
public static float AvatarStepHeight { get; private set; }
public static float AvatarStepApproachFactor { get; private set; }
public static float AvatarStepForceFactor { get; private set; }
+ public static float AvatarStepUpCorrectionFactor { get; private set; }
+ public static int AvatarStepSmoothingSteps { get; private set; }
// Vehicle parameters
public static float VehicleMaxLinearVelocity { get; private set; }
@@ -234,6 +236,7 @@ public static class BSParam
objectSet = pObjSetter;
}
/* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work
+ * TODO: Maybe use reflection and the name of the variable to create a reference for the getter/setter.
public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc)
: base(pName, pDesc)
{
@@ -561,7 +564,7 @@ public static class BSParam
(s) => { return AvatarBelowGroundUpCorrectionMeters; },
(s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ),
new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
- 0.3f,
+ 0.6f,
(s) => { return AvatarStepHeight; },
(s,v) => { AvatarStepHeight = v; } ),
new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
@@ -569,9 +572,17 @@ public static class BSParam
(s) => { return AvatarStepApproachFactor; },
(s,v) => { AvatarStepApproachFactor = v; } ),
new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
- 2.0f,
+ 1.0f,
(s) => { return AvatarStepForceFactor; },
(s,v) => { AvatarStepForceFactor = v; } ),
+ new ParameterDefn("AvatarStepUpCorrectionFactor", "Multiplied by height of step collision to create up movement at step",
+ 1.0f,
+ (s) => { return AvatarStepUpCorrectionFactor; },
+ (s,v) => { AvatarStepUpCorrectionFactor = v; } ),
+ new ParameterDefn("AvatarStepSmoothingSteps", "Number of frames after a step collision that we continue walking up stairs",
+ 2,
+ (s) => { return AvatarStepSmoothingSteps; },
+ (s,v) => { AvatarStepSmoothingSteps = v; } ),
new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
1000.0f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98eb4ca9ad..309d004274 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -96,7 +96,7 @@ public abstract class BSPhysObject : PhysicsActor
SetMaterial((int)MaterialAttributes.Material.Wood);
CollisionCollection = new CollisionEventUpdate();
- CollisionsLastTick = CollisionCollection;
+ CollisionsLastReported = CollisionCollection;
SubscribedEventsMs = 0;
CollidingStep = 0;
CollidingGroundStep = 0;
@@ -368,11 +368,14 @@ public abstract class BSPhysObject : PhysicsActor
}
}
- // The collisions that have been collected this tick
+ // The collisions that have been collected for the next collision reporting (throttled by subscription)
protected CollisionEventUpdate CollisionCollection;
- // Remember collisions from last tick for fancy collision based actions
+ // This is the collision collection last reported to the Simulator.
+ public CollisionEventUpdate CollisionsLastReported;
+ // Remember the collisions recorded in the last tick for fancy collision checking
// (like a BSCharacter walking up stairs).
public CollisionEventUpdate CollisionsLastTick;
+ private long CollisionsLastTickStep = -1;
// The simulation step is telling this object about a collision.
// Return 'true' if a collision was processed and should be sent up.
@@ -399,6 +402,15 @@ public abstract class BSPhysObject : PhysicsActor
// For movement tests, remember if we are colliding with an object that is moving.
ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
+ // Make a collection of the collisions that happened the last simulation tick.
+ // This is different than the collection created for sending up to the simulator as it is cleared every tick.
+ if (CollisionsLastTickStep != PhysicsScene.SimulationStep)
+ {
+ CollisionsLastTick = new CollisionEventUpdate();
+ CollisionsLastTickStep = PhysicsScene.SimulationStep;
+ }
+ CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
+
// If someone has subscribed for collision events log the collision so it will be reported up
if (SubscribedEvents()) {
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
@@ -419,7 +431,7 @@ public abstract class BSPhysObject : PhysicsActor
bool ret = true;
// If the 'no collision' call, force it to happen right now so quick collision_end
- bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0);
+ bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
// throttle the collisions to the number of milliseconds specified in the subscription
if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
@@ -438,7 +450,7 @@ public abstract class BSPhysObject : PhysicsActor
base.SendCollisionUpdate(CollisionCollection);
// Remember the collisions from this tick for some collision specific processing.
- CollisionsLastTick = CollisionCollection;
+ CollisionsLastReported = CollisionCollection;
// The CollisionCollection instance is passed around in the simulator.
// Make sure we don't have a handle to that one and that a new one is used for next time.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 3423d2ea6b..4bc266bea7 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -69,12 +69,17 @@ public class BSPrim : BSPhysObject
private int CrossingFailures { get; set; }
+ // Keep a handle to the vehicle actor so it is easy to set parameters on same.
public BSDynamics VehicleActor;
public const string VehicleActorName = "BasicVehicle";
+ // Parameters for the hover actor
public const string HoverActorName = "HoverActor";
+ // Parameters for the axis lock actor
public const String LockedAxisActorName = "BSPrim.LockedAxis";
+ // Parameters for the move to target actor
public const string MoveToTargetActorName = "MoveToTargetActor";
+ // Parameters for the setForce and setTorque actors
public const string SetForceActorName = "SetForceActor";
public const string SetTorqueActorName = "SetTorqueActor";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 76860e4859..57e74a3c9c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -162,11 +162,8 @@ public sealed class BSShapeCollection : IDisposable
// If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
- if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
- {
- PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
- if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
- }
+ // Removing an object not in the world is a NOOP
+ PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
// Zero any reference to the shape so it is not freed when the body is deleted.
PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
@@ -615,7 +612,7 @@ public sealed class BSShapeCollection : IDisposable
newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
// Take evasive action if the mesh was not constructed.
- newShape = VerifyMeshCreated(newShape, prim);
+ newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
ReferenceShape(newShape);
@@ -724,7 +721,7 @@ public sealed class BSShapeCollection : IDisposable
newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
// It might not have been created if we're waiting for an asset.
- newShape = VerifyMeshCreated(newShape, prim);
+ newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
ReferenceShape(newShape);
@@ -928,7 +925,7 @@ public sealed class BSShapeCollection : IDisposable
// Create a hash of all the shape parameters to be used as a key
// for this particular shape.
- private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
+ public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
{
// level of detail based on size and type of the object
float lod = BSParam.MeshLOD;
@@ -949,7 +946,7 @@ public sealed class BSShapeCollection : IDisposable
return pbs.GetMeshKey(size, lod);
}
// For those who don't want the LOD
- private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
+ public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
{
float lod;
return ComputeShapeKey(size, pbs, out lod);
@@ -962,7 +959,7 @@ public sealed class BSShapeCollection : IDisposable
// us to not loop forever.
// Called after creating a physical mesh or hull. If the physical shape was created,
// just return.
- private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
+ public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
{
// If the shape was successfully created, nothing more to do
if (newShape.HasPhysicalShape)
@@ -974,7 +971,7 @@ public sealed class BSShapeCollection : IDisposable
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
{
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
- PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
+ physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
}
else
@@ -986,14 +983,14 @@ public sealed class BSShapeCollection : IDisposable
&& prim.BaseShape.SculptTexture != OMV.UUID.Zero
)
{
- DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
+ physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
// Multiple requestors will know we're waiting for this asset
prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
BSPhysObject xprim = prim;
Util.FireAndForget(delegate
{
- RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
+ RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
if (assetProvider != null)
{
BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
@@ -1021,7 +1018,7 @@ public sealed class BSShapeCollection : IDisposable
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
else
yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
- DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
+ physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
});
@@ -1029,8 +1026,8 @@ public sealed class BSShapeCollection : IDisposable
else
{
xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
- PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
- LogHeader, PhysicsScene.Name);
+ physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
+ LogHeader, physicsScene.Name);
}
});
}
@@ -1038,15 +1035,15 @@ public sealed class BSShapeCollection : IDisposable
{
if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
{
- PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
+ physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
}
}
}
// While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
- BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
- DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
+ BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
+ physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
return fillinShape;
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index ee18379a2e..dd5ae1ae60 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -29,6 +29,9 @@ using System;
using System.Collections.Generic;
using System.Text;
+using OpenSim.Framework;
+using OpenSim.Region.Physics.Manager;
+
using OMV = OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin
@@ -37,11 +40,19 @@ public abstract class BSShape
{
public int referenceCount { get; set; }
public DateTime lastReferenced { get; set; }
+ public BulletShape physShapeInfo { get; set; }
public BSShape()
{
referenceCount = 0;
lastReferenced = DateTime.Now;
+ physShapeInfo = new BulletShape();
+ }
+ public BSShape(BulletShape pShape)
+ {
+ referenceCount = 0;
+ lastReferenced = DateTime.Now;
+ physShapeInfo = pShape;
}
// Get a reference to a physical shape. Create if it doesn't exist
@@ -79,21 +90,30 @@ public abstract class BSShape
return ret;
}
- public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
+ private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
{
+ BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
+ BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
return null;
}
- public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
+
+ // Called when this shape is being used again.
+ public virtual void IncrementReference()
{
- return null;
+ referenceCount++;
+ lastReferenced = DateTime.Now;
+ }
+
+ // Called when this shape is being used again.
+ public virtual void DecrementReference()
+ {
+ referenceCount--;
+ lastReferenced = DateTime.Now;
}
// Release the use of a physical shape.
public abstract void Dereference(BSScene physicsScene);
- // All shapes have a static call to get a reference to the physical shape
- // protected abstract static BSShape GetReference();
-
// Returns a string for debugging that uniquily identifies the memory used by this instance
public virtual string AddrString
{
@@ -112,6 +132,7 @@ public abstract class BSShape
}
}
+// ============================================================================================================
public class BSShapeNull : BSShape
{
public BSShapeNull() : base()
@@ -121,23 +142,39 @@ public class BSShapeNull : BSShape
public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
}
+// ============================================================================================================
public class BSShapeNative : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
- public BSShapeNative() : base()
+ public BSShapeNative(BulletShape pShape) : base(pShape)
{
}
- public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
- BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
- {
- // Native shapes are not shared and are always built anew.
- //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
- return null;
- }
- private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
- BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
+ public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
+ BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
{
+ // Native shapes are not shared and are always built anew.
+ return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
+ }
+
+ // Make this reference to the physical shape go away since native shapes are not shared.
+ public override void Dereference(BSScene physicsScene)
+ {
+ // Native shapes are not tracked and are released immediately
+ if (physShapeInfo.HasPhysicalShape)
+ {
+ physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
+ physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
+ }
+ physShapeInfo.Clear();
+ // Garbage collection will free up this instance.
+ }
+
+ private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
+ BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
+ {
+ BulletShape newShape;
+
ShapeData nativeShapeData = new ShapeData();
nativeShapeData.Type = shapeType;
nativeShapeData.ID = prim.LocalID;
@@ -146,63 +183,164 @@ public class BSShapeNative : BSShape
nativeShapeData.MeshKey = (ulong)shapeKey;
nativeShapeData.HullKey = (ulong)shapeKey;
-
- /*
if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
{
- ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
- physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
+ newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
+ physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale);
}
else
{
- ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
+ newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
}
- if (ptr == IntPtr.Zero)
+ if (!newShape.HasPhysicalShape)
{
physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
LogHeader, prim.LocalID, shapeType);
}
- type = shapeType;
- key = (UInt64)shapeKey;
- */
- }
- // Make this reference to the physical shape go away since native shapes are not shared.
- public override void Dereference(BSScene physicsScene)
- {
- /*
- // Native shapes are not tracked and are released immediately
- physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
- PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
- ptr = IntPtr.Zero;
- // Garbage collection will free up this instance.
- */
+ newShape.type = shapeType;
+ newShape.isNativeShape = true;
+ newShape.shapeKey = (UInt64)shapeKey;
+ return newShape;
}
+
}
+// ============================================================================================================
public class BSShapeMesh : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE MESH]";
private static Dictionary Meshes = new Dictionary();
- public BSShapeMesh() : base()
+ public BSShapeMesh(BulletShape pShape) : base(pShape)
{
}
- public static BSShape GetReference() { return new BSShapeNull(); }
- public override void Dereference(BSScene physicsScene) { }
+ public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
+ {
+ float lod;
+ System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
+
+ physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
+ prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
+
+ BSShapeMesh retMesh;
+ lock (Meshes)
+ {
+ if (Meshes.TryGetValue(newMeshKey, out retMesh))
+ {
+ // The mesh has already been created. Return a new reference to same.
+ retMesh.IncrementReference();
+ }
+ else
+ {
+ // An instance of this mesh has not been created. Build and remember same.
+ BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
+ // Take evasive action if the mesh was not constructed.
+ newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
+
+ retMesh = new BSShapeMesh(newShape);
+
+ Meshes.Add(newMeshKey, retMesh);
+ }
+ }
+ return retMesh;
+ }
+ public override void Dereference(BSScene physicsScene)
+ {
+ lock (Meshes)
+ {
+ this.DecrementReference();
+ // TODO: schedule aging and destruction of unused meshes.
+ }
+ }
+
+ private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
+ PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
+ {
+ BulletShape newShape = null;
+
+ IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
+ false, // say it is not physical so a bounding box is not built
+ false // do not cache the mesh and do not use previously built versions
+ );
+
+ if (meshData != null)
+ {
+
+ int[] indices = meshData.getIndexListAsInt();
+ int realIndicesIndex = indices.Length;
+ float[] verticesAsFloats = meshData.getVertexListAsFloat();
+
+ if (BSParam.ShouldRemoveZeroWidthTriangles)
+ {
+ // Remove degenerate triangles. These are triangles with two of the vertices
+ // are the same. This is complicated by the problem that vertices are not
+ // made unique in sculpties so we have to compare the values in the vertex.
+ realIndicesIndex = 0;
+ for (int tri = 0; tri < indices.Length; tri += 3)
+ {
+ // Compute displacements into vertex array for each vertex of the triangle
+ int v1 = indices[tri + 0] * 3;
+ int v2 = indices[tri + 1] * 3;
+ int v3 = indices[tri + 2] * 3;
+ // Check to see if any two of the vertices are the same
+ if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
+ && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
+ && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
+ || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
+ && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
+ && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
+ || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
+ && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
+ && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
+ )
+ {
+ // None of the vertices of the triangles are the same. This is a good triangle;
+ indices[realIndicesIndex + 0] = indices[tri + 0];
+ indices[realIndicesIndex + 1] = indices[tri + 1];
+ indices[realIndicesIndex + 2] = indices[tri + 2];
+ realIndicesIndex += 3;
+ }
+ }
+ }
+ physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
+ BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
+
+ if (realIndicesIndex != 0)
+ {
+ newShape = physicsScene.PE.CreateMeshShape(physicsScene.World,
+ realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
+ }
+ else
+ {
+ physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
+ LogHeader, prim.PhysObjectName, prim.RawPosition, physicsScene.Name);
+ }
+ }
+ newShape.shapeKey = newMeshKey;
+
+ return newShape;
+ }
}
+// ============================================================================================================
public class BSShapeHull : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE HULL]";
private static Dictionary Hulls = new Dictionary();
- public BSShapeHull() : base()
+ public BSShapeHull(BulletShape pShape) : base(pShape)
+ {
+ }
+ public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
+ {
+ return new BSShapeNull();
+ }
+ public override void Dereference(BSScene physicsScene)
{
}
- public static BSShape GetReference() { return new BSShapeNull(); }
- public override void Dereference(BSScene physicsScene) { }
}
+// ============================================================================================================
public class BSShapeCompound : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
@@ -216,6 +354,7 @@ public class BSShapeCompound : BSShape
public override void Dereference(BSScene physicsScene) { }
}
+// ============================================================================================================
public class BSShapeAvatar : BSShape
{
private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index a0131c7f89..1284ae7307 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -42,6 +42,8 @@ One sided meshes? Should terrain be built into a closed shape?
VEHICLES TODO LIST:
=================================================
+UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
+ https://github.com/UbitUmarov/Ubit-opensim
Border crossing with linked vehicle causes crash
20121129.1411: editting/moving phys object across region boundries causes crash
getPos-> btRigidBody::upcast -> getBodyType -> BOOM
@@ -167,6 +169,7 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint)
MORE
======================================================
+Compute avatar size and scale correctly. Now it is a bit off from the capsule size.
Create tests for different interface components
Have test objects/scripts measure themselves and turn color if correct/bad
Test functions in SL and calibrate correctness there
diff --git a/bin/CSJ2K.dll b/bin/CSJ2K.dll
index 581e410772..238291f7e7 100755
Binary files a/bin/CSJ2K.dll and b/bin/CSJ2K.dll differ
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 618d4bd3e2..1e94d05955 100755
Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index e3b40fba1b..6216a652d2 100755
Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index 491ac22fe1..68cfcc41ea 100755
Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index a8ad533e87..08c00af019 100755
Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ