diff options
author | Melanie | 2013-04-25 00:22:28 +0100 |
---|---|---|
committer | Melanie | 2013-04-25 00:22:28 +0100 |
commit | d36a52ea55ce85110353e7a7e0b3eeb0b2a3eb4a (patch) | |
tree | dc0becfcbb3e7edcea6cd4d679749394d4564254 /OpenSim/Region | |
parent | Merge branch 'master' into careminster (diff) | |
parent | BulletSim: version of libBulletSim.so for 32 bit systems that doesn't (diff) | |
download | opensim-SC-d36a52ea55ce85110353e7a7e0b3eeb0b2a3eb4a.zip opensim-SC-d36a52ea55ce85110353e7a7e0b3eeb0b2a3eb4a.tar.gz opensim-SC-d36a52ea55ce85110353e7a7e0b3eeb0b2a3eb4a.tar.bz2 opensim-SC-d36a52ea55ce85110353e7a7e0b3eeb0b2a3eb4a.tar.xz |
Merge branch 'master' into careminster
Diffstat (limited to 'OpenSim/Region')
12 files changed, 365 insertions, 85 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 77e8b00..7b823ba 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 | |||
200 | // search the local cache | 200 | // search the local cache |
201 | foreach (UserData data in m_UserCache.Values) | 201 | foreach (UserData data in m_UserCache.Values) |
202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && | 202 | if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && |
203 | (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query))) | 203 | (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) |
204 | users.Add(data); | 204 | users.Add(data); |
205 | 205 | ||
206 | AddAdditionalUsers(avatarID, query, users); | 206 | AddAdditionalUsers(avatarID, query, users); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index 018357a..c48e585 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 | |||
375 | scene.GetRootAgentCount(), scene.RegionInfo.RegionName, | 375 | scene.GetRootAgentCount(), scene.RegionInfo.RegionName, |
376 | scene.RegionInfo.RegionID, | 376 | scene.RegionInfo.RegionID, |
377 | DateTime.UtcNow.ToString("s"))); | 377 | DateTime.UtcNow.ToString("s"))); |
378 | |||
378 | scene.ForEachRootScenePresence(delegate(ScenePresence sp) | 379 | scene.ForEachRootScenePresence(delegate(ScenePresence sp) |
379 | { | 380 | { |
380 | list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID)); | 381 | list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID)); |
381 | list.Append("</avatars>"); | ||
382 | }); | 382 | }); |
383 | |||
384 | list.Append("</avatars>"); | ||
383 | string payload = list.ToString(); | 385 | string payload = list.ToString(); |
384 | 386 | ||
385 | // post via REST to broker | 387 | // post via REST to broker |
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 | ||
271 | public 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 | |||
280 | public 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 | |||
271 | public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) | 290 | public 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, | |||
1414 | public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms); | 1433 | public 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] |
1436 | public static extern IntPtr BuildConvexHullShapeFromMesh2(IntPtr world, IntPtr meshShape); | ||
1437 | |||
1438 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1439 | public 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] | ||
1417 | public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); | 1444 | public 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 | ||
326 | public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms); | 327 | public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms); |
327 | 328 | ||
329 | public abstract BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape); | ||
330 | |||
331 | public abstract BulletShape CreateConvexHullShape(BulletWorld world, | ||
332 | int indicesCount, int[] indices, | ||
333 | int verticesCount, float[] vertices ); | ||
334 | |||
328 | public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); | 335 | public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); |
329 | 336 | ||
330 | public abstract bool IsNativeShape(BulletShape shape); | 337 | public 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 76860e4..57e74a3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -162,11 +162,8 @@ public sealed class BSShapeCollection : IDisposable | |||
162 | // If the caller needs to know the old body is going away, pass the event up. | 162 | // If the caller needs to know the old body is going away, pass the event up. |
163 | if (bodyCallback != null) bodyCallback(body); | 163 | if (bodyCallback != null) bodyCallback(body); |
164 | 164 | ||
165 | if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) | 165 | // Removing an object not in the world is a NOOP |
166 | { | 166 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); |
167 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); | ||
168 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); | ||
169 | } | ||
170 | 167 | ||
171 | // Zero any reference to the shape so it is not freed when the body is deleted. | 168 | // Zero any reference to the shape so it is not freed when the body is deleted. |
172 | PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); | 169 | PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); |
@@ -615,7 +612,7 @@ public sealed class BSShapeCollection : IDisposable | |||
615 | 612 | ||
616 | newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod); | 613 | newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod); |
617 | // Take evasive action if the mesh was not constructed. | 614 | // Take evasive action if the mesh was not constructed. |
618 | newShape = VerifyMeshCreated(newShape, prim); | 615 | newShape = VerifyMeshCreated(PhysicsScene, newShape, prim); |
619 | 616 | ||
620 | ReferenceShape(newShape); | 617 | ReferenceShape(newShape); |
621 | 618 | ||
@@ -724,7 +721,7 @@ public sealed class BSShapeCollection : IDisposable | |||
724 | 721 | ||
725 | newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod); | 722 | newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod); |
726 | // It might not have been created if we're waiting for an asset. | 723 | // It might not have been created if we're waiting for an asset. |
727 | newShape = VerifyMeshCreated(newShape, prim); | 724 | newShape = VerifyMeshCreated(PhysicsScene, newShape, prim); |
728 | 725 | ||
729 | ReferenceShape(newShape); | 726 | ReferenceShape(newShape); |
730 | 727 | ||
@@ -928,7 +925,7 @@ public sealed class BSShapeCollection : IDisposable | |||
928 | 925 | ||
929 | // Create a hash of all the shape parameters to be used as a key | 926 | // Create a hash of all the shape parameters to be used as a key |
930 | // for this particular shape. | 927 | // for this particular shape. |
931 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | 928 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) |
932 | { | 929 | { |
933 | // level of detail based on size and type of the object | 930 | // level of detail based on size and type of the object |
934 | float lod = BSParam.MeshLOD; | 931 | float lod = BSParam.MeshLOD; |
@@ -949,7 +946,7 @@ public sealed class BSShapeCollection : IDisposable | |||
949 | return pbs.GetMeshKey(size, lod); | 946 | return pbs.GetMeshKey(size, lod); |
950 | } | 947 | } |
951 | // For those who don't want the LOD | 948 | // For those who don't want the LOD |
952 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) | 949 | public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) |
953 | { | 950 | { |
954 | float lod; | 951 | float lod; |
955 | return ComputeShapeKey(size, pbs, out lod); | 952 | return ComputeShapeKey(size, pbs, out lod); |
@@ -962,7 +959,7 @@ public sealed class BSShapeCollection : IDisposable | |||
962 | // us to not loop forever. | 959 | // us to not loop forever. |
963 | // Called after creating a physical mesh or hull. If the physical shape was created, | 960 | // Called after creating a physical mesh or hull. If the physical shape was created, |
964 | // just return. | 961 | // just return. |
965 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) | 962 | public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim) |
966 | { | 963 | { |
967 | // If the shape was successfully created, nothing more to do | 964 | // If the shape was successfully created, nothing more to do |
968 | if (newShape.HasPhysicalShape) | 965 | if (newShape.HasPhysicalShape) |
@@ -974,7 +971,7 @@ public sealed class BSShapeCollection : IDisposable | |||
974 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | 971 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) |
975 | { | 972 | { |
976 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | 973 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; |
977 | PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", | 974 | physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", |
978 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | 975 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); |
979 | } | 976 | } |
980 | else | 977 | else |
@@ -986,14 +983,14 @@ public sealed class BSShapeCollection : IDisposable | |||
986 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero | 983 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero |
987 | ) | 984 | ) |
988 | { | 985 | { |
989 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); | 986 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); |
990 | // Multiple requestors will know we're waiting for this asset | 987 | // Multiple requestors will know we're waiting for this asset |
991 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; | 988 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; |
992 | 989 | ||
993 | BSPhysObject xprim = prim; | 990 | BSPhysObject xprim = prim; |
994 | Util.FireAndForget(delegate | 991 | Util.FireAndForget(delegate |
995 | { | 992 | { |
996 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; | 993 | RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod; |
997 | if (assetProvider != null) | 994 | if (assetProvider != null) |
998 | { | 995 | { |
999 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | 996 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. |
@@ -1021,7 +1018,7 @@ public sealed class BSShapeCollection : IDisposable | |||
1021 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; | 1018 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; |
1022 | else | 1019 | else |
1023 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | 1020 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; |
1024 | DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", | 1021 | physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", |
1025 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); | 1022 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); |
1026 | 1023 | ||
1027 | }); | 1024 | }); |
@@ -1029,8 +1026,8 @@ public sealed class BSShapeCollection : IDisposable | |||
1029 | else | 1026 | else |
1030 | { | 1027 | { |
1031 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | 1028 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; |
1032 | PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", | 1029 | physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", |
1033 | LogHeader, PhysicsScene.Name); | 1030 | LogHeader, physicsScene.Name); |
1034 | } | 1031 | } |
1035 | }); | 1032 | }); |
1036 | } | 1033 | } |
@@ -1038,15 +1035,15 @@ public sealed class BSShapeCollection : IDisposable | |||
1038 | { | 1035 | { |
1039 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) | 1036 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) |
1040 | { | 1037 | { |
1041 | PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", | 1038 | physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", |
1042 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | 1039 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); |
1043 | } | 1040 | } |
1044 | } | 1041 | } |
1045 | } | 1042 | } |
1046 | 1043 | ||
1047 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. | 1044 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. |
1048 | BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | 1045 | BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); |
1049 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); | 1046 | physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); |
1050 | 1047 | ||
1051 | return fillinShape; | 1048 | return fillinShape; |
1052 | } | 1049 | } |
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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Text; | 30 | using System.Text; |
31 | 31 | ||
32 | using OpenSim.Framework; | ||
33 | using OpenSim.Region.Physics.Manager; | ||
34 | |||
32 | using OMV = OpenMetaverse; | 35 | using OMV = OpenMetaverse; |
33 | 36 | ||
34 | namespace OpenSim.Region.Physics.BulletSPlugin | 37 | namespace 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 | // ============================================================================================================ | ||
115 | public class BSShapeNull : BSShape | 136 | public 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 | // ============================================================================================================ | ||
124 | public class BSShapeNative : BSShape | 146 | public 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 | // ============================================================================================================ | ||
182 | public class BSShapeMesh : BSShape | 209 | public 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 | // ============================================================================================================ | ||
194 | public class BSShapeHull : BSShape | 326 | public 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 | // ============================================================================================================ | ||
206 | public class BSShapeCompound : BSShape | 344 | public 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 | // ============================================================================================================ | ||
219 | public class BSShapeAvatar : BSShape | 358 | public 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 | ||
43 | VEHICLES TODO LIST: | 43 | VEHICLES TODO LIST: |
44 | ================================================= | 44 | ================================================= |
45 | UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims: | ||
46 | https://github.com/UbitUmarov/Ubit-opensim | ||
45 | Border crossing with linked vehicle causes crash | 47 | Border 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 | ||
168 | MORE | 170 | MORE |
169 | ====================================================== | 171 | ====================================================== |
172 | Compute avatar size and scale correctly. Now it is a bit off from the capsule size. | ||
170 | Create tests for different interface components | 173 | Create 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 |