コード例 #1
0
ファイル: BluffBody.cs プロジェクト: swipswaps/VoloAirsport
    private void FixedUpdate()
    {
        if (_wind == null)
        {
            return;
        }

        if (OnPreFixedUpdate != null)
        {
            OnPreFixedUpdate(this);
        }

        Vector3 centerPosition = transform.position;

        Vector3 windVelocity = _wind.GetWindVelocity(centerPosition);
        float   airDensity   = _wind.GetAirDensity(centerPosition);

        RelativeVelocity = _body.velocity - windVelocity;
        AirSpeed         = RelativeVelocity.magnitude;

        Vector3 force = -RelativeVelocity.normalized * (0.5f * airDensity * _referenceArea * AirSpeed * AirSpeed * _cDrag); // Todo: optimize by not normalizing relative velocity

        _body.AddForceAtPosition(force, transform.position);

        if (OnPostFixedUpdate != null)
        {
            OnPostFixedUpdate(this);
        }
    }
コード例 #2
0
    private void FixedUpdate()
    {
        if (_body == null || _wind == null)
        {
            return;
        }

        if (OnPreFixedUpdate != null)
        {
            OnPreFixedUpdate(this);
        }

        Vector3 centerPosition = transform.position;

        Vector3 windVelocity = _wind.GetWindVelocity(centerPosition);
        float   airDensity   = _wind.GetAirDensity(centerPosition);

        RelativeVelocity = _body.velocity - windVelocity;
        AirSpeed         = RelativeVelocity.magnitude;

        Vector3 worldLongitudinalAxis = transform.TransformDirection(_longitudinalAxis);
        Vector3 axis = Vector3.Cross(worldLongitudinalAxis, RelativeVelocity).normalized;

        AngleOfAttack = MathUtils.AngleAroundAxis(worldLongitudinalAxis, RelativeVelocity, axis);

        float liftCoefficient = _liftCoeffients.Evaluate(AngleOfAttack) * _liftCoefficientMultiplier;
        float dragCoefficient = _dragCoeffients.Evaluate(AngleOfAttack) * _dragCoefficientMultiplier;

        float dynamicSurfacePressure = 0.5f * airDensity * _referenceArea * AirSpeed * AirSpeed;

        // Todo: can optimize by not normalizing relative velocity
        LiftForce = Vector3.Cross(RelativeVelocity, axis).normalized *(dynamicSurfacePressure * liftCoefficient);
        DragForce = -RelativeVelocity.normalized * (dynamicSurfacePressure * dragCoefficient);

        _body.AddForceAtPosition(LiftForce + DragForce, transform.position);

        if (OnPostFixedUpdate != null)
        {
            OnPostFixedUpdate(this);
        }
    }
コード例 #3
0
ファイル: Airfoil1D.cs プロジェクト: swipswaps/VoloAirsport
    private void EvaluateForces()
    {
        Vector3 position = _transform.position;

        Vector3 windVelocity = _wind.GetWindVelocity(position);
        float   airDensity   = _wind.GetAirDensity(position);

        Vector3 velocity = (position - _lastPosition) / Time.deltaTime;

        _lastPosition    = position;
        RelativeVelocity = velocity - windVelocity;
        AirSpeed         = RelativeVelocity.magnitude;

        Vector3 relativeDirection = RelativeVelocity.normalized;

        float dynamicSurfacePressure = 0.5f * airDensity * _surfaceArea * AirSpeed * AirSpeed;

        // Bug: This method of determining angle of attack only works for the default axis configuration!!
        // Bug: if lift coeff goes negative, we get NaNs really quickly!

        Vector3 localRelativeVelocity = _transform.InverseTransformDirection(RelativeVelocity);
        Vector2 pitchPlaneVelocity    = new Vector2(localRelativeVelocity.z, localRelativeVelocity.y);

        AngleOfAttack = AngleSigned(Vector2.right, pitchPlaneVelocity);

        if (float.IsNaN(AngleOfAttack))
        {
            Debug.LogError("Angle of Attack is NaN " + RelativeVelocity);
#if UNITY_EDITOR
            EditorApplication.isPlaying = false;
#endif
            return;
        }

        Vector3 worldAxis = _transform.TransformDirection(_pitchAxis);

        Vector3 linearForce = Vector3.zero;

        if (_liftResponse.Enabled)
        {
            float   liftCoefficient = _liftResponse.Coefficients.Evaluate(AngleOfAttack) * _liftResponse.Multiplier;
            float   liftMagnitude   = dynamicSurfacePressure * liftCoefficient * Efficiency;
            Vector3 liftDirection   = Vector3.Cross(relativeDirection, worldAxis);
            LiftForce    = liftDirection * liftMagnitude;
            linearForce += LiftForce;
        }

        if (_dragResponse.Enabled)
        {
            float dragCoefficient = _dragResponse.Coefficients.Evaluate(AngleOfAttack) * _dragResponse.Multiplier;
            float dragMagnitude   = dynamicSurfacePressure * dragCoefficient * Efficiency;
            DragForce    = relativeDirection * -dragMagnitude;
            linearForce += DragForce;
        }

        if (_momentResponse.Enabled)
        {
            float momentCoefficient = _momentResponse.Coefficients.Evaluate(AngleOfAttack) * _momentResponse.Multiplier;
            float momentMagnitude   = dynamicSurfacePressure * momentCoefficient;
            MomentForce = worldAxis * momentMagnitude;
        }

        Vector3 pressurePoint = _transform.TransformPoint(_chordPressurePoint); // Todo: only needed if applying force from within this script

        if (_body)
        {
            _body.AddForceAtPosition(linearForce, pressurePoint);
            _body.AddTorqueAtPosition(MomentForce, _rollAxis, pressurePoint, ForceMode.Force);
        }
    }
