Пример #1
0
        private void UpdateWheelInfo(WheelInfo info)
        {
            info.LeftTyreTemp.ActualQuantity        = Temperature.FromCelsius(_tyreTemp - 5);
            info.CenterTyreTemp.ActualQuantity      = Temperature.FromCelsius(_tyreTemp);
            info.RightTyreTemp.ActualQuantity       = Temperature.FromCelsius(_tyreTemp + 5);
            info.TyreCoreTemperature.ActualQuantity = Temperature.FromCelsius(_tyreTemp);
            info.TyreType = "Slick";
            info.BrakeTemperature.ActualQuantity = Temperature.FromCelsius(_brakeTemp);

            info.TyrePressure.ActualQuantity = Pressure.FromKiloPascals(200);
        }
Пример #2
0
        public void UpdateSuspension(float step)
        {
            float chassisMass = 1.0f / chassisBody.InvMass;

            for (int w_it = 0; w_it < NumWheels; w_it++)
            {
                WheelInfo wheel_info = wheelInfo[w_it];

                if (wheel_info.RaycastInfo.IsInContact)
                {
                    float force;
                    //	Spring
                    {
                        float susp_length    = wheel_info.SuspensionRestLength;
                        float current_length = wheel_info.RaycastInfo.SuspensionLength;

                        float length_diff = (susp_length - current_length);

                        force = wheel_info.SuspensionStiffness
                                * length_diff * wheel_info.ClippedInvContactDotSuspension;
                    }

                    // Damper
                    {
                        float projected_rel_vel = wheel_info.SuspensionRelativeVelocity;
                        {
                            float susp_damping;
                            if (projected_rel_vel < 0.0f)
                            {
                                susp_damping = wheel_info.WheelsDampingCompression;
                            }
                            else
                            {
                                susp_damping = wheel_info.WheelsDampingRelaxation;
                            }
                            force -= susp_damping * projected_rel_vel;
                        }
                    }

                    // RESULT
                    wheel_info.WheelsSuspensionForce = force * chassisMass;
                    if (wheel_info.WheelsSuspensionForce < 0)
                    {
                        wheel_info.WheelsSuspensionForce = 0;
                    }
                }
                else
                {
                    wheel_info.WheelsSuspensionForce = 0;
                }
            }
        }
Пример #3
0
        void ResetSuspension()
        {
            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = GetWheelInfo(i);
                wheel.RaycastInfo.SuspensionLength = wheel.SuspensionRestLength;
                wheel.SuspensionRelativeVelocity   = 0;

                wheel.RaycastInfo.ContactNormalWS = -wheel.RaycastInfo.WheelDirectionWS;
                //wheel.ContactFriction = 0;
                wheel.ClippedInvContactDotSuspension = 1;
            }
        }
    private void FixedUpdate()
    {
        if (carWheels == null)
        {
            return;
        }

        /*On every physics update, update all the wheels*/
        for (int i = 0; i < carWheels.Length; i++)
        {
            WheelInfo currentWheel = carWheels[i];
            float     currentSpeed = carRB.velocity.magnitude;

            //If wheels have motor or steering apply forces
            if (currentWheel.motor)
            {
                //Only accelerate if we are under the max speed
                if (currentSpeed < maxSpeed)
                {
                    currentWheel.collider.motorTorque = accelerateInput * motorPower;
                }
                else
                {
                    currentWheel.collider.motorTorque = 0f;
                }
            }
            if (currentWheel.steer)
            {
                currentWheel.collider.steerAngle = steerInput * maxSteerAngle;
            }

            //Apply rotation to the wheels and update the wheels mesh renderer
            const float secondsInMin    = 60f;
            const float degreesInCircle = 360f;
            currentWheel.rotation = currentWheel.collider.rpm / secondsInMin * degreesInCircle * currentSpeed;

            if (currentWheel.meshRenderer != null)
            {
                currentWheel.meshRenderer.transform.localRotation =
                    Quaternion.Euler(0f, currentWheel.collider.steerAngle, currentWheel.rotation);
            }
        }

        //Apply force to rigidbody
        const float forceModifier = -0.1f;
        Transform   carTransform  = transform;

        carRB.AddForceAtPosition(carTransform.up * (carRB.velocity.magnitude * forceModifier * wheelGrip), carTransform.position + (carTransform.rotation * carCenterOfMass));
    }
Пример #5
0
        private void CalculateLapsUntilHeavyWear(WheelInfo wheelInfo, SimulatorDataSet simulatorDataSet)
        {
            TimeSpan?playersPace = _paceProvider.PlayersPace;

            if (_wearPerMinute == 0 || !playersPace.HasValue || playersPace.Value == TimeSpan.Zero)
            {
                LapsUntilHeavyWear = 0;
                return;
            }

            double wearLeft    = (wheelInfo.TyreWear.HeavyWearLimit - wheelInfo.TyreWear.ActualWear);
            double minutesLeft = wearLeft / _wearPerMinute;

            LapsUntilHeavyWear = (int)Math.Floor(minutesLeft / playersPace.Value.TotalMinutes);
        }
        private Velocity ComputeSuspensionVelocity(WheelInfo wheel, Distance lastSuspTravel, Velocity lastSuspensionVelocity, double sessionTimeSeconds)
        {
            double interval = sessionTimeSeconds - _lastSessionTimeSeconds;

            if (interval <= 0)
            {
                wheel.SuspensionVelocity = lastSuspensionVelocity;
                return(lastSuspensionVelocity);
            }

            Distance distanceTraveled   = wheel.SuspensionTravel - lastSuspTravel;
            Velocity suspensionVelocity = Velocity.FromMs(distanceTraveled.InMeters / interval);

            wheel.SuspensionVelocity = suspensionVelocity;
            return(suspensionVelocity);
        }
