protected override void ComponentsCreatedHandler(object sender, EventArgs e) { base.ComponentsCreatedHandler(sender, e); TerrainRenderComponent terrainRenderComponent = Owner.GetComponent <TerrainRenderComponent>(ComponentType.Render); if (terrainRenderComponent == null) { throw new LevelManifestException("TerrainCollisionComponent expect to be accompanied by a TerrainRenderComponent."); } float[,] heightVals = terrainRenderComponent.Heights; XnaVector3 originShift = new XnaVector3(terrainRenderComponent.TerrainAsset.XZScale * (terrainRenderComponent.TerrainAsset.VertexCountAlongXAxis - 1) * 0.5f, 0.0f, terrainRenderComponent.TerrainAsset.XZScale * (terrainRenderComponent.TerrainAsset.VertexCountAlongZAxis - 1) * 0.5f); AffineTransform terrainTransform = new BEPUutilities.AffineTransform( new BEPUutilities.Vector3(terrainRenderComponent.TerrainAsset.XZScale, 1.0f, terrainRenderComponent.TerrainAsset.XZScale), BepuConverter.Convert(mTransformComponent.Orientation), BepuConverter.Convert(mTransformComponent.Translation - originShift)); mSimTerrain = new BepuTerrain(heightVals, terrainTransform); mSimTerrain.Material.Bounciness = 0.60f; mSimTerrain.Material.StaticFriction = 1.0f; mSimTerrain.Material.KineticFriction = 1.0f; mSimTerrain.Tag = Owner.Id; }
///<summary> /// Cleans up the pair handler. ///</summary> public override void CleanUp() { base.CleanUp(); terrain = null; convex = null; }
protected override void ComponentsCreatedHandler(object sender, EventArgs e) { base.ComponentsCreatedHandler(sender, e); TerrainRenderComponent terrainRenderComponent = Owner.GetComponent<TerrainRenderComponent>(ComponentType.Render); if (terrainRenderComponent == null) throw new LevelManifestException("TerrainCollisionComponent expect to be accompanied by a TerrainRenderComponent."); float[,] heightVals = terrainRenderComponent.Heights; XnaVector3 originShift = new XnaVector3(terrainRenderComponent.TerrainAsset.XZScale * (terrainRenderComponent.TerrainAsset.VertexCountAlongXAxis - 1) * 0.5f, 0.0f, terrainRenderComponent.TerrainAsset.XZScale * (terrainRenderComponent.TerrainAsset.VertexCountAlongZAxis - 1) * 0.5f); AffineTransform terrainTransform = new BEPUutilities.AffineTransform( new BEPUutilities.Vector3(terrainRenderComponent.TerrainAsset.XZScale, 1.0f, terrainRenderComponent.TerrainAsset.XZScale), BepuConverter.Convert(mTransformComponent.Orientation), BepuConverter.Convert(mTransformComponent.Translation - originShift)); mSimTerrain = new BepuTerrain(heightVals, terrainTransform); mSimTerrain.Material.Bounciness = 0.60f; mSimTerrain.Material.StaticFriction = 1.0f; mSimTerrain.Material.KineticFriction = 1.0f; mSimTerrain.Tag = Owner.Id; }
///<summary> /// Initializes the pair handler. ///</summary> ///<param name="entryA">First entry in the pair.</param> ///<param name="entryB">Second entry in the pair.</param> public override void Initialize(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { terrain = entryA as Terrain; convex = entryB as ConvexCollidable; if (terrain == null || convex == null) { terrain = entryB as Terrain; convex = entryA as ConvexCollidable; if (terrain == null || convex == null) throw new ArgumentException("Inappropriate types used to initialize pair."); } //Contact normal goes from A to B. broadPhaseOverlap.entryA = convex; broadPhaseOverlap.entryB = terrain; UpdateMaterialProperties(convex.entity != null ? convex.entity.material : null, terrain.material); base.Initialize(entryA, entryB); }
/// <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 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> /// Initializes the manifold. ///</summary> ///<param name="newCollidableA">First collidable.</param> ///<param name="newCollidableB">Second collidable.</param> public override void Initialize(Collidable newCollidableA, Collidable newCollidableB) { convex = newCollidableA as ConvexCollidable; terrain = newCollidableB as Terrain; if (convex == null || terrain == null) { convex = newCollidableB as ConvexCollidable; terrain = newCollidableA as Terrain; if (convex == null || terrain == null) throw new ArgumentException("Inappropriate types used to initialize contact manifold."); } }
///<summary> /// Initializes the pair handler. ///</summary> ///<param name="entryA">First entry in the pair.</param> ///<param name="entryB">Second entry in the pair.</param> public override void Initialize(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { mesh = entryA as Terrain; if (mesh == null) { mesh = entryB as Terrain; if (mesh == null) { throw new Exception("Inappropriate types used to initialize pair."); } } base.Initialize(entryA, entryB); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public AccumulationTestDemo(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 = .5f; float zSpacing = .5f; 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)(10 * (Math.Sin(x / 8) + Math.Sin(z / 8))); } } //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))); Space.Add(terrain); game.ModelDrawer.Add(terrain); eventHandler = (sender, other, pair) => { var entityCollidable = other as EntityCollidable; if (entityCollidable == null || !entityCollidable.Entity.IsDynamic) { sender.Events.RemoveAllEvents(); sender.Entity.LinearVelocity = new Vector3(); sender.Entity.AngularVelocity = new Vector3(); sender.Entity.BecomeKinematic(); sender.CollisionRules.Group = CollisionRules.DefaultDynamicCollisionGroup; } }; game.Camera.Position = new Vector3(0, 30, 20); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public SpiderDemo(DemosGame game) : base(game) { game.Camera.Position = new Vector3(0, 2, 15); Space.Add(new Box(new Vector3(0, -5, 0), 20, 1, 20)); BuildBot(new Vector3(0, 3, 0), out legJoints); //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 TornadoDemo(DemosGame game) : base(game) { shape = new BoundingBoxForceFieldShape(new BoundingBox(new Vector3(-100, -20, -40), new Vector3(-20, 120, 40))); tornado = new Tornado(shape, (shape.BoundingBox.Min + shape.BoundingBox.Max) / 2, new Vector3(0, 1, 0), 150, false, 50, 10, 200, 200, 80, 2000, 40, 10); tornado.ForceWakeUp = true; //The tornado will be moving, so it should wake up things that it comes into contact with. Space.Add(tornado); //Create the unfortunate box-like citizens about to be hit by the tornado. int numColumns = 10; int numRows = 10; int numHigh = 1; float separation = 1.5f; 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 - numRows * separation / 2, 5 + k * separation, separation * j - numColumns * separation / 2), 1, 1, 1, 10); Space.Add(toAdd); } //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)Math.Pow(1.2 * Math.Sqrt(x * x + y * y), 2); //heights[i,j] = -1f / (x * x + y * y); //heights[i,j] = (float)(x * y / 100f); heights[i,j] = (float)(5 * (Math.Sin(x / 8f) + Math.Sin(z / 8f))); //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))); Space.Add(terrain); game.ModelDrawer.Add(terrain); game.Camera.Position = new Vector3(0, 5, 60); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ReverseTrikeDemo(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, 1, 3, 10); body.CollisionInformation.LocalPosition = new Vector3(0, .8f, 0); Space.Add(body); #region First Wheel var wheel = new Cylinder(body.Position + new Vector3(-1.3f, 0, -1.5f), .2f, .5f, 4); wheel.Material = new Material(1.5f, 1.5f, 0); wheel.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(body, wheel, CollisionRule.NoBroadPhase); //Connect the wheel to the body. var ballSocketJoint = new BallSocketJoint(body, wheel, wheel.Position); var swivelHingeAngularJoint = new SwivelHingeAngularJoint(body, wheel, Vector3.Up, Vector3.Right); //Motorize the wheel. drivingMotor1 = new RevoluteMotor(body, wheel, Vector3.Left); drivingMotor1.Settings.VelocityMotor.Softness = .2f; //Let it roll when the user isn't giving specific commands. drivingMotor1.IsActive = false; steeringMotor1 = new RevoluteMotor(body, wheel, Vector3.Up); steeringMotor1.Settings.Mode = MotorMode.Servomechanism; //The constructor makes a guess about how to set up the constraint. //It can't always be right since it doesn't have all the information; //in this case, it chooses the basis and test axis incorrectly. //This leads to a 'flipping' behavior when the wheel is rolling //(the test axis is 'rolling' with the wheel, and passes over //a singularity which causes a flip). //To fix this, we configure the constraint directly. //The basis is aligned with how the wheel is set up; we choose 'up' as //the motorized axis, and right/forward to define the angle measurement plane. //The test axis is set to be perpendicular to the wheel's rotation so that //it only measures the steering angle. //If you're curious, the angle measurement is just a Math.Atan2. //The current world test axis is dotted against the two plane axes (Right and Forward here). //This gives an x and y value. These can be plugged into Atan2 just like when //you compute an angle on a normal 2d graph. steeringMotor1.Basis.SetWorldAxes(Vector3.Up, Vector3.Right); steeringMotor1.TestAxis = Vector3.Right; //Add the wheel and connection to the space. Space.Add(wheel); Space.Add(ballSocketJoint); Space.Add(swivelHingeAngularJoint); Space.Add(drivingMotor1); Space.Add(steeringMotor1); #endregion #region Second Wheel wheel = new Cylinder(body.Position + new Vector3(1.3f, 0, -1.5f), .2f, .5f, 4); wheel.Material = new Material(1.5f, 1.5f, 0); wheel.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(body, wheel, CollisionRule.NoBroadPhase); //Connect the wheel to the body. ballSocketJoint = new BallSocketJoint(body, wheel, wheel.Position); swivelHingeAngularJoint = new SwivelHingeAngularJoint(body, wheel, Vector3.Up, Vector3.Right); //Motorize the wheel. drivingMotor2 = new RevoluteMotor(body, wheel, Vector3.Left); drivingMotor2.Settings.VelocityMotor.Softness = .2f; //Let it roll when the user isn't giving specific commands. drivingMotor2.IsActive = false; steeringMotor2 = new RevoluteMotor(body, wheel, Vector3.Up); steeringMotor2.Settings.Mode = MotorMode.Servomechanism; //Configure the motor. See wheel 1 for more description. steeringMotor2.Basis.SetWorldAxes(Vector3.Up, Vector3.Right); steeringMotor2.TestAxis = Vector3.Right; //Add the wheel and connection to the space. Space.Add(wheel); Space.Add(ballSocketJoint); Space.Add(swivelHingeAngularJoint); Space.Add(drivingMotor2); Space.Add(steeringMotor2); #endregion #region Third Wheel wheel = new Cylinder(body.Position + new Vector3(0, -.3f, 1.5f), .2f, .5f, 4); wheel.Material = new Material(1.5f, 1.5f, 0); wheel.Orientation = Quaternion.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2); //Preventing the occasional pointless collision pair can speed things up. CollisionRules.AddRule(body, wheel, CollisionRule.NoBroadPhase); //Connect the wheel to the body. ballSocketJoint = new BallSocketJoint(body, wheel, wheel.Position); //Notice that the third wheel isn't a swivel hinge, it's just a revolute axis. //This lets it roll, but prevents flopping around like the wheels of a grocery cart. //Could have used a RevoluteJoint solver group here, but this shows it's possible to do //the same things without using the combo-constraints. var revoluteAngularJoint = new RevoluteAngularJoint(body, wheel, Vector3.Right); //Add the wheel and connection to the space. Space.Add(wheel); Space.Add(ballSocketJoint); Space.Add(revoluteAngularJoint); #endregion 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))); Space.Add(terrain); game.ModelDrawer.Add(terrain); }
public TerrainCollisionComponent(Actor owner) : base(owner) { mSimTerrain = null; }
/// <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; 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)(20 * (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> /// Cleans up the pair handler. ///</summary> public override void CleanUp() { base.CleanUp(); mesh = null; }