aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs27
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs10
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs103
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs15
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs22
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs5
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs28
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs215
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt3
10 files changed, 358 insertions, 77 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index f5b84d4..fdf2cb9 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
268 BSPhysicsShapeType.SHAPE_HULL); 268 BSPhysicsShapeType.SHAPE_HULL);
269} 269}
270 270
271public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
272{
273 BulletWorldUnman worldu = world as BulletWorldUnman;
274 BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
275 return new BulletShapeUnman(
276 BSAPICPP.BuildConvexHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
277 BSPhysicsShapeType.SHAPE_CONVEXHULL);
278}
279
280public override BulletShape CreateConvexHullShape(BulletWorld world,
281 int indicesCount, int[] indices,
282 int verticesCount, float[] vertices)
283{
284 BulletWorldUnman worldu = world as BulletWorldUnman;
285 return new BulletShapeUnman(
286 BSAPICPP.CreateConvexHullShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
287 BSPhysicsShapeType.SHAPE_CONVEXHULL);
288}
289
271public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) 290public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
272{ 291{
273 BulletWorldUnman worldu = world as BulletWorldUnman; 292 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1414,6 +1433,14 @@ public static extern IntPtr CreateHullShape2(IntPtr world,
1414public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms); 1433public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms);
1415 1434
1416[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1436public static extern IntPtr BuildConvexHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
1437
1438[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1439public static extern IntPtr CreateConvexHullShape2(IntPtr world,
1440 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1441 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1442
1443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1417public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); 1444public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
1418 1445
1419[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1446[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index f6b4359..b37265a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -1778,6 +1778,16 @@ private sealed class BulletConstraintXNA : BulletConstraint
1778 /* TODO */ return null; 1778 /* TODO */ return null;
1779 } 1779 }
1780 1780
1781 public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
1782 {
1783 /* TODO */ return null;
1784 }
1785
1786 public override BulletShape CreateConvexHullShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1787 {
1788 /* TODO */ return null;
1789 }
1790
1781 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) 1791 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1782 { 1792 {
1783 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); 1793 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index 8416740..bd5ee0b1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -40,10 +40,16 @@ public class BSActorAvatarMove : BSActor
40{ 40{
41 BSVMotor m_velocityMotor; 41 BSVMotor m_velocityMotor;
42 42
43 // Set to true if we think we're going up stairs.
44 // This state is remembered because collisions will turn on and off as we go up stairs.
45 int m_walkingUpStairs;
46 float m_lastStepUp;
47
43 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) 48 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName) 49 : base(physicsScene, pObj, actorName)
45 { 50 {
46 m_velocityMotor = null; 51 m_velocityMotor = null;
52 m_walkingUpStairs = 0;
47 m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID); 53 m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
48 } 54 }
49 55
@@ -119,6 +125,8 @@ public class BSActorAvatarMove : BSActor
119 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); 125 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
120 126
121 m_physicsScene.BeforeStep += Mover; 127 m_physicsScene.BeforeStep += Mover;
128
129 m_walkingUpStairs = 0;
122 } 130 }
123 } 131 }
124 132
@@ -216,8 +224,6 @@ public class BSActorAvatarMove : BSActor
216 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force. 224 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
217 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass; 225 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
218 226
219 // Should we check for move force being small and forcing velocity to zero?
220
221 // Add special movement force to allow avatars to walk up stepped surfaces. 227 // Add special movement force to allow avatars to walk up stepped surfaces.
222 moveForce += WalkUpStairs(); 228 moveForce += WalkUpStairs();
223 229
@@ -233,24 +239,33 @@ public class BSActorAvatarMove : BSActor
233 { 239 {
234 OMV.Vector3 ret = OMV.Vector3.Zero; 240 OMV.Vector3 ret = OMV.Vector3.Zero;
235 241
242 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
243 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
244 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
236 // This test is done if moving forward, not flying and is colliding with something. 245 // This test is done if moving forward, not flying and is colliding with something.
237 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", 246 // Check for stairs climbing if colliding, not flying and moving forward
238 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); 247 if ( m_controllingPrim.IsColliding
239 if (m_controllingPrim.IsColliding && !m_controllingPrim.Flying && m_controllingPrim.TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) 248 && !m_controllingPrim.Flying
249 && m_controllingPrim.TargetVelocitySpeed > 0.1f )
240 { 250 {
241 // The range near the character's feet where we will consider stairs 251 // The range near the character's feet where we will consider stairs
242 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f; 252 // float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
253 // Note: there is a problem with the computation of the capsule height. Thus RawPosition is off
254 // from the height. Revisit size and this computation when height is scaled properly.
255 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - 0.05f;
243 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight; 256 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
244 257
245 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is 258 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is.
259 // Find the highest 'good' collision.
260 OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero;
246 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList) 261 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
247 { 262 {
248 // Don't care about collisions with the terrain 263 // Don't care about collisions with the terrain
249 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID) 264 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
250 { 265 {
251 OMV.Vector3 touchPosition = kvp.Value.Position; 266 OMV.Vector3 touchPosition = kvp.Value.Position;
252 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}", 267 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
253 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition); 268 m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
254 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax) 269 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
255 { 270 {
256 // This contact is within the 'near the feet' range. 271 // This contact is within the 'near the feet' range.
@@ -261,24 +276,76 @@ public class BSActorAvatarMove : BSActor
261 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal)); 276 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
262 if (diff < BSParam.AvatarStepApproachFactor) 277 if (diff < BSParam.AvatarStepApproachFactor)
263 { 278 {
264 // Found the stairs contact point. Push up a little to raise the character. 279 if (highestTouchPosition.Z < touchPosition.Z)
265 float upForce = (touchPosition.Z - nearFeetHeightMin) * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor; 280 highestTouchPosition = touchPosition;
266 ret = new OMV.Vector3(0f, 0f, upForce);
267
268 // Also move the avatar up for the new height
269 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
270 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
271 } 281 }
272 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
273 m_controllingPrim.LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
274 } 282 }
275 } 283 }
276 } 284 }
285 m_walkingUpStairs = 0;
286 // If there is a good step sensing, move the avatar over the step.
287 if (highestTouchPosition != OMV.Vector3.Zero)
288 {
289 // Remember that we are going up stairs. This is needed because collisions
290 // will stop when we move up so this smoothes out that effect.
291 m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps;
292
293 m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin;
294 ret = ComputeStairCorrection(m_lastStepUp);
295 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}",
296 m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret);
297 }
298 }
299 else
300 {
301 // If we used to be going up stairs but are not now, smooth the case where collision goes away while
302 // we are bouncing up the stairs.
303 if (m_walkingUpStairs > 0)
304 {
305 m_walkingUpStairs--;
306 ret = ComputeStairCorrection(m_lastStepUp);
307 }
277 } 308 }
278 309
279 return ret; 310 return ret;
280 } 311 }
281 312
313 private OMV.Vector3 ComputeStairCorrection(float stepUp)
314 {
315 OMV.Vector3 ret = OMV.Vector3.Zero;
316 OMV.Vector3 displacement = OMV.Vector3.Zero;
317
318 if (stepUp > 0f)
319 {
320 // Found the stairs contact point. Push up a little to raise the character.
321 if (BSParam.AvatarStepForceFactor > 0f)
322 {
323 float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
324 ret = new OMV.Vector3(0f, 0f, upForce);
325 }
326
327 // Also move the avatar up for the new height
328 if (BSParam.AvatarStepUpCorrectionFactor > 0f)
329 {
330 // Move the avatar up related to the height of the collision
331 displacement = new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor);
332 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
333 }
334 else
335 {
336 if (BSParam.AvatarStepUpCorrectionFactor < 0f)
337 {
338 // Move the avatar up about the specified step height
339 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight);
340 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
341 }
342 }
343 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,disp={1},force={2}",
344 m_controllingPrim.LocalID, displacement, ret);
345
346 }
347 return ret;
348 }
282} 349}
283} 350}
284 351
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index d0d9f34..bfeec24 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -70,6 +70,7 @@ public enum BSPhysicsShapeType
70 SHAPE_COMPOUND = 22, 70 SHAPE_COMPOUND = 22,
71 SHAPE_HEIGHTMAP = 23, 71 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24, 72 SHAPE_AVATAR = 24,
73 SHAPE_CONVEXHULL= 25,
73}; 74};
74 75
75// The native shapes have predefined shape hash keys 76// The native shapes have predefined shape hash keys
@@ -325,6 +326,12 @@ public abstract BulletShape CreateHullShape(BulletWorld world,
325 326
326public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms); 327public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms);
327 328
329public abstract BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
330
331public abstract BulletShape CreateConvexHullShape(BulletWorld world,
332 int indicesCount, int[] indices,
333 int verticesCount, float[] vertices );
334
328public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); 335public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
329 336
330public abstract bool IsNativeShape(BulletShape shape); 337public abstract bool IsNativeShape(BulletShape shape);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 06df85e..980d405 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -128,6 +128,8 @@ public static class BSParam
128 public static float AvatarStepHeight { get; private set; } 128 public static float AvatarStepHeight { get; private set; }
129 public static float AvatarStepApproachFactor { get; private set; } 129 public static float AvatarStepApproachFactor { get; private set; }
130 public static float AvatarStepForceFactor { get; private set; } 130 public static float AvatarStepForceFactor { get; private set; }
131 public static float AvatarStepUpCorrectionFactor { get; private set; }
132 public static int AvatarStepSmoothingSteps { get; private set; }
131 133
132 // Vehicle parameters 134 // Vehicle parameters
133 public static float VehicleMaxLinearVelocity { get; private set; } 135 public static float VehicleMaxLinearVelocity { get; private set; }
@@ -234,6 +236,7 @@ public static class BSParam
234 objectSet = pObjSetter; 236 objectSet = pObjSetter;
235 } 237 }
236 /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work 238 /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work
239 * TODO: Maybe use reflection and the name of the variable to create a reference for the getter/setter.
237 public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc) 240 public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc)
238 : base(pName, pDesc) 241 : base(pName, pDesc)
239 { 242 {
@@ -561,7 +564,7 @@ public static class BSParam
561 (s) => { return AvatarBelowGroundUpCorrectionMeters; }, 564 (s) => { return AvatarBelowGroundUpCorrectionMeters; },
562 (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), 565 (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ),
563 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", 566 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
564 0.3f, 567 0.6f,
565 (s) => { return AvatarStepHeight; }, 568 (s) => { return AvatarStepHeight; },
566 (s,v) => { AvatarStepHeight = v; } ), 569 (s,v) => { AvatarStepHeight = v; } ),
567 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 570 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
@@ -569,9 +572,17 @@ public static class BSParam
569 (s) => { return AvatarStepApproachFactor; }, 572 (s) => { return AvatarStepApproachFactor; },
570 (s,v) => { AvatarStepApproachFactor = v; } ), 573 (s,v) => { AvatarStepApproachFactor = v; } ),
571 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step", 574 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
572 2.0f, 575 1.0f,
573 (s) => { return AvatarStepForceFactor; }, 576 (s) => { return AvatarStepForceFactor; },
574 (s,v) => { AvatarStepForceFactor = v; } ), 577 (s,v) => { AvatarStepForceFactor = v; } ),
578 new ParameterDefn<float>("AvatarStepUpCorrectionFactor", "Multiplied by height of step collision to create up movement at step",
579 1.0f,
580 (s) => { return AvatarStepUpCorrectionFactor; },
581 (s,v) => { AvatarStepUpCorrectionFactor = v; } ),
582 new ParameterDefn<int>("AvatarStepSmoothingSteps", "Number of frames after a step collision that we continue walking up stairs",
583 2,
584 (s) => { return AvatarStepSmoothingSteps; },
585 (s,v) => { AvatarStepSmoothingSteps = v; } ),
575 586
576 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle", 587 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
577 1000.0f, 588 1000.0f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98eb4ca..309d004 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -96,7 +96,7 @@ public abstract class BSPhysObject : PhysicsActor
96 SetMaterial((int)MaterialAttributes.Material.Wood); 96 SetMaterial((int)MaterialAttributes.Material.Wood);
97 97
98 CollisionCollection = new CollisionEventUpdate(); 98 CollisionCollection = new CollisionEventUpdate();
99 CollisionsLastTick = CollisionCollection; 99 CollisionsLastReported = CollisionCollection;
100 SubscribedEventsMs = 0; 100 SubscribedEventsMs = 0;
101 CollidingStep = 0; 101 CollidingStep = 0;
102 CollidingGroundStep = 0; 102 CollidingGroundStep = 0;
@@ -368,11 +368,14 @@ public abstract class BSPhysObject : PhysicsActor
368 } 368 }
369 } 369 }
370 370
371 // The collisions that have been collected this tick 371 // The collisions that have been collected for the next collision reporting (throttled by subscription)
372 protected CollisionEventUpdate CollisionCollection; 372 protected CollisionEventUpdate CollisionCollection;
373 // Remember collisions from last tick for fancy collision based actions 373 // This is the collision collection last reported to the Simulator.
374 public CollisionEventUpdate CollisionsLastReported;
375 // Remember the collisions recorded in the last tick for fancy collision checking
374 // (like a BSCharacter walking up stairs). 376 // (like a BSCharacter walking up stairs).
375 public CollisionEventUpdate CollisionsLastTick; 377 public CollisionEventUpdate CollisionsLastTick;
378 private long CollisionsLastTickStep = -1;
376 379
377 // The simulation step is telling this object about a collision. 380 // The simulation step is telling this object about a collision.
378 // Return 'true' if a collision was processed and should be sent up. 381 // Return 'true' if a collision was processed and should be sent up.
@@ -399,6 +402,15 @@ public abstract class BSPhysObject : PhysicsActor
399 // For movement tests, remember if we are colliding with an object that is moving. 402 // For movement tests, remember if we are colliding with an object that is moving.
400 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 403 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
401 404
405 // Make a collection of the collisions that happened the last simulation tick.
406 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
407 if (CollisionsLastTickStep != PhysicsScene.SimulationStep)
408 {
409 CollisionsLastTick = new CollisionEventUpdate();
410 CollisionsLastTickStep = PhysicsScene.SimulationStep;
411 }
412 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
413
402 // If someone has subscribed for collision events log the collision so it will be reported up 414 // If someone has subscribed for collision events log the collision so it will be reported up
403 if (SubscribedEvents()) { 415 if (SubscribedEvents()) {
404 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 416 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
@@ -419,7 +431,7 @@ public abstract class BSPhysObject : PhysicsActor
419 bool ret = true; 431 bool ret = true;
420 432
421 // If the 'no collision' call, force it to happen right now so quick collision_end 433 // If the 'no collision' call, force it to happen right now so quick collision_end
422 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 434 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
423 435
424 // throttle the collisions to the number of milliseconds specified in the subscription 436 // throttle the collisions to the number of milliseconds specified in the subscription
425 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 437 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
@@ -438,7 +450,7 @@ public abstract class BSPhysObject : PhysicsActor
438 base.SendCollisionUpdate(CollisionCollection); 450 base.SendCollisionUpdate(CollisionCollection);
439 451
440 // Remember the collisions from this tick for some collision specific processing. 452 // Remember the collisions from this tick for some collision specific processing.
441 CollisionsLastTick = CollisionCollection; 453 CollisionsLastReported = CollisionCollection;
442 454
443 // The CollisionCollection instance is passed around in the simulator. 455 // The CollisionCollection instance is passed around in the simulator.
444 // Make sure we don't have a handle to that one and that a new one is used for next time. 456 // 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 3423d2e..4bc266b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -69,12 +69,17 @@ public class BSPrim : BSPhysObject
69 69
70 private int CrossingFailures { get; set; } 70 private int CrossingFailures { get; set; }
71 71
72 // Keep a handle to the vehicle actor so it is easy to set parameters on same.
72 public BSDynamics VehicleActor; 73 public BSDynamics VehicleActor;
73 public const string VehicleActorName = "BasicVehicle"; 74 public const string VehicleActorName = "BasicVehicle";
74 75
76 // Parameters for the hover actor
75 public const string HoverActorName = "HoverActor"; 77 public const string HoverActorName = "HoverActor";
78 // Parameters for the axis lock actor
76 public const String LockedAxisActorName = "BSPrim.LockedAxis"; 79 public const String LockedAxisActorName = "BSPrim.LockedAxis";
80 // Parameters for the move to target actor
77 public const string MoveToTargetActorName = "MoveToTargetActor"; 81 public const string MoveToTargetActorName = "MoveToTargetActor";
82 // Parameters for the setForce and setTorque actors
78 public const string SetForceActorName = "SetForceActor"; 83 public const string SetForceActorName = "SetForceActor";
79 public const string SetTorqueActorName = "SetTorqueActor"; 84 public const string SetTorqueActorName = "SetTorqueActor";
80 85
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 1976c42..bc26460 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -612,7 +612,7 @@ public sealed class BSShapeCollection : IDisposable
612 612
613 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod); 613 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
614 // Take evasive action if the mesh was not constructed. 614 // Take evasive action if the mesh was not constructed.
615 newShape = VerifyMeshCreated(newShape, prim); 615 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
616 616
617 ReferenceShape(newShape); 617 ReferenceShape(newShape);
618 618
@@ -719,7 +719,7 @@ public sealed class BSShapeCollection : IDisposable
719 719
720 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod); 720 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
721 // It might not have been created if we're waiting for an asset. 721 // It might not have been created if we're waiting for an asset.
722 newShape = VerifyMeshCreated(newShape, prim); 722 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
723 723
724 ReferenceShape(newShape); 724 ReferenceShape(newShape);
725 725
@@ -923,7 +923,7 @@ public sealed class BSShapeCollection : IDisposable
923 923
924 // Create a hash of all the shape parameters to be used as a key 924 // Create a hash of all the shape parameters to be used as a key
925 // for this particular shape. 925 // for this particular shape.
926 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 926 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
927 { 927 {
928 // level of detail based on size and type of the object 928 // level of detail based on size and type of the object
929 float lod = BSParam.MeshLOD; 929 float lod = BSParam.MeshLOD;
@@ -944,7 +944,7 @@ public sealed class BSShapeCollection : IDisposable
944 return pbs.GetMeshKey(size, lod); 944 return pbs.GetMeshKey(size, lod);
945 } 945 }
946 // For those who don't want the LOD 946 // For those who don't want the LOD
947 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) 947 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
948 { 948 {
949 float lod; 949 float lod;
950 return ComputeShapeKey(size, pbs, out lod); 950 return ComputeShapeKey(size, pbs, out lod);
@@ -957,7 +957,7 @@ public sealed class BSShapeCollection : IDisposable
957 // us to not loop forever. 957 // us to not loop forever.
958 // Called after creating a physical mesh or hull. If the physical shape was created, 958 // Called after creating a physical mesh or hull. If the physical shape was created,
959 // just return. 959 // just return.
960 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) 960 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
961 { 961 {
962 // If the shape was successfully created, nothing more to do 962 // If the shape was successfully created, nothing more to do
963 if (newShape.HasPhysicalShape) 963 if (newShape.HasPhysicalShape)
@@ -969,7 +969,7 @@ public sealed class BSShapeCollection : IDisposable
969 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) 969 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
970 { 970 {
971 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; 971 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
972 PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", 972 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
973 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); 973 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
974 } 974 }
975 else 975 else
@@ -981,14 +981,14 @@ public sealed class BSShapeCollection : IDisposable
981 && prim.BaseShape.SculptTexture != OMV.UUID.Zero 981 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
982 ) 982 )
983 { 983 {
984 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); 984 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
985 // Multiple requestors will know we're waiting for this asset 985 // Multiple requestors will know we're waiting for this asset
986 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; 986 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
987 987
988 BSPhysObject xprim = prim; 988 BSPhysObject xprim = prim;
989 Util.FireAndForget(delegate 989 Util.FireAndForget(delegate
990 { 990 {
991 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; 991 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
992 if (assetProvider != null) 992 if (assetProvider != null)
993 { 993 {
994 BSPhysObject yprim = xprim; // probably not necessary, but, just in case. 994 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
@@ -1016,7 +1016,7 @@ public sealed class BSShapeCollection : IDisposable
1016 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; 1016 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
1017 else 1017 else
1018 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; 1018 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1019 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", 1019 physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
1020 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); 1020 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
1021 1021
1022 }); 1022 });
@@ -1024,8 +1024,8 @@ public sealed class BSShapeCollection : IDisposable
1024 else 1024 else
1025 { 1025 {
1026 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; 1026 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1027 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", 1027 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
1028 LogHeader, PhysicsScene.Name); 1028 LogHeader, physicsScene.Name);
1029 } 1029 }
1030 }); 1030 });
1031 } 1031 }
@@ -1033,15 +1033,15 @@ public sealed class BSShapeCollection : IDisposable
1033 { 1033 {
1034 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) 1034 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1035 { 1035 {
1036 PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", 1036 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1037 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); 1037 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1038 } 1038 }
1039 } 1039 }
1040 } 1040 }
1041 1041
1042 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. 1042 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
1043 BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 1043 BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
1044 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); 1044 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
1045 1045
1046 return fillinShape; 1046 return fillinShape;
1047 } 1047 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index ee18379..dd5ae1a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -29,6 +29,9 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
32using OMV = OpenMetaverse; 35using OMV = OpenMetaverse;
33 36
34namespace OpenSim.Region.Physics.BulletSPlugin 37namespace OpenSim.Region.Physics.BulletSPlugin
@@ -37,11 +40,19 @@ public abstract class BSShape
37{ 40{
38 public int referenceCount { get; set; } 41 public int referenceCount { get; set; }
39 public DateTime lastReferenced { get; set; } 42 public DateTime lastReferenced { get; set; }
43 public BulletShape physShapeInfo { get; set; }
40 44
41 public BSShape() 45 public BSShape()
42 { 46 {
43 referenceCount = 0; 47 referenceCount = 0;
44 lastReferenced = DateTime.Now; 48 lastReferenced = DateTime.Now;
49 physShapeInfo = new BulletShape();
50 }
51 public BSShape(BulletShape pShape)
52 {
53 referenceCount = 0;
54 lastReferenced = DateTime.Now;
55 physShapeInfo = pShape;
45 } 56 }
46 57
47 // Get a reference to a physical shape. Create if it doesn't exist 58 // Get a reference to a physical shape. Create if it doesn't exist
@@ -79,21 +90,30 @@ public abstract class BSShape
79 90
80 return ret; 91 return ret;
81 } 92 }
82 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 93 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
83 { 94 {
95 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
96 BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
84 return null; 97 return null;
85 } 98 }
86 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 99
100 // Called when this shape is being used again.
101 public virtual void IncrementReference()
87 { 102 {
88 return null; 103 referenceCount++;
104 lastReferenced = DateTime.Now;
105 }
106
107 // Called when this shape is being used again.
108 public virtual void DecrementReference()
109 {
110 referenceCount--;
111 lastReferenced = DateTime.Now;
89 } 112 }
90 113
91 // Release the use of a physical shape. 114 // Release the use of a physical shape.
92 public abstract void Dereference(BSScene physicsScene); 115 public abstract void Dereference(BSScene physicsScene);
93 116
94 // All shapes have a static call to get a reference to the physical shape
95 // protected abstract static BSShape GetReference();
96
97 // Returns a string for debugging that uniquily identifies the memory used by this instance 117 // Returns a string for debugging that uniquily identifies the memory used by this instance
98 public virtual string AddrString 118 public virtual string AddrString
99 { 119 {
@@ -112,6 +132,7 @@ public abstract class BSShape
112 } 132 }
113} 133}
114 134
135// ============================================================================================================
115public class BSShapeNull : BSShape 136public class BSShapeNull : BSShape
116{ 137{
117 public BSShapeNull() : base() 138 public BSShapeNull() : base()
@@ -121,23 +142,39 @@ public class BSShapeNull : BSShape
121 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 142 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
122} 143}
123 144
145// ============================================================================================================
124public class BSShapeNative : BSShape 146public class BSShapeNative : BSShape
125{ 147{
126 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; 148 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
127 public BSShapeNative() : base() 149 public BSShapeNative(BulletShape pShape) : base(pShape)
128 { 150 {
129 } 151 }
152
130 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 153 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
131 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 154 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
132 { 155 {
133 // Native shapes are not shared and are always built anew. 156 // Native shapes are not shared and are always built anew.
134 //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 157 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
135 return null;
136 } 158 }
137 159
138 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 160 // Make this reference to the physical shape go away since native shapes are not shared.
139 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 161 public override void Dereference(BSScene physicsScene)
162 {
163 // Native shapes are not tracked and are released immediately
164 if (physShapeInfo.HasPhysicalShape)
165 {
166 physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
167 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
168 }
169 physShapeInfo.Clear();
170 // Garbage collection will free up this instance.
171 }
172
173 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
174 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
140 { 175 {
176 BulletShape newShape;
177
141 ShapeData nativeShapeData = new ShapeData(); 178 ShapeData nativeShapeData = new ShapeData();
142 nativeShapeData.Type = shapeType; 179 nativeShapeData.Type = shapeType;
143 nativeShapeData.ID = prim.LocalID; 180 nativeShapeData.ID = prim.LocalID;
@@ -146,63 +183,164 @@ public class BSShapeNative : BSShape
146 nativeShapeData.MeshKey = (ulong)shapeKey; 183 nativeShapeData.MeshKey = (ulong)shapeKey;
147 nativeShapeData.HullKey = (ulong)shapeKey; 184 nativeShapeData.HullKey = (ulong)shapeKey;
148 185
149
150 /*
151 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 186 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
152 { 187 {
153 ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); 188 newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
154 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 189 physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale);
155 } 190 }
156 else 191 else
157 { 192 {
158 ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); 193 newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
159 } 194 }
160 if (ptr == IntPtr.Zero) 195 if (!newShape.HasPhysicalShape)
161 { 196 {
162 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 197 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
163 LogHeader, prim.LocalID, shapeType); 198 LogHeader, prim.LocalID, shapeType);
164 } 199 }
165 type = shapeType; 200 newShape.type = shapeType;
166 key = (UInt64)shapeKey; 201 newShape.isNativeShape = true;
167 */ 202 newShape.shapeKey = (UInt64)shapeKey;
168 } 203 return newShape;
169 // Make this reference to the physical shape go away since native shapes are not shared.
170 public override void Dereference(BSScene physicsScene)
171 {
172 /*
173 // Native shapes are not tracked and are released immediately
174 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
175 PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
176 ptr = IntPtr.Zero;
177 // Garbage collection will free up this instance.
178 */
179 } 204 }
205
180} 206}
181 207
208// ============================================================================================================
182public class BSShapeMesh : BSShape 209public class BSShapeMesh : BSShape
183{ 210{
184 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 211 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
185 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 212 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
186 213
187 public BSShapeMesh() : base() 214 public BSShapeMesh(BulletShape pShape) : base(pShape)
188 { 215 {
189 } 216 }
190 public static BSShape GetReference() { return new BSShapeNull(); } 217 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
191 public override void Dereference(BSScene physicsScene) { } 218 {
219 float lod;
220 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
221
222 physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
223 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
224
225 BSShapeMesh retMesh;
226 lock (Meshes)
227 {
228 if (Meshes.TryGetValue(newMeshKey, out retMesh))
229 {
230 // The mesh has already been created. Return a new reference to same.
231 retMesh.IncrementReference();
232 }
233 else
234 {
235 // An instance of this mesh has not been created. Build and remember same.
236 BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
237 // Take evasive action if the mesh was not constructed.
238 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
239
240 retMesh = new BSShapeMesh(newShape);
241
242 Meshes.Add(newMeshKey, retMesh);
243 }
244 }
245 return retMesh;
246 }
247 public override void Dereference(BSScene physicsScene)
248 {
249 lock (Meshes)
250 {
251 this.DecrementReference();
252 // TODO: schedule aging and destruction of unused meshes.
253 }
254 }
255
256 private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
257 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
258 {
259 BulletShape newShape = null;
260
261 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
262 false, // say it is not physical so a bounding box is not built
263 false // do not cache the mesh and do not use previously built versions
264 );
265
266 if (meshData != null)
267 {
268
269 int[] indices = meshData.getIndexListAsInt();
270 int realIndicesIndex = indices.Length;
271 float[] verticesAsFloats = meshData.getVertexListAsFloat();
272
273 if (BSParam.ShouldRemoveZeroWidthTriangles)
274 {
275 // Remove degenerate triangles. These are triangles with two of the vertices
276 // are the same. This is complicated by the problem that vertices are not
277 // made unique in sculpties so we have to compare the values in the vertex.
278 realIndicesIndex = 0;
279 for (int tri = 0; tri < indices.Length; tri += 3)
280 {
281 // Compute displacements into vertex array for each vertex of the triangle
282 int v1 = indices[tri + 0] * 3;
283 int v2 = indices[tri + 1] * 3;
284 int v3 = indices[tri + 2] * 3;
285 // Check to see if any two of the vertices are the same
286 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
287 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
288 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
289 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
290 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
291 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
292 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
293 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
294 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
295 )
296 {
297 // None of the vertices of the triangles are the same. This is a good triangle;
298 indices[realIndicesIndex + 0] = indices[tri + 0];
299 indices[realIndicesIndex + 1] = indices[tri + 1];
300 indices[realIndicesIndex + 2] = indices[tri + 2];
301 realIndicesIndex += 3;
302 }
303 }
304 }
305 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
306 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
307
308 if (realIndicesIndex != 0)
309 {
310 newShape = physicsScene.PE.CreateMeshShape(physicsScene.World,
311 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
312 }
313 else
314 {
315 physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
316 LogHeader, prim.PhysObjectName, prim.RawPosition, physicsScene.Name);
317 }
318 }
319 newShape.shapeKey = newMeshKey;
320
321 return newShape;
322 }
192} 323}
193 324
325// ============================================================================================================
194public class BSShapeHull : BSShape 326public class BSShapeHull : BSShape
195{ 327{
196 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 328 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
197 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 329 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
198 330
199 public BSShapeHull() : base() 331 public BSShapeHull(BulletShape pShape) : base(pShape)
332 {
333 }
334 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
335 {
336 return new BSShapeNull();
337 }
338 public override void Dereference(BSScene physicsScene)
200 { 339 {
201 } 340 }
202 public static BSShape GetReference() { return new BSShapeNull(); }
203 public override void Dereference(BSScene physicsScene) { }
204} 341}
205 342
343// ============================================================================================================
206public class BSShapeCompound : BSShape 344public class BSShapeCompound : BSShape
207{ 345{
208 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 346 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
@@ -216,6 +354,7 @@ public class BSShapeCompound : BSShape
216 public override void Dereference(BSScene physicsScene) { } 354 public override void Dereference(BSScene physicsScene) { }
217} 355}
218 356
357// ============================================================================================================
219public class BSShapeAvatar : BSShape 358public class BSShapeAvatar : BSShape
220{ 359{
221 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]"; 360 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index a0131c7..1284ae7 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?
42 42
43VEHICLES TODO LIST: 43VEHICLES TODO LIST:
44================================================= 44=================================================
45UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
46 https://github.com/UbitUmarov/Ubit-opensim
45Border crossing with linked vehicle causes crash 47Border crossing with linked vehicle causes crash
46 20121129.1411: editting/moving phys object across region boundries causes crash 48 20121129.1411: editting/moving phys object across region boundries causes crash
47 getPos-> btRigidBody::upcast -> getBodyType -> BOOM 49 getPos-> btRigidBody::upcast -> getBodyType -> BOOM
@@ -167,6 +169,7 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint)
167 169
168MORE 170MORE
169====================================================== 171======================================================
172Compute avatar size and scale correctly. Now it is a bit off from the capsule size.
170Create tests for different interface components 173Create tests for different interface components
171 Have test objects/scripts measure themselves and turn color if correct/bad 174 Have test objects/scripts measure themselves and turn color if correct/bad
172 Test functions in SL and calibrate correctness there 175 Test functions in SL and calibrate correctness there