Example #1
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 7, 20);
            camera.Yaw      = 0;
            camera.Pitch    = 0;

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

            Simulation.Statics.Add(new StaticDescription(new Vector3(), new CollidableDescription(Simulation.Shapes.Add(new Box(100, 1, 100)), 0.1f)));

            var random      = new Random(5);
            var shapeToDrop = new Box(1, 1, 1);

            shapeToDrop.ComputeInertia(1, out var shapeToDropInertia);
            var descriptionToDrop = BodyDescription.CreateDynamic(new Vector3(), shapeToDropInertia, new CollidableDescription(Simulation.Shapes.Add(shapeToDrop), 0.3f), new BodyActivityDescription(0.01f));

            for (int i = 0; i < 128; ++i)
            {
                descriptionToDrop.Pose.Position = new Vector3(-5 + 10 * (float)random.NextDouble(), 45 + 150 * (float)random.NextDouble(), -5 + 10 * (float)random.NextDouble());
                Simulation.Bodies.Add(descriptionToDrop);
            }

            //Add in a static object to test against. Note that the mesh triangles are one sided, so some of the queries whose centers are beneath the mesh do not generate any contacts.
            DemoMeshHelper.CreateDeformedPlane(20, 20, (x, y) => { return(new Vector3(x * 5 - 50, 3 * MathF.Sin(x) * MathF.Sin(y), y * 5 - 50)); }, Vector3.One, BufferPool, out var mesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0, 0), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f)));
        }
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 7, 20);
            camera.Yaw      = 0;
            camera.Pitch    = 0;

            //The PositionFirstTimestepper is the simplest timestepping mode, but since it integrates velocity into position at the start of the frame, directly modified velocities outside of the timestep
            //will be integrated before collision detection or the solver has a chance to intervene. That's fine in this demo. Other built-in options include the PositionLastTimestepper and the SubsteppingTimestepper.
            //Note that the timestepper also has callbacks that you can use for executing logic between processing stages, like BeforeCollisionDetection.
            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), new PositionFirstTimestepper());

            Simulation.Statics.Add(new StaticDescription(new Vector3(), new CollidableDescription(Simulation.Shapes.Add(new Box(100, 1, 100)), 0.1f)));

            var random      = new Random(5);
            var shapeToDrop = new Box(1, 1, 1);

            shapeToDrop.ComputeInertia(1, out var shapeToDropInertia);
            var descriptionToDrop = BodyDescription.CreateDynamic(new Vector3(), shapeToDropInertia, new CollidableDescription(Simulation.Shapes.Add(shapeToDrop), 0.3f), new BodyActivityDescription(0.01f));

            for (int i = 0; i < 128; ++i)
            {
                descriptionToDrop.Pose.Position = new Vector3(-5 + 10 * (float)random.NextDouble(), 45 + 150 * (float)random.NextDouble(), -5 + 10 * (float)random.NextDouble());
                Simulation.Bodies.Add(descriptionToDrop);
            }

            //Add in a static object to test against. Note that the mesh triangles are one sided, so some of the queries whose centers are beneath the mesh do not generate any contacts.
            DemoMeshHelper.CreateDeformedPlane(20, 20, (x, y) => { return(new Vector3(x * 5 - 50, 3 * MathF.Sin(x) * MathF.Sin(y), y * 5 - 50)); }, Vector3.One, BufferPool, out var mesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0, 0), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f)));
        }