Пример #7
0
        private void UpdateBrakeControl(SimulatorDataSet data)
        {
            if (data.PlayerInfo == null)
            {
                return;
            }

            WheelInfo wheel = GetWheelByPosition(data);

            if (wheel == null)
            {
                return;
            }

            lblBreakTemp.Text    = wheel.BrakeTemperature.GetValueInUnits(TemperatureDisplayUnit).ToString("0");
            lblBreakTemp.PixelOn = ComputeColor(wheel.BrakeTemperature.InCelsius, wheel.OptimalBrakeTemperature.InCelsius, wheel.OptimalBrakeWindow);
        }
Пример #8
0
        void UpdateWheelTransformsWS(WheelInfo wheel, bool interpolatedTransform)
        {
            wheel.RaycastInfo.IsInContact = false;

            Matrix chassisTrans = ChassisWorldTransform;

            if (interpolatedTransform && RigidBody.MotionState != null)
            {
                chassisTrans = RigidBody.MotionState.WorldTransform;
            }

            wheel.RaycastInfo.HardPointWS = Vector3.TransformCoordinate(wheel.ChassisConnectionPointCS, chassisTrans);
            Matrix chassisTransBasis = chassisTrans.Basis;

            wheel.RaycastInfo.WheelDirectionWS = Vector3.TransformCoordinate(wheel.WheelDirectionCS, chassisTransBasis);
            wheel.RaycastInfo.WheelAxleWS      = Vector3.TransformCoordinate(wheel.WheelAxleCS, chassisTransBasis);
        }
Пример #9
0
        private void CalculateWearAtRaceEnd(WheelInfo wheelInfo, SimulatorDataSet simulatorDataSet)
        {
            if (simulatorDataSet.SessionInfo.SessionType != SessionType.Race || _wearPerMinute == 0)
            {
                WearAtRaceEnd = 0;
                return;
            }

            TimeSpan timeRemaining = _sessionRemainingCalculator.GetTimeRemaining(simulatorDataSet);

            if (timeRemaining == TimeSpan.Zero)
            {
                WearAtRaceEnd = 0;
                return;
            }

            WearAtRaceEnd = Math.Max(0, 100 - 100 * (wheelInfo.TyreWear.ActualWear + _wearPerMinute * timeRemaining.TotalMinutes));
        }
Пример #10
0
        /// <summary>
        /// Updates the position of the wheel according to the BRaycastVehicle's position and speed.
        /// </summary>
        private void Update()
        {
            if (robot == null)
            {
                return;
            }

            Vector3 velocity      = ((RigidBody)transform.parent.GetComponent <BRigidBody>().GetCollisionObject()).GetVelocityInLocalPoint(basePoint).ToUnity();
            Vector3 localVelocity = transform.parent.InverseTransformDirection(velocity);

            WheelInfo wheelInfo = robot.RaycastRobot.GetWheelInfo(wheelIndex);
            Vector3   wheelAxle = wheelInfo.WheelAxleCS.ToUnity();

            transform.position       = wheelInfo.WorldTransform.Origin.ToUnity();
            transform.localRotation *= Quaternion.AngleAxis(-Vector3.Dot(localVelocity,
                                                                         Quaternion.AngleAxis(90f, Vector3.up) * wheelAxle / (Mathf.PI * radius)), axis);

            Debug.DrawLine(transform.position, transform.position + transform.parent.TransformDirection(wheelInfo.WheelAxleCS.ToUnity()) * 0.1f, Color.red);
        }
Пример #11
0
        public void ApplyWheelInfo(SimulatorDataSet dataSet, WheelInfo wheelInfo)
        {
            SessionInfo sessionInfo = dataSet.SessionInfo;

            if (_lastCheckTime != TimeSpan.Zero && (sessionInfo.SessionTime - _lastCheckTime).TotalSeconds < 30)
            {
                return;
            }

            if (dataSet.SessionInfo.SessionType == SessionType.Na || dataSet.SessionInfo.SessionTime == TimeSpan.Zero)
            {
                return;
            }

            _lastCheckTime = sessionInfo.SessionTime;
            UpdateTyreWear(wheelInfo, dataSet);
            CalculateWearAtRaceEnd(wheelInfo, dataSet);
            CalculateLapsUntilHeavyWear(wheelInfo, dataSet);
        }
Пример #12
0
        private void UpdateWheelTemp(SimulatorDataSet data)
        {
            if (data.PlayerInfo == null)
            {
                return;
            }

            WheelInfo wheel = GetWheelByPosition(data);

            if (wheel == null)
            {
                return;
            }
            wheelTempLeft.Text      = wheel.LeftTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0");
            wheelTempLeft.PixelOn   = ComputeColor(wheel.LeftTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow);
            wheelTempCenter.Text    = wheel.CenterTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0");
            wheelTempCenter.PixelOn = ComputeColor(wheel.CenterTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow);
            wheelTempRight.Text     = wheel.RightTyreTemp.GetValueInUnits(TemperatureDisplayUnit).ToString("0");
            wheelTempRight.PixelOn  = ComputeColor(wheel.RightTyreTemp.InCelsius, wheel.OptimalTyreTemperature.InCelsius, wheel.OptimalTyreWindow);
        }
