void CreateRingPlatform(Vector3 position, Box ringBoxShape, BodyDescription bodyDescription, float radius)
        {
            var   innerCircumference = (float)Math.PI * 2 * (radius - ringBoxShape.HalfLength);
            var   boxCount           = (int)(0.95f * innerCircumference / ringBoxShape.Height);
            float increment          = MathHelper.TwoPi / boxCount;

            for (int i = 0; i < boxCount; i++)
            {
                var angle = i * increment;
                bodyDescription.Pose = new RigidPose(
                    position + new Vector3(-(float)Math.Cos(angle) * radius, ringBoxShape.HalfWidth, (float)Math.Sin(angle) * radius),
                    Quaternion.Concatenate(Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)Math.PI * 0.5f), Quaternion.CreateFromAxisAngle(Vector3.UnitY, angle + (float)Math.PI * 0.5f)));
                Simulation.Bodies.Add(bodyDescription);
            }
        }
Esempio n. 2
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 9, -40);
            camera.Yaw      = MathHelper.Pi;
            camera.Pitch    = 0;
            var filters = new BodyProperty <SubgroupCollisionFilter>();

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

            int ragdollIndex = 0;
            var spacing      = new Vector3(1.7f, 1.8f, 0.5f);
            int width        = 4;
            int height       = 4;
            int length       = 44;
            var origin       = -0.5f * spacing * new Vector3(width - 1, 0, length - 1) + new Vector3(0, 5f, 0);

            for (int i = 0; i < width; ++i)
            {
                for (int j = 0; j < height; ++j)
                {
                    for (int k = 0; k < length; ++k)
                    {
                        RagdollDemo.AddRagdoll(origin + spacing * new Vector3(i, j, k), Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), MathHelper.Pi * 0.05f), ragdollIndex++, filters, Simulation);
                    }
                }
            }

            var         tubeCenter      = new Vector3(0, 8, 0);
            const int   panelCount      = 20;
            const float tubeRadius      = 6;
            var         panelShape      = new Box((float)Math.PI * 2 * tubeRadius / panelCount, 1, 80);
            var         panelShapeIndex = Simulation.Shapes.Add(panelShape);
            var         builder         = new CompoundBuilder(BufferPool, Simulation.Shapes, panelCount + 1);

            for (int i = 0; i < panelCount; ++i)
            {
                var rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, i * MathHelper.TwoPi / panelCount);
                Quaternion.TransformUnitY(rotation, out var localUp);
                var position = localUp * tubeRadius;
                builder.AddForKinematic(panelShapeIndex, new RigidPose(position, rotation), 1);
            }
            builder.AddForKinematic(Simulation.Shapes.Add(new Box(1, 2, panelShape.Length)), new RigidPose(new Vector3(0, tubeRadius - 1, 0)), 0);
            builder.BuildKinematicCompound(out var children);
            var compound = new BigCompound(children, Simulation.Shapes, BufferPool);

            Simulation.Bodies.Add(BodyDescription.CreateKinematic(tubeCenter, new BodyVelocity(default, new Vector3(0, 0, .25f)), new CollidableDescription(Simulation.Shapes.Add(compound), 0.1f), new BodyActivityDescription()));
Esempio n. 3
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-13f, 6, -13f);
            camera.Yaw      = MathF.PI * 3f / 4;
            camera.Pitch    = MathF.PI * 0.05f;
            Simulation      = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            var shapeA = new Cylinder(0.5f, 0.5f);
            var poseA  = new RigidPose(new Vector3(0, 0, 0));
            var shapeB = new Cylinder(0.5f, 0.5f);
            var poseB  = new RigidPose(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathF.PI * 0.5f));

            basePosition = default;
            shapeLines   = MinkowskiShapeVisualizer.CreateLines <Cylinder, CylinderWide, CylinderSupportFinder, Cylinder, CylinderWide, CylinderSupportFinder>(
                shapeA, shapeB, poseA, poseB, 65536,
                0.01f, new Vector3(0.4f, 0.4f, 0),
                0.1f, new Vector3(0, 1, 0), default, basePosition, BufferPool);
        void CreateRingWall(Vector3 position, Box ringBoxShape, BodyDescription bodyDescription, int height, float radius)
        {
            var   circumference   = (float)Math.PI * 2 * radius;
            var   boxCountPerRing = (int)(0.9f * circumference / ringBoxShape.Length);
            float increment       = MathHelper.TwoPi / boxCountPerRing;

            for (int ringIndex = 0; ringIndex < height; ringIndex++)
            {
                for (int i = 0; i < boxCountPerRing; i++)
                {
                    var angle = ((ringIndex & 1) == 0 ? i + 0.5f : i) * increment;
                    bodyDescription.Pose = new RigidPose(
                        position + new Vector3(-(float)Math.Cos(angle) * radius, (ringIndex + 0.5f) * ringBoxShape.Height, (float)Math.Sin(angle) * radius),
                        Quaternion.CreateFromAxisAngle(Vector3.UnitY, angle));
                    Simulation.Bodies.Add(bodyDescription);
                }
            }
        }
