Расчет угловой скорости, необходимой для перемещения на определенное расстояние с помощью эффекта Магнуса - PullRequest
0 голосов
/ 11 ноября 2018

Отлично, так что я занимался этим несколько дней, и из-за того, насколько он замедляет проект, я принял трудное решение просить Интернет. Я работаю над основанной на физике игрой в гольф в Unity и работаю над реализацией эффекта магнуса. Это мой расчет тангенциальной силы на основе крутящего момента:

    void FixedUpdate()
        {
            float _BallRadius = .0427f;
            float _halfmass = Mathf.Sqrt(_BallRadius*.5f );
            float _vv = new Vector3(GetComponent<Rigidbody>().velocity.x, 0, 
            GetComponent<Rigidbody>().velocity.z).magnitude;
            //MAGNUS FORMULA (SIDESPIN ONLY)//
            float _mag = -((1.429f * Mathf.Abs(_vv)* (2 * Mathf.PI * _halfmass * 
            GetComponent<Rigidbody>().angularVelocity.y))) * (_BallRadius * .5f);
            Vector3 _xmagdir = new Vector3(GetComponent<Rigidbody>().velocity.x, 0, GetComponent<Rigidbody>().velocity.z);     
GetComponent<Rigidbody().AddForce(Vector3.Cross(_xmagdir.normalized,Vector3.up)*_mag, ForceMode.Acceleration);
        }

Это работает достаточно хорошо, но теперь мне нужно вычислить правильную сумму, чтобы дать мяч, чтобы получить такой результат: Диаграмма желаемой кривой

Я пробовал несколько разных подходов и пришел к выводу, что это в основном сводится к тригонометрии. Вот где я сейчас нахожусь (это до того, как тангенциальное направление будет применено к конечному вектору скорости):

Vector3 GetMagnusTorque(float Distance, Vector3 V_BallForce, float xdir)
{
    float _BallRadius = .0427f;
    float _halfmass = Mathf.Sqrt(_BallRadius*.5f);
    Vector3 v = GO_Camera.transform.InverseTransformDirection(V_BallForce);
    float HorizontalRange = Distance;
    //THIS IS THE LATERAL DISTANCE WE NEED TO TRAVEL//
    float opposite = (Mathf.Abs(Mathf.Tan(Mathf.Deg2Rad * xdir))) * (HorizontalRange*.5f);
    //THIS IS THE TIME IT WILL NEED TO TAKE//
    float time = ((2 * v.magnitude * Mathf.Sin((2 * (v.normalized.y )))) / -Physics.gravity.y);
    //THIS IS THE SPEED THE MAGNUS EFFECT WILL NEED TO PRODUCE//
    float linearSpeed =Mathf.Abs((opposite/time))*Mathf.Sign(xdir)Mathf.Abs((opposite/time))*Mathf.Sign(xdir)*(Time.timeScale+Time.fixedDeltaTime);
    return GO_Camera.transform.TransformDirection((((linearSpeed /( 2 * Mathf.PI * _halfmass * (_BallRadius * .5f))) / 1.429f))*Mathf.Deg2Rad*GO_PGolfBall.transform.up);
}

Логика позади этого

Результат очень противоречивый, основанный на xdir и V_BallForce, иногда продвигается дальше, а иногда и вовсе. Это было довольно отрезвляющее приключение, когда я обнаружил, что я довольно плохо разбираюсь в математике. Если у кого-нибудь есть какие-либо советы по этому вопросу, я всегда буду у вас в долгу.

Обновление: вот некоторая визуализация проблемы: визуализация