Example #3
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 5, 25);
            camera.Yaw      = 0;
            camera.Pitch    = 0;

            //The PositionFirstTimestepper is the simplest timestepping mode, but since it integrates velocity into position at the start of the frame, directly modified velocities outside of the timestep
            //will be integrated before collision detection or the solver has a chance to intervene. That's fine in this demo. Other built-in options include the PositionLastTimestepper and the SubsteppingTimestepper.
            //Note that the timestepper also has callbacks that you can use for executing logic between processing stages, like BeforeCollisionDetection.
            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), new PositionFirstTimestepper());

            //Drop a pyramid on top of the sensor so there are more contacts to look at.
            var boxShape = new Box(1, 1, 1);

            boxShape.ComputeInertia(1, out var boxInertia);
            var boxIndex = Simulation.Shapes.Add(boxShape);

            const int rowCount = 20;

            for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex)
            {
                int columnCount = rowCount - rowIndex;
                for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex)
                {
                    Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(
                                                                            (-columnCount * 0.5f + columnIndex) * boxShape.Width,
                                                                            (rowIndex + 0.5f) * boxShape.Height + 10, 0),
                                                                        boxInertia,
                                                                        new CollidableDescription(boxIndex, 0.1f),
                                                                        new BodyActivityDescription(0.01f)));
                }
            }


            sensorBodyHandle = Simulation.Bodies.Add(BodyDescription.CreateConvexDynamic(new Vector3(0, 0, 1), 10, Simulation.Shapes, new Box(4, 2, 6)));

            //Put a mesh under the sensor so that nonconvex contacts are shown.
            const int planeWidth  = 128;
            const int planeHeight = 128;

            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeHeight,
                                               (int x, int y) =>
            {
                return(new Vector3(x - planeWidth / 2, 1 * MathF.Cos(x / 2f) * MathF.Sin(y / 2f), y - planeHeight / 2));
            }, new Vector3(2, 1, 2), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, -2, 0), QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-30, 8, -60);
            camera.Yaw      = MathHelper.Pi * 3f / 4;
            camera.Pitch    = 0;

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

            var startTime = Stopwatch.GetTimestamp();

            DemoMeshHelper.CreateDeformedPlane(1025, 1025, (x, y) => new Vector3(x * 0.125f, MathF.Sin(x) + MathF.Sin(y), y * 0.125f), Vector3.One, BufferPool, out var originalMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0, 0), new CollidableDescription(Simulation.Shapes.Add(originalMesh), 0.1f)));
            var endTime = Stopwatch.GetTimestamp();
            var freshConstructionTime = (endTime - startTime) / (double)Stopwatch.Frequency;

            Console.WriteLine($"Fresh construction time (ms): {freshConstructionTime * 1e3}");

            BufferPool.Take(originalMesh.GetSerializedByteCount(), out var serializedMeshBytes);
            originalMesh.Serialize(serializedMeshBytes);
            startTime = Stopwatch.GetTimestamp();
            var loadedMesh = new Mesh(serializedMeshBytes, BufferPool);

            endTime = Stopwatch.GetTimestamp();
            var loadTime = (endTime - startTime) / (double)Stopwatch.Frequency;

            Console.WriteLine($"Load time (ms): {(endTime - startTime) * 1e3 / Stopwatch.Frequency}");
            Console.WriteLine($"Relative speedup: {freshConstructionTime / loadTime}");
            Simulation.Statics.Add(new StaticDescription(new Vector3(128, 0, 0), new CollidableDescription(Simulation.Shapes.Add(loadedMesh), 0.1f)));


            BufferPool.Return(ref serializedMeshBytes);

            var random      = new Random(5);
            var shapeToDrop = new Box(1, 1, 1);

            shapeToDrop.ComputeInertia(1, out var shapeToDropInertia);
            var descriptionToDrop = BodyDescription.CreateDynamic(new Vector3(), shapeToDropInertia, new CollidableDescription(Simulation.Shapes.Add(shapeToDrop), 0.1f), new BodyActivityDescription(0.01f));

            for (int i = 0; i < 1024; ++i)
            {
                descriptionToDrop.Pose.Position = new Vector3(8 + 240 * (float)random.NextDouble(), 10 + 10 * (float)random.NextDouble(), 8 + 112 * (float)random.NextDouble());
                Simulation.Bodies.Add(descriptionToDrop);
            }
        }