Esempio n. 5
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Yaw      = 0;
            camera.Pitch    = 0;
            camera.Position = new Vector3(0, 0, 5);

            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, 0, 0)));


            var a                 = new Cylinder(1f, 1f);
            var b                 = new Cylinder(1f, 1f);
            var localOffsetB      = new Vector3(.1f, 1.1f, 0.1f);
            var localOrientationB = Quaternion.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1, 1, 1)), MathHelper.Pi * 1.5f);

            Simulation.Bodies.Add(BodyDescription.CreateConvexKinematic(new Vector3(), Simulation.Shapes, a));
            Simulation.Bodies.Add(BodyDescription.CreateConvexKinematic(new RigidPose(localOffsetB, localOrientationB), Simulation.Shapes, b));


            CylinderWide aWide = default, bWide = default;
Esempio n. 6
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-32f, 20.5f, 61f);
            camera.Yaw      = MathHelper.Pi * 0.3f;
            camera.Pitch    = MathHelper.Pi * -0.05f;

            filters    = new BodyProperty <SubgroupCollisionFilter>(BufferPool);
            Simulation = Simulation.Create(BufferPool, new SubgroupFilteredCallbacks()
            {
                CollisionFilters = filters
            }, new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            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, 10, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(70, 20, 80)), 0.1f)));
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 7.5f, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(80, 15, 90)), 0.1f)));
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 5, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(90, 10, 100)), 0.1f)));
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 2.5f, 0), new CollidableDescription(Simulation.Shapes.Add(new Box(100, 5, 110)), 0.1f)));

            //High fidelity simulation isn't super important on this one.
            Simulation.Solver.IterationCount = 2;

            DemoMeshHelper.LoadModel(content, BufferPool, "Content\\newt.obj", new Vector3(30), out var mesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 20, 0), Quaternion.CreateFromAxisAngle(Vector3.UnitY, 0), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f)));
        }
