diff options
author | Teravus Ovares | 2008-12-26 12:58:02 +0000 |
---|---|---|
committer | Teravus Ovares | 2008-12-26 12:58:02 +0000 |
commit | ec2dc354b485491d7879686b4a78027971e3ed92 (patch) | |
tree | 3ea0771a55524ce1b9dec3c3c66f0dac24a006ef /OpenSim/Region/Environment/Scenes/SceneObjectPart.cs | |
parent | Prevent exception in terrain module if just the word terrain is entered at th... (diff) | |
download | opensim-SC_OLD-ec2dc354b485491d7879686b4a78027971e3ed92.zip opensim-SC_OLD-ec2dc354b485491d7879686b4a78027971e3ed92.tar.gz opensim-SC_OLD-ec2dc354b485491d7879686b4a78027971e3ed92.tar.bz2 opensim-SC_OLD-ec2dc354b485491d7879686b4a78027971e3ed92.tar.xz |
* Applying Nlin's NINJA Joint patch. v2. Mantis# 2874
* Thanks nlin!
* To try it out, set ninja joints active in the ODEPhysicsSettings
and use the example at:
* http://forge.opensimulator.org/gf/download/frsrelease/142/304/demo-playground.tgz.
* Don't forget to change the .tgz to .oar and load it with load-oar.
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/SceneObjectPart.cs')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/SceneObjectPart.cs | 282 |
1 files changed, 230 insertions, 52 deletions
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 3491645..0f3e065 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs | |||
@@ -419,7 +419,14 @@ namespace OpenSim.Region.Environment.Scenes | |||
419 | public virtual string Name | 419 | public virtual string Name |
420 | { | 420 | { |
421 | get { return m_name; } | 421 | get { return m_name; } |
422 | set { m_name = value; } | 422 | set |
423 | { | ||
424 | m_name = value; | ||
425 | if (PhysActor != null) | ||
426 | { | ||
427 | PhysActor.SOPName = value; | ||
428 | } | ||
429 | } | ||
423 | } | 430 | } |
424 | 431 | ||
425 | public byte Material | 432 | public byte Material |
@@ -681,7 +688,14 @@ namespace OpenSim.Region.Environment.Scenes | |||
681 | public string Description | 688 | public string Description |
682 | { | 689 | { |
683 | get { return m_description; } | 690 | get { return m_description; } |
684 | set { m_description = value; } | 691 | set |
692 | { | ||
693 | m_description = value; | ||
694 | if (PhysActor != null) | ||
695 | { | ||
696 | PhysActor.SOPDescription = value; | ||
697 | } | ||
698 | } | ||
685 | } | 699 | } |
686 | 700 | ||
687 | public Color Color | 701 | public Color Color |
@@ -1287,30 +1301,39 @@ if (m_shape != null) { | |||
1287 | bool isPhysical = (((rootObjectFlags & (uint) PrimFlags.Physics) != 0) && m_physicalPrim); | 1301 | bool isPhysical = (((rootObjectFlags & (uint) PrimFlags.Physics) != 0) && m_physicalPrim); |
1288 | bool isPhantom = ((rootObjectFlags & (uint) PrimFlags.Phantom) != 0); | 1302 | bool isPhantom = ((rootObjectFlags & (uint) PrimFlags.Phantom) != 0); |
1289 | 1303 | ||
1290 | // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored | 1304 | if (IsJoint()) |
1291 | if (VolumeDetectActive) | 1305 | { |
1292 | isPhantom = false; | 1306 | DoPhysicsPropertyUpdate(isPhysical, true); |
1293 | 1307 | } | |
1294 | // Added clarification.. since A rigid body is an object that you can kick around, etc. | 1308 | else |
1295 | bool RigidBody = isPhysical && !isPhantom; | ||
1296 | |||
1297 | // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition | ||
1298 | if (!isPhantom && !IsAttachment) | ||
1299 | { | 1309 | { |
1300 | PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( | 1310 | // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored |
1301 | Name, | 1311 | if (VolumeDetectActive) |
1302 | Shape, | 1312 | isPhantom = false; |
1303 | new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z), | ||
1304 | new PhysicsVector(Scale.X, Scale.Y, Scale.Z), | ||
1305 | RotationOffset, | ||
1306 | RigidBody); | ||
1307 | 1313 | ||
1308 | // Basic Physics returns null.. joy joy joy. | 1314 | // Added clarification.. since A rigid body is an object that you can kick around, etc. |
1309 | if (PhysActor != null) | 1315 | bool RigidBody = isPhysical && !isPhantom; |
1316 | |||
1317 | // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition | ||
1318 | if (!isPhantom && !IsAttachment) | ||
1310 | { | 1319 | { |
1311 | PhysActor.LocalID = LocalId; | 1320 | PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( |
1312 | DoPhysicsPropertyUpdate(RigidBody, true); | 1321 | Name, |
1313 | PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); | 1322 | Shape, |
1323 | new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z), | ||
1324 | new PhysicsVector(Scale.X, Scale.Y, Scale.Z), | ||
1325 | RotationOffset, | ||
1326 | RigidBody); | ||
1327 | |||
1328 | // Basic Physics returns null.. joy joy joy. | ||
1329 | if (PhysActor != null) | ||
1330 | { | ||
1331 | PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info | ||
1332 | PhysActor.SOPDescription = this.Description; | ||
1333 | PhysActor.LocalID = LocalId; | ||
1334 | DoPhysicsPropertyUpdate(RigidBody, true); | ||
1335 | PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); | ||
1336 | } | ||
1314 | } | 1337 | } |
1315 | } | 1338 | } |
1316 | } | 1339 | } |
@@ -1421,57 +1444,160 @@ if (m_shape != null) { | |||
1421 | 1444 | ||
1422 | public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) | 1445 | public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew) |
1423 | { | 1446 | { |
1424 | if (PhysActor != null) | 1447 | if (IsJoint()) |
1425 | { | 1448 | { |
1426 | if (UsePhysics != PhysActor.IsPhysical || isNew) | 1449 | if (UsePhysics) |
1427 | { | 1450 | { |
1428 | if (PhysActor.IsPhysical) | 1451 | // by turning a joint proxy object physical, we cause creation of a joint in the ODE scene. |
1452 | // note that, as a special case, joints have no bodies or geoms in the physics scene, even though they are physical. | ||
1453 | |||
1454 | PhysicsJointType jointType; | ||
1455 | if (IsHingeJoint()) | ||
1456 | { | ||
1457 | jointType = PhysicsJointType.Hinge; | ||
1458 | } | ||
1459 | else if (IsBallJoint()) | ||
1460 | { | ||
1461 | jointType = PhysicsJointType.Ball; | ||
1462 | } | ||
1463 | else | ||
1464 | { | ||
1465 | jointType = PhysicsJointType.Ball; | ||
1466 | } | ||
1467 | |||
1468 | List<string> bodyNames = new List<string>(); | ||
1469 | string RawParams = Description; | ||
1470 | string[] jointParams = RawParams.Split(' '); | ||
1471 | string trackedBodyName = null; | ||
1472 | if (jointParams.Length >= 2) | ||
1473 | { | ||
1474 | for (int iBodyName = 0; iBodyName < 2; iBodyName++) | ||
1475 | { | ||
1476 | string bodyName = jointParams[iBodyName]; | ||
1477 | bodyNames.Add(bodyName); | ||
1478 | if (bodyName != "NULL") | ||
1479 | { | ||
1480 | if (trackedBodyName == null) | ||
1481 | { | ||
1482 | trackedBodyName = bodyName; | ||
1483 | } | ||
1484 | } | ||
1485 | } | ||
1486 | } | ||
1487 | |||
1488 | SceneObjectPart trackedBody = m_parentGroup.Scene.GetSceneObjectPart(trackedBodyName); // FIXME: causes a sequential lookup | ||
1489 | Quaternion localRotation = Quaternion.Identity; | ||
1490 | if (trackedBody != null) | ||
1429 | { | 1491 | { |
1430 | if (!isNew) | 1492 | localRotation = Quaternion.Inverse(trackedBody.RotationOffset) * this.RotationOffset; |
1431 | ParentGroup.Scene.RemovePhysicalPrim(1); | 1493 | } |
1494 | else | ||
1495 | { | ||
1496 | // error, output it below | ||
1497 | } | ||
1432 | 1498 | ||
1433 | PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; | 1499 | PhysicsJoint joint; |
1434 | PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; | 1500 | |
1435 | PhysActor.delink(); | 1501 | joint = m_parentGroup.Scene.PhysicsScene.RequestJointCreation(Name, jointType, |
1502 | new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z), | ||
1503 | this.RotationOffset, | ||
1504 | Description, | ||
1505 | bodyNames, | ||
1506 | trackedBodyName, | ||
1507 | localRotation); | ||
1508 | |||
1509 | if (trackedBody == null) | ||
1510 | { | ||
1511 | ParentGroup.Scene.jointErrorMessage(joint, "warning: tracked body name not found! joint location will not be updated properly. joint: " + Name); | ||
1436 | } | 1512 | } |
1437 | 1513 | ||
1438 | if (!UsePhysics && !isNew) | 1514 | } |
1515 | else | ||
1516 | { | ||
1517 | if (isNew) | ||
1439 | { | 1518 | { |
1440 | // reset velocity to 0 on physics switch-off. Without that, the client thinks the | 1519 | // if the joint proxy is new, and it is not physical, do nothing. There is no joint in ODE to |
1441 | // prim still has velocity and continues to interpolate its position along the old | 1520 | // delete, and if we try to delete it, due to asynchronous processing, the deletion request |
1442 | // velocity-vector. | 1521 | // will get processed later at an indeterminate time, which could cancel a later-arriving |
1522 | // joint creation request. | ||
1523 | } | ||
1524 | else | ||
1525 | { | ||
1526 | // here we turn off the joint object, so remove the joint from the physics scene | ||
1527 | m_parentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed? | ||
1528 | |||
1529 | // make sure client isn't interpolating the joint proxy object | ||
1443 | Velocity = new Vector3(0, 0, 0); | 1530 | Velocity = new Vector3(0, 0, 0); |
1531 | RotationalVelocity = new Vector3(0, 0, 0); | ||
1444 | Acceleration = new Vector3(0, 0, 0); | 1532 | Acceleration = new Vector3(0, 0, 0); |
1445 | AngularVelocity = new Vector3(0, 0, 0); | ||
1446 | } | 1533 | } |
1534 | } | ||
1535 | } | ||
1536 | else | ||
1537 | { | ||
1538 | if (PhysActor != null) | ||
1539 | { | ||
1540 | if (UsePhysics != PhysActor.IsPhysical || isNew) | ||
1541 | { | ||
1542 | if (PhysActor.IsPhysical) // implies UsePhysics==false for this block | ||
1543 | { | ||
1544 | if (!isNew) | ||
1545 | ParentGroup.Scene.RemovePhysicalPrim(1); | ||
1447 | 1546 | ||
1448 | PhysActor.IsPhysical = UsePhysics; | 1547 | PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; |
1548 | PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; | ||
1549 | PhysActor.delink(); | ||
1449 | 1550 | ||
1551 | if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) | ||
1552 | { | ||
1553 | // destroy all joints connected to this now deactivated body | ||
1554 | m_parentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor); | ||
1555 | } | ||
1450 | 1556 | ||
1451 | // If we're not what we're supposed to be in the physics scene, recreate ourselves. | 1557 | // stop client-side interpolation of all joint proxy objects that have just been deleted |
1452 | //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); | 1558 | // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, |
1453 | /// that's not wholesome. Had to make Scene public | 1559 | // which stops client-side interpolation of deactivated joint proxy objects. |
1454 | //PhysActor = null; | 1560 | } |
1455 | 1561 | ||
1456 | if ((ObjectFlags & (uint) PrimFlags.Phantom) == 0) | 1562 | if (!UsePhysics && !isNew) |
1457 | { | ||
1458 | if (UsePhysics) | ||
1459 | { | 1563 | { |
1460 | ParentGroup.Scene.AddPhysicalPrim(1); | 1564 | // reset velocity to 0 on physics switch-off. Without that, the client thinks the |
1565 | // prim still has velocity and continues to interpolate its position along the old | ||
1566 | // velocity-vector. | ||
1567 | Velocity = new Vector3(0, 0, 0); | ||
1568 | Acceleration = new Vector3(0, 0, 0); | ||
1569 | AngularVelocity = new Vector3(0, 0, 0); | ||
1570 | //RotationalVelocity = new Vector3(0, 0, 0); | ||
1571 | } | ||
1572 | |||
1573 | PhysActor.IsPhysical = UsePhysics; | ||
1461 | 1574 | ||
1462 | PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; | 1575 | |
1463 | PhysActor.OnOutOfBounds += PhysicsOutOfBounds; | 1576 | // If we're not what we're supposed to be in the physics scene, recreate ourselves. |
1464 | if (_parentID != 0 && _parentID != LocalId) | 1577 | //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); |
1578 | /// that's not wholesome. Had to make Scene public | ||
1579 | //PhysActor = null; | ||
1580 | |||
1581 | if ((ObjectFlags & (uint)PrimFlags.Phantom) == 0) | ||
1582 | { | ||
1583 | if (UsePhysics) | ||
1465 | { | 1584 | { |
1466 | if (ParentGroup.RootPart.PhysActor != null) | 1585 | ParentGroup.Scene.AddPhysicalPrim(1); |
1586 | |||
1587 | PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; | ||
1588 | PhysActor.OnOutOfBounds += PhysicsOutOfBounds; | ||
1589 | if (_parentID != 0 && _parentID != LocalId) | ||
1467 | { | 1590 | { |
1468 | PhysActor.link(ParentGroup.RootPart.PhysActor); | 1591 | if (ParentGroup.RootPart.PhysActor != null) |
1592 | { | ||
1593 | PhysActor.link(ParentGroup.RootPart.PhysActor); | ||
1594 | } | ||
1469 | } | 1595 | } |
1470 | } | 1596 | } |
1471 | } | 1597 | } |
1472 | } | 1598 | } |
1599 | m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); | ||
1473 | } | 1600 | } |
1474 | m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); | ||
1475 | } | 1601 | } |
1476 | } | 1602 | } |
1477 | 1603 | ||
@@ -3190,6 +3316,53 @@ if (m_shape != null) { | |||
3190 | } | 3316 | } |
3191 | } | 3317 | } |
3192 | 3318 | ||
3319 | public bool IsHingeJoint() | ||
3320 | { | ||
3321 | // For now, we use the NINJA naming scheme for identifying joints. | ||
3322 | // In the future, we can support other joint specification schemes such as a | ||
3323 | // custom checkbox in the viewer GUI. | ||
3324 | if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | ||
3325 | { | ||
3326 | string hingeString = "hingejoint"; | ||
3327 | return (Name.Length >= hingeString.Length && Name.Substring(0, hingeString.Length) == hingeString); | ||
3328 | } | ||
3329 | else | ||
3330 | { | ||
3331 | return false; | ||
3332 | } | ||
3333 | } | ||
3334 | |||
3335 | public bool IsBallJoint() | ||
3336 | { | ||
3337 | // For now, we use the NINJA naming scheme for identifying joints. | ||
3338 | // In the future, we can support other joint specification schemes such as a | ||
3339 | // custom checkbox in the viewer GUI. | ||
3340 | if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | ||
3341 | { | ||
3342 | string ballString = "balljoint"; | ||
3343 | return (Name.Length >= ballString.Length && Name.Substring(0, ballString.Length) == ballString); | ||
3344 | } | ||
3345 | else | ||
3346 | { | ||
3347 | return false; | ||
3348 | } | ||
3349 | } | ||
3350 | |||
3351 | public bool IsJoint() | ||
3352 | { | ||
3353 | // For now, we use the NINJA naming scheme for identifying joints. | ||
3354 | // In the future, we can support other joint specification schemes such as a | ||
3355 | // custom checkbox in the viewer GUI. | ||
3356 | if (m_parentGroup.Scene.PhysicsScene.SupportsNINJAJoints) | ||
3357 | { | ||
3358 | return IsHingeJoint() || IsBallJoint(); | ||
3359 | } | ||
3360 | else | ||
3361 | { | ||
3362 | return false; | ||
3363 | } | ||
3364 | } | ||
3365 | |||
3193 | public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD) | 3366 | public void UpdatePrimFlags(bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVD) |
3194 | { | 3367 | { |
3195 | bool wasUsingPhysics = ((ObjectFlags & (uint) PrimFlags.Physics) != 0); | 3368 | bool wasUsingPhysics = ((ObjectFlags & (uint) PrimFlags.Physics) != 0); |
@@ -3230,6 +3403,11 @@ if (m_shape != null) { | |||
3230 | 3403 | ||
3231 | } | 3404 | } |
3232 | 3405 | ||
3406 | if (UsePhysics && IsJoint()) | ||
3407 | { | ||
3408 | IsPhantom = true; | ||
3409 | } | ||
3410 | |||
3233 | if (UsePhysics) | 3411 | if (UsePhysics) |
3234 | { | 3412 | { |
3235 | AddFlag(PrimFlags.Physics); | 3413 | AddFlag(PrimFlags.Physics); |
@@ -3258,7 +3436,7 @@ if (m_shape != null) { | |||
3258 | } | 3436 | } |
3259 | 3437 | ||
3260 | 3438 | ||
3261 | if (IsPhantom || IsAttachment) | 3439 | if (IsPhantom || IsAttachment) // note: this may have been changed above in the case of joints |
3262 | { | 3440 | { |
3263 | AddFlag(PrimFlags.Phantom); | 3441 | AddFlag(PrimFlags.Phantom); |
3264 | if (PhysActor != null) | 3442 | if (PhysActor != null) |