Example #5
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 5, 25);
            camera.Yaw      = 0;
            camera.Pitch    = 0;
            Simulation      = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            //Drop a pyramid on top of the sensor so there are more contacts to look at.
            var boxShape = new Box(1, 1, 1);

            boxShape.ComputeInertia(1, out var boxInertia);
            var boxIndex = Simulation.Shapes.Add(boxShape);

            const int rowCount = 20;

            for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex)
            {
                int columnCount = rowCount - rowIndex;
                for (int columnIndex = 0; columnIndex < columnCount; ++columnIndex)
                {
                    Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(
                                                                            (-columnCount * 0.5f + columnIndex) * boxShape.Width,
                                                                            (rowIndex + 0.5f) * boxShape.Height + 10, 0),
                                                                        boxInertia,
                                                                        new CollidableDescription(boxIndex, 0.1f),
                                                                        new BodyActivityDescription(0.01f)));
                }
            }


            sensorBodyHandle = Simulation.Bodies.Add(BodyDescription.CreateConvexDynamic(new Vector3(0, 0, 1), 10, Simulation.Shapes, new Box(4, 2, 6)));

            //Put a mesh under the sensor so that nonconvex contacts are shown.
            const int planeWidth  = 128;
            const int planeHeight = 128;

            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeHeight,
                                               (int x, int y) =>
            {
                return(new Vector3(x - planeWidth / 2, 1 * MathF.Cos(x / 2f) * MathF.Sin(y / 2f), y - planeHeight / 2));
            }, new Vector3(2, 1, 2), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, -2, 0), QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
Example #6
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-30, 10, -30);
            //camera.Yaw = MathHelper.Pi ;
            camera.Yaw = MathHelper.Pi * 3f / 4;
            //camera.Pitch = MathHelper.PiOver2 * 0.999f;
            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));
            Simulation.Deterministic = true;

            var       sphere     = new Sphere(1.5f);
            var       capsule    = new Capsule(1f, 1f);
            var       box        = new Box(1f, 3f, 2f);
            var       cylinder   = new Cylinder(1.5f, 0.3f);
            const int pointCount = 32;
            var       points     = new QuickList <Vector3>(pointCount, BufferPool);
            //points.Allocate(BufferPool) = new Vector3(0, 0, 0);
            //points.Allocate(BufferPool) = new Vector3(0, 0, 1);
            //points.Allocate(BufferPool) = new Vector3(0, 1, 0);
            //points.Allocate(BufferPool) = new Vector3(0, 1, 1);
            //points.Allocate(BufferPool) = new Vector3(1, 0, 0);
            //points.Allocate(BufferPool) = new Vector3(1, 0, 1);
            //points.Allocate(BufferPool) = new Vector3(1, 1, 0);
            //points.Allocate(BufferPool) = new Vector3(1, 1, 1);
            var random = new Random(5);

            for (int i = 0; i < pointCount; ++i)
            {
                points.AllocateUnsafely() = new Vector3(3 * (float)random.NextDouble(), 1 * (float)random.NextDouble(), 3 * (float)random.NextDouble());
                //points.AllocateUnsafely() = new Vector3(0, 1, 0) + Vector3.Normalize(new Vector3((float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1)) * (float)random.NextDouble();
            }
            var convexHull = new ConvexHull(points.Span.Slice(points.Count), BufferPool, out _);

            box.ComputeInertia(1, out var boxInertia);
            capsule.ComputeInertia(1, out var capsuleInertia);
            sphere.ComputeInertia(1, out var sphereInertia);
            cylinder.ComputeInertia(1, out var cylinderInertia);
            convexHull.ComputeInertia(1, out var hullInertia);
            var       boxIndex      = Simulation.Shapes.Add(box);
            var       capsuleIndex  = Simulation.Shapes.Add(capsule);
            var       sphereIndex   = Simulation.Shapes.Add(sphere);
            var       cylinderIndex = Simulation.Shapes.Add(cylinder);
            var       hullIndex     = Simulation.Shapes.Add(convexHull);
            const int width         = 8;
            const int height        = 16;
            const int length        = 8;
            var       shapeCount    = 0;

            for (int i = 0; i < width; ++i)
            {
                for (int j = 0; j < height; ++j)
                {
                    for (int k = 0; k < length; ++k)
                    {
                        var location        = new Vector3(6, 3, 6) * new Vector3(i, j, k) + new Vector3(-width * 1.5f, 5.5f, -length * 1.5f);
                        var bodyDescription = new BodyDescription
                        {
                            Activity = new BodyActivityDescription(0.01f),
                            Pose     = new RigidPose
                            {
                                Orientation = Quaternion.Identity,
                                Position    = location
                            },
                            Collidable = new CollidableDescription
                            {
                                Continuity = new ContinuousDetectionSettings {
                                    Mode = ContinuousDetectionMode.Discrete
                                },
                                SpeculativeMargin = 0.1f
                            }
                        };
                        var index = shapeCount++;
                        switch (2 + index % 5)
                        {
                        case 0:
                            bodyDescription.Collidable.Shape = sphereIndex;
                            bodyDescription.LocalInertia     = sphereInertia;
                            break;

                        case 1:
                            bodyDescription.Collidable.Shape = capsuleIndex;
                            bodyDescription.LocalInertia     = capsuleInertia;
                            break;

                        case 2:
                            bodyDescription.Collidable.Shape = boxIndex;
                            bodyDescription.LocalInertia     = boxInertia;
                            break;

                        case 3:
                            bodyDescription.Collidable.Shape = cylinderIndex;
                            bodyDescription.LocalInertia     = cylinderInertia;
                            break;

                        case 4:
                            bodyDescription.Collidable.Shape = hullIndex;
                            bodyDescription.LocalInertia     = hullInertia;
                            break;
                        }
                        Simulation.Bodies.Add(bodyDescription);
                    }
                }
            }

            DemoMeshHelper.CreateDeformedPlane(128, 128, (x, y) => new Vector3(x - 64, 2f * (float)(Math.Sin(x * 0.5f) * Math.Sin(y * 0.5f)), y - 64), new Vector3(4, 1, 4), BufferPool, out var mesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f)));
        }
