public WheelInfo AddWheel(Vector3 connectionPointCS, Vector3 wheelDirectionCS0, Vector3 wheelAxleCS, float suspensionRestLength, float wheelRadius, RaycastVehicle.VehicleTuning tuning, bool isFrontWheel) { WheelInfoConstructionInfo ci = new WheelInfoConstructionInfo(); ci.ChassisConnectionCS = connectionPointCS; ci.WheelDirectionCS = wheelDirectionCS0; ci.WheelAxleCS = wheelAxleCS; ci.SuspensionRestLength = suspensionRestLength; ci.WheelRadius = wheelRadius; ci.SuspensionStiffness = tuning.SuspensionStiffness; ci.WheelsDampingCompression = tuning.SuspensionCompression; ci.WheelsDampingRelaxation = tuning.SuspensionDamping; ci.FrictionSlip = tuning.FrictionSlip; ci.IsFrontWheel = isFrontWheel; ci.MaxSuspensionTravelCm = tuning.MaxSuspensionTravelCm; ci.MaxSuspensionForce = tuning.MaxSuspensionForce; wheelInfo.Add(new WheelInfo(ci)); ci.Dispose(); WheelInfo wheel = wheelInfo[NumWheels - 1]; UpdateWheelTransformsWS(wheel, false); UpdateWheelTransform(NumWheels - 1, false); return wheel; }
public CustomVehicle(RaycastVehicle.VehicleTuning tuning, RigidBody chassis, VehicleRaycaster raycaster) { chassisBody = chassis; vehicleRaycaster = raycaster; }
/// <summary> /// After we create our RigidBody, we turn it into a vehicle /// </summary> protected override void PostCreateBody(ThingDefinition def) { kartMotionState = MotionState as KartMotionState; Body.CcdMotionThreshold = 0.001f; Body.CcdSweptSphereRadius = 0.04f; Raycaster = new DefaultVehicleRaycaster(LKernel.GetG<PhysicsMain>().World); Tuning = new RaycastVehicle.VehicleTuning(); _vehicle = new RaycastVehicle(Tuning, Body, Raycaster); _vehicle.SetCoordinateSystem(0, 1, 2); // I have no idea what this does... I'm assuming something to do with a rotation matrix? LKernel.GetG<PhysicsMain>().World.AddAction(_vehicle); var wheelFac = LKernel.GetG<WheelFactory>(); string frontWheelName = def.GetStringProperty("FrontWheel", null); string backWheelName = def.GetStringProperty("BackWheel", null); WheelFL = wheelFac.CreateWheel(frontWheelName, WheelID.FrontLeft, this, def.GetVectorProperty("FrontLeftWheelPosition", null), def.GetStringProperty("FrontLeftWheelMesh", null)); WheelFR = wheelFac.CreateWheel(frontWheelName, WheelID.FrontRight, this, def.GetVectorProperty("FrontRightWheelPosition", null), def.GetStringProperty("FrontRightWheelMesh", null)); WheelBL = wheelFac.CreateWheel(backWheelName, WheelID.BackLeft, this, def.GetVectorProperty("BackLeftWheelPosition", null), def.GetStringProperty("BackLeftWheelMesh", null)); WheelBR = wheelFac.CreateWheel(backWheelName, WheelID.BackRight, this, def.GetVectorProperty("BackRightWheelPosition", null), def.GetStringProperty("BackRightWheelMesh", null)); LeftParticleNode.Position -= new Vector3(0, WheelBL.DefaultRadius * 0.7f, 0); RightParticleNode.Position -= new Vector3(0, WheelBR.DefaultRadius * 0.7f, 0); Body.LinearVelocity = new Vector3(0, 1, 0); PhysicsMain.FinaliseBeforeSimulation += FinaliseBeforeSimulation; RaceCountdown.OnCountdown += OnCountdown; }
float wheelFriction = 1000; //BT_LARGE_FLOAT; #endregion Fields #region Constructors public Physics(VehicleDemo game) { CollisionShape groundShape = new BoxShape(50, 3, 50); CollisionShapes.Add(groundShape); CollisionConf = new DefaultCollisionConfiguration(); Dispatcher = new CollisionDispatcher(CollisionConf); Solver = new SequentialImpulseConstraintSolver(); Vector3 worldMin = new Vector3(-10000, -10000, -10000); Vector3 worldMax = new Vector3(10000, 10000, 10000); Broadphase = new AxisSweep3(worldMin, worldMax); //Broadphase = new DbvtBroadphase(); World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, Solver, CollisionConf); int i; Matrix tr; Matrix vehicleTr; if (UseTrimeshGround) { const float scale = 20.0f; //create a triangle-mesh ground int vertStride = Vector3.SizeInBytes; int indexStride = 3 * sizeof(int); const int NUM_VERTS_X = 20; const int NUM_VERTS_Y = 20; const int totalVerts = NUM_VERTS_X * NUM_VERTS_Y; const int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1); TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray(); IndexedMesh mesh = new IndexedMesh(); mesh.Allocate(totalVerts, vertStride, totalTriangles, indexStride); BulletSharp.DataStream data = mesh.LockVerts(); for (i = 0; i < NUM_VERTS_X; i++) { for (int j = 0; j < NUM_VERTS_Y; j++) { float wl = .2f; float height = 20.0f * (float)(Math.Sin(i * wl) * Math.Cos(j * wl)); data.Write((i - NUM_VERTS_X * 0.5f) * scale); data.Write(height); data.Write((j - NUM_VERTS_Y * 0.5f) * scale); } } int index = 0; IntArray idata = mesh.TriangleIndices; for (i = 0; i < NUM_VERTS_X - 1; i++) { for (int j = 0; j < NUM_VERTS_Y - 1; j++) { idata[index++] = j * NUM_VERTS_X + i; idata[index++] = j * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = j * NUM_VERTS_X + i; idata[index++] = (j + 1) * NUM_VERTS_X + i + 1; idata[index++] = (j + 1) * NUM_VERTS_X + i; } } vertexArray.AddIndexedMesh(mesh); groundShape = new BvhTriangleMeshShape(vertexArray, true); tr = Matrix.Identity; vehicleTr = Matrix.Translation(0, -2, 0); } else { // Use HeightfieldTerrainShape int width = 40, length = 40; //int width = 128, length = 128; // Debugging is too slow for this float maxHeight = 10.0f; float heightScale = maxHeight / 256.0f; Vector3 scale = new Vector3(20.0f, maxHeight, 20.0f); //PhyScalarType scalarType = PhyScalarType.PhyUChar; //FileStream file = new FileStream(heightfieldFile, FileMode.Open, FileAccess.Read); // Use float data PhyScalarType scalarType = PhyScalarType.PhyFloat; byte[] terr = new byte[width * length * 4]; MemoryStream file = new MemoryStream(terr); BinaryWriter writer = new BinaryWriter(file); for (i = 0; i < width; i++) for (int j = 0; j < length; j++) writer.Write((float)((maxHeight / 2) + 4 * Math.Sin(j * 0.5f) * Math.Cos(i))); writer.Flush(); file.Position = 0; HeightfieldTerrainShape heightterrainShape = new HeightfieldTerrainShape(width, length, file, heightScale, 0, maxHeight, upIndex, scalarType, false); heightterrainShape.SetUseDiamondSubdivision(true); groundShape = heightterrainShape; groundShape.LocalScaling = new Vector3(scale.X, 1, scale.Z); tr = Matrix.Translation(new Vector3(-scale.X / 2, scale.Y / 2, -scale.Z / 2)); vehicleTr = Matrix.Translation(new Vector3(20, 3, -3)); // Create graphics object file.Position = 0; BinaryReader reader = new BinaryReader(file); int totalTriangles = (width - 1) * (length - 1) * 2; int totalVerts = width * length; game.groundMesh = new Mesh(game.Device, totalTriangles, totalVerts, MeshFlags.SystemMemory | MeshFlags.Use32Bit, VertexFormat.Position | VertexFormat.Normal); SlimDX.DataStream data = game.groundMesh.LockVertexBuffer(LockFlags.None); for (i = 0; i < width; i++) { for (int j = 0; j < length; j++) { float height; if (scalarType == PhyScalarType.PhyFloat) { // heightScale isn't applied internally for float data height = reader.ReadSingle(); } else if (scalarType == PhyScalarType.PhyUChar) { height = file.ReadByte() * heightScale; } else { height = 0.0f; } data.Write((j - length * 0.5f) * scale.X); data.Write(height); data.Write((i - width * 0.5f) * scale.Z); // Normals will be calculated later data.Position += 12; } } game.groundMesh.UnlockVertexBuffer(); file.Close(); data = game.groundMesh.LockIndexBuffer(LockFlags.None); for (i = 0; i < width - 1; i++) { for (int j = 0; j < length - 1; j++) { // Using diamond subdivision if ((j + i) % 2 == 0) { data.Write(j * width + i); data.Write((j + 1) * width + i + 1); data.Write(j * width + i + 1); data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } else { data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write(j * width + i + 1); data.Write(j * width + i + 1); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); } /* // Not using diamond subdivision data.Write(j * width + i); data.Write((j + 1) * width + i); data.Write(j * width + i + 1); data.Write(j * width + i + 1); data.Write((j + 1) * width + i); data.Write((j + 1) * width + i + 1); */ } } game.groundMesh.UnlockIndexBuffer(); game.groundMesh.ComputeNormals(); } CollisionShapes.Add(groundShape); //create ground object RigidBody ground = LocalCreateRigidBody(0, tr, groundShape); ground.UserObject = "Ground"; CollisionShape chassisShape = new BoxShape(1.0f, 0.5f, 2.0f); CollisionShapes.Add(chassisShape); CompoundShape compound = new CompoundShape(); CollisionShapes.Add(compound); //localTrans effectively shifts the center of mass with respect to the chassis Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); RigidBody carChassis = LocalCreateRigidBody(800, Matrix.Identity, compound); carChassis.UserObject = "Chassis"; //carChassis.SetDamping(0.2f, 0.2f); //CylinderShapeX wheelShape = new CylinderShapeX(wheelWidth, wheelRadius, wheelRadius); // clientResetScene(); // create vehicle RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); IVehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; World.AddAction(vehicle); float connectionHeight = 1.2f; bool isFrontWheel = true; // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } vehicle.RigidBody.WorldTransform = vehicleTr; }
float wheelFriction = 1000; //BT_LARGE_FLOAT; #endregion Fields #region Methods public override void Evaluate(int SpreadMax) { for (int i = 0; i < SpreadMax; i++) { if (this.CanCreate(i)) { RaycastVehicle vehicle; AbstractRigidShapeDefinition shapedef = this.FShapes[i]; ShapeCustomData sc = new ShapeCustomData(); sc.ShapeDef = shapedef; CompoundShape compound = new CompoundShape(); //List<AbstractRigidShapeDefinition> children = new List<AbstractRigidShapeDefinition>(); CollisionShape chassisShape = shapedef.GetShape(sc); Matrix localTrans = Matrix.Translation(Vector3.UnitY); compound.AddChildShape(localTrans, chassisShape); float mass = shapedef.Mass; bool isDynamic = (mass != 0.0f); Vector3 localInertia = Vector3.Zero; if (isDynamic) chassisShape.CalculateLocalInertia(mass, out localInertia); Vector3D pos = this.FPosition[i]; Vector4D rot = this.FRotation[i]; DefaultMotionState ms = BulletUtils.CreateMotionState(pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, rot.w); RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, ms, compound, localInertia); RigidBody carChassis = new RigidBody(rbInfo); BodyCustomData bd = new BodyCustomData(); carChassis.UserObject = bd; bd.Id = this.FWorld[0].GetNewBodyId(); bd.Custom = this.FCustom[i]; this.FWorld[0].Register(carChassis); RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); VehicleRaycaster vehicleRayCaster = new DefaultVehicleRaycaster(this.FWorld[0].World); vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster); carChassis.ActivationState = ActivationState.DisableDeactivation; this.FWorld[0].World.AddAction(vehicle); float connectionHeight = 1.2f; bool isFrontWheel = true; // choose coordinate system vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); isFrontWheel = false; connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius); vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel); for (i = 0; i < vehicle.NumWheels; i++) { WheelInfo wheel = vehicle.GetWheelInfo(i); wheel.SuspensionStiffness = suspensionStiffness; wheel.WheelsDampingRelaxation = suspensionDamping; wheel.WheelsDampingCompression = suspensionCompression; wheel.FrictionSlip = wheelFriction; wheel.RollInfluence = rollInfluence; } FOutVehicle.SliceCount = 1; FOutVehicle[0] = vehicle; } } }
/// <summary> /// This should only be used by the WheelFactory /// </summary> /// <param name="owner">Which kart is the wheel attached to?</param> /// <param name="connectionPoint">Where is the wheel attached?</param> /// <param name="wheelID">ID number of the wheel</param> /// <param name="dict">The properties and values from the .wheel file this wheel was built from</param> /// <param name="meshName">The filename of the mesh we should use for this wheel</param> public Wheel(Kart owner, Vector3 connectionPoint, WheelID wheelID, IDictionary<string, float> dict, string meshName) { // set up these kart = owner; ID = wheelID; vehicle = kart.Vehicle; // set up our readonlies DefaultRadius = dict["Radius"]; DefaultWidth = dict["Width"]; DefaultSuspensionRestLength = dict["SuspensionRestLength"]; DefaultSpringStiffness = dict["SpringStiffness"]; DefaultSpringCompression = dict["SpringCompression"]; DefaultSpringDamping = dict["SpringDamping"]; Friction = dict["FrictionSlip"]; DefaultRollInfluence = dict["RollInfluence"]; DefaultBrakeForce = dict["BrakeForce"]; DefaultMotorForce = dict["MotorForce"]; DefaultMaxTurnAngle = new Degree(dict["TurnAngle"]).ValueRadians; DefaultSlowSpeed = dict["SlowSpeed"]; DefaultHighSpeed = dict["HighSpeed"]; DefaultSlowTurnAngleMultiplier = dict["SlowTurnAngleMultiplier"]; DefaultSlowTurnSpeedMultiplier = dict["SlowTurnSpeedMultiplier"]; DefaultDriftingTurnAngle = new Degree(dict["DriftingTurnAngle"]).ValueRadians; DefaultDriftingTurnSpeed = new Degree(dict["DriftingTurnSpeed"]).ValueRadians; DefaultSteerIncrementTurn = new Degree(dict["SteerIncrementTurn"]).ValueRadians; DefaultSteerDecrementTurn = new Degree(dict["SteerDecrementTurn"]).ValueRadians; // give our fields some default values AccelerateMultiplier = 0; TurnMultiplier = 0; IsBrakeOn = false; DriftState = WheelDriftState.None; IntWheelID = (int) wheelID; DefaultFrictionSlip = Friction; IdealSteerAngle = 0f; // need to tell bullet whether it's a front wheel or not bool isFrontWheel; if (ID == WheelID.FrontLeft || ID == WheelID.FrontRight) isFrontWheel = true; else isFrontWheel = false; vehicle.AddWheel(connectionPoint, WheelDirection, WheelAxle, DefaultSuspensionRestLength, DefaultRadius, kart.Tuning, isFrontWheel); WheelInfo info = vehicle.GetWheelInfo(IntWheelID); info.SuspensionStiffness = DefaultSpringStiffness; info.WheelDampingRelaxation = DefaultSpringDamping; info.WheelDampingCompression = DefaultSpringCompression; info.FrictionSlip = Friction; info.RollInfluence = DefaultRollInfluence; AxlePoint = connectionPoint + new Vector3(0, -DefaultSuspensionRestLength, 0); // create our node and entity Node = owner.RootNode.CreateChildSceneNode("wheelNode" + kart.ID + ID, AxlePoint); Entity = LKernel.GetG<SceneManager>().CreateEntity("wheelNode" + kart.ID + ID, meshName); Node.AttachObject(Entity); Node.InheritOrientation = false; Node.Orientation = kart.ActualOrientation; // and then hook up to the event PhysicsMain.PostSimulate += PostSimulate; }
public override void Load(Vector3 Location) { VehicleMesh.MeshColor = PrimaryColors[Global.RNG.Next(PrimaryColors.Length)]; CollisionShape chassisShape = new BoxShape(Dimensions.Y / 2, Dimensions.Z / 2, Dimensions.X / 2); collisionShape = new CompoundShape(); //localTrans effectively shifts the center of mass with respect to the chassis Matrix4 localTrans = Matrix4.CreateTranslation(0 * Vector3.UnitY); ((CompoundShape)collisionShape).AddChildShape(localTrans, chassisShape); collisionShape = VehicleMesh.GetCollisionMesh(true); vehicleBody = World.CreateRigidBody(Mass, Matrix4.CreateTranslation(Location), collisionShape); // create vehicle RaycastVehicle.VehicleTuning tuning = new RaycastVehicle.VehicleTuning(); raycastVehicle = new RaycastVehicle(tuning, vehicleBody, new DefaultVehicleRaycaster(World.DynamicsWorld)); vehicleBody.ActivationState = ActivationState.DisableDeactivation; // choose coordinate system raycastVehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex); Vector3 connectionPointCS0 = FrontWheel.Location +(Vector3.UnitY*SuspensionRestLength); // Front left raycastVehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, SuspensionRestLength, WheelRadius, tuning, true); connectionPointCS0 = FrontWheel.Location * new Vector3(-1, 1, 1) + (Vector3.UnitY * SuspensionRestLength); // Front right raycastVehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, -wheelAxleCS, SuspensionRestLength, WheelRadius, tuning, true); connectionPointCS0 = RearWheel.Location * new Vector3(-1, 1, 1) + (Vector3.UnitY * SuspensionRestLength); // Rear right raycastVehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, -wheelAxleCS, SuspensionRestLength, WheelRadius, tuning, false); connectionPointCS0 = RearWheel.Location + (Vector3.UnitY * SuspensionRestLength); // Rear left raycastVehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, SuspensionRestLength, WheelRadius, tuning, false); for (int i = 0; i < raycastVehicle.NumWheels; i++) { WheelInfo wheel = raycastVehicle.GetWheelInfo(i); wheel.SuspensionStiffness = SuspensionStiffness; wheel.WheelsDampingRelaxation = SuspensionDamping; wheel.WheelsDampingCompression = SuspensionCompression; wheel.FrictionSlip = WheelFriction; wheel.RollInfluence = RollInfluence; } World.DynamicsWorld.AddAction(raycastVehicle); }