internal DigitalRunePrismaticJoint(PrismaticJointDescriptor descriptor) { WrappedPrismaticJoint = new PrismaticJoint(); #region set RigidBodies if (!(descriptor.RigidBodyA is RigidBody)) throw new ArgumentException(String.Format("The type of the property 'RigidBodyA' must be '{0}'.", typeof(RigidBody))); WrappedPrismaticJoint.BodyA = ((RigidBody)descriptor.RigidBodyA).WrappedRigidBody; _rigidBodyA = descriptor.RigidBodyA; if (!(descriptor.RigidBodyB is RigidBody)) throw new ArgumentException("The type of the property 'RigidBodyB' must be 'System.Physics.DigitalRune.RigidBody'."); WrappedPrismaticJoint.BodyB = ((RigidBody)descriptor.RigidBodyB).WrappedRigidBody; _rigidBodyB = descriptor.RigidBodyB; #endregion WrappedPrismaticJoint.AnchorPoseALocal = descriptor.AnchorPoseALocal.ToDigitalRune(); WrappedPrismaticJoint.AnchorPoseBLocal = descriptor.AnchorPoseBLocal.ToDigitalRune(); WrappedPrismaticJoint.Maximum = descriptor.MaximumDistance; WrappedPrismaticJoint.Minimum = descriptor.MinimumDistance; Descriptor = descriptor; }
public ConstraintSample3(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // ----- HingeJoint with AngularVelocityMotor // A board is fixed on a pole like a wind wheel. // An AngularVelocityMotor creates a rotation with constant angular velocity around the // hinge axis. RigidBody box0 = new RigidBody(new BoxShape(0.1f, 2f, 0.1f)) { Pose = new Pose(new Vector3F(-2, 1, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box0); RigidBody box1 = new RigidBody(new BoxShape(0.1f, 0.4f, 1f)) { Pose = new Pose(new Vector3F(-2 + 0.05f, 1.8f, 0)) }; Simulation.RigidBodies.Add(box1); HingeJoint hingeJoint = new HingeJoint { BodyA = box0, BodyB = box1, AnchorPoseALocal = new Pose(new Vector3F(0.05f, 0.8f, 0)), AnchorPoseBLocal = new Pose(new Vector3F(-0.05f, 0, 0)), CollisionEnabled = false, }; Simulation.Constraints.Add(hingeJoint); AngularVelocityMotor angularVelocityMotor = new AngularVelocityMotor { BodyA = box0, // The rotation axis is the local x axis of BodyA. AxisALocal = Vector3F.UnitX, BodyB = box1, TargetVelocity = 10, // The motor power is limit, so that the rotation can be stopped by other objects blocking // the movement. MaxForce = 10000, // The HingeJoint controls all other axes. So this motor must only act on the hinge // axis. UseSingleAxisMode = true, CollisionEnabled = false, }; Simulation.Constraints.Add(angularVelocityMotor); // ----- A PrismaticJoint with a LinearVelocityMotor. RigidBody box2 = new RigidBody(new BoxShape(0.7f, 0.7f, 0.7f)) { Pose = new Pose(new Vector3F(0, 2, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box2); RigidBody box3 = new RigidBody(new BoxShape(0.5f, 1.5f, 0.5f)) { Pose = new Pose(new Vector3F(0, 1, 0)) }; Simulation.RigidBodies.Add(box3); _prismaticJoint = new PrismaticJoint { BodyA = box2, BodyB = box3, AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), AnchorPoseBLocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), CollisionEnabled = false, }; Simulation.Constraints.Add(_prismaticJoint); _linearVelocityMotor = new LinearVelocityMotor { BodyA = box2, AxisALocal = -Vector3F.UnitY, BodyB = box3, TargetVelocity = 1, CollisionEnabled = false, MaxForce = 10000, UseSingleAxisMode = true, }; Simulation.Constraints.Add(_linearVelocityMotor); // ----- A BallJoint with a TwistSwingLimit and a QuaternionMotor // The ball joint connects a cylinder to a static box. // The twist-swing limits rotational movement. // The quaternion motor acts like a spring that controls the angle of joint. RigidBody box4 = new RigidBody(new BoxShape(0.5f, 0.5f, 0.5f)) { Pose = new Pose(new Vector3F(2, 2, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box4); RigidBody cylinder0 = new RigidBody(new CylinderShape(0.1f, 0.75f)) { Pose = new Pose(new Vector3F(2, 2 - 0.75f / 2 - 0.25f, 0)) }; Simulation.RigidBodies.Add(cylinder0); _ballJoint = new BallJoint { BodyA = box4, BodyB = cylinder0, AnchorPositionALocal = new Vector3F(0, -0.25f, 0), AnchorPositionBLocal = new Vector3F(0, 0.75f / 2, 0), CollisionEnabled = false, }; Simulation.Constraints.Add(_ballJoint); _twistSwingLimit = new TwistSwingLimit { BodyA = box4, // The first column is the twist axis (-y). The other two columns are the swing axes. AnchorOrientationALocal = new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1), BodyB = cylinder0, AnchorOrientationBLocal = new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1), CollisionEnabled = false, // The twist is limited to +/- 10°. The swing limits are +/- 40° and +/- 60°. This creates // a deformed cone that limits the swing movements (see visualization). Minimum = new Vector3F(-MathHelper.ToRadians(10), -MathHelper.ToRadians(40), -MathHelper.ToRadians(60)), Maximum = new Vector3F(MathHelper.ToRadians(10), MathHelper.ToRadians(40), MathHelper.ToRadians(60)), }; Simulation.Constraints.Add(_twistSwingLimit); QuaternionMotor quaternionMotor = new QuaternionMotor { BodyA = box4, AnchorOrientationALocal = Matrix33F.Identity, BodyB = cylinder0, AnchorOrientationBLocal = Matrix33F.Identity, CollisionEnabled = false, // The QuaternionMotor controls the orientation of the second body relative to the first // body. Here, we define that the cylinder should swing 30° away from the default // orientation. TargetOrientation = QuaternionF.CreateRotationZ(MathHelper.ToRadians(30)), // Position and orientation motors are similar to damped-springs. We can control // the stiffness and damping of the spring. (It is also possible to set the SpringConstant // to 0 if the QuaternionMotor should only act as a rotational damping.) SpringConstant = 100, DampingConstant = 20, }; Simulation.Constraints.Add(quaternionMotor); }
public ConstraintSample1(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // Tip: It is best to initialize bodies in a position where the constraints are // satisfied - but even if they are initialized in other poses, the simulation // will try to move them to the correct positions. // ----- FixedJoint // Create two boxes and connect them with a FixedJoint. RigidBody box0 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(-5, 3, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box0); RigidBody box1 = new RigidBody(new BoxShape(1.2f, 1.2f, 1.2f)) { Pose = new Pose(new Vector3F(-5, 3 - 1.2f, 0)) }; Simulation.RigidBodies.Add(box1); FixedJoint fixedJoint = new FixedJoint { BodyA = box0, // The attachment point on the first box is at the bottom of the box. AnchorPoseALocal = new Pose(new Vector3F(0, -0.5f, 0)), BodyB = box1, // The attachment point on the second box is at the top of the box. AnchorPoseBLocal = new Pose(new Vector3F(0, 0.6f, 0)), // Disable collision between the connected bodies. CollisionEnabled = false, }; Simulation.Constraints.Add(fixedJoint); // ----- BallJoint // Create two boxes and connect a corner of the second box with a ball-and-socked joint // to the first box. RigidBody box2 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(-3, 3, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box2); RigidBody box3 = new RigidBody(new BoxShape(1.2f, 1.2f, 1.2f)) { Pose = new Pose(new Vector3F(-3, 3, 0)) }; Simulation.RigidBodies.Add(box3); BallJoint ballJoint = new BallJoint { BodyA = box2, // The attachment point on the first box is at the box bottom. AnchorPositionALocal = new Vector3F(0, -0.5f, 0), BodyB = box3, // The attachment point on the second box is a corner of the box. AnchorPositionBLocal = new Vector3F(0.6f, 0.6f, 0.6f), }; Simulation.Constraints.Add(ballJoint); // ----- PrismaticJoint // A prismatic joint is like a slider (without rotation around the slider axis). RigidBody box4 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(-1, 3, 0)), }; Simulation.RigidBodies.Add(box4); RigidBody box5 = new RigidBody(new BoxShape(0.5f, 1.5f, 0.5f)) { Pose = new Pose(new Vector3F(-1, 3 - 0.5f, 0)) }; Simulation.RigidBodies.Add(box5); PrismaticJoint prismaticJoint = new PrismaticJoint { BodyA = box4, // The attachment point on the first box is in the center of the box. // The slider joint allows linear movement along the first constraint axis. // --> To define the constraint anchor orientation: // The columns are the axes. We set the local -y axis in the first column. This is the // slider axis. The other two columns are two orthonormal axes. // (All three columns are orthonormal and form a valid rotation matrix.) AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), BodyB = box5, // The attachment point on the second box is at the top of the box. AnchorPoseBLocal = new Pose(new Vector3F(0, 0.75f, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), CollisionEnabled = false, // The slider axis is -y. We limit the up movement, so that the anchor point on the second // body can slide up to the anchor point on the first body, but not higher. Minimum = 0, // The second body can slide down until the anchor points have a max. distance of 0.5. Maximum = 0.5f, }; Simulation.Constraints.Add(prismaticJoint); // ----- CylindricalJoint // A cylindrical joint is a slider that allows rotation around the slider axis. RigidBody box6 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(1, 3, 0)), }; Simulation.RigidBodies.Add(box6); RigidBody box7 = new RigidBody(new BoxShape(0.5f, 1.5f, 0.5f)) { Pose = new Pose(new Vector3F(1, 3 - 0.5f, 0)) }; Simulation.RigidBodies.Add(box7); CylindricalJoint cylindricalJoint = new CylindricalJoint { BodyA = box6, AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), BodyB = box7, AnchorPoseBLocal = new Pose(new Vector3F(0, 0.75f, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), CollisionEnabled = false, // The linear movement limits on the slider axis. LinearMinimum = 0, LinearMaximum = 0.5f, // The rotation limits around the slider axis (in radians). Here, we allow free // rotations. AngularMinimum = float.NegativeInfinity, AngularMaximum = float.PositiveInfinity, }; Simulation.Constraints.Add(cylindricalJoint); // ----- HingeJoint // Hinge joints allow rotations around one axis. They can be used to model swinging doors // or rotating wheels. RigidBody cylinder0 = new RigidBody(new CylinderShape(0.1f, 2f)) { Pose = new Pose(new Vector3F(3, 1, 0)), MotionType = MotionType.Static }; Simulation.RigidBodies.Add(cylinder0); RigidBody box8 = new RigidBody(new BoxShape(1f, 1.8f, 0.1f)) { Pose = new Pose(new Vector3F(3 + 0.5f, 1, 0)) }; Simulation.RigidBodies.Add(box8); HingeJoint hingeJoint = new HingeJoint { BodyA = cylinder0, AnchorPoseALocal = new Pose(new Vector3F(0, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), BodyB = box8, AnchorPoseBLocal = new Pose(new Vector3F(-0.5f, 0, 0), new Matrix33F(0, 1, 0, -1, 0, 0, 0, 0, 1)), CollisionEnabled = false, // The rotation limits around the hinge axis (in radians). Minimum = -ConstantsF.PiOver2, Maximum = ConstantsF.PiOver2, }; Simulation.Constraints.Add(hingeJoint); }