Example #7
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-15f, 20, -15f);
            camera.Yaw      = MathHelper.Pi * 3f / 4;
            camera.Pitch    = MathHelper.Pi * 0.1f;
            //Using minimum sized allocations forces as many resizes as possible.
            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), initialAllocationSizes:
                                           new SimulationAllocationSizes
            {
                Bodies = 1,
                ConstraintCountPerBodyEstimate = 1,
                Constraints             = 1,
                ConstraintsPerTypeBatch = 1,
                Islands       = 1,
                ShapesPerType = 1,
                Statics       = 1
            });

            Simulation.Deterministic = true;

            const int planeWidth  = 8;
            const int planeHeight = 8;

            DemoMeshHelper.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.2f * offsetFromCenter.LengthSquared(), offsetFromCenter.Y));
            }, new Vector3(2, 1, 2), BufferPool, out var staticShape);
            var         staticShapeIndex           = Simulation.Shapes.Add(staticShape);
            const int   staticGridWidthInInstances = 128;
            const float staticSpacing = 8;

            for (int i = 0; i < staticGridWidthInInstances; ++i)
            {
                for (int j = 0; j < staticGridWidthInInstances; ++j)
                {
                    var staticDescription = new StaticDescription
                    {
                        Collidable = new CollidableDescription
                        {
                            Continuity = new ContinuousDetectionSettings {
                                Mode = ContinuousDetectionMode.Discrete
                            },
                            Shape             = staticShapeIndex,
                            SpeculativeMargin = 0.1f
                        },
                        Pose = new RigidPose
                        {
                            Position = new Vector3(
                                -staticGridWidthInInstances * staticSpacing * 0.5f + i * staticSpacing,
                                -4 + 4 * (float)Math.Cos(i * 0.3) + 4 * (float)Math.Cos(j * 0.3),
                                -staticGridWidthInInstances * staticSpacing * 0.5f + j * staticSpacing),
                            Orientation = Quaternion.Identity
                        }
                    };
                    Simulation.Statics.Add(staticDescription);
                }
            }

            //A bunch of kinematic balls do acrobatics as an extra stressor.
            var kinematicShape      = new Sphere(8);
            var kinematicShapeIndex = Simulation.Shapes.Add(kinematicShape);
            var kinematicCount      = 64;
            var anglePerKinematic   = MathHelper.TwoPi / kinematicCount;
            var startingRadius      = 256;

            kinematicHandles = new BodyHandle[kinematicCount];
            for (int i = 0; i < kinematicCount; ++i)
            {
                var angle       = anglePerKinematic * i;
                var description = new BodyDescription
                {
                    Collidable = new CollidableDescription
                    {
                        Continuity = new ContinuousDetectionSettings {
                            Mode = ContinuousDetectionMode.Discrete
                        },
                        Shape             = kinematicShapeIndex,
                        SpeculativeMargin = 0.1f
                    },
                    Pose = new RigidPose
                    {
                        Position = new Vector3(
                            startingRadius * (float)Math.Cos(angle),
                            0,
                            startingRadius * (float)Math.Sin(angle)),
                        Orientation = Quaternion.Identity
                    },
                    Activity = new BodyActivityDescription {
                        SleepThreshold = 0, MinimumTimestepCountUnderThreshold = 4
                    },
                };
                kinematicHandles[i] = Simulation.Bodies.Add(description);
            }

            dynamicHandles = new QuickQueue <BodyHandle>(65536, BufferPool);
            removedStatics = new QuickQueue <StaticDescription>(512, BufferPool);
            random         = new Random(5);
        }
