diff options
author | Melanie | 2013-02-13 01:54:06 +0000 |
---|---|---|
committer | Melanie | 2013-02-13 01:54:06 +0000 |
commit | d0c5e0990bbfe3104afa78c8c6dbe500a451396d (patch) | |
tree | 082e368b1d2b5c7cb7cef27e50523c1406aa3e3e /OpenSim | |
parent | Merge branch 'master' into careminster (diff) | |
parent | Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim (diff) | |
download | opensim-SC-d0c5e0990bbfe3104afa78c8c6dbe500a451396d.zip opensim-SC-d0c5e0990bbfe3104afa78c8c6dbe500a451396d.tar.gz opensim-SC-d0c5e0990bbfe3104afa78c8c6dbe500a451396d.tar.bz2 opensim-SC-d0c5e0990bbfe3104afa78c8c6dbe500a451396d.tar.xz |
Merge branch 'master' into careminster
Diffstat (limited to 'OpenSim')
10 files changed, 522 insertions, 156 deletions
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs index eb4bc22..f25f290 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs | |||
@@ -135,6 +135,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
135 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | 135 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); |
136 | Assert.That(value, Is.EqualTo("42.15")); | 136 | Assert.That(value, Is.EqualTo("42.15")); |
137 | } | 137 | } |
138 | |||
139 | // Test with an array as the root node | ||
140 | { | ||
141 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]"); | ||
142 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
143 | |||
144 | string value = (string)InvokeOp("JsonGetValue", storeId, "[1]"); | ||
145 | Assert.That(value, Is.EqualTo("two")); | ||
146 | } | ||
138 | } | 147 | } |
139 | 148 | ||
140 | [Test] | 149 | [Test] |
@@ -260,25 +269,69 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
260 | TestHelpers.InMethod(); | 269 | TestHelpers.InMethod(); |
261 | // TestHelpers.EnableLogging(); | 270 | // TestHelpers.EnableLogging(); |
262 | 271 | ||
263 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | 272 | // Test remove of node in object pointing to a string |
273 | { | ||
274 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
275 | |||
276 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
277 | Assert.That(returnValue, Is.EqualTo(1)); | ||
278 | |||
279 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | ||
280 | Assert.That(result, Is.EqualTo(0)); | ||
281 | |||
282 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
283 | Assert.That(returnValue2, Is.EqualTo("")); | ||
284 | } | ||
285 | |||
286 | // Test remove of node in object pointing to another object | ||
287 | { | ||
288 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }"); | ||
289 | |||
290 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
291 | Assert.That(returnValue, Is.EqualTo(1)); | ||
264 | 292 | ||
265 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | 293 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); |
266 | Assert.That(returnValue, Is.EqualTo(1)); | 294 | Assert.That(result, Is.EqualTo(0)); |
295 | |||
296 | string returnValue2 = (string)InvokeOp("JsonGetValueJson", storeId, "Hello"); | ||
297 | Assert.That(returnValue2, Is.EqualTo("")); | ||
298 | } | ||
267 | 299 | ||
268 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | 300 | // Test remove of node in an array |
269 | Assert.That(result, Is.EqualTo(0)); | 301 | { |
302 | UUID storeId | ||
303 | = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }"); | ||
304 | |||
305 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); | ||
306 | Assert.That(returnValue, Is.EqualTo(1)); | ||
270 | 307 | ||
271 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | 308 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]"); |
272 | Assert.That(returnValue2, Is.EqualTo("")); | 309 | Assert.That(result, Is.EqualTo(1)); |
310 | |||
311 | result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]"); | ||
312 | Assert.That(result, Is.EqualTo(0)); | ||
313 | |||
314 | string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); | ||
315 | Assert.That(stringReturnValue, Is.EqualTo("value2")); | ||
316 | |||
317 | stringReturnValue = (string)InvokeOp("JsonGetValueJson", storeId, "Hello[1]"); | ||
318 | Assert.That(stringReturnValue, Is.EqualTo("")); | ||
319 | } | ||
273 | 320 | ||
274 | // Test remove of non-existing value | 321 | // Test remove of non-existing value |
275 | int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Hello"); | 322 | { |
276 | Assert.That(fakeValueRemove, Is.EqualTo(0)); | 323 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); |
277 | 324 | ||
278 | // Test get from non-existing store | 325 | int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese"); |
279 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 326 | Assert.That(fakeValueRemove, Is.EqualTo(0)); |
280 | int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); | 327 | } |
281 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | 328 | |
329 | { | ||
330 | // Test get from non-existing store | ||
331 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
332 | int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); | ||
333 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
334 | } | ||
282 | } | 335 | } |
283 | 336 | ||
284 | [Test] | 337 | [Test] |
@@ -352,7 +405,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
352 | // TestHelpers.EnableLogging(); | 405 | // TestHelpers.EnableLogging(); |
353 | 406 | ||
354 | { | 407 | { |
355 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 408 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); |
356 | 409 | ||
357 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); | 410 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); |
358 | Assert.That(result, Is.EqualTo(1)); | 411 | Assert.That(result, Is.EqualTo(1)); |
@@ -361,9 +414,159 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
361 | Assert.That(value, Is.EqualTo("Times")); | 414 | Assert.That(value, Is.EqualTo("Times")); |
362 | } | 415 | } |
363 | 416 | ||
417 | // Commented out as this currently unexpectedly fails. | ||
418 | // Test setting a key containing periods with delineation | ||
419 | // { | ||
420 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
421 | // | ||
422 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times"); | ||
423 | // Assert.That(result, Is.EqualTo(1)); | ||
424 | // | ||
425 | // string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}"); | ||
426 | // Assert.That(value, Is.EqualTo("Times")); | ||
427 | // } | ||
428 | |||
429 | // *** Test [] *** | ||
430 | |||
431 | // Test setting a key containing unbalanced ] without delineation. Expecting failure | ||
432 | { | ||
433 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
434 | |||
435 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times"); | ||
436 | Assert.That(result, Is.EqualTo(0)); | ||
437 | |||
438 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus"); | ||
439 | Assert.That(value, Is.EqualTo("")); | ||
440 | } | ||
441 | |||
442 | // Test setting a key containing unbalanced [ without delineation. Expecting failure | ||
443 | { | ||
444 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
445 | |||
446 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times"); | ||
447 | Assert.That(result, Is.EqualTo(0)); | ||
448 | |||
449 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus"); | ||
450 | Assert.That(value, Is.EqualTo("")); | ||
451 | } | ||
452 | |||
453 | // Test setting a key containing unbalanced [] without delineation. Expecting failure | ||
454 | { | ||
455 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
456 | |||
457 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times"); | ||
458 | Assert.That(result, Is.EqualTo(0)); | ||
459 | |||
460 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus"); | ||
461 | Assert.That(value, Is.EqualTo("")); | ||
462 | } | ||
463 | |||
464 | // Test setting a key containing unbalanced ] with delineation | ||
465 | { | ||
466 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
467 | |||
468 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times"); | ||
469 | Assert.That(result, Is.EqualTo(1)); | ||
470 | |||
471 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}"); | ||
472 | Assert.That(value, Is.EqualTo("Times")); | ||
473 | } | ||
474 | |||
475 | // Test setting a key containing unbalanced [ with delineation | ||
476 | { | ||
477 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
478 | |||
479 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times"); | ||
480 | Assert.That(result, Is.EqualTo(1)); | ||
481 | |||
482 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}"); | ||
483 | Assert.That(value, Is.EqualTo("Times")); | ||
484 | } | ||
485 | |||
486 | // Test setting a key containing empty balanced [] with delineation | ||
487 | { | ||
488 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
489 | |||
490 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times"); | ||
491 | Assert.That(result, Is.EqualTo(1)); | ||
492 | |||
493 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}"); | ||
494 | Assert.That(value, Is.EqualTo("Times")); | ||
495 | } | ||
496 | |||
497 | // Commented out as this currently unexpectedly fails. | ||
498 | // // Test setting a key containing brackets around an integer with delineation | ||
499 | // { | ||
500 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
501 | // | ||
502 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times"); | ||
503 | // Assert.That(result, Is.EqualTo(1)); | ||
504 | // | ||
505 | // string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}"); | ||
506 | // Assert.That(value, Is.EqualTo("Times")); | ||
507 | // } | ||
508 | |||
509 | // *** Test {} *** | ||
510 | |||
511 | // Test setting a key containing unbalanced } without delineation. Expecting failure (?) | ||
512 | { | ||
513 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
514 | |||
515 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times"); | ||
516 | Assert.That(result, Is.EqualTo(0)); | ||
517 | |||
518 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
519 | Assert.That(value, Is.EqualTo("")); | ||
520 | } | ||
521 | |||
522 | // Test setting a key containing unbalanced { without delineation. Expecting failure (?) | ||
523 | { | ||
524 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
525 | |||
526 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times"); | ||
527 | Assert.That(result, Is.EqualTo(0)); | ||
528 | |||
529 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
530 | Assert.That(value, Is.EqualTo("")); | ||
531 | } | ||
532 | |||
533 | // Commented out as this currently unexpectedly fails. | ||
534 | // // Test setting a key containing unbalanced } | ||
535 | // { | ||
536 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
537 | // | ||
538 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times"); | ||
539 | // Assert.That(result, Is.EqualTo(1)); | ||
540 | // | ||
541 | // string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun}Circus}"); | ||
542 | // Assert.That(value, Is.EqualTo("Times")); | ||
543 | // } | ||
544 | |||
545 | // Test setting a key containing unbalanced { with delineation | ||
546 | { | ||
547 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
548 | |||
549 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times"); | ||
550 | Assert.That(result, Is.EqualTo(1)); | ||
551 | |||
552 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}"); | ||
553 | Assert.That(value, Is.EqualTo("Times")); | ||
554 | } | ||
555 | |||
556 | // Test setting a key containing balanced {} with delineation. This should fail. | ||
557 | { | ||
558 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
559 | |||
560 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times"); | ||
561 | Assert.That(result, Is.EqualTo(0)); | ||
562 | |||
563 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}"); | ||
564 | Assert.That(value, Is.EqualTo("")); | ||
565 | } | ||
566 | |||
364 | // Test setting to location that does not exist. This should fail. | 567 | // Test setting to location that does not exist. This should fail. |
365 | { | 568 | { |
366 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 569 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); |
367 | 570 | ||
368 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); | 571 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); |
369 | Assert.That(result, Is.EqualTo(0)); | 572 | Assert.That(result, Is.EqualTo(0)); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs index 7ab86d2..3f83ef0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs | |||
@@ -225,9 +225,10 @@ public enum CollisionFlags : uint | |||
225 | CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, | 225 | CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, |
226 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, | 226 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, |
227 | // Following used by BulletSim to control collisions and updates | 227 | // Following used by BulletSim to control collisions and updates |
228 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, | 228 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, // return collision events from unmanaged to managed |
229 | BS_FLOATS_ON_WATER = 1 << 11, | 229 | BS_FLOATS_ON_WATER = 1 << 11, // the object should float at water level |
230 | BS_VEHICLE_COLLISIONS = 1 << 12, | 230 | BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking |
231 | BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape | ||
231 | BS_NONE = 0, | 232 | BS_NONE = 0, |
232 | BS_ALL = 0xFFFFFFFF | 233 | BS_ALL = 0xFFFFFFFF |
233 | }; | 234 | }; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f781aea..8dca7c6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -83,7 +83,7 @@ public sealed class BSCharacter : BSPhysObject | |||
83 | _velocity = OMV.Vector3.Zero; | 83 | _velocity = OMV.Vector3.Zero; |
84 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 84 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
85 | Friction = BSParam.AvatarStandingFriction; | 85 | Friction = BSParam.AvatarStandingFriction; |
86 | Density = BSParam.AvatarDensity; | 86 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; |
87 | 87 | ||
88 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | 88 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, |
89 | // replace with the default values. | 89 | // replace with the default values. |
@@ -231,6 +231,15 @@ public sealed class BSCharacter : BSPhysObject | |||
231 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 231 | PhysicsScene.PE.SetFriction(PhysBody, Friction); |
232 | } | 232 | } |
233 | } | 233 | } |
234 | else | ||
235 | { | ||
236 | if (Flying) | ||
237 | { | ||
238 | // Flying and not collising and velocity nearly zero. | ||
239 | ZeroMotion(true /* inTaintTime */); | ||
240 | } | ||
241 | } | ||
242 | |||
234 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); | 243 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); |
235 | } | 244 | } |
236 | else | 245 | else |
@@ -274,7 +283,7 @@ public sealed class BSCharacter : BSPhysObject | |||
274 | // This test is done if moving forward, not flying and is colliding with something. | 283 | // This test is done if moving forward, not flying and is colliding with something. |
275 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | 284 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", |
276 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | 285 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); |
277 | if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */) | 286 | if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) |
278 | { | 287 | { |
279 | // The range near the character's feet where we will consider stairs | 288 | // The range near the character's feet where we will consider stairs |
280 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; | 289 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; |
@@ -869,7 +878,7 @@ public sealed class BSCharacter : BSPhysObject | |||
869 | * Math.Min(Size.X, Size.Y) / 2 | 878 | * Math.Min(Size.X, Size.Y) / 2 |
870 | * Size.Y / 2f // plus the volume of the capsule end caps | 879 | * Size.Y / 2f // plus the volume of the capsule end caps |
871 | ); | 880 | ); |
872 | _mass = Density * _avatarVolume; | 881 | _mass = Density * BSParam.DensityScaleFactor * _avatarVolume; |
873 | } | 882 | } |
874 | 883 | ||
875 | // The physics engine says that properties have updated. Update same and inform | 884 | // The physics engine says that properties have updated. Update same and inform |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index e35311f..4ece1eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -127,6 +127,8 @@ public abstract class BSLinkset | |||
127 | m_children = new HashSet<BSPrimLinkable>(); | 127 | m_children = new HashSet<BSPrimLinkable>(); |
128 | LinksetMass = parent.RawMass; | 128 | LinksetMass = parent.RawMass; |
129 | Rebuilding = false; | 129 | Rebuilding = false; |
130 | |||
131 | parent.ClearDisplacement(); | ||
130 | } | 132 | } |
131 | 133 | ||
132 | // Link to a linkset where the child knows the parent. | 134 | // Link to a linkset where the child knows the parent. |
@@ -280,6 +282,7 @@ public abstract class BSLinkset | |||
280 | return mass; | 282 | return mass; |
281 | } | 283 | } |
282 | 284 | ||
285 | // Computes linkset's center of mass in world coordinates. | ||
283 | protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() | 286 | protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() |
284 | { | 287 | { |
285 | OMV.Vector3 com; | 288 | OMV.Vector3 com; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 36bae9b..4ce58c7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -93,7 +93,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
93 | { | 93 | { |
94 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; | 94 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; |
95 | 95 | ||
96 | public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent) | 96 | public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) |
97 | : base(scene, parent) | ||
97 | { | 98 | { |
98 | } | 99 | } |
99 | 100 | ||
@@ -217,59 +218,45 @@ public sealed class BSLinksetCompound : BSLinkset | |||
217 | // and that is caused by us updating the object. | 218 | // and that is caused by us updating the object. |
218 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) | 219 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) |
219 | { | 220 | { |
220 | // Gather the child info. It might not be there if the linkset is in transition. | ||
221 | BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo; | ||
222 | if (lsi != null) | ||
223 | { | ||
224 | // Since the child moved or rotationed, it needs a new relative position within the linkset | ||
225 | BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, OMV.Vector3.Zero); | ||
226 | updated.LinksetInfo = newLsi; | ||
227 | |||
228 | // Find the physical instance of the child | 221 | // Find the physical instance of the child |
229 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) | 222 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) |
223 | { | ||
224 | // It is possible that the linkset is still under construction and the child is not yet | ||
225 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will | ||
226 | // build the whole thing with the new position or rotation. | ||
227 | // The index must be checked because Bullet references the child array but does no validity | ||
228 | // checking of the child index passed. | ||
229 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); | ||
230 | if (updated.LinksetChildIndex < numLinksetChildren) | ||
230 | { | 231 | { |
231 | // It is possible that the linkset is still under construction and the child is not yet | 232 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); |
232 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will | 233 | if (linksetChildShape.HasPhysicalShape) |
233 | // build the whole thing with the new position or rotation. | ||
234 | // The index must be checked because Bullet references the child array but does no validity | ||
235 | // checking of the child index passed. | ||
236 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); | ||
237 | if (lsi.Index < numLinksetChildren) | ||
238 | { | 234 | { |
239 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); | 235 | // Found the child shape within the compound shape |
240 | if (linksetChildShape.HasPhysicalShape) | 236 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, |
241 | { | 237 | updated.RawPosition - LinksetRoot.RawPosition, |
242 | // Found the child shape within the compound shape | 238 | updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), |
243 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, | 239 | true /* shouldRecalculateLocalAabb */); |
244 | newLsi.OffsetFromCenterOfMass, | 240 | updatedChild = true; |
245 | newLsi.OffsetRot, | 241 | DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}", |
246 | true /* shouldRecalculateLocalAabb */); | 242 | updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation); |
247 | updatedChild = true; | ||
248 | DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", | ||
249 | updated.LocalID, whichUpdated, newLsi); | ||
250 | } | ||
251 | else // DEBUG DEBUG | ||
252 | { // DEBUG DEBUG | ||
253 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", | ||
254 | updated.LocalID, linksetChildShape); | ||
255 | } // DEBUG DEBUG | ||
256 | } | 243 | } |
257 | else // DEBUG DEBUG | 244 | else // DEBUG DEBUG |
258 | { // DEBUG DEBUG | 245 | { // DEBUG DEBUG |
259 | // the child is not yet in the compound shape. This is non-fatal. | 246 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", |
260 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}", | 247 | updated.LocalID, linksetChildShape); |
261 | updated.LocalID, numLinksetChildren, lsi.Index); | ||
262 | } // DEBUG DEBUG | 248 | } // DEBUG DEBUG |
263 | } | 249 | } |
264 | else // DEBUG DEBUG | 250 | else // DEBUG DEBUG |
265 | { // DEBUG DEBUG | 251 | { // DEBUG DEBUG |
266 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); | 252 | // the child is not yet in the compound shape. This is non-fatal. |
253 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}", | ||
254 | updated.LocalID, numLinksetChildren, updated.LinksetChildIndex); | ||
267 | } // DEBUG DEBUG | 255 | } // DEBUG DEBUG |
268 | } | 256 | } |
269 | else // DEBUG DEBUG | 257 | else // DEBUG DEBUG |
270 | { // DEBUG DEBUG | 258 | { // DEBUG DEBUG |
271 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}", | 259 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); |
272 | updated.LocalID, LinksetRoot.PhysShape); | ||
273 | } // DEBUG DEBUG | 260 | } // DEBUG DEBUG |
274 | 261 | ||
275 | if (!updatedChild) | 262 | if (!updatedChild) |
@@ -379,6 +366,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
379 | // Safe to call even if the child is not really in the linkset. | 366 | // Safe to call even if the child is not really in the linkset. |
380 | protected override void RemoveChildFromLinkset(BSPrimLinkable child) | 367 | protected override void RemoveChildFromLinkset(BSPrimLinkable child) |
381 | { | 368 | { |
369 | child.ClearDisplacement(); | ||
370 | |||
382 | if (m_children.Remove(child)) | 371 | if (m_children.Remove(child)) |
383 | { | 372 | { |
384 | DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 373 | DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
@@ -424,30 +413,31 @@ public sealed class BSLinksetCompound : BSLinkset | |||
424 | // The center of mass for the linkset is the geometric center of the group. | 413 | // The center of mass for the linkset is the geometric center of the group. |
425 | // Compute a displacement for each component so it is relative to the center-of-mass. | 414 | // Compute a displacement for each component so it is relative to the center-of-mass. |
426 | // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass | 415 | // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass |
427 | OMV.Vector3 centerOfMass; | 416 | OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition; |
428 | OMV.Vector3 centerDisplacement = OMV.Vector3.Zero; | 417 | if (!disableCOM) // DEBUG DEBUG |
429 | if (disableCOM) // DEBUG DEBUG | ||
430 | { // DEBUG DEBUG | ||
431 | centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG | ||
432 | // LinksetRoot.PositionDisplacement = OMV.Vector3.Zero; | ||
433 | } // DEBUG DEBUG | ||
434 | else | ||
435 | { | 418 | { |
436 | centerOfMass = ComputeLinksetCenterOfMass(); | 419 | // Compute a center-of-mass in world coordinates. |
437 | // 'centerDisplacement' is the value to *add* to all the shape offsets | 420 | centerOfMassW = ComputeLinksetCenterOfMass(); |
438 | centerDisplacement = LinksetRoot.RawPosition - centerOfMass; | ||
439 | |||
440 | // Since we're displacing the center of the shape, we need to move the body in the world | ||
441 | // LinksetRoot.PositionDisplacement = centerDisplacement; | ||
442 | |||
443 | // This causes the root prim position to be set properly based on the new PositionDisplacement | ||
444 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; | ||
445 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM | ||
446 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false); | ||
447 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", | ||
448 | LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement); | ||
449 | } | 421 | } |
450 | 422 | ||
423 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); | ||
424 | |||
425 | // 'centerDisplacement' is the value to subtract from children to give physical offset position | ||
426 | OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; | ||
427 | LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement); | ||
428 | |||
429 | // This causes the physical position of the root prim to be offset to accomodate for the displacements | ||
430 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; | ||
431 | |||
432 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM | ||
433 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, | ||
434 | -centerDisplacement, | ||
435 | OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, | ||
436 | false /* shouldRecalculateLocalAabb (is done later after linkset built) */); | ||
437 | |||
438 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", | ||
439 | LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); | ||
440 | |||
451 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", | 441 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", |
452 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); | 442 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); |
453 | 443 | ||
@@ -455,38 +445,33 @@ public sealed class BSLinksetCompound : BSLinkset | |||
455 | int memberIndex = 1; | 445 | int memberIndex = 1; |
456 | ForEachMember(delegate(BSPrimLinkable cPrim) | 446 | ForEachMember(delegate(BSPrimLinkable cPrim) |
457 | { | 447 | { |
458 | if (!IsRoot(cPrim)) | 448 | if (IsRoot(cPrim)) |
459 | { | 449 | { |
460 | // Compute the displacement of the child from the root of the linkset. | 450 | cPrim.LinksetChildIndex = 0; |
461 | // This info is saved in the child prim so the relationship does not | 451 | } |
462 | // change over time and the new child position can be computed | 452 | else |
463 | // when the linkset is being disassembled (the linkset may have moved). | 453 | { |
464 | BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; | 454 | cPrim.LinksetChildIndex = memberIndex; |
465 | if (lci == null) | ||
466 | { | ||
467 | lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement); | ||
468 | cPrim.LinksetInfo = lci; | ||
469 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); | ||
470 | } | ||
471 | |||
472 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}", | ||
473 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci); | ||
474 | 455 | ||
475 | if (cPrim.PhysShape.isNativeShape) | 456 | if (cPrim.PhysShape.isNativeShape) |
476 | { | 457 | { |
477 | // A native shape is turned into a hull collision shape because native | 458 | // A native shape is turned into a hull collision shape because native |
478 | // shapes are not shared so we have to hullify it so it will be tracked | 459 | // shapes are not shared so we have to hullify it so it will be tracked |
479 | // and freed at the correct time. This also solves the scaling problem | 460 | // and freed at the correct time. This also solves the scaling problem |
480 | // (native shapes scaled but hull/meshes are assumed to not be). | 461 | // (native shapes scale but hull/meshes are assumed to not be). |
481 | // TODO: decide of the native shape can just be used in the compound shape. | 462 | // TODO: decide of the native shape can just be used in the compound shape. |
482 | // Use call to CreateGeomNonSpecial(). | 463 | // Use call to CreateGeomNonSpecial(). |
483 | BulletShape saveShape = cPrim.PhysShape; | 464 | BulletShape saveShape = cPrim.PhysShape; |
484 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape | 465 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape |
485 | // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); | ||
486 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | 466 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); |
487 | BulletShape newShape = cPrim.PhysShape; | 467 | BulletShape newShape = cPrim.PhysShape; |
488 | cPrim.PhysShape = saveShape; | 468 | cPrim.PhysShape = saveShape; |
489 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); | 469 | |
470 | OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; | ||
471 | OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; | ||
472 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot); | ||
473 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}", | ||
474 | LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot); | ||
490 | } | 475 | } |
491 | else | 476 | else |
492 | { | 477 | { |
@@ -498,9 +483,13 @@ public sealed class BSLinksetCompound : BSLinkset | |||
498 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | 483 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", |
499 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | 484 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); |
500 | } | 485 | } |
501 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); | 486 | OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; |
487 | OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; | ||
488 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); | ||
489 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}", | ||
490 | LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); | ||
491 | |||
502 | } | 492 | } |
503 | lci.Index = memberIndex; | ||
504 | memberIndex++; | 493 | memberIndex++; |
505 | } | 494 | } |
506 | return false; // 'false' says to move onto the next child in the list | 495 | return false; // 'false' says to move onto the next child in the list |
@@ -509,12 +498,16 @@ public sealed class BSLinksetCompound : BSLinkset | |||
509 | // With all of the linkset packed into the root prim, it has the mass of everyone. | 498 | // With all of the linkset packed into the root prim, it has the mass of everyone. |
510 | LinksetMass = ComputeLinksetMass(); | 499 | LinksetMass = ComputeLinksetMass(); |
511 | LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); | 500 | LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); |
501 | |||
502 | // Enable the physical position updator to return the position and rotation of the root shape | ||
503 | PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); | ||
512 | } | 504 | } |
513 | finally | 505 | finally |
514 | { | 506 | { |
515 | Rebuilding = false; | 507 | Rebuilding = false; |
516 | } | 508 | } |
517 | 509 | ||
510 | // See that the Aabb surrounds the new shape | ||
518 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); | 511 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); |
519 | } | 512 | } |
520 | } | 513 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 3e0b4bc..329169f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | |||
@@ -49,6 +49,7 @@ public static class BSParam | |||
49 | public static float MaxLinearVelocity { get; private set; } | 49 | public static float MaxLinearVelocity { get; private set; } |
50 | public static float MaxAngularVelocity { get; private set; } | 50 | public static float MaxAngularVelocity { get; private set; } |
51 | public static float MaxAddForceMagnitude { get; private set; } | 51 | public static float MaxAddForceMagnitude { get; private set; } |
52 | public static float DensityScaleFactor { get; private set; } | ||
52 | 53 | ||
53 | public static float LinearDamping { get; private set; } | 54 | public static float LinearDamping { get; private set; } |
54 | public static float AngularDamping { get; private set; } | 55 | public static float AngularDamping { get; private set; } |
@@ -281,29 +282,35 @@ public static class BSParam | |||
281 | new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", | 282 | new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", |
282 | 0.0001f, | 283 | 0.0001f, |
283 | (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, | 284 | (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, |
284 | (s) => { return (float)MinimumObjectMass; }, | 285 | (s) => { return MinimumObjectMass; }, |
285 | (s,p,l,v) => { MinimumObjectMass = v; } ), | 286 | (s,p,l,v) => { MinimumObjectMass = v; } ), |
286 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | 287 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", |
287 | 10000.01f, | 288 | 10000.01f, |
288 | (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, | 289 | (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, |
289 | (s) => { return (float)MaximumObjectMass; }, | 290 | (s) => { return MaximumObjectMass; }, |
290 | (s,p,l,v) => { MaximumObjectMass = v; } ), | 291 | (s,p,l,v) => { MaximumObjectMass = v; } ), |
291 | new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", | 292 | new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", |
292 | 1000.0f, | 293 | 1000.0f, |
293 | (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); }, | 294 | (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); }, |
294 | (s) => { return (float)MaxLinearVelocity; }, | 295 | (s) => { return MaxLinearVelocity; }, |
295 | (s,p,l,v) => { MaxLinearVelocity = v; } ), | 296 | (s,p,l,v) => { MaxLinearVelocity = v; } ), |
296 | new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", | 297 | new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", |
297 | 1000.0f, | 298 | 1000.0f, |
298 | (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); }, | 299 | (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); }, |
299 | (s) => { return (float)MaxAngularVelocity; }, | 300 | (s) => { return MaxAngularVelocity; }, |
300 | (s,p,l,v) => { MaxAngularVelocity = v; } ), | 301 | (s,p,l,v) => { MaxAngularVelocity = v; } ), |
301 | // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject | 302 | // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject |
302 | new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", | 303 | new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", |
303 | 20000.0f, | 304 | 20000.0f, |
304 | (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); }, | 305 | (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); }, |
305 | (s) => { return (float)MaxAddForceMagnitude; }, | 306 | (s) => { return MaxAddForceMagnitude; }, |
306 | (s,p,l,v) => { MaxAddForceMagnitude = v; } ), | 307 | (s,p,l,v) => { MaxAddForceMagnitude = v; } ), |
308 | // Density is passed around as 100kg/m3. This scales that to 1kg/m3. | ||
309 | new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", | ||
310 | 0.01f, | ||
311 | (s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); }, | ||
312 | (s) => { return DensityScaleFactor; }, | ||
313 | (s,p,l,v) => { DensityScaleFactor = v; } ), | ||
307 | 314 | ||
308 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | 315 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", |
309 | 2200f, | 316 | 2200f, |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index de69fa0..f953c1e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -99,6 +99,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
99 | CollisionAccumulation = 0; | 99 | CollisionAccumulation = 0; |
100 | ColliderIsMoving = false; | 100 | ColliderIsMoving = false; |
101 | CollisionScore = 0; | 101 | CollisionScore = 0; |
102 | |||
103 | // All axis free. | ||
104 | LockedAxis = LockedAxisFree; | ||
102 | } | 105 | } |
103 | 106 | ||
104 | // Tell the object to clean up. | 107 | // Tell the object to clean up. |
@@ -136,6 +139,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
136 | 139 | ||
137 | // The objects base shape information. Null if not a prim type shape. | 140 | // The objects base shape information. Null if not a prim type shape. |
138 | public PrimitiveBaseShape BaseShape { get; protected set; } | 141 | public PrimitiveBaseShape BaseShape { get; protected set; } |
142 | |||
139 | // Some types of objects have preferred physical representations. | 143 | // Some types of objects have preferred physical representations. |
140 | // Returns SHAPE_UNKNOWN if there is no preference. | 144 | // Returns SHAPE_UNKNOWN if there is no preference. |
141 | public virtual BSPhysicsShapeType PreferredPhysicalShape | 145 | public virtual BSPhysicsShapeType PreferredPhysicalShape |
@@ -150,15 +154,17 @@ public abstract class BSPhysObject : PhysicsActor | |||
150 | public EntityProperties LastEntityProperties { get; set; } | 154 | public EntityProperties LastEntityProperties { get; set; } |
151 | 155 | ||
152 | public virtual OMV.Vector3 Scale { get; set; } | 156 | public virtual OMV.Vector3 Scale { get; set; } |
153 | public abstract bool IsSolid { get; } | ||
154 | public abstract bool IsStatic { get; } | ||
155 | public abstract bool IsSelected { get; } | ||
156 | 157 | ||
157 | // It can be confusing for an actor to know if it should move or update an object | 158 | // It can be confusing for an actor to know if it should move or update an object |
158 | // depeneding on the setting of 'selected', 'physical, ... | 159 | // depeneding on the setting of 'selected', 'physical, ... |
159 | // This flag is the true test -- if true, the object is being acted on in the physical world | 160 | // This flag is the true test -- if true, the object is being acted on in the physical world |
160 | public abstract bool IsPhysicallyActive { get; } | 161 | public abstract bool IsPhysicallyActive { get; } |
161 | 162 | ||
163 | // Detailed state of the object. | ||
164 | public abstract bool IsSolid { get; } | ||
165 | public abstract bool IsStatic { get; } | ||
166 | public abstract bool IsSelected { get; } | ||
167 | |||
162 | // Materialness | 168 | // Materialness |
163 | public MaterialAttributes.Material Material { get; private set; } | 169 | public MaterialAttributes.Material Material { get; private set; } |
164 | public override void SetMaterial(int material) | 170 | public override void SetMaterial(int material) |
@@ -169,7 +175,8 @@ public abstract class BSPhysObject : PhysicsActor | |||
169 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); | 175 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); |
170 | Friction = matAttrib.friction; | 176 | Friction = matAttrib.friction; |
171 | Restitution = matAttrib.restitution; | 177 | Restitution = matAttrib.restitution; |
172 | Density = matAttrib.density; | 178 | Density = matAttrib.density / BSParam.DensityScaleFactor; |
179 | DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); | ||
173 | } | 180 | } |
174 | 181 | ||
175 | // Stop all physical motion. | 182 | // Stop all physical motion. |
@@ -185,14 +192,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
185 | public abstract OMV.Quaternion RawOrientation { get; set; } | 192 | public abstract OMV.Quaternion RawOrientation { get; set; } |
186 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 193 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
187 | 194 | ||
188 | public virtual float TargetSpeed | ||
189 | { | ||
190 | get | ||
191 | { | ||
192 | OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation)); | ||
193 | return characterOrientedVelocity.X; | ||
194 | } | ||
195 | } | ||
196 | public abstract OMV.Vector3 RawVelocity { get; set; } | 195 | public abstract OMV.Vector3 RawVelocity { get; set; } |
197 | public abstract OMV.Vector3 ForceVelocity { get; set; } | 196 | public abstract OMV.Vector3 ForceVelocity { get; set; } |
198 | 197 | ||
@@ -202,6 +201,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
202 | 201 | ||
203 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } | 202 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } |
204 | 203 | ||
204 | // The current velocity forward | ||
205 | public virtual float ForwardSpeed | 205 | public virtual float ForwardSpeed |
206 | { | 206 | { |
207 | get | 207 | get |
@@ -210,6 +210,22 @@ public abstract class BSPhysObject : PhysicsActor | |||
210 | return characterOrientedVelocity.X; | 210 | return characterOrientedVelocity.X; |
211 | } | 211 | } |
212 | } | 212 | } |
213 | // The forward speed we are trying to achieve (TargetVelocity) | ||
214 | public virtual float TargetVelocitySpeed | ||
215 | { | ||
216 | get | ||
217 | { | ||
218 | OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation)); | ||
219 | return characterOrientedVelocity.X; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // The user can optionally set the center of mass. The user's setting will override any | ||
224 | // computed center-of-mass (like in linksets). | ||
225 | public OMV.Vector3? UserSetCenterOfMass { get; set; } | ||
226 | |||
227 | public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. | ||
228 | public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free | ||
213 | 229 | ||
214 | #region Collisions | 230 | #region Collisions |
215 | 231 | ||
@@ -407,9 +423,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
407 | { | 423 | { |
408 | // Clean out any existing action | 424 | // Clean out any existing action |
409 | UnRegisterPreStepAction(op, id); | 425 | UnRegisterPreStepAction(op, id); |
410 | |||
411 | RegisteredPrestepActions[identifier] = actn; | 426 | RegisteredPrestepActions[identifier] = actn; |
412 | |||
413 | PhysicsScene.BeforeStep += actn; | 427 | PhysicsScene.BeforeStep += actn; |
414 | } | 428 | } |
415 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); | 429 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); |
@@ -455,9 +469,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
455 | { | 469 | { |
456 | // Clean out any existing action | 470 | // Clean out any existing action |
457 | UnRegisterPostStepAction(op, id); | 471 | UnRegisterPostStepAction(op, id); |
458 | |||
459 | RegisteredPoststepActions[identifier] = actn; | 472 | RegisteredPoststepActions[identifier] = actn; |
460 | |||
461 | PhysicsScene.AfterStep += actn; | 473 | PhysicsScene.AfterStep += actn; |
462 | } | 474 | } |
463 | DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier); | 475 | DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier); |
@@ -494,7 +506,58 @@ public abstract class BSPhysObject : PhysicsActor | |||
494 | } | 506 | } |
495 | DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID); | 507 | DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID); |
496 | } | 508 | } |
497 | 509 | ||
510 | // When an update to the physical properties happens, this event is fired to let | ||
511 | // different actors to modify the update before it is passed around | ||
512 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); | ||
513 | public event PreUpdatePropertyAction OnPreUpdateProperty; | ||
514 | protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop) | ||
515 | { | ||
516 | PreUpdatePropertyAction actions = OnPreUpdateProperty; | ||
517 | if (actions != null) | ||
518 | actions(ref entprop); | ||
519 | } | ||
520 | |||
521 | private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>(); | ||
522 | public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn) | ||
523 | { | ||
524 | lock (RegisteredPreUpdatePropertyActions) | ||
525 | { | ||
526 | // Clean out any existing action | ||
527 | UnRegisterPreUpdatePropertyAction(identifier); | ||
528 | RegisteredPreUpdatePropertyActions[identifier] = actn; | ||
529 | OnPreUpdateProperty += actn; | ||
530 | } | ||
531 | DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier); | ||
532 | } | ||
533 | public bool UnRegisterPreUpdatePropertyAction(string identifier) | ||
534 | { | ||
535 | bool removed = false; | ||
536 | lock (RegisteredPreUpdatePropertyActions) | ||
537 | { | ||
538 | if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier)) | ||
539 | { | ||
540 | OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier]; | ||
541 | RegisteredPreUpdatePropertyActions.Remove(identifier); | ||
542 | removed = true; | ||
543 | } | ||
544 | } | ||
545 | DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed); | ||
546 | return removed; | ||
547 | } | ||
548 | public void UnRegisterAllPreUpdatePropertyActions() | ||
549 | { | ||
550 | lock (RegisteredPreUpdatePropertyActions) | ||
551 | { | ||
552 | foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions) | ||
553 | { | ||
554 | OnPreUpdateProperty -= kvp.Value; | ||
555 | } | ||
556 | RegisteredPreUpdatePropertyActions.Clear(); | ||
557 | } | ||
558 | DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID); | ||
559 | } | ||
560 | |||
498 | #endregion // Per Simulation Step actions | 561 | #endregion // Per Simulation Step actions |
499 | 562 | ||
500 | // High performance detailed logging routine used by the physical objects. | 563 | // High performance detailed logging routine used by the physical objects. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index cf7aa0f..0323b0d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -242,6 +242,45 @@ public class BSPrim : BSPhysObject | |||
242 | public override void LockAngularMotion(OMV.Vector3 axis) | 242 | public override void LockAngularMotion(OMV.Vector3 axis) |
243 | { | 243 | { |
244 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); | 244 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); |
245 | |||
246 | OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); | ||
247 | if (axis.X != 1) locking.X = 0f; | ||
248 | if (axis.Y != 1) locking.Y = 0f; | ||
249 | if (axis.Z != 1) locking.Z = 0f; | ||
250 | LockedAxis = locking; | ||
251 | |||
252 | /* Not implemented yet | ||
253 | if (LockedAxis != LockedAxisFree) | ||
254 | { | ||
255 | // Something is locked so start the thingy that keeps that axis from changing | ||
256 | RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop) | ||
257 | { | ||
258 | if (LockedAxis != LockedAxisFree) | ||
259 | { | ||
260 | if (IsPhysicallyActive) | ||
261 | { | ||
262 | // Bullet can lock axis but it only works for global axis. | ||
263 | // Check if this prim is aligned on global axis and use Bullet's | ||
264 | // system if so. | ||
265 | |||
266 | ForceOrientation = entprop.Rotation; | ||
267 | ForceRotationalVelocity = entprop.RotationalVelocity; | ||
268 | } | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); | ||
273 | } | ||
274 | |||
275 | }); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | // Everything seems unlocked | ||
280 | UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); | ||
281 | } | ||
282 | */ | ||
283 | |||
245 | return; | 284 | return; |
246 | } | 285 | } |
247 | 286 | ||
@@ -311,7 +350,8 @@ public class BSPrim : BSPhysObject | |||
311 | 350 | ||
312 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 351 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
313 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 352 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
314 | if (RawPosition.Z < terrainHeight) | 353 | float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); |
354 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) | ||
315 | { | 355 | { |
316 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight); | 356 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight); |
317 | float targetHeight = terrainHeight + (Size.Z / 2f); | 357 | float targetHeight = terrainHeight + (Size.Z / 2f); |
@@ -442,7 +482,7 @@ public class BSPrim : BSPhysObject | |||
442 | RegisterPreStepAction("BSPrim.setForce", LocalID, | 482 | RegisterPreStepAction("BSPrim.setForce", LocalID, |
443 | delegate(float timeStep) | 483 | delegate(float timeStep) |
444 | { | 484 | { |
445 | if (!IsPhysicallyActive) | 485 | if (!IsPhysicallyActive || _force == OMV.Vector3.Zero) |
446 | { | 486 | { |
447 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | 487 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); |
448 | return; | 488 | return; |
@@ -576,6 +616,8 @@ public class BSPrim : BSPhysObject | |||
576 | } | 616 | } |
577 | } | 617 | } |
578 | } | 618 | } |
619 | // The simulator/viewer keep density as 100kg/m3. | ||
620 | // Remember to use BSParam.DensityScaleFactor to create the physical density. | ||
579 | public override float Density | 621 | public override float Density |
580 | { | 622 | { |
581 | get { return base.Density; } | 623 | get { return base.Density; } |
@@ -647,7 +689,7 @@ public class BSPrim : BSPhysObject | |||
647 | RegisterPreStepAction("BSPrim.setTorque", LocalID, | 689 | RegisterPreStepAction("BSPrim.setTorque", LocalID, |
648 | delegate(float timeStep) | 690 | delegate(float timeStep) |
649 | { | 691 | { |
650 | if (!IsPhysicallyActive) | 692 | if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero) |
651 | { | 693 | { |
652 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | 694 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); |
653 | return; | 695 | return; |
@@ -1569,7 +1611,8 @@ public class BSPrim : BSPhysObject | |||
1569 | profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; | 1611 | profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; |
1570 | volume *= (profileEnd - profileBegin); | 1612 | volume *= (profileEnd - profileBegin); |
1571 | 1613 | ||
1572 | returnMass = Density * volume; | 1614 | returnMass = Density * BSParam.DensityScaleFactor * volume; |
1615 | DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); | ||
1573 | 1616 | ||
1574 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); | 1617 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); |
1575 | 1618 | ||
@@ -1607,6 +1650,8 @@ public class BSPrim : BSPhysObject | |||
1607 | // the world that things have changed. | 1650 | // the world that things have changed. |
1608 | public override void UpdateProperties(EntityProperties entprop) | 1651 | public override void UpdateProperties(EntityProperties entprop) |
1609 | { | 1652 | { |
1653 | TriggerPreUpdatePropertyAction(ref entprop); | ||
1654 | |||
1610 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet | 1655 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
1611 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | 1656 | // TODO: handle physics introduced by Bullet with computed vehicle physics. |
1612 | if (VehicleController.IsActive) | 1657 | if (VehicleController.IsActive) |
@@ -1619,7 +1664,11 @@ public class BSPrim : BSPhysObject | |||
1619 | // Assign directly to the local variables so the normal set actions do not happen | 1664 | // Assign directly to the local variables so the normal set actions do not happen |
1620 | _position = entprop.Position; | 1665 | _position = entprop.Position; |
1621 | _orientation = entprop.Rotation; | 1666 | _orientation = entprop.Rotation; |
1622 | _velocity = entprop.Velocity; | 1667 | // _velocity = entprop.Velocity; |
1668 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be | ||
1669 | // very sensitive to velocity changes. | ||
1670 | if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) | ||
1671 | _velocity = entprop.Velocity; | ||
1623 | _acceleration = entprop.Acceleration; | 1672 | _acceleration = entprop.Acceleration; |
1624 | _rotationalVelocity = entprop.RotationalVelocity; | 1673 | _rotationalVelocity = entprop.RotationalVelocity; |
1625 | 1674 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs index 6401308..f1c3b5c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs | |||
@@ -44,72 +44,107 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
44 | { | 44 | { |
45 | public class BSPrimDisplaced : BSPrim | 45 | public class BSPrimDisplaced : BSPrim |
46 | { | 46 | { |
47 | // 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is. | 47 | // The purpose of this module is to do any mapping between what the simulator thinks |
48 | // Because Bullet needs the zero coordinate to be the center of mass of the linkset, | 48 | // the prim position and orientation is and what the physical position/orientation. |
49 | // sometimes it is necessary to displace the position the physics engine thinks | 49 | // This difference happens because Bullet assumes the center-of-mass is the <0,0,0> |
50 | // the position is. PositionDisplacement must be added and removed from the | 50 | // of the prim/linkset. The simulator tracks the location of the prim/linkset by |
51 | // position as the simulator position is stored and fetched from the physics | 51 | // the location of the root prim. So, if center-of-mass is anywhere but the origin |
52 | // engine. Similar to OrientationDisplacement. | 52 | // of the root prim, the physical origin is displaced from the simulator origin. |
53 | // | ||
54 | // This routine works by capturing the Force* setting of position/orientation/... and | ||
55 | // adjusting the simulator values (being set) into the physical values. | ||
56 | // The conversion is also done in the opposite direction (physical origin -> simulator origin). | ||
57 | // | ||
58 | // The updateParameter call is also captured and the values from the physics engine | ||
59 | // are converted into simulator origin values before being passed to the base | ||
60 | // class. | ||
61 | |||
53 | public virtual OMV.Vector3 PositionDisplacement { get; set; } | 62 | public virtual OMV.Vector3 PositionDisplacement { get; set; } |
54 | public virtual OMV.Quaternion OrientationDisplacement { get; set; } | 63 | public virtual OMV.Quaternion OrientationDisplacement { get; set; } |
55 | public virtual OMV.Vector3 CenterOfMassLocation { get; set; } | ||
56 | public virtual OMV.Vector3 GeometricCenterLocation { get; set; } | ||
57 | 64 | ||
58 | public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 65 | public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
59 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 66 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
60 | : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) | 67 | : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) |
61 | { | 68 | { |
62 | CenterOfMassLocation = RawPosition; | 69 | ClearDisplacement(); |
63 | GeometricCenterLocation = RawPosition; | ||
64 | } | 70 | } |
65 | 71 | ||
66 | public override Vector3 ForcePosition | 72 | public void ClearDisplacement() |
73 | { | ||
74 | PositionDisplacement = OMV.Vector3.Zero; | ||
75 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
76 | } | ||
77 | |||
78 | // Set this sets and computes the displacement from the passed prim to the center-of-mass. | ||
79 | // A user set value for center-of-mass overrides whatever might be passed in here. | ||
80 | // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). | ||
81 | public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) | ||
67 | { | 82 | { |
68 | get | 83 | Vector3 comDisp; |
84 | if (UserSetCenterOfMass.HasValue) | ||
85 | comDisp = (OMV.Vector3)UserSetCenterOfMass; | ||
86 | else | ||
87 | comDisp = centerOfMassDisplacement; | ||
88 | |||
89 | if (comDisp == Vector3.Zero) | ||
69 | { | 90 | { |
70 | return base.ForcePosition; | 91 | // If there is no diplacement. Things get reset. |
92 | PositionDisplacement = OMV.Vector3.Zero; | ||
93 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
71 | } | 94 | } |
72 | set | 95 | else |
73 | { | 96 | { |
74 | base.ForcePosition = value; | 97 | // Remember the displacement from root as well as the origional rotation of the |
75 | CenterOfMassLocation = RawPosition; | 98 | // new center-of-mass. |
76 | GeometricCenterLocation = RawPosition; | 99 | PositionDisplacement = comDisp; |
100 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
77 | } | 101 | } |
78 | } | 102 | } |
79 | 103 | ||
80 | public override Quaternion ForceOrientation | 104 | public override Vector3 ForcePosition |
81 | { | 105 | { |
82 | get | 106 | get { return base.ForcePosition; } |
107 | set | ||
83 | { | 108 | { |
84 | return base.ForceOrientation; | 109 | if (PositionDisplacement != OMV.Vector3.Zero) |
110 | base.ForcePosition = value - (PositionDisplacement * RawOrientation); | ||
111 | else | ||
112 | base.ForcePosition = value; | ||
85 | } | 113 | } |
114 | } | ||
115 | |||
116 | public override Quaternion ForceOrientation | ||
117 | { | ||
118 | get { return base.ForceOrientation; } | ||
86 | set | 119 | set |
87 | { | 120 | { |
88 | base.ForceOrientation = value; | 121 | base.ForceOrientation = value; |
89 | } | 122 | } |
90 | } | 123 | } |
91 | 124 | ||
125 | // TODO: decide if this is the right place for these variables. | ||
126 | // Somehow incorporate the optional settability by the user. | ||
92 | // Is this used? | 127 | // Is this used? |
93 | public override OMV.Vector3 CenterOfMass | 128 | public override OMV.Vector3 CenterOfMass |
94 | { | 129 | { |
95 | get { return CenterOfMassLocation; } | 130 | get { return RawPosition; } |
96 | } | 131 | } |
97 | 132 | ||
98 | // Is this used? | 133 | // Is this used? |
99 | public override OMV.Vector3 GeometricCenter | 134 | public override OMV.Vector3 GeometricCenter |
100 | { | 135 | { |
101 | get { return GeometricCenterLocation; } | 136 | get { return RawPosition; } |
102 | } | 137 | } |
103 | 138 | ||
104 | |||
105 | public override void UpdateProperties(EntityProperties entprop) | 139 | public override void UpdateProperties(EntityProperties entprop) |
106 | { | 140 | { |
107 | // Undo any center-of-mass displacement that might have been done. | 141 | // Undo any center-of-mass displacement that might have been done. |
108 | if (PositionDisplacement != OMV.Vector3.Zero) | 142 | if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) |
109 | { | 143 | { |
110 | // Correct for any rotation around the center-of-mass | 144 | // Correct for any rotation around the center-of-mass |
111 | // TODO!!! | 145 | // TODO!!! |
112 | entprop.Position -= PositionDisplacement; | 146 | entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); |
147 | // entprop.Rotation = something; | ||
113 | } | 148 | } |
114 | 149 | ||
115 | base.UpdateProperties(entprop); | 150 | base.UpdateProperties(entprop); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 9898562..d65d407 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs | |||
@@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
38 | public class BSPrimLinkable : BSPrimDisplaced | 38 | public class BSPrimLinkable : BSPrimDisplaced |
39 | { | 39 | { |
40 | public BSLinkset Linkset { get; set; } | 40 | public BSLinkset Linkset { get; set; } |
41 | // The index of this child prim. | ||
42 | public int LinksetChildIndex { get; set; } | ||
43 | |||
41 | public BSLinksetInfo LinksetInfo { get; set; } | 44 | public BSLinksetInfo LinksetInfo { get; set; } |
42 | 45 | ||
43 | public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 46 | public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
@@ -90,7 +93,6 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
90 | DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", | 93 | DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", |
91 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | 94 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); |
92 | return; | 95 | return; |
93 | base.delink(); | ||
94 | } | 96 | } |
95 | 97 | ||
96 | // When simulator changes position, this might be moving a child of the linkset. | 98 | // When simulator changes position, this might be moving a child of the linkset. |
@@ -133,7 +135,8 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
133 | // When going from non-physical to physical, this re-enables the constraints that | 135 | // When going from non-physical to physical, this re-enables the constraints that |
134 | // had been automatically disabled when the mass was set to zero. | 136 | // had been automatically disabled when the mass was set to zero. |
135 | // For compound based linksets, this enables and disables interactions of the children. | 137 | // For compound based linksets, this enables and disables interactions of the children. |
136 | Linkset.Refresh(this); | 138 | if (Linkset != null) // null can happen during initialization |
139 | Linkset.Refresh(this); | ||
137 | } | 140 | } |
138 | 141 | ||
139 | protected override void MakeDynamic(bool makeStatic) | 142 | protected override void MakeDynamic(bool makeStatic) |