/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MoreConstraintsTestDemo(DemosGame game) : base(game) { Box boxA = new Box(new Vector3(0, 5, 0), 1, 2, 1, 10); Box boxB = new Box(new Vector3(0, 8, 0), 1, 2, 1, 10); boxA.Orientation = Quaternion.CreateFromYawPitchRoll(0, MathHelper.PiOver4, 0); boxB.Orientation = Quaternion.CreateFromYawPitchRoll(MathHelper.PiOver4, 0, 0); WeldJoint weld = new WeldJoint(boxA, boxB); Space.Add(boxA); Space.Add(boxB); Space.Add(weld); boxA = new Box(new Vector3(3, 5, 0), 1, 2, 1, 10); boxB = new Box(new Vector3(3, 8, 0), 1, 2, 1, 10); boxA.Orientation = Quaternion.CreateFromYawPitchRoll(0, MathHelper.PiOver4, 0); boxB.Orientation = Quaternion.CreateFromYawPitchRoll(MathHelper.PiOver4, 0, 0); BallSocketJoint ballSocket = new BallSocketJoint(boxA, boxB, (boxA.Position + boxB.Position) / 2); AngularMotor angularMotor = new AngularMotor(boxA, boxB); angularMotor.Settings.Mode = MotorMode.Servomechanism; Space.Add(boxA); Space.Add(boxB); Space.Add(ballSocket); Space.Add(angularMotor); Box ground = new Box(new Vector3(0, 0, 0), 10, 1, 10); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public PlanetDemo(DemosGame game) : base(game) { Space.ForceUpdater.Gravity = Vector3.Zero; //By pre-allocating a bunch of box-box pair handlers, the simulation will avoid having to allocate new ones at runtime. NarrowPhaseHelper.Factories.BoxBox.EnsureCount(1000); var planet = new Sphere(new Vector3(0, 0, 0), 30); Space.Add(planet); var field = new GravitationalField(new InfiniteForceFieldShape(), planet.Position, 66730 / 2f, 100); Space.Add(field); //Drop the "meteorites" on the planet. Entity toAdd; int numColumns = 10; int numRows = 10; int numHigh = 10; float separation = 5; for (int i = 0; i < numRows; i++) for (int j = 0; j < numColumns; j++) for (int k = 0; k < numHigh; k++) { toAdd = new Box(new Vector3(separation * i - numRows * separation / 2, 40 + k * separation, separation * j - numColumns * separation / 2), 1f, 1f, 1f, 5); toAdd.LinearVelocity = new Vector3(30, 0, 0); toAdd.LinearDamping = 0; toAdd.AngularDamping = 0; Space.Add(toAdd); } game.Camera.Position = new Vector3(0, 0, 150); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public LotsOSpheresDemo(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 8, 25); Space.Add(new Box(new Vector3(0, 0, 0), 120, 1, 120)); int numColumns = 5; int numRows = 5; int numHigh = 5; Fix64 xSpacing = 2.09m; Fix64 ySpacing = 2.08m; Fix64 zSpacing = 2.09m; for (int i = 0; i < numRows; i++) { for (int j = 0; j < numColumns; j++) { for (int k = 0; k < numHigh; k++) { Space.Add(new Sphere(new Vector3( xSpacing * i - (numRows - 1) * xSpacing / 2, 1.58m + k * (ySpacing), 2 + zSpacing * j - (numColumns - 1) * zSpacing / 2), 1, 1)); } } } }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MultipendulumDemo(DemosGame game) : base(game) { //Create the blocks in the pendulum. var link1 = new Box(new Vector3(3, 5, 0), 1.1f, 1.1f, 1.1f, 2); var link2 = new Box(new Vector3(6, 5, 0), 1.1f, 1.1f, 1.1f, 2); Space.Add(link1); Space.Add(link2); var ground = new Box(new Vector3(3, -3, 0), 20, 1, 10); Space.Add(ground); //Connect them together. Space.Add(new BallSocketJoint(link1, link2, (link1.Position + link2.Position) / 2)); Space.Add(new BallSocketJoint(link1, ground, new Vector3(0, 5, 0))); Entity toAdd; //Create a target stack. for (int k = 0; k < 4; k++) { toAdd = new Box(new Vector3(-2f, -1f + 2 * k, 0), 1.5f, 1.5f, 1.5f, 1); Space.Add(toAdd); } game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 2, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public DetectorVolumeDemo(DemosGame game) : base(game) { var tubeModel = game.Content.Load <Model>("tube"); Vector3[] modelVertices; int[] modelIndices; ModelDataExtractor.GetVerticesAndIndicesFromModel(tubeModel, out modelVertices, out modelIndices); var detectorVolume = new DetectorVolume(new StaticMeshData(modelVertices, modelIndices), Space.BroadPhase.QueryAccelerator); Space.Add(detectorVolume); game.ModelDrawer.Add(detectorVolume.TriangleMesh); Entity toAdd = new Box(new Vector3(0, -10, 0), 1, 1, 1); toAdd.Tag = "noDisplayObject"; displayBox = game.ModelDrawer.Add(toAdd); displayBox.TextureIndex = 0; game.ModelDrawer.IsWireframe = true; toAdd.LinearVelocity = new Vector3(0, 1, 0); Space.Add(toAdd); //Create the ground detectorVolume.EntityBeginsTouching += BeginsTouching; detectorVolume.EntityStopsTouching += StopsTouching; detectorVolume.VolumeBeginsContainingEntity += BeginsContaining; detectorVolume.VolumeStopsContainingEntity += StopsContaining; game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 0, 22); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public GeneralConvexPairStressDemo(DemosGame game) : base(game) { Space.Remove(vehicle.Vehicle); //Enable simplex caching. ConfigurationHelper.ApplySuperSpeedySettings(Space); for (int i = 0; i < 2000; i++) { EntityShape shape; switch (i % 3) { case 0: shape = new CylinderShape(0.5m + (Fix64)random.NextDouble() * 1.5m, 0.5m + (Fix64)random.NextDouble() * 1.5m); break; case 1: shape = new ConeShape(0.5m + (Fix64)random.NextDouble() * 1.5m, 0.5m + (Fix64)random.NextDouble() * 1.5m); break; default: shape = new CapsuleShape(0.5m + (Fix64)random.NextDouble() * 1.5m, 0.5m + (Fix64)random.NextDouble() * 1.5m); break; } var toAdd = new Entity(shape, 2); //toAdd.LocalInertiaTensorInverse = new BEPUutilities.Matrix3x3(); RandomizeEntityState(toAdd); Space.Add(toAdd); } Space.ForceUpdater.Gravity = new Vector3(); game.Camera.Position = new Vector3(0, 6, 15); }
protected Demo(DemosGame game) { Game = game; Space = new Space(); //This section lets the engine know that it can make use of multithreaded systems //by adding threads to its thread pool. #if XBOX360 //Note that not all four available hardware threads are used. //Currently, BEPUphysics will allocate an equal amount of work to each thread on the xbox360. //If two threads are put on one core, it will bottleneck the engine and run significantly slower than using 3 hardware threads. Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null); Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null); Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null); #else if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { Space.ThreadManager.AddThread(); } } #endif game.Camera.Yaw = 0; game.Camera.Pitch = 0; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ColosseumDemo(DemosGame game) : base(game) { double angle; int numBoxesPerRing = 12; float blockWidth = 2; float blockHeight = 2; float blockLength = 6f; float radius = 15; Entity toAdd; Space.Add(new Box(new Vector3(0, -blockHeight / 2 - 1, 0), 100, 2f, 100)); double increment = MathHelper.TwoPi / numBoxesPerRing; for (int i = 0; i < 8; i++) { for (int k = 0; k < numBoxesPerRing; k++) { if (i % 2 == 0) { angle = k * increment; toAdd = new Box(new Vector3(-(float) Math.Cos(angle) * radius, i * blockHeight, (float) Math.Sin(angle) * radius), blockWidth, blockHeight, blockLength, 20); toAdd.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Up, (float) angle); Space.Add(toAdd); } else { angle = (k + .5f) * increment; toAdd = new Box(new Vector3(-(float)Math.Cos(angle) * radius, i * blockHeight, (float)Math.Sin(angle) * radius), blockWidth, blockHeight, blockLength, 20); toAdd.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Up, (float) angle); Space.Add(toAdd); } } } game.Camera.Position = new Vector3(0, 2, 2); }
protected Demo(DemosGame game) { Game = game; parallelLooper = new ParallelLooper(); //This section lets the engine know that it can make use of multithreaded systems //by adding threads to its thread pool. #if XBOX360 parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }); parallelLooper.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }); #else if (Environment.ProcessorCount > 1) { for (int i = 0; i < Environment.ProcessorCount; i++) { parallelLooper.AddThread(); } } #endif Space = new Space(parallelLooper); game.Camera.LockedUp = Vector3.Up; game.Camera.ViewDirection = new Vector3(0, 0, -1); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public WallDemo(DemosGame game) : base(game) { int width = 10; int height = 10; float blockWidth = 2f; float blockHeight = 1f; float blockLength = 1f; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { var toAdd = new Box( new Vector3( i * blockWidth + .5f * blockWidth * (j % 2) - width * blockWidth * .5f, blockHeight * .5f + j * (blockHeight), 0), blockWidth, blockHeight, blockLength, 10); Space.Add(toAdd); } } Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public IncomingDemo(DemosGame game) : base(game) { Entity toAdd; //Build the stack... for (int k = 1; k <= 12; k++) { if (k % 2 == 1) { toAdd = new Box(new Vector3(-3, k, 0), 1, 1, 7, 10); Space.Add(toAdd); toAdd = new Box(new Vector3(3, k, 0), 1, 1, 7, 10); Space.Add(toAdd); } else { toAdd = new Box(new Vector3(0, k, -3), 7, 1, 1, 10); Space.Add(toAdd); toAdd = new Box(new Vector3(0, k, 3), 7, 1, 1, 10); Space.Add(toAdd); } } //And then smash it! toAdd = new Sphere(new Vector3(0, 150, 0), 3, 100); Space.Add(toAdd); Space.Add(new Box(new Vector3(0, 0, 0), 10, 1f, 10)); game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 6, 30); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public StackDemo(DemosGame game) : base(game) { kapow.PositionUpdateMode = BEPUphysics.PositionUpdating.PositionUpdateMode.Continuous; int height = 50; float blockWidth = 3f; float blockHeight = 1f; float blockLength = 3f; for (int i = 0; i < height; i++) { var toAdd = new Box( new Vector3( 0, blockHeight * .5f + i * (blockHeight), 0), blockWidth, blockHeight, blockLength, 10); Space.Add(toAdd); } Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BridgeDemo(DemosGame game) : base(game) { //Form a long chain of planks connected by revolute joints. //The revolute joints control the three linear degrees of freedom and two angular degrees of freedom. //The third allowed angular degree of freedom allows the bridge to flex like a rope bridge. Vector3 startPosition = new Vector3(0, 0, 0); var startPlatform = new Box(startPosition - new Vector3(0, 0, 3.2f), 8, .5f, 8); Space.Add(startPlatform); Vector3 offset = new Vector3(0, 0, 1.7f); Box previousLink = startPlatform; Vector3 position = new Vector3(); for (int i = 1; i <= 200; i++) { position = startPosition + offset * i; Box link = new Box(position, 4.5f, .3f, 1.5f, 50); Space.Add(link); Space.Add(new RevoluteJoint(previousLink, link, position - offset * .5f, Vector3.Right)); previousLink = link; } var endPlatform = new Box(position - new Vector3(0, 0, -4.8f), 8, .5f, 8); Space.Add(endPlatform); Space.Add(new RevoluteJoint(previousLink, endPlatform, position + offset * .5f, Vector3.Right)); game.Camera.Position = startPosition + new Vector3(0, 1, offset.Z * 200 + 5); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhaseDemo(DemosGame game) : base(game) { //Make a fatter kapow sphere. Space.Remove(kapow); kapow = new Sphere(new Vector3(11000, 0, 0), 1.5f, 1000); Space.Add(kapow); Space.Solver.IterationLimit = 1; //Essentially no sustained contacts, so don't need to worry about accuracy. Space.ForceUpdater.Gravity = Vector3.Zero; int numColumns = 15; int numRows = 15; int numHigh = 15; float separation = 3; Entity toAdd; for (int i = 0; i < numRows; i++) for (int j = 0; j < numColumns; j++) for (int k = 0; k < numHigh; k++) { toAdd = new Box(new Vector3(separation * i, k * separation, separation * j), 1, 1, 1, 1); toAdd.Material.Bounciness = 1; //Superbouncy boxes help propagate shock waves. toAdd.LinearDamping = 0f; toAdd.AngularDamping = 0f; Space.Add(toAdd); } game.Camera.Position = new Vector3(0, 3, -10); game.Camera.ViewDirection = new Vector3(0, 0, 1); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public IncomingDemo(DemosGame game) : base(game) { Entity toAdd; //Build the stack... for (int k = 1; k <= 12; k++) { if (k % 2 == 1) { toAdd = new Box(new Vector3(-3, k, 0), 1, 1, 7, 10); Space.Add(toAdd); toAdd = new Box(new Vector3(3, k, 0), 1, 1, 7, 10); Space.Add(toAdd); } else { toAdd = new Box(new Vector3(0, k, -3), 7, 1, 1, 10); Space.Add(toAdd); toAdd = new Box(new Vector3(0, k, 3), 7, 1, 1, 10); Space.Add(toAdd); } } //And then smash it! toAdd = new Sphere(new Vector3(0, 150, 0), 3, 100); Space.Add(toAdd); Space.Add(new Box(new Vector3(0, 0, 0), 10, 1f, 10)); game.Camera.Position = new Vector3(0, 6, 30); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AddRemoveStressDemo(DemosGame game) : base(game) { NarrowPhaseHelper.Factories.BoxBox.EnsureCount(5000); NarrowPhaseHelper.Factories.CompoundCompound.EnsureCount(5000); Space.Remove(vehicle.Vehicle); for (int i = 0; i < 1000; i++) { var position = new Vector3( (float)(random.NextDouble() - 0.5) * width, (float)(random.NextDouble() - 0.5) * height, (float)(random.NextDouble() - 0.5) * length); var toAdd = new CompoundBody(new List <CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1, 1, 1), position, 1) }, 10); //var toAdd = new Box(position, 1, 1, 1, 1); toAdd.IsAffectedByGravity = false; toAdd.LinearVelocity = 3 * Vector3.Normalize(toAdd.Position); Space.Add(toAdd); addedEntities.Add(toAdd); } //Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); //Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public TwistTestDemo(DemosGame game) : base(game) { var a = new Box(new Vector3(-2, 2, 0), 1, 2, 2, 5); var b = new Box(new Vector3(2, 2, 0), 1, 2, 2, 5); b.Orientation = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), MathHelper.PiOver4); Space.Add(a); Space.Add(b); var twistJoint = new TwistJoint(a, b, a.OrientationMatrix.Right, b.OrientationMatrix.Right); var twistMotor = new TwistMotor(a, b, a.OrientationMatrix.Right, b.OrientationMatrix.Right); twistMotor.Settings.Mode = MotorMode.Servomechanism; //Space.Add(twistJoint); Space.Add(twistMotor); var ballSocketJoint = new BallSocketJoint(a, b, (a.Position + b.Position) * 0.5f); var swingLimit = new SwingLimit(a, b, a.OrientationMatrix.Right, a.OrientationMatrix.Right, MathHelper.PiOver2); Space.Add(ballSocketJoint); Space.Add(swingLimit); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public CollisionFilteringDemo(DemosGame game) : base(game) { Entity toAdd; toAdd = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(toAdd); //Set up two stacks which go through each other var firstStackGroup = new CollisionGroup(); var secondStackGroup = new CollisionGroup(); //Adding this rule to the space's collision group rules will prevent entities belong to these two groups from generating collision pairs with each other. groupPair = new CollisionGroupPair(firstStackGroup, secondStackGroup); CollisionRules.CollisionGroupRules.Add(groupPair, CollisionRule.NoBroadPhase); for (int k = 0; k < 10; k++) { toAdd = new Box( new Vector3(-4 + .12f * k, .5f + k, 0), 1f, 1f, 1f, 10); toAdd.CollisionInformation.CollisionRules.Group = firstStackGroup; Space.Add(toAdd); toAdd = new Box(new Vector3(4 - .12f * k, .5f + k, 0), 1f, 1f, 1f, 10); toAdd.CollisionInformation.CollisionRules.Group = secondStackGroup; Space.Add(toAdd); } //Add another two boxes which ignore each other using the specific entities method; they will still collide with the stacks since they will have the default dynamic collision group. toAdd = new Box(new Vector3(1, 3, 0), 1f, 4f, 2f, 10); var toAdd2 = new Box(new Vector3(-1, 3, 0), 1f, 4f, 2f, 15); CollisionRules.AddRule(toAdd, toAdd2, CollisionRule.NoBroadPhase); Space.Add(toAdd); Space.Add(toAdd2); game.Camera.Position = new Vector3(0, 6, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BridgeDemo(DemosGame game) : base(game) { //Form a long chain of planks connected by revolute joints. //The revolute joints control the three linear degrees of freedom and two angular degrees of freedom. //The third allowed angular degree of freedom allows the bridge to flex like a rope bridge. Vector3 startPosition = new Vector3(0, 0, 0); var startPlatform = new Box(startPosition - new Vector3(0, 0, (Fix64)3.2m), 8, (Fix64).5m, 8); Space.Add(startPlatform); Vector3 offset = new Vector3(0, 0, (Fix64)1.7m); Box previousLink = startPlatform; Vector3 position = new Vector3(); for (int i = 1; i <= 200; i++) { position = startPosition + offset * i; Box link = new Box(position, (Fix64)4.5m, (Fix64).3m, (Fix64)1.5m, 50); Space.Add(link); Space.Add(new RevoluteJoint(previousLink, link, position - offset * (Fix64).5m, Vector3.Right)); previousLink = link; } var endPlatform = new Box(position - new Vector3(0, 0, (Fix64)(-4.8m)), 8, (Fix64).5m, 8); Space.Add(endPlatform); Space.Add(new RevoluteJoint(previousLink, endPlatform, position + offset * (Fix64).5m, Vector3.Right)); game.Camera.Position = startPosition + new Vector3(0, 1, offset.Z * 200 + 5); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public TerrainDemo(DemosGame game) : base(game) { //x and y, in terms of heightmaps, refer to their local x and y coordinates. In world space, they correspond to x and z. //Setup the heights of the terrain. //[The size here is limited by the Reach profile the demos use- the drawer draws the terrain as a big block and runs into primitive drawing limits. //The physics can support far larger terrains!] int xLength = 180; int zLength = 180; float xSpacing = 8f; float zSpacing = 8f; var heights = new float[xLength, zLength]; for (int i = 0; i < xLength; i++) { for (int j = 0; j < zLength; j++) { float x = i - xLength / 2; float z = j - zLength / 2; //heights[i,j] = (float)(x * y / 1000f); heights[i, j] = (float)(10 * (Math.Sin(x / 8) + Math.Sin(z / 8))); //heights[i,j] = 3 * (float)Math.Sin(x * y / 100f); //heights[i,j] = (x * x * x * y - y * y * y * x) / 1000f; } } //Create the terrain. var terrain = new Terrain(heights, new AffineTransform( new Vector3(-xSpacing, 1, -zSpacing), Quaternion.Identity, new Vector3(xLength * xSpacing / 2, 0, zLength * zSpacing / 2))); terrain.Shape.QuadTriangleOrganization = BEPUphysics.CollisionShapes.QuadTriangleOrganization.BottomRightUpperLeft; //terrain.Thickness = 5; //Uncomment this and shoot some things at the bottom of the terrain! They'll be sucked up through the ground. Space.Add(terrain); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 5; k++) { Space.Add(new Box( new Vector3(0 + i * 4, 100 - j * 10, 0 + k * 4), 2 + i * j * k, 2 + i * j * k, 2 + i * j * k, 4 + 20 * i * j * k)); } } } game.ModelDrawer.Add(terrain); game.Camera.Position = new Vector3(0, 30, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BoxBoxTestDemo(DemosGame game) : base(game) { //float blockWidth = 2; //float blockHeight = 2; //float blockLength = 6f; //Entity toAdd; //toAdd = new Box(new Vector3(0, 2,0), blockWidth, blockHeight, blockLength, 20); //toAdd.ActivityInformation.IsAlwaysActive = true; //toAdd.AllowStabilization = false; //Space.Add(toAdd); int numColumns = 3; int numRows = 3; int numHigh = 30; float xSpacing = 1.01f; float ySpacing = 1.01f; float zSpacing = 1.01f; for (int i = 0; i < numRows; i++) for (int j = 0; j < numColumns; j++) for (int k = 0; k < numHigh; k++) { Space.Add(new Box(new Vector3( xSpacing * i - (numRows - 1) * xSpacing / 2f, 1f + k * (ySpacing), zSpacing * j - (numColumns - 1) * zSpacing / 2f), .5f, .5f, .5f, 5)); } Space.Add(new Box(new Vector3(0, 0, 0), 20, 1f, 20)); game.Camera.Position = new Vector3(0, 3, 10); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MultithreadedScalingTestDemo(DemosGame game) : base(game) { simulationBuilders = new Func<Space, int>[] { BuildPileSimulation, BuildWallSimulation, BuildPlanetSimulation }; #if WINDOWS int coreCountMax = Environment.ProcessorCount; testResults = new double[coreCountMax, simulationBuilders.Length]; int reruns = 1; for (int i = 0; i < reruns; i++) { GC.Collect(); var threadManager = new SpecializedThreadManager(); //Try different thread counts. for (int j = 0; j < coreCountMax; j++) { threadManager.AddThread(); for (int k = 0; k < simulationBuilders.Length; k++) testResults[j, k] = RunTest(threadManager, simulationBuilders[k]); GC.Collect(); } } #else testResults = new double[4, simulationBuilders.Length]; int reruns = 10; for (int i = 0; i < reruns; i++) { GC.Collect(); var threadManager = new SpecializedThreadManager(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[0, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[1, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[2, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }, null); for (int k = 0; k < simulationBuilders.Length; k++) testResults[3, k] += RunTest(threadManager, simulationBuilders[k]); GC.Collect(); } #endif }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AddRemoveStressDemo(DemosGame game) : base(game) { NarrowPhaseHelper.Factories.BoxBox.EnsureCount(5000); NarrowPhaseHelper.Factories.CompoundCompound.EnsureCount(5000); Space.Remove(vehicle.Vehicle); for (int i = 0; i < 1000; i++) { var position = new Vector3( (float)(random.NextDouble() - 0.5) * width, (float)(random.NextDouble() - 0.5) * height, (float)(random.NextDouble() - 0.5) * length); var toAdd = new CompoundBody(new List<CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1,1,1), position, 1) }, 10); //var toAdd = new Box(position, 1, 1, 1, 1); toAdd.IsAffectedByGravity = false; toAdd.LinearVelocity = 3 * Vector3.Normalize(toAdd.Position); Space.Add(toAdd); addedEntities.Add(toAdd); } //Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); //Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public WallDemo(DemosGame game) : base(game) { int width = 10; int height = 10; float blockWidth = 2f; float blockHeight = 1f; float blockLength = 1f; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { var toAdd = new Box( new Vector3( i * blockWidth + .5f * blockWidth * (j % 2) - width * blockWidth * .5f, blockHeight * .5f + j * (blockHeight), 0), blockWidth, blockHeight, blockLength, 10); Space.Add(toAdd); } } Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhaseDemo(DemosGame game) : base(game) { //Make a fatter kapow sphere. Space.Remove(kapow); kapow = new Sphere(new Vector3(11000, 0, 0), 1.5f, 1000); Space.Add(kapow); Space.Solver.IterationLimit = 1; //Essentially no sustained contacts, so don't need to worry about accuracy. Space.ForceUpdater.Gravity = Vector3.Zero; int numColumns = 15; int numRows = 15; int numHigh = 15; float separation = 3; Entity toAdd; for (int i = 0; i < numRows; i++) { for (int j = 0; j < numColumns; j++) { for (int k = 0; k < numHigh; k++) { toAdd = new Box(new Vector3(separation * i, k * separation, separation * j), 1, 1, 1, 1); toAdd.Material.Bounciness = 1; //Superbouncy boxes help propagate shock waves. toAdd.LinearDamping = 0f; toAdd.AngularDamping = 0f; Space.Add(toAdd); } } } game.Camera.Position = new Vector3(0, 3, -10); game.Camera.ViewDirection = new Vector3(0, 0, 1); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public PrimitiveSceneBugDemo(DemosGame game) : base(game) { character = new BugShowerCharacterController(Space, game.Camera, game); Space.ForceUpdater.Gravity = new Vector3(0, -16, 0); game.Camera.Position = new Vector3(5, 0.85f, 4); game.Camera.ViewDirection = new Vector3(0, 0, 1); //Since this is the character playground, turn on the character by default. character.Activate(); //Having the character body visible would be a bit distracting. character.CharacterController.Body.Tag = "noDisplayObject"; //Load in mesh data for the environment. Vector3[] staticTriangleVertices; int[] staticTriangleIndices; var playgroundModel = game.Content.Load <Model>("bugPrimitiveRoom"); //This is a little convenience method used to extract vertices and indices from a model. //It doesn't do anything special; any approach that gets valid vertices and indices will work. ModelDataExtractor.GetVerticesAndIndicesFromModel(playgroundModel, out staticTriangleVertices, out staticTriangleIndices); var staticMesh = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(new Vector3(1, 1, 1), Quaternion.Identity, new Vector3(0, 0, 0))); staticMesh.Sidedness = TriangleSidedness.Counterclockwise; Space.Add(staticMesh); game.ModelDrawer.Add(staticMesh); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ParallelSpaceTestDemo(DemosGame game) : base(game) { for (int i = 0; i < 32; i++) { var space = new Space(null); space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); var box = new Box(new Vector3(20 * i, 0, 0), 100, 1, 100); space.Add(box); //game.ModelDrawer.Add(box); for (int j = 0; j < 30; j++) { for (int k = 0; k < 10; k++) { box = new Box(new Vector3(20 * i, 2 + j * 1.1f, 0), 1, 1, 1, 1); entities.Add(box); space.Add(box); //game.ModelDrawer.Add(box); } } spaces.Add(space); } game.Camera.Position = new Vector3(20, 10, 70); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public FishInABarrelDemo(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 7, 30); var detector = new Box(new Vector3(0, 0, 0), 1.5f, 1.5f, 1.5f); detector.CollisionInformation.CollisionRules.Personal = CollisionRule.NoSolver; var acceptedTriggerEntity = new Box(new Vector3(5, 0, 0), 1.6f, .7f, .4f, 1); acceptedTrigger = acceptedTriggerEntity.CollisionInformation; detector.Tag = "noDisplayObject"; acceptedTriggerEntity.Tag = "noDisplayObject"; Space.Add(detector); Space.Add(acceptedTriggerEntity); var fish = game.Content.Load<Model>("fish"); game.ModelDrawer.Add(new DisplayEntityModel(acceptedTriggerEntity, fish, game.ModelDrawer)); var barrelAndPlatform = game.Content.Load<Model>("barrelAndPlatform"); Vector3[] staticTriangleVertices; int[] staticTriangleIndices; ModelDataExtractor.GetVerticesAndIndicesFromModel(barrelAndPlatform, out staticTriangleVertices, out staticTriangleIndices); //Note that the final 'margin' parameter is optional, but can be used to specify a collision margin on triangles in the static triangle group. var fishDepositoryGroup = new StaticMesh(staticTriangleVertices, staticTriangleIndices); CollisionRules.AddRule(fishDepositoryGroup, detector, CollisionRule.NoBroadPhase); Space.Add(fishDepositoryGroup); game.ModelDrawer.Add(fishDepositoryGroup); movedBox = new Box(new Vector3(-4, 5, 0), 1, 1, 1, 1); detector.Space.Add(movedBox); detector.CollisionInformation.Events.InitialCollisionDetected += InitialCollisionDetected; detector.CollisionInformation.Events.CollisionEnded += CollisionEnded; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public RayCastTestDemo(DemosGame game) : base(game) { Space.Add(new Box(new Vector3(0, -0.5f, 0), 50, 1, 50)); //Put whatever you'd like to ray cast here. var capsule = new Capsule(new Vector3(0, 1.2f, 0), 1, 0.6f); capsule.AngularVelocity = new Vector3(1, 1, 1); Space.Add(capsule); var cylinder = new Cylinder(new Vector3(0, 5, 0), 2, .5f); cylinder.AngularVelocity = new Vector3(1, -1, 1); Space.Add(cylinder); var points = new List<Vector3>(); var random = new Random(0); for (int k = 0; k < 40; k++) { points.Add(new Vector3(1 * (float)random.NextDouble(), 3 * (float)random.NextDouble(), 2 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 10, 0), points); convexHull.AngularVelocity = new Vector3(-1, 1, 1); Space.Add(convexHull); game.Camera.Position = new Vector3(-10, 5, 10); game.Camera.Yaw((float)Math.PI / -4f); game.Camera.Pitch(-(float)Math.PI / 9f); //Starter ray. origin = new Vector3(10, 5, 0); direction = new Vector3(-3, -1, 0); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public WallDemo(DemosGame game) : base(game) { int width = 10; int height = 10; Fix64 blockWidth = 2; Fix64 blockHeight = 1; Fix64 blockLength = 1; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { var toAdd = new Box( new Vector3( i * blockWidth + .5m * blockWidth * (j % 2) - width * blockWidth * .5m, blockHeight * .5m + j * (blockHeight), 0), blockWidth, blockHeight, blockLength, 10); Space.Add(toAdd); } } Box ground = new Box(new Vector3(0, -.5m, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public GeneralConvexPairStressDemo(DemosGame game) : base(game) { Space.Remove(vehicle.Vehicle); //Enable simplex caching. ConfigurationHelper.ApplySuperSpeedySettings(Space); for (int i = 0; i < 2000; i++) { EntityShape shape; switch (i % 3) { case 0: shape = new CylinderShape(0.5f + (float)random.NextDouble() * 1.5f, 0.5f + (float)random.NextDouble() * 1.5f); break; case 1: shape = new ConeShape(0.5f + (float)random.NextDouble() * 1.5f, 0.5f + (float)random.NextDouble() * 1.5f); break; default: shape = new CapsuleShape(0.5f + (float)random.NextDouble() * 1.5f, 0.5f + (float)random.NextDouble() * 1.5f); break; } var toAdd = new Entity(shape, 2); //toAdd.LocalInertiaTensorInverse = new BEPUutilities.Matrix3x3(); RandomizeEntityState(toAdd); Space.Add(toAdd); } Space.ForceUpdater.Gravity = new Vector3(); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ConvexHullTestDemo(DemosGame game) : base(game) { var random = new Random(5); for (int i = 0; i < 500000; ++i) { List<Vector3> points = new List<Vector3>(); for (int k = 0; k < random.Next(8, 60); k++) { points.Add(new Vector3(-100 + 30 * (float)random.NextDouble(), 100 + 500 * (float)random.NextDouble(), 100 + 30 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 7, 0), points, 10); Console.WriteLine(convexHull.CollisionInformation.Shape.Vertices.Count); } var vertices = new[] { new Vector3(0, -1.750886E-9f, -1.5f), new Vector3(1, 1, 0.5f), new Vector3(1, -1, 0.5f), new Vector3(-1, 1, 0.5f), new Vector3(-1, -1, 0.5f), }; var hullVertices = new RawList<Vector3>(); ConvexHullHelper.GetConvexHull(vertices, hullVertices); ConvexHull hull = new ConvexHull(vertices, 5); Space.Add(hull); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public LotsOSpheresDemo(DemosGame game) : base(game) { game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 8, 25); Space.Add(new Box(new Vector3(0, 0, 0), 120, 1, 120)); int numColumns = 5; int numRows = 5; int numHigh = 5; float xSpacing = 2.09f; float ySpacing = 2.08f; float zSpacing = 2.09f; for (int i = 0; i < numRows; i++) { for (int j = 0; j < numColumns; j++) { for (int k = 0; k < numHigh; k++) { Space.Add(new Sphere(new Vector3( xSpacing * i - (numRows - 1) * xSpacing / 2f, 1.58f + k * (ySpacing), 2 + zSpacing * j - (numColumns - 1) * zSpacing / 2f), 1, 1)); } } } }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhaseRemovalTestDemo(DemosGame game) : base(game) { Entity toAdd; //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7)); BEPUutilities.BoundingBox box = new BEPUutilities.BoundingBox(new BEPUutilities.Vector3(-500, -500, -500), new BEPUutilities.Vector3(500, 500, 500)); DynamicHierarchy dh = new DynamicHierarchy(); Random rand = new Random(0); RawList <Entity> entities = new RawList <Entity>(); for (int k = 0; k < 1000; k++) { BEPUutilities.Vector3 position = new BEPUutilities.Vector3((Fix64)rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X, (Fix64)rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y, (Fix64)rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z); toAdd = new Box(position, 1, 1, 1, 1); entities.Add(toAdd); } testResults = new double[2]; int runCount = 10; for (int k = 0; k < runCount; k++) { for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } long start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveFast(entities[i].CollisionInformation); } long end = Stopwatch.GetTimestamp(); testResults[0] += (end - start) / (double)Stopwatch.Frequency; for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveBrute(entities[i].CollisionInformation); } end = Stopwatch.GetTimestamp(); testResults[1] += (end - start) / (double)Stopwatch.Frequency; } testResults[0] /= runCount; testResults[1] /= runCount; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MutableCompoundDemo(DemosGame game) : base(game) { int width = 3; int height = 3; int length = 10; float blockWidth = 1f; float blockHeight = 1f; float blockLength = 1f; for (int q = 0; q < 1; q++) { List <CompoundShapeEntry> shapes = new List <CompoundShapeEntry>(); float totalWeight = 0; float density = 1; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { for (int k = 0; k < length; k++) { float weight = density * blockWidth * blockLength * blockHeight; totalWeight += weight; shapes.Add(new CompoundShapeEntry( new BoxShape(blockWidth, blockHeight, blockLength), new Vector3(5 + q * 20 + i * blockWidth, j * blockHeight, k * blockLength), weight)); } } } var compound = new CompoundBody(shapes, totalWeight); //compound.Orientation = Quaternion.CreateFromYawPitchRoll(1, 1, 1); //compound.AngularVelocity = new Vector3(0, 1, 0); Entity <CompoundCollidable> compound2, compound3; CompoundHelper.SplitCompound(x => x.ShapeIndex >= shapes.Count / 2, compound, out compound2); CompoundHelper.SplitCompound(x => x.ShapeIndex >= 3 * shapes.Count / 4, compound2, out compound3); //compound.ActivityInformation.IsAlwaysActive = true; //compound.IsAffectedByGravity = false; //compound2.ActivityInformation.IsAlwaysActive = true; //compound2.IsAffectedByGravity = false; //compound3.ActivityInformation.IsAlwaysActive = true; //compound3.IsAffectedByGravity = false; //compound.Tag = "noDisplayObject"; Space.Add(compound); Space.Add(compound2); Space.Add(compound3); } Box ground = new Box(new Vector3(0, -4.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AddRemoveStressDemo(DemosGame game) : base(game) { Space.Remove(vehicle.Vehicle); var compoundShape = new CompoundShape(new List <CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, 1, 0), 1), new CompoundShapeEntry(new BoxShape(2, 1, 2), new Vector3(), 1), new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, -1, 0), 1) }); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(compoundShape, 10); addedEntities.Add(toAdd); } var boxShape = new BoxShape(1, 1, 1); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(boxShape, 10); addedEntities.Add(toAdd); } Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load <Model>("cube"), out vertices, out indices); var mobileMeshShape = new MobileMeshShape(vertices, indices, new AffineTransform(Matrix3x3.CreateScale(1, 2, 1), new Vector3()), MobileMeshSolidity.Counterclockwise); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(mobileMeshShape, 10); addedEntities.Add(toAdd); } for (int i = 0; i < addedEntities.Count; ++i) { var entity = addedEntities[i]; entity.Gravity = new Vector3(); entity.Position = GetRandomPosition(random); entity.LinearVelocity = 3 * Vector3.Normalize(entity.Position); Space.Add(entity); } var playgroundModel = game.Content.Load <Model>("playground"); ModelDataExtractor.GetVerticesAndIndicesFromModel(playgroundModel, out vertices, out indices); var staticMesh = new StaticMesh(vertices, indices, new AffineTransform(Matrix3x3.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), new Vector3(0, -30, 0))); staticMesh.Sidedness = TriangleSidedness.Counterclockwise; Space.Add(staticMesh); game.ModelDrawer.Add(staticMesh); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs the character and internal physics character controller. /// </summary> /// <param name="owningSpace">Space to add the character to.</param> /// <param name="camera">Camera to attach to the character.</param> /// <param name="game">The running game.</param> public SphereCharacterControllerInput(Space owningSpace, Camera camera, DemosGame game) { CharacterController = new SphereCharacterController(); Camera = camera; CameraControlScheme = new FixedOffsetCameraControlScheme(CharacterController.Body, camera, game); Space = owningSpace; }
/// <summary> /// Constructs the character and internal physics character controller. /// </summary> /// <param name="owningSpace">Space to add the character to.</param> /// <param name="camera">Camera to attach to the character.</param> /// <param name="game">The running game.</param> public CharacterControllerInput(Space owningSpace, Camera camera, DemosGame game) { CharacterController = new CharacterController(); Camera = camera; CameraControlScheme = new CharacterCameraControlScheme(CharacterController, camera, game); Space = owningSpace; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public TerrainDemo(DemosGame game) : base(game) { //x and y, in terms of heightmaps, refer to their local x and y coordinates. In world space, they correspond to x and z. //Setup the heights of the terrain. //[The size here is limited by the Reach profile the demos use- the drawer draws the terrain as a big block and runs into primitive drawing limits. //The physics can support far larger terrains!] int xLength = 180; int zLength = 180; float xSpacing = 8f; float zSpacing = 8f; var heights = new float[xLength, zLength]; for (int i = 0; i < xLength; i++) { for (int j = 0; j < zLength; j++) { float x = i - xLength / 2; float z = j - zLength / 2; //heights[i,j] = (float)(x * y / 1000f); heights[i, j] = (float)(10 * (Math.Sin(x / 8) + Math.Sin(z / 8))); //heights[i,j] = 3 * (float)Math.Sin(x * y / 100f); //heights[i,j] = (x * x * x * y - y * y * y * x) / 1000f; } } //Create the terrain. var terrain = new Terrain(heights, new AffineTransform( new Vector3(xSpacing, 1, zSpacing), Quaternion.Identity, new Vector3(-xLength * xSpacing / 2, 0, -zLength * zSpacing / 2))); //terrain.Thickness = 5; //Uncomment this and shoot some things at the bottom of the terrain! They'll be sucked up through the ground. Space.Add(terrain); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 5; k++) { Space.Add(new Box( new Vector3(0 + i * 4, 100 - j * 10, 0 + k * 4), 2 + i * j * k, 2 + i * j * k, 2 + i * j * k, 4 + 20 * i * j * k)); } } } game.ModelDrawer.Add(terrain); game.Camera.Position = new Vector3(0, 30, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public BroadPhaseRemovalTestDemo(DemosGame game) : base(game) { Entity toAdd; //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7)); BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500)); DynamicHierarchy dh = new DynamicHierarchy(); Random rand = new Random(0); RawList<Entity> entities = new RawList<Entity>(); for (int k = 0; k < 1000; k++) { Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X), (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y), (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)); toAdd = new Box(MathConverter.Convert(position), 1, 1, 1, 1); entities.Add(toAdd); } testResults = new double[2]; int runCount = 10; for (int k = 0; k < runCount; k++) { for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } long start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveFast(entities[i].CollisionInformation); } long end = Stopwatch.GetTimestamp(); testResults[0] += (end - start) / (double)Stopwatch.Frequency; for (int i = 0; i < entities.Count; i++) { dh.Add(entities[i].CollisionInformation); } start = Stopwatch.GetTimestamp(); for (int i = 0; i < entities.Count; i++) { //dh.RemoveBrute(entities[i].CollisionInformation); } end = Stopwatch.GetTimestamp(); testResults[1] += (end - start) / (double)Stopwatch.Frequency; } testResults[0] /= runCount; testResults[1] /= runCount; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public TankDemo(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 2, 15); Space.Add(new Box(new Vector3(0, -5, 0), 20, 1, 20)); playerTank = new Tank(new Vector3(0, 0, 0)); playerTank.AddToSpace(Space); //Create a bunch of other tanks. autoTanks = new List <Tank>(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { var autoTank = new Tank(new Vector3(-30 + i * 10, 30, -30 + j * 10)); autoTanks.Add(autoTank); autoTank.AddToSpace(Space); } } //x and y, in terms of heightmaps, refer to their local x and y coordinates. In world space, they correspond to x and z. //Setup the heights of the terrain. int xLength = 180; int zLength = 180; Fix64 xSpacing = 8; Fix64 zSpacing = 8; var heights = new Fix64[xLength, zLength]; for (int i = 0; i < xLength; i++) { for (int j = 0; j < zLength; j++) { Fix64 x = i - xLength / 2; Fix64 z = j - zLength / 2; //heights[i,j] = (Fix64)(x * y / 1000f); heights[i, j] = 20 * (Fix64.Sin(x / 8) + Fix64.Sin(z / 8)); //heights[i,j] = 3 * (Fix64)Math.Sin(x * y / 100f); //heights[i,j] = (x * x * x * y - y * y * y * x) / 1000f; } } //Create the terrain. var terrain = new Terrain(heights, new AffineTransform( new Vector3(xSpacing, 1, zSpacing), Quaternion.Identity, new Vector3(-xLength * xSpacing / 2, -10, -zLength * zSpacing / 2))); //terrain.Thickness = 5; //Uncomment this and shoot some things at the bottom of the terrain! They'll be sucked up through the ground. Space.Add(terrain); game.ModelDrawer.Add(terrain); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public SuspensionCarDemo2(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 2, 15); Space.Add(new Box(new Vector3(0, -5, 0), 20, 1, 20)); var body = new Box(new Vector3(0, 0, 0), 2, .5f, 3, 20); body.CollisionInformation.LocalPosition = new Vector3(0, 1f, 0); Space.Add(body); AddBackWheel(new Vector3(-1f, .55f, 1.3f), body, true); AddBackWheel(new Vector3(1f, .55f, 1.3f), body, false); Box suspensionLeg1, suspensionLeg2; AddDriveWheel(new Vector3(-1f, .55f, -1.3f), body, true, out drivingMotor1, out steeringMotor1, out suspensionLeg1); AddDriveWheel(new Vector3(1f, .55f, -1.3f), body, false, out drivingMotor2, out steeringMotor2, out suspensionLeg2); //Add a stabilizer so that the wheels can't point different directions. var steeringStabilizer = new RevoluteAngularJoint(suspensionLeg1, suspensionLeg2, Vector3.Right); Space.Add(steeringStabilizer); //x and y, in terms of heightmaps, refer to their local x and y coordinates. In world space, they correspond to x and z. //Setup the heights of the terrain. int xLength = 180; int zLength = 180; float xSpacing = 8f; float zSpacing = 8f; var heights = new float[xLength, zLength]; for (int i = 0; i < xLength; i++) { for (int j = 0; j < zLength; j++) { float x = i - xLength / 2; float z = j - zLength / 2; //heights[i,j] = (float)(x * y / 1000f); heights[i, j] = (float)(10 * (Math.Sin(x / 8) + Math.Sin(z / 8))); //heights[i,j] = 3 * (float)Math.Sin(x * y / 100f); //heights[i,j] = (x * x * x * y - y * y * y * x) / 1000f; } } //Create the terrain. var terrain = new Terrain(heights, new AffineTransform( new Vector3(xSpacing, 1, zSpacing), Quaternion.Identity, new Vector3(-xLength * xSpacing / 2, -10, -zLength * zSpacing / 2))); //terrain.Thickness = 5; //Uncomment this and shoot some things at the bottom of the terrain! They'll be sucked up through the ground. Space.Add(terrain); game.ModelDrawer.Add(terrain); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public GraphicMatchingDemo(DemosGame game) : base(game) { //When creating a collision shape based on a model, the graphic will generally be offset at first. //This is because the collision shape computes the center of mass and offsets itself to align with the local origin. //That offset must be applied to the graphic to make it match the collision shape. //Check out the documentation page for more information: //http://bepuphysics.codeplex.com/wikipage?title=Shape%20Recentering var model = game.Content.Load <Model>("guy"); BEPUutilities.Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(model, out vertices, out indices); //Create an entity based on the model. ConvexHull hull = new ConvexHull(vertices, 10); Space.Add(hull); //Create a graphic for the hull. The BEPUphysicsDrawer will also automatically receive a visualization of the convex hull which we can compare our graphic against. //The graphic will be offset from the collision shape because we have not attempted to offset it to match the collision shape's origin. var graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); game.ModelDrawer.Add(graphic); //Now let's create another entity from the same vertices. hull = new ConvexHull(vertices, 10); Space.Add(hull); //Note that the prefab entity type ConvexHull uses the ConvexHullShape constructor internally, which outputs the computed center of the shape //prior to offset. The ConvexHull constructor sets the entity's Position to that position so that the initial world space location of the vertices //matches what was passed into the constructor. //The same process could be performed using this code: //Vector3 computedCenter; //var shape = new ConvexHullShape(vertices, out computedCenter); //<-- It spits out the computed center here; this is what is used to offset the graphic! //var entity = new Entity(shape, 10); //entity.Position = computedCenter; //Space.Add(entity); //For more information about constructing entities, check out the EntityConstructionDemo. //But for now, let's just use the prefab entity type. As mentioned earlier, the constructor set the entity's Position using the computed center. //Since we didn't overwrite it with some other position yet, we can still use it. graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); graphic.LocalTransform = Matrix.CreateTranslation(-hull.Position); game.ModelDrawer.Add(graphic); //This graphic is perfectly aligned with the collision shape! Hooray! Box ground = new Box(new Vector3(0, -1.5m, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public SleepModeDemo(DemosGame game) : base(game) { SpawnRow(); game.Camera.Position = new Vector3(-30, 30, -30); game.Camera.Yaw((float)(-3 * Math.PI / 4)); game.Camera.Pitch(-(float)Math.PI / 12); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public SleepModeDemo(DemosGame game) : base(game) { SpawnRow(); game.Camera.Position = new Vector3(-30, 30, -30); game.Camera.Yaw((Fix64)(-3 * Math.PI / 4)); game.Camera.Pitch(-(Fix64)Math.PI / 12); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MobileMeshDemo(DemosGame game) : base(game) { Vector3[] vertices; int[] indices; //Create a big hollow sphere (squished into an ellipsoid). ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load <Model>("hollowsphere"), out vertices, out indices); var transform = new AffineTransform(new Vector3(.06f, .04f, .06f), Quaternion.Identity, new Vector3(0, 0, 0)); //Note that meshes can also be made solid (MobileMeshSolidity.Solid). This gives meshes a solid collidable volume, instead of just //being thin shells. However, enabling solidity is more expensive. var mesh = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Counterclockwise); mesh.Position = new Vector3(0, 0, 0); //Make the mesh spin a bit! mesh.AngularVelocity = new Vector3(0, 1, 0); Space.Add(mesh); //Add another mobile mesh inside. ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load <Model>("tube"), out vertices, out indices); transform = new AffineTransform(new Vector3(1, 1, 1), Quaternion.Identity, new Vector3(0, 0, 0)); mesh = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Counterclockwise, 10); mesh.Position = new Vector3(0, 10, 0); Space.Add(mesh); //Create a bunch of boxes. #if WINDOWS int numColumns = 5; int numRows = 5; int numHigh = 5; #else //Keep the simulation a bit smaller on the xbox. int numColumns = 4; int numRows = 4; int numHigh = 4; #endif float separation = 1.5f; for (int i = 0; i < numRows; i++) { for (int j = 0; j < numColumns; j++) { for (int k = 0; k < numHigh; k++) { Space.Add(new Box(new Vector3(separation * i, k * separation, separation * j), 1, 1, 1, 5)); } } } //Space.Add(new Box(new Vector3(0, -10, 0), 1, 1, 1)); game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, -10, 5); game.Camera.Yaw = 0; game.Camera.Pitch = 0; }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public TerrainDemo(DemosGame game) : base(game) { //x and y, in terms of heightmaps, refer to their local x and y coordinates. In world space, they correspond to x and z. //Setup the heights of the terrain. int xLength = 256; int zLength = 256; float xSpacing = 8f; float zSpacing = 8f; var heights = new float[xLength, zLength]; for (int i = 0; i < xLength; i++) { for (int j = 0; j < zLength; j++) { float x = i - xLength / 2; float z = j - zLength / 2; //heights[i,j] = (float)(x * y / 1000f); heights[i, j] = (float)(10 * (Math.Sin(x / 8) + Math.Sin(z / 8))); //heights[i,j] = 3 * (float)Math.Sin(x * y / 100f); //heights[i,j] = (x * x * x * y - y * y * y * x) / 1000f; } } //Create the terrain. var terrain = new Terrain(heights, new AffineTransform( new Vector3(xSpacing, 1, zSpacing), Quaternion.Identity, new Vector3(-xLength * xSpacing / 2, 0, -zLength * zSpacing / 2))); //terrain.Thickness = 5; //Uncomment this and shoot some things at the bottom of the terrain! They'll be sucked up through the ground. Space.Add(terrain); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 5; k++) { Space.Add(new Box( new Vector3(0 + i * 4, 100 - j * 10, 0 + k * 4), 2 + i * j * k, 2 + i * j * k, 2 + i * j * k, 4 + 20 * i * j * k)); } } } game.ModelDrawer.Add(terrain); game.Camera.Position = new Microsoft.Xna.Framework.Vector3(0, 30, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public LotsOfBoxesTestDemo(DemosGame game) : base(game) { var ground = new Box(new Vector3(0, -.5m, 0), 200, 1, 200); Space.Add(ground); var spawnVolume = new BoundingBox { Min = new Vector3(-25, 2, -25), Max = new Vector3(25, 102, 25) }; var span = spawnVolume.Max - spawnVolume.Min; NarrowPhaseHelper.Factories.BoxBox.EnsureCount(30000); var random = new Random(5); for (int i = 0; i < 5000; ++i) { Vector3 position; position.X = spawnVolume.Min.X + (Fix64)random.NextDouble() * span.X; position.Y = spawnVolume.Min.Y + (Fix64)random.NextDouble() * span.Y; position.Z = spawnVolume.Min.Z + (Fix64)random.NextDouble() * span.Z; var entity = new Box(position, 2, 2, 2, 10); Space.Add(entity); } for (int i = 0; i < 100; ++i) { Space.Update(); } Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; var start = Stopwatch.GetTimestamp(); for (int i = 0; i < 200; ++i) { Space.Update(); } var end = Stopwatch.GetTimestamp(); var time = (end - start) / (double)Stopwatch.Frequency; Console.WriteLine("Time: {0}", time); game.Camera.Position = new Vector3(-10, 10, 10); game.Camera.Yaw(MathHelper.Pi / -4); game.Camera.Pitch(MathHelper.Pi / 9); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public GraphicMatchingDemo(DemosGame game) : base(game) { //When creating a collision shape based on a model, the graphic will generally be offset at first. //This is because the collision shape computes the center of mass and offsets itself to align with the local origin. //That offset must be applied to the graphic to make it match the collision shape. //Check out the documentation page for more information: //http://bepuphysics.codeplex.com/wikipage?title=Shape%20Recentering var model = game.Content.Load<Model>("guy"); BEPUutilities.Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(model, out vertices, out indices); //Create an entity based on the model. ConvexHull hull = new ConvexHull(vertices, 10); Space.Add(hull); //Create a graphic for the hull. The BEPUphysicsDrawer will also automatically receive a visualization of the convex hull which we can compare our graphic against. //The graphic will be offset from the collision shape because we have not attempted to offset it to match the collision shape's origin. var graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); game.ModelDrawer.Add(graphic); //Now let's create another entity from the same vertices. hull = new ConvexHull(vertices, 10); Space.Add(hull); //Note that the prefab entity type ConvexHull uses the ConvexHullShape constructor internally, which outputs the computed center of the shape //prior to offset. The ConvexHull constructor sets the entity's Position to that position so that the initial world space location of the vertices //matches what was passed into the constructor. //The same process could be performed using this code: //Vector3 computedCenter; //var shape = new ConvexHullShape(vertices, out computedCenter); //<-- It spits out the computed center here; this is what is used to offset the graphic! //var entity = new Entity(shape, 10); //entity.Position = computedCenter; //Space.Add(entity); //For more information about constructing entities, check out the EntityConstructionDemo. //But for now, let's just use the prefab entity type. As mentioned earlier, the constructor set the entity's Position using the computed center. //Since we didn't overwrite it with some other position yet, we can still use it. graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); graphic.LocalTransform = Matrix.CreateTranslation(-hull.Position); game.ModelDrawer.Add(graphic); //This graphic is perfectly aligned with the collision shape! Hooray! Box ground = new Box(new Vector3(0, -1.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AddRemoveStressDemo(DemosGame game) : base(game) { Space.Remove(vehicle.Vehicle); var compoundShape = new CompoundShape(new List<CompoundShapeEntry> { new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, 1, 0), 1), new CompoundShapeEntry(new BoxShape(2, 1, 2), new Vector3(), 1), new CompoundShapeEntry(new BoxShape(1, 1, 1), new Vector3(0, -1, 0), 1) }); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(compoundShape, 10); addedEntities.Add(toAdd); } var boxShape = new BoxShape(1, 1, 1); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(boxShape, 10); addedEntities.Add(toAdd); } Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load<Model>("cube"), out vertices, out indices); var mobileMeshShape = new MobileMeshShape(vertices, indices, new AffineTransform(Matrix3x3.CreateScale(1, 2, 1), new Vector3()), MobileMeshSolidity.Counterclockwise); for (int i = 0; i < 300; ++i) { var toAdd = new Entity(mobileMeshShape, 10); addedEntities.Add(toAdd); } for (int i = 0; i < addedEntities.Count; ++i) { var entity = addedEntities[i]; entity.Gravity = new Vector3(); entity.Position = GetRandomPosition(random); entity.LinearVelocity = 3 * Vector3.Normalize(entity.Position); Space.Add(entity); } var playgroundModel = game.Content.Load<Model>("playground"); ModelDataExtractor.GetVerticesAndIndicesFromModel(playgroundModel, out vertices, out indices); var staticMesh = new StaticMesh(vertices, indices, new AffineTransform(Matrix3x3.CreateFromAxisAngle(Vector3.Up, MathHelper.Pi), new Vector3(0, -30, 0))); staticMesh.Sidedness = TriangleSidedness.Counterclockwise; Space.Add(staticMesh); game.ModelDrawer.Add(staticMesh); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public MobileMeshDemo(DemosGame game) : base(game) { Vector3[] vertices; int[] indices; //Create a big hollow sphere (squished into an ellipsoid). ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load<Model>("hollowsphere"), out vertices, out indices); var transform = new AffineTransform(new Vector3(.06f, .04f, .06f), Quaternion.Identity, new Vector3(0, 0, 0)); //Note that meshes can also be made solid (MobileMeshSolidity.Solid). This gives meshes a solid collidable volume, instead of just //being thin shells. However, enabling solidity is more expensive. var mesh = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Counterclockwise); mesh.Position = new Vector3(0, 0, 0); //Make the mesh spin a bit! mesh.AngularVelocity = new Vector3(0, 1, 0); Space.Add(mesh); //Add another mobile mesh inside. ModelDataExtractor.GetVerticesAndIndicesFromModel(game.Content.Load<Model>("tube"), out vertices, out indices); transform = new AffineTransform(new Vector3(1, 1, 1), Quaternion.Identity, new Vector3(0, 0, 0)); mesh = new MobileMesh(vertices, indices, transform, MobileMeshSolidity.Counterclockwise, 10); mesh.Position = new Vector3(0, 10, 0); Space.Add(mesh); //Create a bunch of boxes. #if WINDOWS int numColumns = 5; int numRows = 5; int numHigh = 5; #else //Keep the simulation a bit smaller on the xbox. int numColumns = 4; int numRows = 4; int numHigh = 4; #endif float separation = 1.5f; for (int i = 0; i < numRows; i++) for (int j = 0; j < numColumns; j++) for (int k = 0; k < numHigh; k++) { Space.Add(new Box(new Vector3(separation * i, k * separation, separation * j), 1, 1, 1, 5)); } //Space.Add(new Box(new Vector3(0, -10, 0), 1, 1, 1)); game.Camera.Position = new Vector3(0, -10, 5); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public InverseKinematicsTestDemo(DemosGame game) : base(game) { cameraControl = new FreeCameraControlScheme(10, game.Camera, game); whitePixel = game.Content.Load<Texture2D>("whitePixel"); game.Camera.Position = new Vector3(0, 3, 5); Box ground = new Box(new Vector3(0, 0, 0), 30, 1, 30); Space.Add(ground); Space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0); stateControlGroup = new StateControlGroup(game.Camera, controls); drawer = new InstancedModelDrawer(game); solver.ActiveSet.UseAutomass = true; solver.AutoscaleControlImpulses = true; solver.AutoscaleControlMaximumForce = float.MaxValue; solver.TimeStepDuration = .1f; solver.ControlIterationCount = 100; solver.FixerIterationCount = 10; solver.VelocitySubiterationCount = 3; BuildChain(new Vector3(-5, 2, 0)); BuildStick(new Vector3(-10, 2, 0)); BuildActionFigure(new Vector3(5, 6, -8)); BuildActionFigure(new Vector3(5, 6, -3)); BuildActionFigure(new Vector3(5, 6, 3)); BuildActionFigure(new Vector3(5, 6, 8)); BuildCyclicMesh(new Vector3(-5, 5, -5)); //BuildJointTest(new Vector3(0, 5, 0)); //BuildTinyTest(new Vector3(0, 15, 0)); BuildRoboArmThing(new Vector3(0, 5, 0)); BuildRing(new Vector3(0, 10, 8)); //Create the display objects. Model cylinder = game.Content.Load<Model>("cylinder"); for (int i = 0; i < bones.Count; i++) { var displayBone = new DisplayModel(cylinder, drawer); var completedBone = bones[i]; completedBone.DisplayBone = displayBone; bones[i] = completedBone; drawer.Add(displayBone); } }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public JengaDemo(DemosGame game) : base(game) { Space.Remove(kapow); //Have to shrink the ball a little to make it fit between jenga tower blocks. kapow = new Sphere(new Vector3(-11000, 0, 0), .2f, 20); kapow.PositionUpdateMode = PositionUpdateMode.Continuous; //The ball's really tiny! It will work better if it's handled continuously. Space.Add(kapow); int numBlocksTall = 18; //How many 'stories' tall. float blockWidth = 3f; //Total width/length of the tower. float blockHeight = 1 / 2f; Entity toAdd; //The default number of iterations is 10, which works fine, but this demo //is all about stability (it's jenga!). Increase the iterations a bit. //Even though it's using twice as many iterations, it will early-out //before reaching the limit MOST of the time. //It's still pretty playable at around 7-8 max iterations, though. Space.Solver.IterationLimit = 20; for (int i = 0; i < numBlocksTall; i++) { if (i % 2 == 0) { for (int j = 0; j < 3; j++) { toAdd = new Box(new Vector3( j * (blockWidth / 3) - blockWidth / 3f, blockHeight / 2 + i * (blockHeight), 0), blockWidth / 3, blockHeight, blockWidth, 10); Space.Add(toAdd); } } else { for (int j = 0; j < 3; j++) { toAdd = new Box(new Vector3( 0, blockHeight / 2 + (i) * (blockHeight), j * (blockWidth / 3) - blockWidth / 3f), blockWidth, blockHeight, blockWidth / 3, 10); Space.Add(toAdd); } } } Space.Add(new Box(new Vector3(0, -.5f, 0), 40, 1, 40)); game.Camera.Position = new Vector3(0, 5, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public InverseKinematicsTestDemo2(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 3, 5); Box ground = new Box(new Vector3(0, -3, 0), 30, 1, 30); Space.Add(ground); Space.ForceUpdater.Gravity = new Vector3(0, -9.81m, 0); var solver = new IKSolver(); solver.ActiveSet.UseAutomass = true; //solver.AutoscaleControlImpulses = true; //solver.AutoscaleControlMaximumForce = Fix64.MaxValue; solver.ControlIterationCount = 20; solver.FixerIterationCount = 0; solver.VelocitySubiterationCount = 3; List <Bone> bones; List <Entity> boneEntities; int boneCount = 10; BuildStick(new Vector3(0, 0.5m, 0), boneCount, out bones, out boneEntities); DragControl dragger = new DragControl { TargetBone = bones[boneCount - 1], MaximumForce = Fix64.MaxValue }; dragger.LinearMotor.Rigidity = 16; dragger.LinearMotor.LocalOffset = new Vector3(0, 0.5m, 0); dragger.LinearMotor.TargetPosition = new Vector3(10, 0, 0); bones[0].Pinned = true; var controls = new List <Control>(); controls.Add(dragger); solver.Solve(controls); var tipLocation = bones[boneCount - 1].Position + Matrix3x3.CreateFromQuaternion(bones[boneCount - 1].Orientation).Up * 0.5m; for (int i = 0; i < bones.Count; ++i) { boneEntities[i].Position = bones[i].Position; boneEntities[i].Orientation = bones[i].Orientation; Space.Add(boneEntities[i]); } }