Example #8
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(-10, 0, -10);
            //camera.Yaw = MathHelper.Pi ;
            camera.Yaw = MathHelper.Pi * 3f / 4;
            //camera.Pitch = MathHelper.PiOver2 * 0.999f;
            Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), new PositionFirstTimestepper());

            var box     = new Box(1f, 3f, 2f);
            var capsule = new Capsule(1f, 1f);
            var sphere  = new Sphere(1f);

            box.ComputeInertia(1, out var boxInertia);
            capsule.ComputeInertia(1, out var capsuleInertia);
            sphere.ComputeInertia(1, out var sphereInertia);
            var       boxIndex     = Simulation.Shapes.Add(box);
            var       capsuleIndex = Simulation.Shapes.Add(capsule);
            var       sphereIndex  = Simulation.Shapes.Add(sphere);
            const int width        = 16;
            const int height       = 3;
            const int length       = 16;

            for (int i = 0; i < width; ++i)
            {
                for (int j = 0; j < height; ++j)
                {
                    for (int k = 0; k < length; ++k)
                    {
                        var location        = new Vector3(5, 5, 5) * new Vector3(i, j, k);// + new Vector3(-width * 1.5f, 1.5f, -length * 1.5f);
                        var bodyDescription = new BodyDescription
                        {
                            Activity = new BodyActivityDescription {
                                MinimumTimestepCountUnderThreshold = 32, SleepThreshold = 0.01f
                            },
                            Pose = new RigidPose
                            {
                                Orientation = Quaternion.Identity,
                                Position    = location
                            },
                            Collidable = new CollidableDescription
                            {
                                Continuity = new ContinuousDetectionSettings {
                                    Mode = ContinuousDetectionMode.Discrete
                                },
                                SpeculativeMargin = 0.1f
                            }
                        };
                        switch ((i + j) % 3)
                        {
                        case 0:
                            bodyDescription.Collidable.Shape = sphereIndex;
                            bodyDescription.LocalInertia     = sphereInertia;
                            break;

                        case 1:
                            bodyDescription.Collidable.Shape = capsuleIndex;
                            bodyDescription.LocalInertia     = capsuleInertia;
                            break;

                        case 2:
                            bodyDescription.Collidable.Shape = boxIndex;
                            bodyDescription.LocalInertia     = boxInertia;
                            break;
                        }
                        Simulation.Bodies.Add(bodyDescription);
                    }
                }
            }

            //var testShape = new Box(50, 2, 0.2f);
            //testShape.ComputeInertia(1, out var testInertia);
            //Simulation.Bodies.Add(BodyDescription.CreateDynamic(new Vector3(10, 10, 10), testInertia, new CollidableDescription(Simulation.Shapes.Add(testShape), 10.1f), new BodyActivityDescription(-0.01f)));


            DemoMeshHelper.LoadModel(content, BufferPool, @"Content\newt.obj", new Vector3(5, 5, 5), out var newtMesh);
            newtMesh.ComputeClosedInertia(10, out var newtInertia, out _);
            Simulation.Bodies.Add(BodyDescription.CreateDynamic(new RigidPose(new Vector3(30, 20, 30)), newtInertia,
                                                                new CollidableDescription(Simulation.Shapes.Add(newtMesh), 0.1f), new BodyActivityDescription(0.01f)));

            Simulation.Statics.Add(new StaticDescription(new Vector3(30, 15, 30), new CollidableDescription(Simulation.Shapes.Add(new Box(15, 1, 15)), 0.1f)));

            DemoMeshHelper.LoadModel(content, BufferPool, @"Content\box.obj", new Vector3(5, 1, 5), out var boxMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(10, 5, -20), new CollidableDescription(Simulation.Shapes.Add(boxMesh), 0.1f)));

            DemoMeshHelper.CreateFan(64, 16, new Vector3(1, 1, 1), BufferPool, out var fanMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(-10, 0, -20), new CollidableDescription(Simulation.Shapes.Add(fanMesh), 0.1f)));

            const int planeWidth  = 128;
            const int planeHeight = 128;

            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeHeight,
                                               (int x, int y) =>
            {
                return(new Vector3(x - planeWidth / 2, 1 * MathF.Cos(x / 2f) * MathF.Sin(y / 2f), y - planeHeight / 2));
            }, new Vector3(2, 1, 2), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(64, -10, 64), BepuUtilities.QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
