public void Initialize(Simulation simulation)
 {
     if (this.ContactSpringiness.AngularFrequency == 0 && this.ContactSpringiness.TwiceDampingRatio == 0)
     {
         this.ContactSpringiness      = new(30, 1);
         this.MaximumRecoveryVelocity = 2f;
         this.FrictionCoefficient     = 1f;
     }
 }
Beispiel #2
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-5f, 5.5f, 5f);
            camera.Yaw      = MathHelper.Pi / 4;
            camera.Pitch    = MathHelper.Pi * 0.15f;

            var filters = new BodyProperty <DeformableCollisionFilter>();

            Simulation = Simulation.Create(BufferPool, new DeformableCallbacks {
                Filters = filters
            }, new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            var   meshContent = content.Load <MeshContent>("Content\\newt.obj");
            float cellSize    = 0.1f;

            DumbTetrahedralizer.Tetrahedralize(meshContent.Triangles, cellSize, BufferPool,
                                               out var vertices, out var vertexSpatialIndices, out var cellVertexIndices, out var tetrahedraVertexIndices);
            var weldSpringiness   = new SpringSettings(30f, 0);
            var volumeSpringiness = new SpringSettings(30f, 1);

            for (int i = 0; i < 5; ++i)
            {
                NewtDemo.CreateDeformable(Simulation, new Vector3(i * 3, 5 + i * 1.5f, 0), Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathF.PI * (i * 0.55f)), 1f, cellSize, weldSpringiness, volumeSpringiness, i, filters, ref vertices, ref vertexSpatialIndices, ref cellVertexIndices, ref tetrahedraVertexIndices);
            }

            BufferPool.Return(ref vertices);
            vertexSpatialIndices.Dispose(BufferPool);
            BufferPool.Return(ref cellVertexIndices);
            BufferPool.Return(ref tetrahedraVertexIndices);

            Simulation.Bodies.Add(BodyDescription.CreateConvexDynamic(new Vector3(0, 100, -.5f), 10, Simulation.Shapes, new Sphere(5)));

            Simulation.Statics.Add(new StaticDescription(new Vector3(0, -0.5f, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(1500, 1, 1500)), 0.1f)));
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, -1.5f, 0), new CollidableDescription(Simulation.Shapes.Add(new Sphere(3)), 0.1f)));

            var bulletShape = new Sphere(0.5f);

            bulletShape.ComputeInertia(.25f, out var bulletInertia);
            bulletDescription = BodyDescription.CreateDynamic(RigidPose.Identity, bulletInertia, new CollidableDescription(Simulation.Shapes.Add(bulletShape), 1f), new BodyActivityDescription(0.01f));

            DemoMeshHelper.LoadModel(content, BufferPool, "Content\\newt.obj", new Vector3(20), out var mesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(200, 0.5f, 120), Quaternion.CreateFromAxisAngle(Vector3.UnitY, -3 * MathHelper.PiOver4), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f)));
        }
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(25, 4, 40);
            camera.Yaw      = 0;
            Simulation      = Simulation.Create(BufferPool, new TestCallbacks());

            Simulation.PoseIntegrator.Gravity = new Vector3(0, -10, 0);

            var shapeA      = new Box(.75f, 1, .5f);
            var shapeIndexA = Simulation.Shapes.Add(shapeA);
            var collidableA = new CollidableDescription(shapeIndexA, 0.1f);
            var shapeB      = new Box(.75f, 1, .5f);
            var shapeIndexB = Simulation.Shapes.Add(shapeB);
            var collidableB = new CollidableDescription(shapeIndexB, 0.1f);
            var activity    = new BodyActivityDescription(0.01f);

            shapeA.ComputeInertia(1, out var inertiaA);
            shapeA.ComputeInertia(1, out var inertiaB);
            var nextX = -10f;

            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new Hinge
                {
                    LocalOffsetA    = new Vector3(0, 1, 0),
                    LocalHingeAxisA = new Vector3(0, 1, 0),
                    LocalOffsetB    = new Vector3(0, -1, 0),
                    LocalHingeAxisB = new Vector3(0, 1, 0),
                    SpringSettings  = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularSwivelHinge {
                    LocalSwivelAxisA = new Vector3(1, 0, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new SwingLimit {
                    AxisLocalA = new Vector3(0, 1, 0), AxisLocalB = new Vector3(0, 1, 0), MaximumSwingAngle = MathHelper.PiOver2, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new SwivelHinge
                {
                    LocalOffsetA     = new Vector3(0, 1, 0),
                    LocalSwivelAxisA = new Vector3(1, 0, 0),
                    LocalOffsetB     = new Vector3(0, -1, 0),
                    LocalHingeAxisB  = new Vector3(0, 1, 0),
                    SpringSettings   = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new SwingLimit {
                    AxisLocalA = new Vector3(0, 1, 0), AxisLocalB = new Vector3(0, 1, 0), MaximumSwingAngle = MathHelper.PiOver2, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistServo
                {
                    LocalBasisA    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    LocalBasisB    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    TargetAngle    = MathHelper.PiOver4,
                    SpringSettings = new SpringSettings(30, 1),
                    ServoSettings  = new ServoSettings(float.MaxValue, 0, float.MaxValue)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistLimit
                {
                    LocalBasisA    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    LocalBasisB    = RagdollDemo.CreateBasis(new Vector3(0, 1, 0), new Vector3(1, 0, 0)),
                    MinimumAngle   = MathHelper.Pi * -0.5f,
                    MaximumAngle   = MathHelper.Pi * 0.95f,
                    SpringSettings = new SpringSettings(30, 1),
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new TwistMotor
                {
                    LocalAxisA     = new Vector3(0, 1, 0),
                    LocalAxisB     = new Vector3(0, 1, 0),
                    TargetVelocity = MathHelper.Pi * 2,
                    Settings       = new MotorSettings(float.MaxValue, 0.1f)
                });
                Simulation.Solver.Add(a, b, new AngularHinge {
                    LocalHingeAxisA = new Vector3(0, 1, 0), LocalHingeAxisB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(x, 3, 0), collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularServo
                {
                    TargetRelativeRotationLocalA = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathHelper.PiOver2),
                    ServoSettings  = new ServoSettings(float.MaxValue, 0, 12f),
                    SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x = GetNextPosition(ref nextX);
                var a = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity));
                var b = Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity));
                Simulation.Solver.Add(a, b, new BallSocket {
                    LocalOffsetA = new Vector3(0, 1, 0), LocalOffsetB = new Vector3(0, -1, 0), SpringSettings = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(a, b, new AngularMotor {
                    TargetVelocityLocalA = new Vector3(0, 1, 0), Settings = new MotorSettings(15, 0.0001f)
                });
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 5, 0), inertiaB, collidableB, activity);
                //aDescription.Velocity.Angular = new Vector3(0, 0, 5);
                var a = Simulation.Bodies.Add(aDescription);
                var b = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new Weld {
                    LocalOffset = new Vector3(0, 2, 0), LocalOrientation = Quaternion.Identity, SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var x      = GetNextPosition(ref nextX);
                var sphere = new Sphere(0.125f);
                //Treat each vertex as a point mass that cannot rotate.
                var sphereInertia = new BodyInertia {
                    InverseMass = 1
                };
                var sphereCollidable = new CollidableDescription(Simulation.Shapes.Add(sphere), 0.1f);
                var a                   = new Vector3(x, 3, 0);
                var b                   = new Vector3(x, 4, 0);
                var c                   = new Vector3(x, 3, 1);
                var d                   = new Vector3(x + 1, 3, 0);
                var aDescription        = BodyDescription.CreateDynamic(a, sphereInertia, sphereCollidable, activity);
                var bDescription        = BodyDescription.CreateDynamic(b, sphereInertia, sphereCollidable, activity);
                var cDescription        = BodyDescription.CreateDynamic(c, sphereInertia, sphereCollidable, activity);
                var dDescription        = BodyDescription.CreateDynamic(d, sphereInertia, sphereCollidable, activity);
                var aHandle             = Simulation.Bodies.Add(aDescription);
                var bHandle             = Simulation.Bodies.Add(bDescription);
                var cHandle             = Simulation.Bodies.Add(cDescription);
                var dHandle             = Simulation.Bodies.Add(dDescription);
                var distanceSpringiness = new SpringSettings(3f, 1);
                Simulation.Solver.Add(aHandle, bHandle, new CenterDistanceConstraint(Vector3.Distance(a, b), distanceSpringiness));
                Simulation.Solver.Add(aHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(a, c), distanceSpringiness));
                Simulation.Solver.Add(aHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(a, d), distanceSpringiness));
                Simulation.Solver.Add(bHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(b, c), distanceSpringiness));
                Simulation.Solver.Add(bHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(b, d), distanceSpringiness));
                Simulation.Solver.Add(cHandle, dHandle, new CenterDistanceConstraint(Vector3.Distance(c, d), distanceSpringiness));
                Simulation.Solver.Add(aHandle, bHandle, cHandle, dHandle, new VolumeConstraint(a, b, c, d, new SpringSettings(30, 1)));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 6, 0), inertiaB, collidableB, activity);
                var a            = Simulation.Bodies.Add(aDescription);
                var b            = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new DistanceServo(new Vector3(0, 0.55f, 0), new Vector3(0, -0.55f, 0), 1.9f, new SpringSettings(30, 1), ServoSettings.Default));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), inertiaA, collidableA, activity);
                var bDescription = BodyDescription.CreateDynamic(new Vector3(x, 6, 0), inertiaB, collidableB, activity);
                var a            = Simulation.Bodies.Add(aDescription);
                var b            = Simulation.Bodies.Add(bDescription);
                Simulation.Solver.Add(a, b, new DistanceLimit(new Vector3(0, 0.55f, 0), new Vector3(0, -0.55f, 0), 1f, 3, new SpringSettings(30, 1)));
            }
            {
                var x      = GetNextPosition(ref nextX);
                var sphere = new Sphere(0.125f);
                //Treat each vertex as a point mass that cannot rotate.
                var sphereInertia = new BodyInertia {
                    InverseMass = 1
                };
                var sphereCollidable = new CollidableDescription(Simulation.Shapes.Add(sphere), 0.1f);
                var a                   = new Vector3(x, 3, 0);
                var b                   = new Vector3(x, 4, 0);
                var c                   = new Vector3(x + 1, 3, 0);
                var aDescription        = BodyDescription.CreateDynamic(a, sphereInertia, sphereCollidable, activity);
                var bDescription        = BodyDescription.CreateDynamic(b, sphereInertia, sphereCollidable, activity);
                var cDescription        = BodyDescription.CreateDynamic(c, sphereInertia, sphereCollidable, activity);
                var aHandle             = Simulation.Bodies.Add(aDescription);
                var bHandle             = Simulation.Bodies.Add(bDescription);
                var cHandle             = Simulation.Bodies.Add(cDescription);
                var distanceSpringiness = new SpringSettings(3f, 1);
                Simulation.Solver.Add(aHandle, bHandle, new CenterDistanceConstraint(Vector3.Distance(a, b), distanceSpringiness));
                Simulation.Solver.Add(aHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(a, c), distanceSpringiness));
                Simulation.Solver.Add(bHandle, cHandle, new CenterDistanceConstraint(Vector3.Distance(b, c), distanceSpringiness));
                Simulation.Solver.Add(aHandle, bHandle, cHandle, new AreaConstraint(a, b, c, new SpringSettings(30, 1)));
            }
            {
                var x            = GetNextPosition(ref nextX);
                var aDescription = BodyDescription.CreateDynamic(new Vector3(x, 3, 0), default, collidableA, activity);
Beispiel #4
0
 public Spring(SpringSettings _settings, Vector3 _startPosition)
 {
     settings = _settings;
     position = _startPosition;
 }
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 25, 80);
            camera.Yaw      = 0;
            camera.Pitch    = 0;
            timestepper     = new SubsteppingTimestepper(8);
            Simulation      = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks()
            {
                ContactSpringiness = new SpringSettings(120, 120)
            }, new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), timestepper, 8);

            rolloverInfo = new RolloverInfo();
            {
                //We'll create a 0 level arm rope like the one from the RopeStabilityDemo. No skip constraints, though- and the mass ratio will be 1000:1 instead of 100:1!
                var         startLocation  = new Vector3(15, 40, 0);
                const float bodySpacing    = 0.3f;
                const float bodyRadius     = 0.5f;
                var         springSettings = new SpringSettings(240, 480);
                var         bodyHandles    = RopeStabilityDemo.BuildRope(Simulation, startLocation, 12, bodyRadius, bodySpacing, 0, 1, 0, springSettings);

                var bigWreckingBall = new Sphere(5);
                bigWreckingBall.ComputeInertia(1000, out var bigWreckingBallInertia);

                RopeStabilityDemo.AttachWreckingBall(Simulation, bodyHandles, bodyRadius, bodySpacing, 0, bigWreckingBall.Radius, bigWreckingBallInertia, Simulation.Shapes.Add(bigWreckingBall), springSettings);
                rolloverInfo.Add(startLocation + new Vector3(0, 2, 0), "1000:1 mass ratio");
            }

            {
                //Stack with a heavy block on top. Note that the contact springiness we chose in the DemoNarrowPhaseCallbacks above is important to making the stack resist the weight of the top block.
                //It's also the reason why we need higher substeps- 120hz frequency is too high for 60hz solving! Watch what happens when you drop the substep count to 3.
                //(Note that the demos timestep frequency is 60hz, so 4 substeps is a 240hz solve rate- twice the 120hz contact frequency.)
                var boxShape = new Box(4, 0.5f, 6f);
                boxShape.ComputeInertia(1, out var boxInertia);
                //Note that sleeping is disabled with a negative velocity threshold. We want to watch the stack as we change simulation settings; if it's inactive, it won't respond!
                var boxDescription = BodyDescription.CreateDynamic(new Vector3(), boxInertia, new CollidableDescription(Simulation.Shapes.Add(boxShape), 0.1f), new BodyActivityDescription(-1f));
                for (int i = 0; i < 20; ++i)
                {
                    boxDescription.Pose = new RigidPose(new Vector3(0, 0.5f + boxShape.Height * (i + 0.5f), 0), QuaternionEx.CreateFromAxisAngle(Vector3.UnitY, MathF.PI * 0.05f * i));
                    Simulation.Bodies.Add(boxDescription);
                }
                var topBlockShape = new Box(8, 2, 8);
                topBlockShape.ComputeInertia(200, out var topBlockInertia);
                Simulation.Bodies.Add(
                    BodyDescription.CreateDynamic(boxDescription.Pose.Position + new Vector3(0, boxShape.HalfHeight + 1f, 0), topBlockInertia,
                                                  new CollidableDescription(Simulation.Shapes.Add(topBlockShape), 0.1f), new BodyActivityDescription(-1f)));

                rolloverInfo.Add(boxDescription.Pose.Position + new Vector3(0, 4, 0), "200:1 mass ratio");
            }

            {
                //Now a weird rotating multi-arm thing. Long constraint sequences with high leverages under stress are a really tough problem for iterative velocity solvers.
                //(Fortunately, all 5 degrees of freedom of each hinge constraint are solved analytically, so the convergence issues aren't quite as bad as they could be.)
                var basePosition  = new Vector3(-20, 20, 0);
                var boxShape      = new Box(0.5f, 0.5f, 3f);
                var boxCollidable = new CollidableDescription(Simulation.Shapes.Add(boxShape), 0.1f);
                boxShape.ComputeInertia(1, out var boxInertia);
                var linkDescription = BodyDescription.CreateDynamic(new Vector3(), boxInertia, boxCollidable, new BodyActivityDescription(0.01f));


                for (int chainIndex = 0; chainIndex < 4; ++chainIndex)
                {
                    linkDescription.Pose.Position = basePosition + new Vector3(0, 0, chainIndex * 15);
                    var previousLinkHandle = Simulation.Bodies.Add(BodyDescription.CreateKinematic(linkDescription.Pose.Position, boxCollidable, new BodyActivityDescription(0.01f)));
                    for (int linkIndex = 0; linkIndex < 8; ++linkIndex)
                    {
                        var previousPosition = linkDescription.Pose.Position;
                        var offset           = new Vector3(boxShape.Width * 1.05f, 0, boxShape.Length - boxShape.Width);
                        linkDescription.Pose.Position += offset;
                        var linkHandle = Simulation.Bodies.Add(linkDescription);
                        Simulation.Solver.Add(previousLinkHandle, linkHandle, new Hinge
                        {
                            LocalHingeAxisA = Vector3.UnitX,
                            LocalHingeAxisB = Vector3.UnitX,
                            LocalOffsetA    = offset * 0.5f,
                            LocalOffsetB    = offset * -0.5f,
                            //Once again, the choice of high stiffness makes this potentially unstable without substepping.
                            SpringSettings = new SpringSettings(120, 1)
                        });
                        Simulation.Solver.Add(previousLinkHandle, linkHandle, new AngularAxisMotor
                        {
                            LocalAxisA     = Vector3.UnitX,
                            TargetVelocity = .25f,
                            Settings       = new MotorSettings(float.MaxValue, 0.0001f)
                        });
                        previousLinkHandle = linkHandle;
                    }
                }
                rolloverInfo.Add(basePosition + new Vector3(0, 4, 0), "High stiffness, long lever arm motorized chain");
            }


            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(200, 1, 200)), 0.1f)));
        }
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-20, 10, -20);
            //camera.Yaw = MathHelper.Pi ;
            camera.Yaw = MathHelper.Pi * 3f / 4;
            //camera.Pitch = MathHelper.PiOver2 * 0.999f;
            Simulation = Simulation.Create(BufferPool, new TestCallbacks());

            Simulation.PoseIntegrator.Gravity = new Vector3(0, -10, 0);
            Simulation.Deterministic          = false;
            var a = AddBody(new Box(3, 1, 1), 1, new RigidPose {
                Position = new Vector3(0, 10, 0), Orientation = BepuUtilities.Quaternion.Identity
            }, Simulation);
            var b = AddBody(new Box(3, 1, 1), 0, new RigidPose {
                Position = new Vector3(5, 10, 0), Orientation = BepuUtilities.Quaternion.Identity
            }, Simulation);

            a.Velocity.Angular = new Vector3(1f, 5f, 1f);
            //a.Pose.Orientation = BepuUtilities.Quaternion.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1, 1, 1)), MathHelper.PiOver4);
            var springSettings = new SpringSettings(15, 1);
            var ballSocket     = new BallSocket
            {
                LocalOffsetA   = new Vector3(2.5f, 0, 0),
                LocalOffsetB   = new Vector3(-2.5f, 0, 0),
                SpringSettings = springSettings
            };

            Simulation.Solver.Add(a.Handle, b.Handle, ref ballSocket);
            //springSettings = new BepuPhysics.CollisionDetection.SpringSettings { DampingRatio = 0f, NaturalFrequency = MathHelper.Pi * 1 };
            var angularHinge = new AngularHinge
            {
                HingeAxisLocalA = Vector3.Normalize(new Vector3(0, 1, 0)),
                HingeAxisLocalB = Vector3.Normalize(new Vector3(0, 1, 0)),
                SpringSettings  = springSettings
            };

            Simulation.Solver.Add(a.Handle, b.Handle, ref angularHinge);
            //var swivelHinge = new AngularSwivelHinge
            //{
            //    SwivelAxisLocalA = new Vector3(1, 0, 0),
            //    HingeAxisLocalB = new Vector3(0, 1, 0),
            //    SpringSettings = springSettings
            //};
            //Simulation.Solver.Add(a.Handle, b.Handle, ref swivelHinge);
            var swingLimit = new SwingLimit
            {
                AxisLocalA     = new Vector3(1, 0, 0),
                AxisLocalB     = new Vector3(1, 0, 0),
                MinimumDot     = -0.5f,
                SpringSettings = new SpringSettings(15, 1)
            };

            Simulation.Solver.Add(a.Handle, b.Handle, ref swingLimit);

            var staticShape      = new Box(100, 1, 100);
            var staticShapeIndex = Simulation.Shapes.Add(staticShape);

            var staticDescription = new StaticDescription
            {
                Collidable = new CollidableDescription
                {
                    Continuity = new ContinuousDetectionSettings {
                        Mode = ContinuousDetectionMode.Discrete
                    },
                    Shape             = staticShapeIndex,
                    SpeculativeMargin = 0.1f
                },
                Pose = new RigidPose
                {
                    Position    = new Vector3(1, -0.5f, 1),
                    Orientation = BepuUtilities.Quaternion.Identity
                }
            };

            Simulation.Statics.Add(staticDescription);
        }