aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/SceneObjectPart.cs')
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs282
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)