Example #9
0
        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, -10f, 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());
                            orientationLengthSquared = QuaternionEx.LengthSquared(ref localPose.Orientation);
                        }while (orientationLengthSquared < 1e-9f);
                        QuaternionEx.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;

            DemoMeshHelper.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), QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), MathF.PI / 2),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }
Example #10
0
        public override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 5, 10);
            camera.Yaw      = 0;
            camera.Pitch    = 0;

            bodyProperties = new CollidableProperty <TankDemoBodyProperties>();
            //We assign velocities outside of the timestep to fire bullets, so using the PositionLastTimestepper avoids integrating those velocities into positions before the solver has a chance to intervene.
            //We could have also modified velocities in the PositionFirstTimestepper's BeforeCollisionDetection callback, but it's just a little simpler to do this with very little cost.
            Simulation = Simulation.Create(BufferPool, new TankCallbacks()
            {
                Properties = bodyProperties
            }, new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)), new PositionLastTimestepper());

            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);

            var projectileShape = new Sphere(0.1f);

            projectileShape.ComputeInertia(0.2f, out var projectileInertia);
            var tankDescription = new TankDescription
            {
                Body         = TankPartDescription.Create(10, new Box(4f, 1, 5), RigidPose.Identity, 0.5f, Simulation.Shapes),
                Turret       = TankPartDescription.Create(1, new Box(1.5f, 0.7f, 2f), new RigidPose(new Vector3(0, 0.85f, 0.4f)), 0.5f, Simulation.Shapes),
                Barrel       = TankPartDescription.Create(0.5f, new Box(0.2f, 0.2f, 3f), new RigidPose(new Vector3(0, 0.85f, 0.4f - 1f - 1.5f)), 0.5f, Simulation.Shapes),
                TurretAnchor = new Vector3(0f, 0.5f, 0.4f),
                BarrelAnchor = new Vector3(0, 0.5f + 0.35f, 0.4f - 1f),
                TurretBasis  = Quaternion.Identity,
                TurretServo  = new ServoSettings(1f, 0f, 40f),
                TurretSpring = new SpringSettings(10f, 1f),
                BarrelServo  = new ServoSettings(1f, 0f, 40f),
                BarrelSpring = new SpringSettings(10f, 1f),

                ProjectileShape            = Simulation.Shapes.Add(projectileShape),
                ProjectileSpeed            = 100f,
                BarrelLocalProjectileSpawn = new Vector3(0, 0, -1.5f),
                ProjectileInertia          = projectileInertia,

                LeftTreadOffset    = new Vector3(-1.9f, 0f, 0),
                RightTreadOffset   = new Vector3(1.9f, 0f, 0),
                SuspensionLength   = 1f,
                SuspensionSettings = new SpringSettings(2.5f, 1.5f),
                WheelShape         = wheelShapeIndex,
                WheelInertia       = wheelInertia,
                WheelFriction      = 2f,
                TreadSpacing       = 1f,
                WheelCountPerTread = 5,
                WheelOrientation   = QuaternionEx.CreateFromAxisAngle(Vector3.UnitZ, MathF.PI * -0.5f),
            };

            playerController = new TankController(Tank.Create(Simulation, bodyProperties, BufferPool, new RigidPose(new Vector3(0, 10, 0), Quaternion.Identity), tankDescription), 20, 5, 2, 1, 3.5f);


            const int   planeWidth          = 257;
            const float terrainScale        = 3;
            const float inverseTerrainScale = 1f / terrainScale;
            var         terrainPosition     = new Vector2(1 - planeWidth, 1 - planeWidth) * terrainScale * 0.5f;

            random = new Random(5);

            //Add some building-ish landmarks.
            var landmarkMin  = new Vector3(planeWidth * terrainScale * -0.45f, 0, planeWidth * terrainScale * -0.45f);
            var landmarkMax  = new Vector3(planeWidth * terrainScale * 0.45f, 0, planeWidth * terrainScale * 0.45f);
            var landmarkSpan = landmarkMax - landmarkMin;

            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);
                var position      = landmarkMin + landmarkSpan * new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble());
                Simulation.Statics.Add(new StaticDescription(
                                           new Vector3(0, buildingShape.HalfHeight - 4f + GetHeightForPosition(position.X, position.Z, planeWidth, inverseTerrainScale, terrainPosition), 0) + position,
                                           QuaternionEx.CreateFromAxisAngle(Vector3.UnitY, (float)random.NextDouble() * MathF.PI),
                                           new CollidableDescription(Simulation.Shapes.Add(buildingShape), 0.1f)));
            }

            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeWidth,
                                               (int vX, int vY) =>
            {
                var position2D = new Vector2(vX, vY) * terrainScale + terrainPosition;
                return(new Vector3(position2D.X, GetHeightForPosition(position2D.X, position2D.Y, planeWidth, inverseTerrainScale, terrainPosition), position2D.Y));
            }, new Vector3(1, 1, 1), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(0, 0, 0),
                                                         new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));

            explosions = new QuickList <Explosion>(32, BufferPool);

            //Create the AI tanks.
            const int aiTankCount = 100;

            aiTanks     = new QuickList <AITank>(aiTankCount, BufferPool);
            playAreaMin = new Vector2(landmarkMin.X, landmarkMin.Z);
            playAreaMax = new Vector2(landmarkMax.X, landmarkMax.Z);
            var playAreaSpan = playAreaMax - playAreaMin;

            for (int i = 0; i < aiTankCount; ++i)
            {
                var horizontalPosition = playAreaMin + new Vector2((float)random.NextDouble(), (float)random.NextDouble()) * playAreaSpan;
                aiTanks.AllocateUnsafely() = new AITank
                {
                    Controller = new TankController(
                        Tank.Create(Simulation, bodyProperties, BufferPool, new RigidPose(
                                        new Vector3(horizontalPosition.X, 10, horizontalPosition.Y),
                                        QuaternionEx.CreateFromAxisAngle(new Vector3(0, 1, 0), (float)random.NextDouble() * 0.1f)),
                                    tankDescription), 20, 5, 2, 1, 3.5f),
                    HitPoints = 5
                };
            }
        }