Пример #13
0
        private void UpdateTyreWearControl(SimulatorDataSet data)
        {
            if (data.PlayerInfo == null)
            {
                return;
            }

            WheelInfo wheel = GetWheelByPosition(data);

            if (wheel == null)
            {
                return;
            }

            double wear = wheel.TyreWear;

            lblTyreType.Text    = wheel.TyreType;
            lblTyreType.Visible = wheel.TyreTypeFilled;
            pnlWear.Width       = (int)((1 - wear) * Width);
            lbWear.Text         = ((1 - wear) * 100).ToString("0");
        }
Пример #14
0
        protected void AddWheels(Vector3 halfExtents, RaycastVehicle vehicle, VehicleTuning tuning, float wheelRadius)
        {
            //The direction of the raycast, the btRaycastVehicle uses raycasts instead of simiulating the wheels with rigid bodies
            Vector3 wheelDirectionCS0 = new Vector3(0, -1, 0);

            //The axis which the wheel rotates arround
            Vector3 wheelAxleCS = new Vector3(-1, 0, 0);

            //All the wheel configuration assumes the vehicle is centered at the origin and a right handed coordinate system is used
            Vector4 points = contactInfoByChassis(mesh.Name);

            points.Y += suspensionLength + meshAxisRadius.Y - (meshRealHeight / 2f);

            //Adds the rear wheels
            Vector3 wheelConnectionPoint = new Vector3(points.X, points.Y - rearWheelsHeight, points.Z);

            vehicle.AddWheel(wheelConnectionPoint, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, false);
            vehicle.AddWheel(wheelConnectionPoint * new Vector3(-1, 1, 1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, false);

            //Adds the front wheels
            wheelConnectionPoint = new Vector3(points.X, points.Y - frontWheelsHeight, points.W);
            vehicle.AddWheel(wheelConnectionPoint * new Vector3(1, 1, -1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, true);
            vehicle.AddWheel(wheelConnectionPoint * new Vector3(-1, 1, -1), wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, true);

            //Configures each wheel of our vehicle, setting its friction, damping compression, etc.
            //For more details on what each parameter does, refer to the docs
            for (int i = 0; i < vehicle.NumWheels; i++)
            {
                WheelInfo wheel = vehicle.GetWheelInfo(i);
                wheel.MaxSuspensionForce = 700000;
                //wheel.MaxSuspensionTravelCm = 80;
                wheel.SuspensionStiffness      = suspensionStiffness;
                wheel.WheelsDampingCompression = dampingCompression * 2 * FastMath.Sqrt(wheel.SuspensionStiffness);
                wheel.WheelsDampingRelaxation  = dampingRelaxation * 2 * FastMath.Sqrt(wheel.SuspensionStiffness);
                wheel.FrictionSlip             = frictionSlip;
                wheel.RollInfluence            = rollInfluence;
            }
        }
Пример #15
0
        public void Evaluate(int SpreadMax)
        {
            if (FInVehicle.PluginIO.IsConnected)
            {
                FOutTransform.SliceCount = this.FInVehicle[0].NumWheels;

                RaycastVehicle v = this.FInVehicle[0];

                for (int i = 0; i < v.NumWheels; i++)
                {
                    WheelInfo wi = v.GetWheelInfo(i);

                    Matrix m = wi.WorldTransform;

                    Matrix4x4 mn = new Matrix4x4(m.M11, m.M12, m.M13, m.M14,
                                                 m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34,
                                                 m.M41, m.M42, m.M43, m.M44);
                    //wi.r

                    this.FOutTransform[i] = mn;
                }
            }
        }
        private void FillWheelIdealQuantities(WheelInfo wheel, OptimalQuantity <Pressure> optimalPressure, OptimalQuantity <Temperature> optimalTemperature)
        {
            if (optimalPressure != null)
            {
                wheel.TyrePressure.IdealQuantity.InKpa       = optimalPressure.IdealQuantity.InKpa;
                wheel.TyrePressure.IdealQuantityWindow.InKpa = optimalPressure.IdealQuantityWindow.InKpa;
            }

            if (optimalTemperature != null)
            {
                wheel.TyreCoreTemperature.IdealQuantity.InCelsius       = optimalTemperature.IdealQuantity.InCelsius;
                wheel.TyreCoreTemperature.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius;

                wheel.LeftTyreTemp.IdealQuantity.InCelsius       = optimalTemperature.IdealQuantity.InCelsius;
                wheel.LeftTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius;

                wheel.CenterTyreTemp.IdealQuantity.InCelsius       = optimalTemperature.IdealQuantity.InCelsius;
                wheel.CenterTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius;

                wheel.RightTyreTemp.IdealQuantity.InCelsius       = optimalTemperature.IdealQuantity.InCelsius;
                wheel.RightTyreTemp.IdealQuantityWindow.InCelsius = optimalTemperature.IdealQuantityWindow.InCelsius;
            }
        }
Пример #17
0
        /// <summary>
        /// Adds a wheel to the BRaycastVehicle from the given information.
        /// </summary>
        /// <param name="connectionPoint"></param>
        /// <param name="axle"></param>
        /// <param name="suspensionRestLength"></param>
        /// <param name="radius"></param>
        /// <returns></returns>
        public int AddWheel(WheelType wheelType, BulletSharp.Math.Vector3 connectionPoint, BulletSharp.Math.Vector3 axle, float suspensionRestLength, float radius)
        {
            switch (wheelType)
            {
            case WheelType.MECANUM:
                RaycastRobot.SlidingFriction = 0.1f;
                axle = (Quaternion.AngleAxis((connectionPoint.X > 0 && connectionPoint.Z > 0) || (connectionPoint.X < 0 && connectionPoint.Z < 0) ? -45 : 45,
                                             Vector3.up) * axle.ToUnity()).ToBullet();
                break;

            case WheelType.OMNI:
                RaycastRobot.SlidingFriction = 0.1f;
                break;
            }

            WheelInfo w = RaycastRobot.AddWheel(connectionPoint,
                                                -BulletSharp.Math.Vector3.UnitY, axle, suspensionRestLength,
                                                radius, vehicleTuning, false);

            w.RollInfluence = 0.25f;
            w.Brake         = RollingFriction / radius;

            return(RaycastRobot.NumWheels - 1);
        }
 protected override double GetXWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot)
 {
     return(snapshot.PlayerData.CarInfo.Acceleration.ZinG);
 }
Пример #19
0
        public void UpdateFriction(float timeStep)
        {
            //calculate the impulse, so that the wheels don't move sidewards
            int numWheel = NumWheels;

            if (numWheel == 0)
            {
                return;
            }

            Array.Resize(ref forwardWS, numWheel);
            Array.Resize(ref axle, numWheel);
            Array.Resize(ref forwardImpulse, numWheel);
            Array.Resize(ref sideImpulse, numWheel);

            int numWheelsOnGround = 0;

            //collapse all those loops into one!
            for (int i = 0; i < NumWheels; i++)
            {
                RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    numWheelsOnGround++;
                }
                sideImpulse[i]    = 0;
                forwardImpulse[i] = 0;
            }

            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    Matrix wheelTrans = GetWheelTransformWS(i);

                    axle[i] = new Vector3(
                        wheelTrans[0, indexRightAxis],
                        wheelTrans[1, indexRightAxis],
                        wheelTrans[2, indexRightAxis]);

                    Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS;
                    float   proj;
                    Vector3.Dot(ref axle[i], ref surfNormalWS, out proj);
                    axle[i] -= surfNormalWS * proj;
                    axle[i].Normalize();

                    Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]);
                    forwardWS[i].Normalize();

                    ResolveSingleBilateral(chassisBody, wheel.RaycastInfo.ContactPointWS,
                                           groundObject, wheel.RaycastInfo.ContactPointWS,
                                           0, axle[i], ref sideImpulse[i], timeStep);

                    sideImpulse[i] *= sideFrictionStiffness2;
                }
            }

            const float sideFactor = 1.0f;
            const float fwdFactor  = 0.5f;

            bool sliding = false;

            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel        = wheelInfo[i];
                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                float rollingFriction = 0.0f;

                if (groundObject != null)
                {
                    if (wheel.EngineForce != 0.0f)
                    {
                        rollingFriction = wheel.EngineForce * timeStep;
                    }
                    else
                    {
                        float defaultRollingFrictionImpulse = 0.0f;
                        float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse;
                        rollingFriction = CalcRollingFriction(chassisBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse);
                    }
                }

                //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)

                forwardImpulse[i]     = 0;
                wheelInfo[i].SkidInfo = 1.0f;

                if (groundObject != null)
                {
                    wheelInfo[i].SkidInfo = 1.0f;

                    float maximp     = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip;
                    float maximpSide = maximp;

                    float maximpSquared = maximp * maximpSide;


                    forwardImpulse[i] = rollingFriction;//wheel.EngineForce* timeStep;

                    float x = forwardImpulse[i] * fwdFactor;
                    float y = sideImpulse[i] * sideFactor;

                    float impulseSquared = (x * x + y * y);

                    if (impulseSquared > maximpSquared)
                    {
                        sliding = true;

                        float factor = maximp / (float)Math.Sqrt(impulseSquared);

                        wheelInfo[i].SkidInfo *= factor;
                    }
                }
            }

            if (sliding)
            {
                for (int wheel = 0; wheel < NumWheels; wheel++)
                {
                    if (sideImpulse[wheel] != 0)
                    {
                        if (wheelInfo[wheel].SkidInfo < 1.0f)
                        {
                            forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo;
                            sideImpulse[wheel]    *= wheelInfo[wheel].SkidInfo;
                        }
                    }
                }
            }

            // apply the impulses
            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS -
                                  chassisBody.CenterOfMassPosition;

                if (forwardImpulse[i] != 0)
                {
                    chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos);
                }
                if (sideImpulse[i] != 0)
                {
                    RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                    Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS -
                                       groundObject.CenterOfMassPosition;


                    Vector3 sideImp = axle[i] * sideImpulse[i];

#if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
                    //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis);
                    Vector3 vChassisWorldUp = new Vector3(
                        RigidBody.CenterOfMassTransform.Row1[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row2[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row3[indexUpAxis]);
                    float dot;
                    Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot);
                    rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence));