Esempio n. 7
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);
Esempio n. 9
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 4, 15);
            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 shapeB = new Box(.75f, 1, .5f);

            shapeA.ComputeInertia(1, out var inertiaA);
            shapeA.ComputeInertia(1, out var inertiaB);
            {
                var a = Simulation.Bodies.Add(new BodyDescription(new Vector3(-10, 3, 0), inertiaA, Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(-10, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 a = Simulation.Bodies.Add(new BodyDescription(new Vector3(-7, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(-7, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 {
                    HingeAxisLocalA = new Vector3(0, 1, 0), HingeAxisLocalB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var a = Simulation.Bodies.Add(new BodyDescription(new Vector3(-4, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(-4, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 {
                    SwivelAxisLocalA = new Vector3(0, 1, 0), HingeAxisLocalB = new Vector3(1, 0, 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 a = Simulation.Bodies.Add(new BodyDescription(new Vector3(-1, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(-1, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 a = Simulation.Bodies.Add(new BodyDescription(new Vector3(2, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(2, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 {
                    HingeAxisLocalA = new Vector3(0, 1, 0), HingeAxisLocalB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var a = Simulation.Bodies.Add(new BodyDescription(new Vector3(5, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(5, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 {
                    HingeAxisLocalA = new Vector3(0, 1, 0), HingeAxisLocalB = new Vector3(0, 1, 0), SpringSettings = new SpringSettings(30, 1)
                });
            }
            {
                var a = Simulation.Bodies.Add(new BodyDescription(new Vector3(8, 3, 0), new BodyInertia(), Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(8, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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 a = Simulation.Bodies.Add(new BodyDescription(new Vector3(11, 3, 0), inertiaA, Simulation.Shapes.Add(shapeA), 0.1f, new BodyActivityDescription(0.01f)));
                var b = Simulation.Bodies.Add(new BodyDescription(new Vector3(11, 5, 0), inertiaB, Simulation.Shapes.Add(shapeB), 0.1f, new BodyActivityDescription(0.01f)));
                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)
                });
            }

            Simulation.Statics.Add(new StaticDescription(new Vector3(), new CollidableDescription(Simulation.Shapes.Add(new Box(256, 1, 256)), 0.1f)));
        }
Esempio n. 10
0
        //Constructor which sets up the whole game world scene
        public GameWorld(GameLoop Loop, ContentArchive Content)
        {
            //Store references from the GameLoop class
            ApplicationWindow = Loop.Window;
            UserInput         = Loop.Input;

            //Assign the camera reference
            ObservationCamera.SetCamera(Loop);

            this.Content = Content;
            TimeSamples  = new SimulationTimeSamples(512, Loop.Pool);
            UserControls = Controls.Default;

            //Load font from the content archive
            var FontContent = Content.Load <FontContent>(@"Carlito-Regular.ttf");

            UIFont = new Font(Loop.Surface.Device, Loop.Surface.Context, FontContent);

            //Position the camera
            ObservationCamera.PositionCamera(new Vector3(2.7f, 6.48f, 9.76f));
            ObservationCamera.FaceCamera(0.269f, 0.15899f);

            //Setup character controller and world simulation
            BufferPool       = new BufferPool();
            ThreadDispatcher = new SimpleThreadDispatcher(Environment.ProcessorCount);
            World            = Simulation.Create(BufferPool, new CharacterNarrowphaseCallbacks(new CharacterControllers(BufferPool)), new ScenePoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            //Initialize the mesh loader
            MeshManager.Initialize(Content, BufferPool);

            //Load in the numbers display the direction of the X/Z axes
            AxisMarkers.LoadModels();
            AxisMarkers.AddModels(World);

            //Load in the PVP arena
            ArenaMeshHandle = MeshManager.LoadMesh(@"Arena.obj", new Vector3(1));
            //Define its starting position and location
            Vector3    ArenaPosition = new Vector3(29.82f, 3.62f, 0.94f);
            Quaternion ArenaRotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), Trig.DegreesToRadians(180));

            //Use those to add it into the world
            MeshManager.AddStatic(World, ArenaMeshHandle, ArenaPosition, ArenaRotation);

            //Place the jumping cubes
            World.Statics.Add(new StaticDescription(new Vector3(1.299f, 2.3f, -31.24f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-26.56f, 2.3f, -35.2f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-33.12f, 2.3f, -21.65f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-26.05f, 2.3f, -9.38f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-10.31f, 2.3f, -5.62f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(1.94f, 2.3f, -15.88f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));
            World.Statics.Add(new StaticDescription(new Vector3(-11.3f, 2.3f, -37.44f), new CollidableDescription(World.Shapes.Add(new Box(5, 5, 5)), 0.1f)));

            //Place a ground plane to walk on
            World.Statics.Add(new StaticDescription(new Vector3(0, -0.5f, 0), new CollidableDescription(World.Shapes.Add(new Box(100, 1, 100)), 0.1f)));

            //Setup the command executor
            CommandInputField.Initialize();

            //Make sure the window size is correct relative to the current resolution
            OnResize(ApplicationWindow.Resolution);
        }
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-13f, 6, -13f);
            camera.Yaw      = MathHelper.Pi * 3f / 4;
            camera.Pitch    = MathHelper.Pi * 0.05f;
            Simulation      = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            using (var compoundBuilder = new CompoundBuilder(BufferPool, Simulation.Shapes, 8))
            {
                {
                    //Note that, in bepuphysics v2, there is no 'recentering' when constructing a shape. The pose you pass in for a child is exactly the pose that the compound will use,
                    //even if the 'true' center of mass isn't at the local origin.
                    //Instead, if recentering is desired, it should performed ahead of time. The CompoundBuilder can help with this.
                    //We'll construct this compound using shapes far from the origin, and then use the CompoundBuilder overload that recenters the children and outputs the computed center.
                    var capsuleChildShape = new Capsule(0.5f, 0.5f);
                    var capsuleLocalPose  = new RigidPose {
                        Position = new Vector3(-0.5f, 4, 4), Orientation = Quaternion.Identity
                    };
                    var boxChildShape = new Box(0.5f, 1f, 1.5f);
                    var boxLocalPose  = new RigidPose {
                        Position = new Vector3(0.5f, 4, 4), Orientation = Quaternion.Identity
                    };

                    //All allocations from the buffer pool used for the final compound shape will be disposed when the demo is disposed. Don't have to worry about leaks in these demos.
                    compoundBuilder.Add(capsuleChildShape, capsuleLocalPose, 1);
                    compoundBuilder.Add(boxChildShape, boxLocalPose, 1);
                    compoundBuilder.BuildDynamicCompound(out var compoundChildren, out var compoundInertia, out var compoundCenter);
                    compoundBuilder.Reset();
                    var compound            = new Compound(compoundChildren);
                    var compoundDescription = new BodyDescription
                    {
                        Activity = new BodyActivityDescription {
                            SleepThreshold = 0.01f, MinimumTimestepCountUnderThreshold = 32
                        },
                        Collidable = new CollidableDescription
                        {
                            Shape             = Simulation.Shapes.Add(compound),
                            SpeculativeMargin = 0.1f,
                        },
                        LocalInertia = compoundInertia,
                        Pose         = new RigidPose {
                            Position = compoundCenter, Orientation = Quaternion.Identity
                        },
                    };

                    Simulation.Bodies.Add(compoundDescription);
                }

                //Build a stack of sphere grids to stress manifold reduction heuristics in a convex-ish situation.
                {
                    var         gridShape      = new Sphere(0.5f);
                    const float gridSpacing    = 1.5f;
                    const int   gridWidth      = 3;
                    var         gridShapeIndex = Simulation.Shapes.Add(gridShape);
                    gridShape.ComputeInertia(1, out var gridBoxInertia);
                    float localPoseOffset = -0.5f * gridSpacing * (gridWidth - 1);
                    for (int i = 0; i < gridWidth; ++i)
                    {
                        for (int j = 0; j < gridWidth; ++j)
                        {
                            var localPose = new RigidPose
                            {
                                Orientation = Quaternion.Identity,
                                Position    = new Vector3(localPoseOffset, 0, localPoseOffset) + new Vector3(gridSpacing) * new Vector3(i, 0, j)
                            };
                            compoundBuilder.Add(gridShapeIndex, localPose, gridBoxInertia.InverseInertiaTensor, 1);
                        }
                    }
                    compoundBuilder.BuildDynamicCompound(out var gridChildren, out var gridInertia, out var center);
                    compoundBuilder.Reset();
                    var gridCompound    = new Compound(gridChildren);
                    var bodyDescription = new BodyDescription
                    {
                        Activity = new BodyActivityDescription {
                            SleepThreshold = 0.01f, MinimumTimestepCountUnderThreshold = 32
                        },
                        Collidable = new CollidableDescription
                        {
                            Shape             = Simulation.Shapes.Add(gridCompound),
                            SpeculativeMargin = 0.1f,
                        },
                        LocalInertia = gridInertia,
                        Pose         = new RigidPose {
                            Orientation = Quaternion.Identity
                        }
                    };

                    for (int i = 0; i < 4; ++i)
                    {
                        bodyDescription.Pose.Position = new Vector3(0, 2 + i * 3, 0);
                        //if (i == 0)
                        //    gridDescription.LocalInertia = new BodyInertia();
                        //else
                        //    gridDescription.LocalInertia = gridInertia;
                        Simulation.Bodies.Add(bodyDescription);
                    }
                }

                //Build a table and use it for a couple of different tests.
                {
                    var legShape = new Box(0.2f, 1, 0.2f);
                    legShape.ComputeInertia(1f, out var legInverseInertia);
                    var legShapeIndex = Simulation.Shapes.Add(legShape);
                    var legPose0      = new RigidPose {
                        Position = new Vector3(-1.5f, 0, -1.5f), Orientation = Quaternion.Identity
                    };
                    var legPose1 = new RigidPose {
                        Position = new Vector3(-1.5f, 0, 1.5f), Orientation = Quaternion.Identity
                    };
                    var legPose2 = new RigidPose {
                        Position = new Vector3(1.5f, 0, -1.5f), Orientation = Quaternion.Identity
                    };
                    var legPose3 = new RigidPose {
                        Position = new Vector3(1.5f, 0, 1.5f), Orientation = Quaternion.Identity
                    };
                    compoundBuilder.Add(legShapeIndex, legPose0, legInverseInertia.InverseInertiaTensor, 1);
                    compoundBuilder.Add(legShapeIndex, legPose1, legInverseInertia.InverseInertiaTensor, 1);
                    compoundBuilder.Add(legShapeIndex, legPose2, legInverseInertia.InverseInertiaTensor, 1);
                    compoundBuilder.Add(legShapeIndex, legPose3, legInverseInertia.InverseInertiaTensor, 1);
                    var tableTopPose = new RigidPose {
                        Position = new Vector3(0, 0.6f, 0), Orientation = Quaternion.Identity
                    };
                    var tableTopShape = new Box(3.2f, 0.2f, 3.2f);
                    compoundBuilder.Add(tableTopShape, tableTopPose, 3);

                    compoundBuilder.BuildDynamicCompound(out var tableChildren, out var tableInertia, out var tableCenter);
                    compoundBuilder.Reset();
                    var table            = new Compound(tableChildren);
                    var tableDescription = new BodyDescription
                    {
                        Activity = new BodyActivityDescription {
                            SleepThreshold = 0.01f, MinimumTimestepCountUnderThreshold = 32
                        },
                        Collidable = new CollidableDescription
                        {
                            Shape             = Simulation.Shapes.Add(table),
                            SpeculativeMargin = 0.1f,
                        },
                        LocalInertia = tableInertia,
                        Pose         = new RigidPose {
                            Orientation = Quaternion.Identity
                        }
                    };

                    //Stack some tables.
                    {
                        for (int i = 0; i < 10; ++i)
                        {
                            tableDescription.Pose.Position = new Vector3(10, 3 + i * 1.4f, 10);
                            Simulation.Bodies.Add(tableDescription);
                        }
                    }
                    {
                        for (int k = 0; k < 5; ++k)
                        {
                            tableDescription.Pose.Position = new Vector3(64 + k * 3, 6 + k * 1.4f, 32);
                            Simulation.Bodies.Add(tableDescription);
                        }
                        //for (int i = 0; i < 10; ++i)
                        //{
                        //    for (int j = 0; j < 20; ++j)
                        //    {
                        //        for (int k = 0; k < 10; ++k)
                        //        {
                        //            tableDescription.Pose.Position = new Vector3(32 + i * 6, 6 + j * 1.4f, 16 + k * 6);
                        //            Simulation.Bodies.Add(tableDescription);
                        //        }
                        //    }
                        //}
                    }

                    //Put a table on top of a sphere to stress out nonconvex reduction for divergent normals.
                    {
                        tableDescription.Pose.Position = new Vector3(10, 6, 0);
                        Simulation.Bodies.Add(tableDescription);

                        var sphereShape       = new Sphere(3);
                        var sphereIndex       = Simulation.Shapes.Add(sphereShape);
                        var sphereDescription = new StaticDescription
                        {
                            Collidable = new CollidableDescription
                            {
                                Shape             = sphereIndex,
                                SpeculativeMargin = 0.1f,
                            },
                            Pose = new RigidPose {
                                Position = new Vector3(10, 2, 0), Orientation = Quaternion.Identity
                            }
                        };
                        Simulation.Statics.Add(sphereDescription);
                    }

                    //Put another table on the ground, but with a clamp-ish thing on it that generates opposing normals.
                    {
                        tableDescription.Pose.Position = new Vector3(10, 3, -10);
                        Simulation.Bodies.Add(tableDescription);

                        var clampPieceShape = new Box(2f, 0.1f, 0.3f);
                        clampPieceShape.ComputeInertia(1f, out var clampPieceInverseInertia);
                        var clampPieceShapeIndex = Simulation.Shapes.Add(clampPieceShape);
                        var clamp0 = new RigidPose {
                            Position = new Vector3(0, -0.2f, -1.1f), Orientation = Quaternion.Identity
                        };
                        var clamp1 = new RigidPose {
                            Position = new Vector3(0, 0.2f, -1.1f), Orientation = Quaternion.Identity
                        };
                        var clamp2 = new RigidPose {
                            Position = new Vector3(0, -0.2f, 0), Orientation = Quaternion.Identity
                        };
                        var clamp3 = new RigidPose {
                            Position = new Vector3(0, 0.2f, 0), Orientation = Quaternion.Identity
                        };
                        var clamp4 = new RigidPose {
                            Position = new Vector3(0, -0.2f, 1.1f), Orientation = Quaternion.Identity
                        };
                        var clamp5 = new RigidPose {
                            Position = new Vector3(0, 0.2f, 1.1f), Orientation = Quaternion.Identity
                        };
                        compoundBuilder.Add(clampPieceShapeIndex, clamp0, clampPieceInverseInertia.InverseInertiaTensor, 1);
                        compoundBuilder.Add(clampPieceShapeIndex, clamp1, clampPieceInverseInertia.InverseInertiaTensor, 1);
                        compoundBuilder.Add(clampPieceShapeIndex, clamp2, clampPieceInverseInertia.InverseInertiaTensor, 1);
                        compoundBuilder.Add(clampPieceShapeIndex, clamp3, clampPieceInverseInertia.InverseInertiaTensor, 1);
                        compoundBuilder.Add(clampPieceShapeIndex, clamp4, clampPieceInverseInertia.InverseInertiaTensor, 1);
                        compoundBuilder.Add(clampPieceShapeIndex, clamp5, clampPieceInverseInertia.InverseInertiaTensor, 1);

                        compoundBuilder.BuildDynamicCompound(out var clampChildren, out var clampInertia, out var clampCenter);
                        compoundBuilder.Reset();
                        var clamp            = new Compound(clampChildren);
                        var clampDescription = new BodyDescription
                        {
                            Activity = new BodyActivityDescription {
                                SleepThreshold = 0.01f, MinimumTimestepCountUnderThreshold = 32
                            },
                            Collidable = new CollidableDescription
                            {
                                Shape             = Simulation.Shapes.Add(clamp),
                                SpeculativeMargin = 0.1f,
                            },
                            LocalInertia = clampInertia,
                            Pose         = new RigidPose {
                                Position = tableDescription.Pose.Position + new Vector3(2f, 0.3f, 0), Orientation = Quaternion.Identity
                            }
                        };
                        Simulation.Bodies.Add(clampDescription);
                    }
                }

                //Create a tree-accelerated big compound.
                {
                    var random = new Random(5);
                    var treeCompoundBoxShape      = new Box(0.5f, 1.5f, 1f);
                    var treeCompoundBoxShapeIndex = Simulation.Shapes.Add(treeCompoundBoxShape);
                    treeCompoundBoxShape.ComputeInertia(1, out var childInertia);
                    for (int i = 0; i < 128; ++i)
                    {
                        RigidPose localPose;
                        localPose.Position = new Vector3(12, 6, 12) * (0.5f * new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()) - Vector3.One);
                        float orientationLengthSquared;
                        do
                        {
                            localPose.Orientation = new Quaternion((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());
                        }while ((orientationLengthSquared = localPose.Orientation.LengthSquared()) < 1e-9f);
                        Quaternion.Scale(localPose.Orientation, 1f / MathF.Sqrt(orientationLengthSquared), out localPose.Orientation);
                        //Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), MathF.PI, out localPose.Orientation);

                        compoundBuilder.Add(treeCompoundBoxShapeIndex, localPose, childInertia.InverseInertiaTensor, 1);
                    }
                    compoundBuilder.BuildDynamicCompound(out var children, out var inertia, out var center);
                    compoundBuilder.Reset();

                    var compound = new BigCompound(children, Simulation.Shapes, BufferPool);
                    //var compound = new Compound(children);
                    var compoundIndex = Simulation.Shapes.Add(compound);
                    for (int i = 0; i < 8; ++i)
                    {
                        Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(0, 4 + 5 * i, 32), inertia, new CollidableDescription(compoundIndex, 0.1f), new BodyActivityDescription(0.01f)));
                    }
                }
            }

            //Prevent stuff from falling into the infinite void.
            {
                var boxShape          = new Box(256, 1, 256);
                var groundShapeIndex  = Simulation.Shapes.Add(boxShape);
                var groundDescription = new StaticDescription
                {
                    Collidable = new CollidableDescription
                    {
                        Shape             = groundShapeIndex,
                        SpeculativeMargin = 0.1f,
                    },
                    Pose = new RigidPose {
                        Position = new Vector3(0, 0, 0), Orientation = Quaternion.Identity
                    }
                };
                Simulation.Statics.Add(groundDescription);
            }
            const int planeWidth  = 48;
            const int planeHeight = 48;

            MeshDemo.CreateDeformedPlane(planeWidth, planeHeight,
                                         (int x, int y) =>
            {
                Vector2 offsetFromCenter = new Vector2(x - planeWidth / 2, y - planeHeight / 2);
                return(new Vector3(offsetFromCenter.X, MathF.Cos(x / 4f) * MathF.Sin(y / 4f) - 0.01f * offsetFromCenter.LengthSquared(), offsetFromCenter.Y));
            }, new Vector3(2, 1, 2), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(64, 4, 32), Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
Esempio n. 12
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(20, 10, 20);
            camera.Yaw      = MathF.PI;
            camera.Pitch    = 0;
            characters      = new CharacterControllers(BufferPool);
            Simulation      = Simulation.Create(BufferPool, new CharacterNarrowphaseCallbacks(characters), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            CreateCharacter(new Vector3(0, 2, -4));

            //Create a bunch of legos to hurt your feet on.
            var random  = new Random(5);
            var origin  = new Vector3(-3f, 0.5f, 0);
            var spacing = new Vector3(0.5f, 0, -0.5f);

            for (int i = 0; i < 12; ++i)
            {
                for (int j = 0; j < 12; ++j)
                {
                    var position    = origin + new Vector3(i, 0, j) * spacing;
                    var orientation = Quaternion.CreateFromAxisAngle(Vector3.Normalize(new Vector3(0.0001f) + new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble())), 10 * (float)random.NextDouble());
                    var shape       = new Box(0.1f + 0.3f * (float)random.NextDouble(), 0.1f + 0.3f * (float)random.NextDouble(), 0.1f + 0.3f * (float)random.NextDouble());
                    var collidable  = new CollidableDescription(Simulation.Shapes.Add(shape), 0.1f);
                    shape.ComputeInertia(1, out var inertia);
                    var choice = (i + j) % 3;
                    switch (choice)
                    {
                    case 0:
                        Simulation.Bodies.Add(BodyDescription.CreateDynamic(new RigidPose(position, orientation), inertia, collidable, new BodyActivityDescription(0.01f)));
                        break;

                    case 1:
                        Simulation.Bodies.Add(BodyDescription.CreateKinematic(new RigidPose(position, orientation), collidable, new BodyActivityDescription(0.01f)));
                        break;

                    case 2:
                        Simulation.Statics.Add(new StaticDescription(position, orientation, collidable));
                        break;
                    }
                }
            }

            //Add some spinning fans to get slapped by.
            var bladeDescription     = BodyDescription.CreateConvexDynamic(new Vector3(), 3, Simulation.Shapes, new Box(10, 0.2f, 2));
            var bladeBaseDescription = BodyDescription.CreateConvexKinematic(new Vector3(), Simulation.Shapes, new Box(0.2f, 1, 0.2f));

            for (int i = 0; i < 3; ++i)
            {
                bladeBaseDescription.Pose.Position = new Vector3(-22, 1, i * 11);
                bladeDescription.Pose.Position     = new Vector3(-22, 1.7f, i * 11);
                var baseHandle  = Simulation.Bodies.Add(bladeBaseDescription);
                var bladeHandle = Simulation.Bodies.Add(bladeDescription);
                Simulation.Solver.Add(baseHandle, bladeHandle,
                                      new Hinge
                {
                    LocalHingeAxisA = Vector3.UnitY,
                    LocalHingeAxisB = Vector3.UnitY,
                    LocalOffsetA    = new Vector3(0, 0.7f, 0),
                    LocalOffsetB    = new Vector3(0, 0, 0),
                    SpringSettings  = new SpringSettings(30, 1)
                });
                Simulation.Solver.Add(baseHandle, bladeHandle,
                                      new AngularAxisMotor
                {
                    LocalAxisA     = Vector3.UnitY,
                    TargetVelocity = (i + 1) * (i + 1) * (i + 1) * (i + 1) * 0.2f,
                    Settings       = new MotorSettings(5 * (i + 1), 0.0001f)
                });
            }

            //Include a giant newt to test character-newt behavior and to ensure thematic consistency.
            DemoMeshHelper.LoadModel(content, BufferPool, @"Content\newt.obj", new Vector3(15, 15, 15), out var newtMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0.5f, 0), new CollidableDescription(Simulation.Shapes.Add(newtMesh), 0.1f)));

            //Give the newt a tongue, I guess.
            var tongueBase = Simulation.Bodies.Add(BodyDescription.CreateKinematic(new Vector3(0, 8.4f, 24), default, default));
Esempio n. 13
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 5, 10);
            camera.Yaw      = 0;
            camera.Pitch    = 0;

            var properties = new BodyProperty <CarBodyProperties>();

            Simulation = Simulation.Create(BufferPool, new CarCallbacks()
            {
                Properties = properties
            }, new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            var builder = new CompoundBuilder(BufferPool, Simulation.Shapes, 2);

            builder.Add(new Box(1.85f, 0.7f, 4.73f), RigidPose.Identity, 10);
            builder.Add(new Box(1.85f, 0.6f, 2.5f), new RigidPose(new Vector3(0, 0.65f, -0.35f)), 0.5f);
            builder.BuildDynamicCompound(out var children, out var bodyInertia, out _);
            builder.Dispose();
            var bodyShape      = new Compound(children);
            var bodyShapeIndex = Simulation.Shapes.Add(bodyShape);
            var wheelShape     = new Cylinder(0.4f, .18f);

            wheelShape.ComputeInertia(0.25f, out var wheelInertia);
            var wheelShapeIndex = Simulation.Shapes.Add(wheelShape);

            const float x      = 0.9f;
            const float y      = -0.1f;
            const float frontZ = 1.7f;
            const float backZ  = -1.7f;

            playerController = new SimpleCarController(SimpleCar.Create(Simulation, properties, new RigidPose(new Vector3(0, 10, 0), Quaternion.Identity), bodyShapeIndex, bodyInertia, 0.5f, wheelShapeIndex, wheelInertia, 2f,
                                                                        new Vector3(-x, y, frontZ), new Vector3(x, y, frontZ), new Vector3(-x, y, backZ), new Vector3(x, y, backZ), new Vector3(0, -1, 0), 0.25f,
                                                                        new SpringSettings(5f, 0.7f), Quaternion.CreateFromAxisAngle(Vector3.UnitZ, MathF.PI * 0.5f)),
                                                       forwardSpeed: 75, forwardForce: 6, zoomMultiplier: 2, backwardSpeed: 30, backwardForce: 4, idleForce: 0.25f, brakeForce: 7, steeringSpeed: 1.5f, maximumSteeringAngle: MathF.PI * 0.23f);

            //Create a bunch of AI cars to race against.
            const int aiCount = 384;

            BufferPool.Take(aiCount, out aiControllers);


            const int   planeWidth      = 257;
            const float scale           = 3;
            Vector2     terrainPosition = new Vector2(1 - planeWidth, 1 - planeWidth) * scale * 0.5f;

            raceTrack = new RaceTrack {
                QuadrantRadius = (planeWidth - 32) * scale * 0.25f, Center = default
            };
            var random = new Random(5);

            //Add some building-ish landmarks in the middle of each of the four racetrack quadrants.
            for (int i = 0; i < 4; ++i)
            {
                var landmarkCenter = new Vector3((i & 1) * raceTrack.QuadrantRadius * 2 - raceTrack.QuadrantRadius, -20, (i & 2) * raceTrack.QuadrantRadius - raceTrack.QuadrantRadius);
                var landmarkMin    = landmarkCenter - new Vector3(raceTrack.QuadrantRadius * 0.5f, 0, raceTrack.QuadrantRadius * 0.5f);
                var landmarkSpan   = new Vector3(raceTrack.QuadrantRadius, 0, raceTrack.QuadrantRadius);
                for (int j = 0; j < 25; ++j)
                {
                    var buildingShape = new Box(10 + (float)random.NextDouble() * 10, 20 + (float)random.NextDouble() * 20, 10 + (float)random.NextDouble() * 10);
                    Simulation.Statics.Add(new StaticDescription(
                                               new Vector3(0, buildingShape.HalfHeight, 0) + landmarkMin + landmarkSpan * new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()),
                                               Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)random.NextDouble() * MathF.PI),
                                               new CollidableDescription(Simulation.Shapes.Add(buildingShape), 0.1f)));
                }
            }

            Vector3 min  = new Vector3(-planeWidth * scale * 0.45f, 10, -planeWidth * scale * 0.45f);
            Vector3 span = new Vector3(planeWidth * scale * 0.9f, 15, planeWidth * scale * 0.9f);

            for (int i = 0; i < aiCount; ++i)
            {
                //The AI cars are very similar, except... we handicap them a little to make the player good about themselves.
                var position    = min + span * new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());
                var orientation = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), (float)random.NextDouble() * MathF.PI * 2);
                aiControllers[i].Controller = new SimpleCarController(SimpleCar.Create(Simulation, properties, new RigidPose(position, orientation), bodyShapeIndex, bodyInertia, 0.5f, wheelShapeIndex, wheelInertia, 2f,
                                                                                       new Vector3(-x, y, frontZ), new Vector3(x, y, frontZ), new Vector3(-x, y, backZ), new Vector3(x, y, backZ), new Vector3(0, -1, 0), 0.25f,
                                                                                       new SpringSettings(5, 0.7f), Quaternion.CreateFromAxisAngle(Vector3.UnitZ, MathF.PI * 0.5f)),
                                                                      forwardSpeed: 50, forwardForce: 5, zoomMultiplier: 2, backwardSpeed: 10, backwardForce: 4, idleForce: 0.25f, brakeForce: 7, steeringSpeed: 1.5f, maximumSteeringAngle: MathF.PI * 0.23f);
                aiControllers[i].LaneOffset = (float)random.NextDouble() * 20 - 10;
            }


            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeWidth,
                                               (int vX, int vY) =>
            {
                var octave0         = (MathF.Sin((vX + 5f) * 0.05f) + MathF.Sin((vY + 11) * 0.05f)) * 1.8f;
                var octave1         = (MathF.Sin((vX + 17) * 0.15f) + MathF.Sin((vY + 19) * 0.15f)) * 0.9f;
                var octave2         = (MathF.Sin((vX + 37) * 0.35f) + MathF.Sin((vY + 93) * 0.35f)) * 0.4f;
                var octave3         = (MathF.Sin((vX + 53) * 0.65f) + MathF.Sin((vY + 47) * 0.65f)) * 0.2f;
                var octave4         = (MathF.Sin((vX + 67) * 1.50f) + MathF.Sin((vY + 13) * 1.5f)) * 0.125f;
                var distanceToEdge  = planeWidth / 2 - Math.Max(Math.Abs(vX - planeWidth / 2), Math.Abs(vY - planeWidth / 2));
                var edgeRamp        = 25f / (distanceToEdge + 1);
                var terrainHeight   = octave0 + octave1 + octave2 + octave3 + octave4;
                var vertexPosition  = new Vector2(vX * scale, vY * scale) + terrainPosition;
                var distanceToTrack = raceTrack.GetDistance(vertexPosition);
                var trackWeight     = MathF.Min(1f, 3f / (distanceToTrack * 0.1f + 1f));
                var height          = trackWeight * -10f + terrainHeight * (1 - trackWeight);
                return(new Vector3(vertexPosition.X, height + edgeRamp, vertexPosition.Y));
            }, new Vector3(1, 1, 1), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, -15, 0), Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
Esempio n. 14
0
        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), Quaternion.CreateFromAxisAngle(Vector3.UnitY, (float)Math.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)));
        }