Example #11
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)));
        }
Example #12
0
        public unsafe override void Initialize(ContentArchive content, Camera camera)
        {
            camera.Position = new Vector3(0, 10, 40);
            camera.Yaw      = 0;
            camera.Pitch    = 0;
            Simulation      = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0)));

            var box     = new Box(2f, 2f, 2f);
            var capsule = new Capsule(1f, 1f);
            var sphere  = new Sphere(1.5f);

            box.ComputeInertia(1, out var boxInertia);
            capsule.ComputeInertia(1, out var capsuleInertia);
            sphere.ComputeInertia(1, out var sphereInertia);
            var       boxIndex     = Simulation.Shapes.Add(box);
            var       capsuleIndex = Simulation.Shapes.Add(capsule);
            var       sphereIndex  = Simulation.Shapes.Add(sphere);
            const int width        = 12;
            const int height       = 3;
            const int length       = 12;

            for (int i = 0; i < width; ++i)
            {
                for (int j = 0; j < height; ++j)
                {
                    for (int k = 0; k < length; ++k)
                    {
                        var location        = new Vector3(5, 5, 5) * new Vector3(i, j, k) + new Vector3(-width * 2.5f, 2.5f, -length * 2.5f);
                        var bodyDescription = new BodyDescription
                        {
                            Activity = new BodyActivityDescription {
                                MinimumTimestepCountUnderThreshold = 32, SleepThreshold = 0.1f
                            },
                            Pose = new RigidPose
                            {
                                Orientation = Quaternion.Identity,
                                Position    = location
                            },
                            Collidable = new CollidableDescription
                            {
                                Continuity = new ContinuousDetectionSettings {
                                    Mode = ContinuousDetectionMode.Discrete
                                },
                                SpeculativeMargin = 0.1f
                            }
                        };
                        switch (j % 3)
                        {
                        case 0:
                            bodyDescription.Collidable.Shape = boxIndex;
                            bodyDescription.LocalInertia     = boxInertia;
                            break;

                        case 1:
                            bodyDescription.Collidable.Shape = capsuleIndex;
                            bodyDescription.LocalInertia     = capsuleInertia;
                            break;

                        case 2:
                            bodyDescription.Collidable.Shape = sphereIndex;
                            bodyDescription.LocalInertia     = sphereInertia;
                            break;
                        }
                        Simulation.Bodies.Add(bodyDescription);
                    }
                }
            }

            //Don't really want to regenerate a convex hull every frame; just cache one out.
            const int pointCount = 32;
            var       points     = new QuickList <Vector3>(pointCount, BufferPool);
            var       random     = new Random(5);

            for (int i = 0; i < pointCount; ++i)
            {
                points.AllocateUnsafely() = new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
            }
            ConvexHullHelper.CreateShape(points.Span.Slice(0, points.Count), BufferPool, out _, out hull);
            points.Dispose(BufferPool);

            //var staticShapeIndex = Simulation.Shapes.Add(new Box(100, 1, 100));
            //var staticDescription = new StaticDescription
            //{
            //    Collidable = new CollidableDescription
            //    {
            //        Continuity = new ContinuousDetectionSettings { Mode = ContinuousDetectionMode.Discrete },
            //        Shape = Simulation.Shapes.Add(new Box(100, 1, 100)),
            //        SpeculativeMargin = 0.1f
            //    },
            //    Pose = new RigidPose { Position = new Vector3(0, -1, 0), Orientation = Quaternion.Identity }
            //};
            //Simulation.Statics.Add(staticDescription);

            const int planeWidth  = 64;
            const int planeHeight = 64;

            DemoMeshHelper.CreateDeformedPlane(planeWidth, planeHeight,
                                               (int x, int y) =>
            {
                return(new Vector3(x, 1 * (float)Math.Cos(x / 4f) * (float)Math.Sin(y / 4f), y));
            }, new Vector3(2, 3, 2), BufferPool, out var planeMesh);
            Simulation.Statics.Add(new StaticDescription(new Vector3(-64, -10, -64), new CollidableDescription(Simulation.Shapes.Add(planeMesh), 0.1f)));
        }