#else
                    rel_pos[indexUpAxis] *= wheel.RollInfluence;
#endif
                    chassisBody.ApplyImpulse(sideImp, rel_pos);

                    //apply friction impulse on the ground
                    groundObject.ApplyImpulse(-sideImp, rel_pos2);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Updates the friction for the RaycastRobot.
        /// </summary>
        /// <param name="timeStep"></param>
        public void UpdateFriction(float timeStep)
        {
            //calculate the impulse, so that the wheels don't move sidewards
            int numWheel = NumWheels;

            if (numWheel == 0)
            {
                return;
            }

            Array.Resize <Vector3>(ref forwardWS, numWheel);
            Array.Resize <Vector3>(ref axle, numWheel);
            Array.Resize <float>(ref forwardImpulse, numWheel);
            Array.Resize <float>(ref sideImpulse, numWheel);

            int numWheelsOnGround = 0;

            //collapse all those loops into one!
            for (int i = 0; i < NumWheels; i++)
            {
                RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    numWheelsOnGround++;
                }
                sideImpulse[i]    = 0;
                forwardImpulse[i] = 0;
            }

            for (int i = 0; i < NumWheels; i++)
            {
                RobotWheelInfo wheel = wheelInfo[i];

                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    Matrix wheelTrans = GetWheelTransformWS(i);

                    axle[i] = new Vector3(
                        wheelTrans[0, indexRightAxis],
                        wheelTrans[1, indexRightAxis],
                        wheelTrans[2, indexRightAxis]);

                    Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS;
                    float   proj;
                    Vector3.Dot(ref axle[i], ref surfNormalWS, out proj);
                    axle[i] -= surfNormalWS * proj;
                    axle[i].Normalize();

                    Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]);
                    forwardWS[i].Normalize();

                    ResolveSingleBilateral(RootRigidBody, wheel.RaycastInfo.ContactPointWS,
                                           groundObject, wheel.RaycastInfo.ContactPointWS,
                                           0, axle[i], ref sideImpulse[i], timeStep);

                    sideImpulse[i] *= wheel.SlidingFriction;
                }
                else
                {
                    if (wheel.Speed > 0)
                    {
                        wheel.Speed = Math.Max(wheel.Speed - wheel.FreeSpinDamping, 0f);
                    }
                    else if (wheel.Speed < 0)
                    {
                        wheel.Speed = Math.Min(wheel.Speed + wheel.FreeSpinDamping, 0f);
                    }
                }
            }

            bool sliding = false;

            for (int i = 0; i < NumWheels; i++)
            {
                RobotWheelInfo wheel        = wheelInfo[i];
                RigidBody      groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                float rollingFriction = 0.0f;

                if (groundObject != null)
                {
                    Vector3 velocity      = chassisBody.GetVelocityInLocalPoint(wheel.ChassisConnectionPointCS);
                    Vector3 localVelocity = Vector3.TransformNormal(velocity, Matrix.Invert(chassisBody.WorldTransform.Basis));
                    Vector3 forwardAxis   = (UnityEngine.Quaternion.AngleAxis(90f, UnityEngine.Vector3.up) *
                                             wheel.WheelAxleCS.ToUnity() / (MathUtil.SIMD_PI * wheel.WheelsRadius)).ToBullet();

                    float speed = Vector3.Dot(localVelocity, forwardAxis);

                    wheel.Speed = speed;

                    if (wheel.EngineForce != 0.0f)
                    {
                        //apply torque curves
                        float engineForce = wheel.EngineForce;

                        if (speed * engineForce > 0)
                        {
                            engineForce *= 1 - (Math.Abs(speed) / MaxWheelAngularVelocity);
                        }

                        rollingFriction = engineForce * timeStep;

                        if (!RootRigidBody.IsActive)
                        {
                            RootRigidBody.Activate();
                        }
                    }
                    else
                    {
                        float defaultRollingFrictionImpulse = 0.0f;
                        float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse;
                        rollingFriction = CalcRollingFriction(RootRigidBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse);
                    }
                }

                //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)

                forwardImpulse[i]     = 0;
                wheelInfo[i].SkidInfo = 1.0f;

                if (groundObject != null)
                {
                    wheelInfo[i].SkidInfo = 1.0f;

                    float maximp     = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip;
                    float maximpSide = maximp;

                    float maximpSquared = maximp * maximpSide;

                    forwardImpulse[i] = rollingFriction;

                    float x = forwardImpulse[i] * fwdFactor;
                    float y = sideImpulse[i] * sideFactor;

                    float impulseSquared = (x * x + y * y);

                    if (impulseSquared > maximpSquared)
                    {
                        sliding = true;

                        float factor = maximp / (float)System.Math.Sqrt(impulseSquared);

                        wheelInfo[i].SkidInfo *= factor;
                    }
                }
            }

            if (sliding)
            {
                for (int wheel = 0; wheel < NumWheels; wheel++)
                {
                    if (sideImpulse[wheel] != 0)
                    {
                        if (wheelInfo[wheel].SkidInfo < 1.0f)
                        {
                            forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo;
                            sideImpulse[wheel]    *= wheelInfo[wheel].SkidInfo;
                        }
                    }
                }
            }

            // apply the impulses
            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS -
                                  chassisBody.CenterOfMassPosition;

                if (forwardImpulse[i] != 0)
                {
                    chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos);
                }
                if (sideImpulse[i] != 0)
                {
                    RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                    Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS -
                                       groundObject.CenterOfMassPosition;


                    Vector3 sideImp = axle[i] * sideImpulse[i];

#if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
                    //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis);
                    Vector3 vChassisWorldUp = new Vector3(
                        RigidBody.CenterOfMassTransform.Row1[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row2[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row3[indexUpAxis]);
                    float dot;
                    Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot);
                    rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence));
