private void SerializeJoint(Joint joint) { if (joint.IsFixedType()) return; _writer.WriteStartElement("Joint"); _writer.WriteAttributeString("Type", joint.JointType.ToString()); WriteElement("BodyA", FindBodyIndex(joint.BodyA)); WriteElement("BodyB", FindBodyIndex(joint.BodyB)); WriteElement("CollideConnected", joint.CollideConnected); WriteElement("Breakpoint", joint.Breakpoint); if (joint.UserData != null) { _writer.WriteStartElement("UserData"); WriteDynamicType(joint.UserData.GetType(), joint.UserData); _writer.WriteEndElement(); } switch (joint.JointType) { case JointType.Distance: { DistanceJoint djd = (DistanceJoint)joint; WriteElement("DampingRatio", djd.DampingRatio); WriteElement("FrequencyHz", djd.Frequency); WriteElement("Length", djd.Length); WriteElement("LocalAnchorA", djd.LocalAnchorA); WriteElement("LocalAnchorB", djd.LocalAnchorB); } break; case JointType.Friction: { FrictionJoint fjd = (FrictionJoint)joint; WriteElement("LocalAnchorA", fjd.LocalAnchorA); WriteElement("LocalAnchorB", fjd.LocalAnchorB); WriteElement("MaxForce", fjd.MaxForce); WriteElement("MaxTorque", fjd.MaxTorque); } break; case JointType.Gear: throw new Exception("Gear joint not supported by serialization"); case JointType.Line: { LineJoint ljd = (LineJoint)joint; WriteElement("EnableMotor", ljd.MotorEnabled); WriteElement("LocalAnchorA", ljd.LocalAnchorA); WriteElement("LocalAnchorB", ljd.LocalAnchorB); WriteElement("MotorSpeed", ljd.MotorSpeed); WriteElement("DampingRatio", ljd.DampingRatio); WriteElement("MaxMotorTorque", ljd.MaxMotorTorque); WriteElement("FrequencyHz", ljd.Frequency); WriteElement("LocalXAxis", ljd.LocalXAxis); } break; case JointType.Prismatic: { PrismaticJoint pjd = (PrismaticJoint)joint; //NOTE: Does not conform with Box2DScene WriteElement("EnableLimit", pjd.LimitEnabled); WriteElement("EnableMotor", pjd.MotorEnabled); WriteElement("LocalAnchorA", pjd.LocalAnchorA); WriteElement("LocalAnchorB", pjd.LocalAnchorB); WriteElement("LocalXAxis1", pjd.LocalXAxis1); WriteElement("LowerTranslation", pjd.LowerLimit); WriteElement("UpperTranslation", pjd.UpperLimit); WriteElement("MaxMotorForce", pjd.MaxMotorForce); WriteElement("MotorSpeed", pjd.MotorSpeed); } break; case JointType.Pulley: { PulleyJoint pjd = (PulleyJoint)joint; WriteElement("GroundAnchorA", pjd.GroundAnchorA); WriteElement("GroundAnchorB", pjd.GroundAnchorB); WriteElement("LengthA", pjd.LengthA); WriteElement("LengthB", pjd.LengthB); WriteElement("LocalAnchorA", pjd.LocalAnchorA); WriteElement("LocalAnchorB", pjd.LocalAnchorB); WriteElement("MaxLengthA", pjd.MaxLengthA); WriteElement("MaxLengthB", pjd.MaxLengthB); WriteElement("Ratio", pjd.Ratio); } break; case JointType.Revolute: { RevoluteJoint rjd = (RevoluteJoint)joint; WriteElement("EnableLimit", rjd.LimitEnabled); WriteElement("EnableMotor", rjd.MotorEnabled); WriteElement("LocalAnchorA", rjd.LocalAnchorA); WriteElement("LocalAnchorB", rjd.LocalAnchorB); WriteElement("LowerAngle", rjd.LowerLimit); WriteElement("MaxMotorTorque", rjd.MaxMotorTorque); WriteElement("MotorSpeed", rjd.MotorSpeed); WriteElement("ReferenceAngle", rjd.ReferenceAngle); WriteElement("UpperAngle", rjd.UpperLimit); } break; case JointType.Weld: { WeldJoint wjd = (WeldJoint)joint; WriteElement("LocalAnchorA", wjd.LocalAnchorA); WriteElement("LocalAnchorB", wjd.LocalAnchorB); } break; // // Not part of Box2DScene // case JointType.Rope: { RopeJoint rjd = (RopeJoint)joint; WriteElement("LocalAnchorA", rjd.LocalAnchorA); WriteElement("LocalAnchorB", rjd.LocalAnchorB); WriteElement("MaxLength", rjd.MaxLength); } break; case JointType.Angle: { AngleJoint aj = (AngleJoint)joint; WriteElement("BiasFactor", aj.BiasFactor); WriteElement("MaxImpulse", aj.MaxImpulse); WriteElement("Softness", aj.Softness); WriteElement("TargetAngle", aj.TargetAngle); } break; case JointType.Slider: { SliderJoint sliderJoint = (SliderJoint)joint; WriteElement("DampingRatio", sliderJoint.DampingRatio); WriteElement("FrequencyHz", sliderJoint.Frequency); WriteElement("MaxLength", sliderJoint.MaxLength); WriteElement("MinLength", sliderJoint.MinLength); WriteElement("LocalAnchorA", sliderJoint.LocalAnchorA); WriteElement("LocalAnchorB", sliderJoint.LocalAnchorB); } break; default: throw new Exception("Joint not supported"); } _writer.WriteEndElement(); }
private void DrawJoint(Joint joint) { if (!joint.Enabled) return; Body b1 = joint.BodyA; Body b2 = joint.BodyB; Transform xf1; b1.GetTransform(out xf1); Vector2 x2 = Vector2.Zero; // WIP David if (!joint.IsFixedType()) { Transform xf2; b2.GetTransform(out xf2); x2 = xf2.p; } Vector2 p1 = joint.WorldAnchorA; Vector2 p2 = joint.WorldAnchorB; Vector2 x1 = xf1.p; Color color = Color.FromArgb(255, 128, 205, 205); switch (joint.JointType) { case JointType.Distance: DrawSegment(p1, p2, color); break; case JointType.Pulley: PulleyJoint pulley = (PulleyJoint)joint; Vector2 s1 = b1.GetWorldPoint(pulley.LocalAnchorA); Vector2 s2 = b2.GetWorldPoint(pulley.LocalAnchorB); DrawSegment(p1, p2, color); DrawSegment(p1, s1, color); DrawSegment(p2, s2, color); break; case JointType.FixedMouse: DrawPoint(p1, 0.5f, Color.FromArgb(255, 0, 255, 0)); DrawSegment(p1, p2, Color.FromArgb(255, 205, 205, 205)); break; case JointType.Revolute: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); DrawSegment(x2, p2, color); DrawSolidCircle(p2, 0.1f, Vector2.Zero, Colors.Red); DrawSolidCircle(p1, 0.1f, Vector2.Zero, Colors.Blue); break; case JointType.FixedAngle: //Should not draw anything. break; case JointType.FixedRevolute: DrawSegment(x1, p1, color); DrawSolidCircle(p1, 0.1f, Vector2.Zero, Colors.Purple); break; case JointType.FixedLine: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedDistance: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedPrismatic: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.Gear: DrawSegment(x1, x2, color); break; default: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); DrawSegment(x2, p2, color); break; } }
private void DrawJoint(Joint joint) { Body b1 = joint.BodyA; Body b2 = joint.BodyB; Transform xf1, xf2; b1.GetTransform(out xf1); Vector2 x2 = new Vector2(); // WIP David if (!joint.IsFixedType()) { b2.GetTransform(out xf2); x2 = xf2.Position; } Vector2 p2 = joint.WorldAnchorB; Vector2 x1 = xf1.Position; Vector2 p1 = joint.WorldAnchorA; Color color = new Color(0.5f, 0.8f, 0.8f); switch (joint.JointType) { case JointType.Distance: DrawSegment(p1, p2, color); break; case JointType.Pulley: { PulleyJoint pulley = (PulleyJoint) joint; Vector2 s1 = pulley.GroundAnchorA; Vector2 s2 = pulley.GroundAnchorB; DrawSegment(s1, p1, color); DrawSegment(s2, p2, color); DrawSegment(s1, s2, color); } break; case JointType.FixedMouse: FixedMouseJoint fixedMouseJoint = (FixedMouseJoint) joint; p1 = fixedMouseJoint.Target; DrawPoint(p2, 0.5f, new Color(0.0f, 1.0f, 0.0f)); DrawSegment(p1, p2, new Color(0.8f, 0.8f, 0.8f)); break; case JointType.Revolute: //DrawSegment(x2, p1, color); DrawSegment(p2, p1, color); DrawSolidCircle(p2, 0.1f, new Vector2(), Color.Red); DrawSolidCircle(p1, 0.1f, new Vector2(), Color.Blue); break; case JointType.FixedRevolute: DrawSolidCircle(p1, 0.1f, new Vector2(), Color.Pink); break; case JointType.FixedLine: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedDistance: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedPrismatic: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.Gear: DrawSegment(x1, x2, color); //DrawSegment(x1, p1, color); //DrawSegment(p1, p2, color); break; default: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); DrawSegment(x2, p2, color); break; } }
private void DrawJoint(Joint joint) { Body b1 = joint.BodyA; Body b2 = joint.BodyB; Transform xf1, xf2; b1.GetTransform(out xf1); Vector2 x2 = new Vector2(); // WIP David if (!joint.IsFixedType()) { b2.GetTransform(out xf2); x2 = xf2.p; } Vector2 p2 = joint.WorldAnchorB; Vector2 x1 = xf1.p; Vector2 p1 = joint.WorldAnchorA; Color color = Color.FromArgb(255, 128, 205, 205); switch (joint.JointType) { case JointType.Distance: DrawSegment(p1, p2, color); break; case JointType.Pulley: { PulleyJoint pulley = (PulleyJoint)joint; Vector2 s1 = pulley.GroundAnchorA; Vector2 s2 = pulley.GroundAnchorB; DrawSegment(s1, p1, color); DrawSegment(s2, p2, color); DrawSegment(s1, s2, color); } break; case JointType.FixedMouse: DrawPoint(p1, 0.5f, Color.FromArgb(255, 0, 255, 0)); DrawSegment(p1, p2, Color.FromArgb(255, 205, 205, 205)); break; case JointType.Revolute: //DrawSegment(x2, p1, color); DrawSegment(p2, p1, color); DrawSolidCircle(p2, 0.1f, new Vector2(), Colors.Red); DrawSolidCircle(p1, 0.1f, new Vector2(), Colors.Blue); break; case JointType.FixedRevolute: DrawSolidCircle(p1, 0.1f, new Vector2(), Colors.Purple); break; case JointType.FixedLine: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedDistance: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.FixedPrismatic: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); break; case JointType.Gear: DrawSegment(x1, x2, color); //DrawSegment(x1, p1, color); //DrawSegment(p1, p2, color); break; default: DrawSegment(x1, p1, color); DrawSegment(p1, p2, color); DrawSegment(x2, p2, color); break; } }
/// <summary> /// Destroy a joint. This may cause the connected bodies to begin colliding. /// Warning: This function is locked during callbacks. /// </summary> /// <param name="joint">The joint.</param> public void RemoveJoint(Joint joint) { Debug.Assert(!IsLocked); if (IsLocked) { return; } bool collideConnected = joint.CollideConnected; // Remove from the world list. JointList.Remove(joint); // Disconnect from island graph. Body bodyA = joint.BodyA; Body bodyB = joint.BodyB; // Wake up connected bodies. bodyA.Awake = true; // WIP David if (!joint.IsFixedType()) { bodyB.Awake = true; } // Remove from body 1. if (joint.EdgeA.Prev != null) { joint.EdgeA.Prev.Next = joint.EdgeA.Next; } if (joint.EdgeA.Next != null) { joint.EdgeA.Next.Prev = joint.EdgeA.Prev; } if (joint.EdgeA == bodyA.JointList) { bodyA.JointList = joint.EdgeA.Next; } joint.EdgeA.Prev = null; joint.EdgeA.Next = null; // WIP David if (!joint.IsFixedType()) { // Remove from body 2 if (joint.EdgeB.Prev != null) { joint.EdgeB.Prev.Next = joint.EdgeB.Next; } if (joint.EdgeB.Next != null) { joint.EdgeB.Next.Prev = joint.EdgeB.Prev; } if (joint.EdgeB == bodyB.JointList) { bodyB.JointList = joint.EdgeB.Next; } joint.EdgeB.Prev = null; joint.EdgeB.Next = null; } // WIP David if (!joint.IsFixedType()) { // If the joint prevents collisions, then flag any contacts for filtering. if (collideConnected == false) { ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.Other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge.Contact.FlagForFiltering(); } edge = edge.Next; } } } if (JointRemoved != null) { JointRemoved(joint); } }
/// <summary> /// Create a joint to constrain bodies together. This may cause the connected bodies to cease colliding. /// Warning: This function is locked during callbacks. /// </summary> /// <param name="joint">The joint.</param> public void AddJoint(Joint joint) { Debug.Assert(!IsLocked); if (IsLocked) { return; } // Connect to the world list. JointList.Add(joint); // Connect to the bodies' doubly linked lists. joint.EdgeA.Joint = joint; joint.EdgeA.Other = joint.BodyB; joint.EdgeA.Prev = null; joint.EdgeA.Next = joint.BodyA.JointList; if (joint.BodyA.JointList != null) joint.BodyA.JointList.Prev = joint.EdgeA; joint.BodyA.JointList = joint.EdgeA; // WIP David if (!joint.IsFixedType()) { joint.EdgeB.Joint = joint; joint.EdgeB.Other = joint.BodyA; joint.EdgeB.Prev = null; joint.EdgeB.Next = joint.BodyB.JointList; if (joint.BodyB.JointList != null) joint.BodyB.JointList.Prev = joint.EdgeB; joint.BodyB.JointList = joint.EdgeB; } // WIP David if (!joint.IsFixedType()) { Body bodyA = joint.BodyA; Body bodyB = joint.BodyB; // If the joint prevents collisions, then flag any contacts for filtering. if (joint.CollideConnected == false) { ContactEdge edge = bodyB.ContactList; while (edge != null) { if (edge.Other == bodyA) { // Flag the contact for filtering at the next time step (where either // body is awake). edge.Contact.FlagForFiltering(); } edge = edge.Next; } } } if (JointAdded != null) JointAdded(joint); // Note: creating a joint doesn't wake the bodies. }