Esempio n. 1
0
    private static void ApplyMoment(SectionForceInput input)
    {
        Vector3 moment = input.worldAxis * input.force;

        input.section.Moment += moment;

        if (!input.body)
        {
            return;
        }
        input.body.AddTorqueAtPosition(moment, input.worldAxisZero, input.sectionWorldPosition, ForceMode.Force);
    }
Esempio n. 2
0
    private static void ApplyDrag(SectionForceInput input)
    {
        Vector3 drag = input.sectionRelativeDirection * -input.force;

        input.section.Drag += drag;

        if (!input.body)
        {
            return;
        }
        input.body.AddForceAtPosition(drag, input.sectionWorldPosition);
    }
Esempio n. 3
0
    // Todo: We might be able to skip a normalize and a scale operation if we use RelativeVelocity instead of RelativeDirection+Magnitude breakup

    private static void ApplyLift(SectionForceInput input)
    {
        Vector3 liftDirection = Vector3.Cross(input.sectionRelativeDirection, input.worldAxis);
        float   liftMagnitude = input.force * Mathf.Pow(input.efficiency, 2f);
        Vector3 lift          = liftDirection * liftMagnitude;

        input.section.Lift += lift;

        if (!input.body)
        {
            return;
        }
        input.body.AddForceAtPosition(lift, input.sectionWorldPosition);
    }
Esempio n. 4
0
    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;
                }
            }
        }
    }