#else
                    rel_pos[indexUpAxis] *= wheel.RollInfluence;
#endif
                    chassisBody.ApplyImpulse(sideImp, rel_pos);

                    //apply friction impulse on the ground
                    groundObject.ApplyImpulse(-sideImp, rel_pos2);
                }
            }
        }
Пример #21
0
        private float RayCast(WheelInfo wheel)
        {
            UpdateWheelTransformsWS(wheel, false);

            float depth  = -1;
            float raylen = wheel.SuspensionRestLength + wheel.WheelsRadius;

            Vector3 rayvector = wheel.RaycastInfo.WheelDirectionWS * raylen;
            Vector3 source    = wheel.RaycastInfo.HardPointWS;

            wheel.RaycastInfo.ContactPointWS = source + rayvector;
            Vector3 target = wheel.RaycastInfo.ContactPointWS;

            float param = 0;
            VehicleRaycasterResult rayResults = new VehicleRaycasterResult();

            Debug.Assert(vehicleRaycaster != null);
            object obj = vehicleRaycaster.CastRay(ref source, ref target, rayResults);

            wheel.RaycastInfo.GroundObject = null;

            if (obj != null)
            {
                param = rayResults.DistFraction;
                depth = raylen * rayResults.DistFraction;
                wheel.RaycastInfo.ContactNormalWS = rayResults.HitNormalInWorld;
                wheel.RaycastInfo.IsInContact     = true;

                wheel.RaycastInfo.GroundObject = fixedBody;///@todo for driving on dynamic/movable objects!;
                /////wheel.RaycastInfo.GroundObject = object;

                float hitDistance = param * raylen;
                wheel.RaycastInfo.SuspensionLength = hitDistance - wheel.WheelsRadius;
                //clamp on max suspension travel

                float minSuspensionLength = wheel.SuspensionRestLength - wheel.MaxSuspensionTravelCm * 0.01f;
                float maxSuspensionLength = wheel.SuspensionRestLength + wheel.MaxSuspensionTravelCm * 0.01f;
                if (wheel.RaycastInfo.SuspensionLength < minSuspensionLength)
                {
                    wheel.RaycastInfo.SuspensionLength = minSuspensionLength;
                }
                if (wheel.RaycastInfo.SuspensionLength > maxSuspensionLength)
                {
                    wheel.RaycastInfo.SuspensionLength = maxSuspensionLength;
                }

                wheel.RaycastInfo.ContactPointWS = rayResults.HitPointInWorld;

                float denominator = Vector3.Dot(wheel.RaycastInfo.ContactNormalWS, wheel.RaycastInfo.WheelDirectionWS);

                Vector3 chassis_velocity_at_contactPoint;
                Vector3 relpos = wheel.RaycastInfo.ContactPointWS - RigidBody.CenterOfMassPosition;

                chassis_velocity_at_contactPoint = RigidBody.GetVelocityInLocalPoint(relpos);

                float projVel = Vector3.Dot(wheel.RaycastInfo.ContactNormalWS, chassis_velocity_at_contactPoint);

                if (denominator >= -0.1f)
                {
                    wheel.SuspensionRelativeVelocity     = 0;
                    wheel.ClippedInvContactDotSuspension = 1.0f / 0.1f;
                }
                else
                {
                    float inv = -1.0f / denominator;
                    wheel.SuspensionRelativeVelocity     = projVel * inv;
                    wheel.ClippedInvContactDotSuspension = inv;
                }
            }
            else
            {
                //put wheel info as in rest position
                wheel.RaycastInfo.SuspensionLength   = wheel.SuspensionRestLength;
                wheel.SuspensionRelativeVelocity     = 0.0f;
                wheel.RaycastInfo.ContactNormalWS    = -wheel.RaycastInfo.WheelDirectionWS;
                wheel.ClippedInvContactDotSuspension = 1.0f;
            }

            return(depth);
        }
