aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment')
-rw-r--r--OpenSim/Region/Environment/Scenes/Scene.cs167
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneGraph.cs17
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs282
3 files changed, 412 insertions, 54 deletions
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index d4d5b90..2d0743c 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -200,8 +200,30 @@ namespace OpenSim.Region.Environment.Scenes
200 // an instance to the physics plugin's Scene object. 200 // an instance to the physics plugin's Scene object.
201 public PhysicsScene PhysicsScene 201 public PhysicsScene PhysicsScene
202 { 202 {
203 set { m_sceneGraph.PhysicsScene = value; }
204 get { return m_sceneGraph.PhysicsScene; } 203 get { return m_sceneGraph.PhysicsScene; }
204 set
205 {
206 // If we're not doing the initial set
207 // Then we've got to remove the previous
208 // event handler
209 if (PhysicsScene != null && PhysicsScene.SupportsNINJAJoints)
210 {
211 PhysicsScene.OnJointMoved -= jointMoved;
212 PhysicsScene.OnJointDeactivated -= jointDeactivated;
213 PhysicsScene.OnJointErrorMessage -= jointErrorMessage;
214 }
215
216 m_sceneGraph.PhysicsScene = value;
217
218 if (PhysicsScene != null && m_sceneGraph.PhysicsScene.SupportsNINJAJoints)
219 {
220 // register event handlers to respond to joint movement/deactivation
221 PhysicsScene.OnJointMoved += jointMoved;
222 PhysicsScene.OnJointDeactivated += jointDeactivated;
223 PhysicsScene.OnJointErrorMessage += jointErrorMessage;
224 }
225
226 }
205 } 227 }
206 228
207 // This gets locked so things stay thread safe. 229 // This gets locked so things stay thread safe.
@@ -1848,7 +1870,11 @@ namespace OpenSim.Region.Environment.Scenes
1848 1870
1849 foreach (SceneObjectPart part in group.Children.Values) 1871 foreach (SceneObjectPart part in group.Children.Values)
1850 { 1872 {
1851 if (part.PhysActor != null) 1873 if (part.IsJoint() && ((part.ObjectFlags&(uint)PrimFlags.Physics) != 0) )
1874 {
1875 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
1876 }
1877 else if (part.PhysActor != null)
1852 { 1878 {
1853 PhysicsScene.RemovePrim(part.PhysActor); 1879 PhysicsScene.RemovePrim(part.PhysActor);
1854 part.PhysActor = null; 1880 part.PhysActor = null;
@@ -4408,5 +4434,142 @@ namespace OpenSim.Region.Environment.Scenes
4408 4434
4409 return 0; 4435 return 0;
4410 } 4436 }
4437
4438 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4439 // update non-physical objects like the joint proxy objects that represent the position
4440 // of the joints in the scene.
4441
4442 // This routine is normally called from within a lock(OdeLock) from within the OdePhysicsScene
4443 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4444 // from within the OdePhysicsScene.
4445
4446 protected internal void jointMoved(PhysicsJoint joint)
4447 {
4448
4449 // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock(OdeLock) when this callback is invoked
4450 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4451 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4452 if (jointProxyObject == null)
4453 {
4454 jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene);
4455 return;
4456 }
4457
4458 // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine
4459 SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup
4460 if (trackedBody == null) return; // the actor may have been deleted but the joint still lingers around a few frames waiting for deletion. during this time, trackedBody is NULL to prevent further motion of the joint proxy.
4461 jointProxyObject.Velocity = trackedBody.Velocity;
4462 jointProxyObject.RotationalVelocity = trackedBody.RotationalVelocity;
4463 switch (joint.Type)
4464 {
4465 case PhysicsJointType.Ball:
4466 {
4467 PhysicsVector jointAnchor = PhysicsScene.GetJointAnchor(joint);
4468 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z);
4469 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
4470 }
4471 break;
4472
4473 case PhysicsJointType.Hinge:
4474 {
4475 PhysicsVector jointAnchor = PhysicsScene.GetJointAnchor(joint);
4476
4477 // Normally, we would just ask the physics scene to return the axis for the joint.
4478 // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should
4479 // never occur. Therefore we cannot rely on ODE to always return a correct joint axis.
4480 // Therefore the following call does not always work:
4481 //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint);
4482
4483 // instead we compute the joint orientation by saving the original joint orientation
4484 // relative to one of the jointed bodies, and applying this transformation
4485 // to the current position of the jointed bodies (the tracked body) to compute the
4486 // current joint orientation.
4487
4488 if (joint.TrackedBodyName == null)
4489 {
4490 jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene);
4491 }
4492
4493 Vector3 proxyPos = new Vector3(jointAnchor.X, jointAnchor.Y, jointAnchor.Z);
4494 Quaternion q = trackedBody.RotationOffset * joint.LocalRotation;
4495
4496 jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update
4497 jointProxyObject.ParentGroup.UpdateGroupRotation(q); // schedules the entire group for a terse update
4498 }
4499 break;
4500 }
4501 }
4502
4503 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4504 // update non-physical objects like the joint proxy objects that represent the position
4505 // of the joints in the scene.
4506
4507 // This routine is normally called from within a lock(OdeLock) from within the OdePhysicsScene
4508 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4509 // from within the OdePhysicsScene.
4510 protected internal void jointDeactivated(PhysicsJoint joint)
4511 {
4512 //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene);
4513 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4514 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4515 if (jointProxyObject == null)
4516 {
4517 jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene);
4518 return;
4519 }
4520
4521 // turn the proxy non-physical, which also stops its client-side interpolation
4522 bool wasUsingPhysics = ((jointProxyObject.ObjectFlags & (uint)PrimFlags.Physics) != 0);
4523 if (wasUsingPhysics)
4524 {
4525 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
4526 }
4527 }
4528
4529 // This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and
4530 // alert the user of errors by using the debug channel in the same way that scripts alert
4531 // the user of compile errors.
4532
4533 // This routine is normally called from within a lock(OdeLock) from within the OdePhysicsScene
4534 // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called
4535 // from within the OdePhysicsScene.
4536 public void jointErrorMessage(PhysicsJoint joint, string message)
4537 {
4538 // FIXME: this causes a sequential lookup of all objects in the scene; use a dictionary
4539 if (joint != null)
4540 {
4541 if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
4542 return;
4543
4544 SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene);
4545 if (jointProxyObject != null)
4546 {
4547 SimChat(Utils.StringToBytes("[NINJA] " + message),
4548 ChatTypeEnum.DebugChannel,
4549 2147483647,
4550 jointProxyObject.AbsolutePosition,
4551 jointProxyObject.Name,
4552 jointProxyObject.UUID,
4553 false);
4554
4555 joint.ErrorMessageCount++;
4556
4557 if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages)
4558 {
4559 SimChat(Utils.StringToBytes("[NINJA] Too many messages for this joint, suppressing further messages."),
4560 ChatTypeEnum.DebugChannel,
4561 2147483647,
4562 jointProxyObject.AbsolutePosition,
4563 jointProxyObject.Name,
4564 jointProxyObject.UUID,
4565 false);
4566 }
4567 }
4568 else
4569 {
4570 // couldn't find the joint proxy object; the error message is silently suppressed
4571 }
4572 }
4573 }
4411 } 4574 }
4412} 4575}
diff --git a/OpenSim/Region/Environment/Scenes/SceneGraph.cs b/OpenSim/Region/Environment/Scenes/SceneGraph.cs
index dbb8539..d998dbb 100644
--- a/OpenSim/Region/Environment/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneGraph.cs
@@ -159,6 +159,22 @@ namespace OpenSim.Region.Environment.Scenes
159 { 159 {
160 lock (m_syncRoot) 160 lock (m_syncRoot)
161 { 161 {
162 // Here is where the Scene calls the PhysicsScene. This is a one-way
163 // interaction; the PhysicsScene cannot access the calling Scene directly.
164 // But with joints, we want a PhysicsActor to be able to influence a
165 // non-physics SceneObjectPart. In particular, a PhysicsActor that is connected
166 // with a joint should be able to move the SceneObjectPart which is the visual
167 // representation of that joint (for editing and serialization purposes).
168 // However the PhysicsActor normally cannot directly influence anything outside
169 // of the PhysicsScene, and the non-physical SceneObjectPart which represents
170 // the joint in the Scene does not exist in the PhysicsScene.
171 //
172 // To solve this, we have an event in the PhysicsScene that is fired when a joint
173 // has changed position (because one of its associated PhysicsActors has changed
174 // position).
175 //
176 // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
177
162 return _PhyScene.Simulate((float)elapsed); 178 return _PhyScene.Simulate((float)elapsed);
163 } 179 }
164 } 180 }
@@ -875,6 +891,7 @@ namespace OpenSim.Region.Environment.Scenes
875 { 891 {
876 List<EntityBase> EntityList = GetEntities(); 892 List<EntityBase> EntityList = GetEntities();
877 893
894 // FIXME: use a dictionary here
878 foreach (EntityBase ent in EntityList) 895 foreach (EntityBase ent in EntityList)
879 { 896 {
880 if (ent is SceneObjectGroup) 897 if (ent is SceneObjectGroup)
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)