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