Пример #22
0
 protected abstract double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot);
Пример #23
0
        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, PhyScalarType.Int32, PhyScalarType.Single);

                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.Single;
                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.Single)
                        {
                            // heightScale isn't applied internally for float data
                            height = reader.ReadSingle();
                        }
                        else if (scalarType == PhyScalarType.Byte)
                        {
                            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;
        }
Пример #24
0
 protected override double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot)
 {
     return(wheelInfo.TyreLoad.GetValueInUnits(ForceUnits));
 }
Пример #25
0
        public void Evaluate(int SpreadMax)
        {
            IRigidBulletWorld inputWorld = this.worldInput[0];

            SpreadMax = 1;

            if (inputWorld != null)
            {
                this.persistedList.UpdateWorld(inputWorld);

                if (this.chassisShape.IsConnected)
                {
                    for (int i = 0; i < SpreadMax; i++)
                    {
                        if (this.doCreate[i])
                        {
                            RigidBodyPose       initialPose = this.initialPoseInput.IsConnected ? this.initialPoseInput[i] : RigidBodyPose.Default;
                            RigidBodyProperties properties  = this.initialProperties.IsConnected ? this.initialProperties[i] : RigidBodyProperties.Default;

                            ShapeCustomData            shapeData = new ShapeCustomData();
                            DynamicShapeDefinitionBase chassisShapeDefinition = this.chassisShape[i];

                            CollisionShape chassisShape = chassisShapeDefinition.GetShape(shapeData);
                            shapeData.ShapeDef = chassisShapeDefinition;

                            RaycastVehicle vehicle;
                            CompoundShape  compoundShape = new CompoundShape();

                            Matrix localTrans = Matrix.Translation(Vector3.UnitY);
                            compoundShape.AddChildShape(localTrans, chassisShape);

                            //Build mass for dynamic object
                            Vector3 localInertia = Vector3.Zero;
                            if (chassisShapeDefinition.Mass > 0.0f)
                            {
                                compoundShape.CalculateLocalInertia(chassisShapeDefinition.Mass, out localInertia);
                            }

                            Tuple <RigidBody, int> createBodyResult = inputWorld.CreateRigidBody(chassisShape, ref initialPose, ref properties, ref localInertia, chassisShapeDefinition.Mass, this.customString[i]);
                            RigidBody carChassis = createBodyResult.Item1;

                            RaycastVehicle.VehicleTuning tuning           = new RaycastVehicle.VehicleTuning();
                            DefaultVehicleRaycaster      vehicleRayCaster = new DefaultVehicleRaycaster(inputWorld.World);
                            vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster);
                            vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex);

                            carChassis.ActivationState = ActivationState.DisableDeactivation;
                            inputWorld.World.AddAction(vehicle);

                            int wheelCount = this.wheelConstruction.SliceCount;

                            //Add wheels
                            for (int j = 0; j < this.wheelConstruction[i].SliceCount; j++)
                            {
                                WheelConstructionProperties wcs = this.wheelConstruction[i][j];
                                Vector3   connectionPointCS0    = wcs.localPosition.ToBulletVector();
                                WheelInfo wheel = vehicle.AddWheel(connectionPointCS0, wcs.wheelDirection.ToBulletVector(), wcs.wheelAxis.ToBulletVector(), wcs.SuspensionRestLength, wcs.WheelRadius, tuning, wcs.isFrontWheel);
                            }

                            //Set Wheel Properties
                            WheelProperties wis = this.wheelInfoSettings[i] != null ? this.wheelInfoSettings[i] : new WheelProperties();
                            for (int j = 0; j < vehicle.NumWheels; j++)
                            {
                                WheelInfo wheel = vehicle.GetWheelInfo(j);
                                wheel.SuspensionStiffness      = wis.SuspensionStiffness;
                                wheel.WheelsDampingRelaxation  = wis.WheelsDampingRelaxation;
                                wheel.WheelsDampingCompression = wis.WheelsDampingCompression;
                                wheel.FrictionSlip             = wis.FrictionSlip;
                                wheel.RollInfluence            = wis.RollInfluence;
                            }

                            BodyCustomData bd = (BodyCustomData)carChassis.UserObject;
                            bd.Vehicle = vehicle;

                            this.persistedList.Append(createBodyResult.Item1, createBodyResult.Item2);
                        }
                    }


                    List <RigidBody> bodies = this.persistedList.Bodies;
                    this.vehicleOutput.SliceCount = bodies.Count;
                    this.chassisOutput.SliceCount = bodies.Count;
                    for (int i = 0; i < bodies.Count; i++)
                    {
                        BodyCustomData bd = (BodyCustomData)bodies[i].UserObject;
                        this.vehicleOutput[i] = bd.Vehicle;
                        this.chassisOutput[i] = bodies[i];
                    }
                }
            }
            else
            {
                this.vehicleOutput.SliceCount = 0;
                this.chassisOutput.SliceCount = 0;
            }
        }
