protected virtual void DoJointDeactivated(PhysicsJoint joint) { // We need this to allow subclasses (but not other classes) to invoke the event; C# does // not allow subclasses to invoke the parent class event. if (OnJointDeactivated != null) { OnJointDeactivated(joint); } }
protected virtual void DoJointErrorMessage(PhysicsJoint joint, string message) { // We need this to allow subclasses (but not other classes) to invoke the event; C# does // not allow subclasses to invoke the parent class event. if (OnJointErrorMessage != null) { OnJointErrorMessage(joint, message); } }
public virtual Vector3 GetJointAxis(PhysicsJoint joint) { return Vector3.Zero; }
protected virtual void DoJointErrorMessage(PhysicsJoint joint, string message) { // We need this to allow subclasses (but not other classes) to invoke the event; C# does // not allow subclasses to invoke the parent class event. if (OnJointErrorMessage != null) { OnJointErrorMessage(joint, message); } }
protected virtual void DoJointDeactivated(PhysicsJoint joint) { // We need this to allow subclasses (but not other classes) to invoke the event; C# does // not allow subclasses to invoke the parent class event. if (OnJointDeactivated != null) { OnJointDeactivated(joint); } }
public virtual Vector3 GetJointAxis(PhysicsJoint joint) { return(Vector3.Zero); }
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and // update non-physical objects like the joint proxy objects that represent the position // of the joints in the scene. // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called // from within the OdePhysicsScene. protected internal void jointDeactivated(PhysicsJoint joint) { //m_log.Debug("[NINJA] SceneGraph.jointDeactivated, joint:" + joint.ObjectNameInScene); SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); if (jointProxyObject == null) { jointErrorMessage(joint, "WARNING, trying to deactivate (stop interpolation of) joint proxy, but not found, name " + joint.ObjectNameInScene); return; } // turn the proxy non-physical, which also stops its client-side interpolation bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); if (wasUsingPhysics) { jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock } }
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and // alert the user of errors by using the debug channel in the same way that scripts alert // the user of compile errors. // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called // from within the OdePhysicsScene. public void jointErrorMessage(PhysicsJoint joint, string message) { if (joint != null) { if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) return; SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); if (jointProxyObject != null) { SimChat(Utils.StringToBytes("[NINJA]: " + message), ChatTypeEnum.DebugChannel, 2147483647, jointProxyObject.AbsolutePosition, jointProxyObject.Name, jointProxyObject.UUID, false); joint.ErrorMessageCount++; if (joint.ErrorMessageCount > PhysicsJoint.maxErrorMessages) { SimChat(Utils.StringToBytes("[NINJA]: Too many messages for this joint, suppressing further messages."), ChatTypeEnum.DebugChannel, 2147483647, jointProxyObject.AbsolutePosition, jointProxyObject.Name, jointProxyObject.UUID, false); } } else { // couldn't find the joint proxy object; the error message is silently suppressed } } }
// This callback allows the PhysicsScene to call back to its caller (the SceneGraph) and // update non-physical objects like the joint proxy objects that represent the position // of the joints in the scene. // This routine is normally called from within a lock (OdeLock) from within the OdePhysicsScene // WARNING: be careful of deadlocks here if you manipulate the scene. Remember you are being called // from within the OdePhysicsScene. protected internal void jointMoved(PhysicsJoint joint) { // m_parentScene.PhysicsScene.DumpJointInfo(); // non-thread-locked version; we should already be in a lock (OdeLock) when this callback is invoked SceneObjectPart jointProxyObject = GetSceneObjectPart(joint.ObjectNameInScene); if (jointProxyObject == null) { jointErrorMessage(joint, "WARNING, joint proxy not found, name " + joint.ObjectNameInScene); return; } // now update the joint proxy object in the scene to have the position of the joint as returned by the physics engine SceneObjectPart trackedBody = GetSceneObjectPart(joint.TrackedBodyName); // FIXME: causes a sequential lookup 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. jointProxyObject.Velocity = trackedBody.Velocity; jointProxyObject.AngularVelocity = trackedBody.AngularVelocity; switch (joint.Type) { case PhysicsJointType.Ball: { Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); Vector3 proxyPos = jointAnchor; jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update } break; case PhysicsJointType.Hinge: { Vector3 jointAnchor = PhysicsScene.GetJointAnchor(joint); // Normally, we would just ask the physics scene to return the axis for the joint. // Unfortunately, ODE sometimes returns <0,0,0> for the joint axis, which should // never occur. Therefore we cannot rely on ODE to always return a correct joint axis. // Therefore the following call does not always work: //PhysicsVector phyJointAxis = _PhyScene.GetJointAxis(joint); // instead we compute the joint orientation by saving the original joint orientation // relative to one of the jointed bodies, and applying this transformation // to the current position of the jointed bodies (the tracked body) to compute the // current joint orientation. if (joint.TrackedBodyName == null) { jointErrorMessage(joint, "joint.TrackedBodyName is null, joint " + joint.ObjectNameInScene); } Vector3 proxyPos = jointAnchor; Quaternion q = trackedBody.RotationOffset * joint.LocalRotation; jointProxyObject.ParentGroup.UpdateGroupPosition(proxyPos); // schedules the entire group for a terse update jointProxyObject.ParentGroup.UpdateGroupRotationR(q); // schedules the entire group for a terse update } break; } }
/// <summary> /// Get joint axis. /// </summary> /// <remarks> /// normally called from within OnJointMoved, which is called from within a lock (OdeLock) /// WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function /// appears to be unreliable. Fortunately we can compute the joint axis ourselves by /// keeping track of the joint's original orientation relative to one of the involved bodies. /// </remarks> /// <param name="joint"></param> /// <returns></returns> public override Vector3 GetJointAxis(PhysicsJoint joint) { Debug.Assert(joint.IsInPhysicsEngine); d.Vector3 axis = new d.Vector3(); if (!(joint is OdePhysicsJoint)) { DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); } else { OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; switch (odeJoint.Type) { case PhysicsJointType.Ball: DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene); break; case PhysicsJointType.Hinge: d.JointGetHingeAxis(odeJoint.jointID, out axis); break; } } return new Vector3(axis.X, axis.Y, axis.Z); }
// internal utility function: must be called within a lock (OdeLock) private void InternalRemoveActiveJoint(PhysicsJoint joint) { activeJoints.Remove(joint); SOPName_to_activeJoint.Remove(joint.ObjectNameInScene); }
// internal utility function: must be called within a lock (OdeLock) private void InternalRemovePendingJoint(PhysicsJoint joint) { pendingJoints.Remove(joint); SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene); }
// internal utility function: must be called within a lock (OdeLock) private void InternalAddActiveJoint(PhysicsJoint joint) { activeJoints.Add(joint); SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint); }