コード例 #4
0
ファイル: Airfoil.cs プロジェクト: swipswaps/VoloAirsport
    private void EvaluateForces()
    {
        Transform wingTransform = transform;
        Vector3   wingPosition  = wingTransform.position;

        Vector3 windVelocity = _wind.GetWindVelocity(wingPosition);
        float   airDensity   = _wind.GetAirDensity(wingPosition);

        Vector3 velocity = (wingPosition - _lastPosition) / Time.deltaTime;

        _lastPosition    = wingPosition;
        RelativeVelocity = velocity - windVelocity;
        AirSpeed         = RelativeVelocity.magnitude;

        const float groundEffectHeight     = 32f;
        const float groundEffectPow        = 2f;
        float       groundEffectMultiplier = 1f;
        RaycastHit  hit;

        if (Physics.Raycast(_body.transform.position, Vector3.down, out hit, groundEffectHeight, _layerMask))
        {
            groundEffectMultiplier += Mathf.Pow(Mathf.InverseLerp(groundEffectHeight, 0f, hit.distance), groundEffectPow);
        }

        UpdateStats(wingTransform);

        // Calculate forces per section of the wing
        for (int i = 0; i < _numSections; i++)
        {
            var section = _sectionStates[i];

            Vector3 sectionWorldPosition = wingTransform.TransformPoint(section.LocalPosition);
            Vector3 sectionWorldVelocity = (sectionWorldPosition - section.LastSectionWorldPosition) / Time.fixedDeltaTime;
            section.LastSectionWorldPosition = sectionWorldPosition;
            section.RelativeVelocity         = sectionWorldVelocity - windVelocity;

            section.AirSpeed = section.RelativeVelocity.magnitude;

            float dynamicPressure = 0.5f * airDensity * section.AirSpeed * section.AirSpeed * groundEffectMultiplier;

            section.Lift   = Vector3.zero;
            section.Drag   = Vector3.zero;
            section.Moment = Vector3.zero;

            //Vector3 localRelativeVelocity = wingTransform.InverseTransformDirection(section.RelativeVelocity);

            // Calculate the effects around each axis
            for (int j = 0; j < _components.Length; j++)
            {
                AirfoilAxisResponse coefficient = _components[j];
                AirfoilAxis         airfoilAxis = _axes[(int)coefficient.AxisType];

                Vector3 worldAxis     = wingTransform.TransformDirection(airfoilAxis.Axis);
                Vector3 worldAxisBase = wingTransform.TransformDirection(airfoilAxis.AxisZero);

                // Todo: Collapse this all into 2D calculations around the coefficient axis

                Vector3 projectedVelocity = section.RelativeVelocity - Vector3.Project(section.RelativeVelocity, worldAxis);
                section.AngleOfAttack = MathUtils.AngleAroundAxis(worldAxisBase, projectedVelocity, worldAxis);
                Vector3 sectionRelativeDirection = projectedVelocity.normalized;

                float forceCoefficient = coefficient.Coefficients.Evaluate(section.AngleOfAttack + section.Offset) * coefficient.Multiplier;
                float forceMagnitude   = dynamicPressure * section.SurfaceArea * forceCoefficient;

                var input = new SectionForceInput()
                {
                    body                     = _body,
                    force                    = forceMagnitude,
                    efficiency               = _efficiency,
                    section                  = section,
                    sectionWorldPosition     = sectionWorldPosition,
                    sectionRelativeDirection = sectionRelativeDirection,
                    worldAxis                = worldAxis,
                    worldAxisZero            = worldAxisBase
                };

                //ForceApplicators[(int) coefficient.Type](input);
                switch (coefficient.Type)
                {
                case ForceType.Lift:
                    ApplyLift(input);
                    break;

                case ForceType.Drag:
                    ApplyDrag(input);
                    break;

                case ForceType.Moment:
                    ApplyMoment(input);
                    break;
                }
            }
        }
    }