Пример #26
0
        public void UpdateVehicle(float step)
        {
            for (int i = 0; i < NumWheels; i++)
            {
                UpdateWheelTransform(i, false);
            }

            currentVehicleSpeedKmHour = 3.6f * RigidBody.LinearVelocity.Length;

            Matrix chassisTrans = ChassisWorldTransform;

            Vector3 forwardW = new Vector3(
                chassisTrans[0, indexForwardAxis],
                chassisTrans[1, indexForwardAxis],
                chassisTrans[2, indexForwardAxis]);

            if (Vector3.Dot(forwardW, RigidBody.LinearVelocity) < 0)
            {
                currentVehicleSpeedKmHour *= -1.0f;
            }

            // Simulate suspension

            /*
             * for (int i = 0; i < wheelInfo.Count; i++)
             * {
             *  float depth = RayCast(wheelInfo[i]);
             * }
             */


            UpdateSuspension(step);

            for (int i = 0; i < wheelInfo.Count; i++)
            {
                //apply suspension force
                WheelInfo wheel = wheelInfo[i];

                float suspensionForce = wheel.WheelsSuspensionForce;

                if (suspensionForce > wheel.MaxSuspensionForce)
                {
                    suspensionForce = wheel.MaxSuspensionForce;
                }
                Vector3 impulse = wheel.RaycastInfo.ContactNormalWS * suspensionForce * step;
                Vector3 relpos  = wheel.RaycastInfo.ContactPointWS - RigidBody.CenterOfMassPosition;

                RigidBody.ApplyImpulse(impulse, relpos);
            }


            UpdateFriction(step);

            for (int i = 0; i < wheelInfo.Count; i++)
            {
                WheelInfo wheel  = wheelInfo[i];
                Vector3   relpos = wheel.RaycastInfo.HardPointWS - RigidBody.CenterOfMassPosition;
                Vector3   vel    = RigidBody.GetVelocityInLocalPoint(relpos);

                if (wheel.RaycastInfo.IsInContact)
                {
                    Matrix chassisWorldTransform = ChassisWorldTransform;

                    Vector3 fwd = new Vector3(
                        chassisWorldTransform[0, indexForwardAxis],
                        chassisWorldTransform[1, indexForwardAxis],
                        chassisWorldTransform[2, indexForwardAxis]);

                    float proj = Vector3.Dot(fwd, wheel.RaycastInfo.ContactNormalWS);
                    fwd -= wheel.RaycastInfo.ContactNormalWS * proj;

                    float proj2;
                    Vector3.Dot(ref fwd, ref vel, out proj2);

                    wheel.DeltaRotation = (proj2 * step) / (wheel.WheelsRadius);
                    wheel.Rotation     += wheel.DeltaRotation;
                }
                else
                {
                    wheel.Rotation += wheel.DeltaRotation;
                }

                wheel.DeltaRotation *= 0.99f;//damping of rotation when not in contact
            }
        }
