diff options
Diffstat (limited to 'OpenSim/Region/Environment/Scenes/Scene.cs')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/Scene.cs | 167 |
1 files changed, 165 insertions, 2 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 | } |