コード例 #5
0
        private void EvaluateForces()
        {
            UpdateBodyMatrix();

            var liftPressurePoint = _bodyMatrix.MultiplyPoint(_chordPressurePoint);
            var dragPressurePoint = _bodyMatrix.MultiplyPoint(_chordPressurePoint);
            var windVelocity      = _wind.GetWindVelocity(liftPressurePoint);
            var airDensity        = _wind.GetAirDensity(liftPressurePoint);

            var velocity = (liftPressurePoint - _lastPosition) / _fixedClock.DeltaTime;

            _lastPosition    = liftPressurePoint;
            RelativeVelocity = velocity - windVelocity;
            var relativeDirection = RelativeVelocity.normalized;

            var localRelativeVelocity = _bodyMatrix.inverse.MultiplyVector(RelativeVelocity);
            var pitchPlaneVelocity    = new Vector2(localRelativeVelocity.z, localRelativeVelocity.y);

            AngleOfAttack = AngleSigned(Vector2.right, pitchPlaneVelocity.normalized);

            AirSpeed = pitchPlaneVelocity.magnitude;
            var dynamicSurfacePressure = 0.5f * airDensity * _surfaceArea * AirSpeed * AirSpeed;

            var worldAxis   = _bodyMatrix.MultiplyVector(Vector3.right);
            var linearForce = Vector3.zero;

            DeflectionInputs[0] = 1f - Mathf.Min(1f, DeflectionInputs[1] + DeflectionInputs[2] + DeflectionInputs[3]);

            var c = _definition.GetInterpolated(AngleOfAttack, DeflectionInputs);

            var   liftMagnitude = dynamicSurfacePressure * c.Lift * Mathf.Pow(_sliderFactor, 3f) * _optimalPressureFactor * _optimalPressureFactor;
            float aspectFactor  = 1f - 1f / Mathf.Pow(_totalAspectRatio, 0.5f); // Todo: Stupid simple way to make aspect ratio matter, improve

            liftMagnitude *= aspectFactor;

            var liftDirection = Vector3.Cross(relativeDirection, worldAxis);

            LiftForce    = liftDirection * liftMagnitude;
            linearForce += LiftForce;

            var dragMagnitude = dynamicSurfacePressure * c.Drag * SliderFactor * _optimalPressureFactor;

            DragForce    = relativeDirection * -dragMagnitude;
            linearForce += DragForce;

            var momentMagnitude = dynamicSurfacePressure * c.Moment;

            MomentForce = worldAxis * momentMagnitude;

            if (float.IsNaN(linearForce.magnitude) || float.IsNaN(linearForce.magnitude))
            {
                Debug.LogError("Airfoil Force is NaN " + RelativeVelocity + ", forcing quit...");
    #if UNITY_EDITOR
                EditorApplication.isPlaying = false;
    #else
                Application.Quit();
    #endif
                return;
            }

            if (_body)
            {
                _body.AddForceAtPosition(linearForce, liftPressurePoint);
                _body.AddTorqueAtPosition(MomentForce, dragPressurePoint, ForceMode.Force);
            }
        }