Пример #27
0
        private void CreateVehicle(Matrix transform)
        {
            var chassisShape = new BoxShape(1.0f, 0.5f, 2.0f);

            var compound = new CompoundShape();

            //localTrans effectively shifts the center of mass with respect to the chassis
            Matrix localTrans = Matrix.Translation(Vector3.UnitY);

            compound.AddChildShape(localTrans, chassisShape);
            RigidBody carChassis = PhysicsHelper.CreateBody(800, Matrix.Identity, compound, World);

            carChassis.UserObject = "Chassis";
            //carChassis.SetDamping(0.2f, 0.2f);

            var tuning           = new VehicleTuning();
            var vehicleRayCaster = new DefaultVehicleRaycaster(World);

            //vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster);
            _vehicle = new CustomVehicle(tuning, carChassis, vehicleRayCaster);

            carChassis.ActivationState = ActivationState.DisableDeactivation;
            World.AddAction(_vehicle);


            const float connectionHeight = 1.2f;

            // choose coordinate system
            _vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex);

            Vector3 wheelDirection = Vector3.Zero;
            Vector3 wheelAxle      = Vector3.Zero;

            wheelDirection[upIndex] = -1;
            wheelAxle[rightIndex]   = -1;

            bool isFrontWheel    = true;
            var  connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius);

            _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2 * CUBE_HALF_EXTENTS - wheelRadius);
            _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            isFrontWheel    = false;
            connectionPoint = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius);
            _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

            connectionPoint = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2 * CUBE_HALF_EXTENTS + wheelRadius);
            _vehicle.AddWheel(connectionPoint, wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, isFrontWheel);


            for (int 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 = transform;
        }
 private double GetTyreLoad(WheelInfo wheelInfo)
 {
     return(wheelInfo.TyreLoad.GetValueInUnits(ForceUnits));
 }
Пример #29
0
        public override void Evaluate(int SpreadMax)
        {
            for (int i = 0; i < SpreadMax; i++)
            {
                if (this.CanCreate(i))
                {
                    wheelRadius       = FwheelRadius[0];
                    wheelWidth        = FwheelWidth[0];
                    CUBE_HALF_EXTENTS = FwheelDistance[0];

                    RaycastVehicle vehicle;

                    AbstractRigidShapeDefinition shapedef = this.FShapes[i];
                    ShapeCustomData sc = new ShapeCustomData();
                    sc.ShapeDef = shapedef;


                    CompoundShape compound = new CompoundShape();



                    CollisionShape chassisShape = shapedef.GetShape(sc);
                    Matrix         localTrans   = Matrix.Translation(Vector3.UnitY);
                    compound.AddChildShape(localTrans, chassisShape);

                    float mass = shapedef.Mass;

                    bool isDynamic = (mass != 0.0f);
                    isFrontWheel = true;

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



                    // choose coordinate system
                    vehicle.SetCoordinateSystem(rightIndex, upIndex, forwardIndex);

                    Vector3   connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius);
                    WheelInfo a = vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel);

                    connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], 2 * CUBE_HALF_EXTENTS - wheelRadius);
                    vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel);

                    isFrontWheel       = false;
                    connectionPointCS0 = new Vector3(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius);
                    vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel);

                    connectionPointCS0 = new Vector3(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), FconnectionHeight[0], -2 * CUBE_HALF_EXTENTS + wheelRadius);
                    vehicle.AddWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, FsuspensionRestLength[0], wheelRadius, tuning, isFrontWheel);


                    for (i = 0; i < vehicle.NumWheels; i++)
                    {
                        WheelInfo wheel = vehicle.GetWheelInfo(i);
                        wheel.SuspensionStiffness     = FsuspensionStiffness[0];
                        wheel.WheelDampingRelaxation  = FDampingRelaxation[0];
                        wheel.WheelDampingCompression = FDampingCompression[0];
                        wheel.FrictionSlip            = FwheelFriction[0];
                        wheel.RollInfluence           = FrollInfluence[0];
                        wheel.MaxSuspensionTravelCm   = FmaxSuspensionTravelCm[0];
                        wheel.MaxSuspensionForce      = FmaxSuspensionForce[0];
                    }

                    FOutVehicle.SliceCount = 1;
                    FOutVehicle[0]         = vehicle;
                }
            }
        }
 protected override double GetYWheelValue(WheelInfo wheelInfo, TimedTelemetrySnapshot snapshot)
 {
     return(wheelInfo.RideHeight.GetByUnit(DistanceUnitsSmall));
 }