Обновление: я решил, что должен включить пример кода функции, из которой вызывается GetMagnusTorque, чтобы лучше понять ситуацию:

 void BallApplyForce()
    {
        //_rmult is a [0,1] value that is dependent on the accuracy of the player's swing//
        float _rmult = GetRMult();
        //GETS BALL READY BY ENABLING PHYSICS AND SETTING ITS ROTATION TO THE CAMERA//
        GO_PGolfBall.transform.rotation = new Quaternion(0, GO_Camera.transform.rotation.y, GO_Camera.transform.rotation.z, GO_Camera.transform.rotation.w);
        GO_PGolfBall.GetComponent<SCR_GOLFBALLCONTROL>().B_PhysicsActive = true;
        //YDIR = PITCH, XDIR = YAW. V_ContactPoint is a [-1,1] Vector2 used similar to Mario Golf//
        Vector3 _vdir = Vector3.zero;
        float ydir = ((Mathf.Rad2Deg * DIC_Clubs[I_CurrentClub].LandAngle) + (-2.5f * (.1f) * (DIC_Clubs[I_CurrentClub].LoftAngle * Mathf.Rad2Deg)));
        float _xdir = Mathf.Rad2Deg * (-(V_ContactPoint.x) * (DIC_Clubs[I_CurrentClub].LoftAngle)*3f);

        _vdir.y = ydir;
        _vdir = _vdir.normalized;
        _vdir.y *= Mathf.Rad2Deg;

        //MAX DISTANCE OF THE CLUB BEING USED TO METERS//
        float _dist = ((DIC_Clubs[I_CurrentClub].MaxDistance * F_UPower) * _rmult) * .9144f;

        //GET FORWARD AND UPWARDS VELOCITIES BASED ON THE DISTANCE GIVEN, XDIR ISN'T FACTORED FOR NOW//
        float Vi = Mathf.Sqrt(_dist * -Physics.gravity.y / (Mathf.Sin(Mathf.Deg2Rad * _vdir.y * 2)));
        float Vy, Vz;
        Vy = Vi * Mathf.Sin(Mathf.Deg2Rad*_vdir.y);
        Vz = Vi * Mathf.Cos(Mathf.Deg2Rad*_vdir.y);
        GO_Camera.transform.eulerAngles = new Vector3(0, GO_Camera.transform.eulerAngles.y, 0);
        Vector3 _velo = GO_Camera.transform.TransformVector(new Vector3(0f, Vy, Vz));

        //CALCULATE VERTICAL ANGULAR VELOCITY, THIS DOESNT NEED TO FOLLOW ANY SORT OF PATTERN FOR NOW//
        float _verRoll = Mathf.Sign(V_ContactPoint.y - .1f) * ((.7135f) * _dist) * Mathf.Sin(DIC_Clubs[I_CurrentClub].LoftAngle +
            ((Mathf.Abs(V_ContactPoint.y + .1f)) * (DIC_Clubs[I_CurrentClub].LaunchAngle))) * 60 * Mathf.Deg2Rad;
        GO_PGolfBall.GetComponent<Rigidbody>().AddTorque(Vector3.Scale(GO_PGolfBall.transform.right, new Vector3(1, 0, 0)) * _verRoll, ForceMode.VelocityChange);
        //CALCULATE HORIZONTAL ANGULAR VELOCITY//
        Debug.Log("MAGNUS CALC:" + GetMagnusTorque(_dist, _velo, _xdir));
        GO_PGolfBall.GetComponent<Rigidbody>().AddTorque(GetMagnusTorque(_dist, _velo, _xdir), ForceMode.VelocityChange);

        //APPLY XDIR TO THE CAMERA ANGLE AND RECALCULATE VELOCITY//
        GO_Camera.transform.eulerAngles = new Vector3(0, GO_Camera.transform.eulerAngles.y+_xdir, 0);
        _velo = GO_Camera.transform.TransformVector(new Vector3(0f, Vy, Vz));

        //APPLY VELOCITY//
        GO_PGolfBall.transform.GetComponent<Rigidbody>().AddForce(_velo, ForceMode.VelocityChange);
    }

Обновление 11/21: в настоящее время я подделываю его методом проб и ошибок. Но для тех, кто все еще заинтересован в решении этой аномалии, я, возможно, нашел вопрос в том, как я рассчитываю направление, чтобы применить к мячу силу, полученную из бокового вращения. Удар по мячу с помощью лопастного клина, который имеет максимальное расстояние 70 ярдов и угол наклона 60 градусов, искомая кривая выглядит примерно так: Клин лопасти Это, очевидно, не имеет смысла, потому что шар летит позади игрока в гольф на короткий период времени. Я сообщу об окончательных числах и расчетах, хотя это не ответит на вопрос, это могло бы помочь указать это в правильном направлении.

...