Calculating Angular Velocity Needed to Travel a Certain Distance Via the Magnus Effect
up vote
0
down vote
favorite
Aight so I've been at this for several days and with how much it's slowing the project down I've made the hard decision to come beg the internet.
I'm working on a physics-based golf game in Unity and am working on implementing the magnus effect. This is my calculation for tangential force based on torque:
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);
}
This works well enough, but now I need to figure out the correct amount to give the ball to get this result:
Diagram of Desired Curve
I've tried several different approaches, and I've come to the conclusion that this is mostly comes down to trigonometry. Here is where I'm at currently (this is before the tangential direction is applied to the final velocity vector):
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);
}
Logic behind this
The result is very inconsistent based on xdir and V_BallForce, sometimes travels further, sometimes barely at all. This has been a pretty sobering adventure in discovering that I'm pretty bad at math.
If anyone has any advice for this issue I would forever be in your debt.
Update: Here is some visualization of the issue:
visualization
Update: I figured I should include a code sample of the function GetMagnusTorque is called from, to better put things in context:
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);
}
Update 11/21: I'm currently in the process of faking it through trial and error. But for those still interested in solving this anomaly, I may have found in issue in how I'm calculating the direction to apply the side-spin derived force to the ball. Hitting the ball with a lob wedge, which has a maximum distance of 70 yards and a loft angle of 60 deg, the desired curve looks something like this: Lob Wedge This obviously makes no sense, because the ball flies behind the golfer for a short period of time. I'll report back with the final numbers and calculations, though it will not answer the question it could help point it in the correct direction.
c# unity3d physics trigonometry
|
show 10 more comments
up vote
0
down vote
favorite
Aight so I've been at this for several days and with how much it's slowing the project down I've made the hard decision to come beg the internet.
I'm working on a physics-based golf game in Unity and am working on implementing the magnus effect. This is my calculation for tangential force based on torque:
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);
}
This works well enough, but now I need to figure out the correct amount to give the ball to get this result:
Diagram of Desired Curve
I've tried several different approaches, and I've come to the conclusion that this is mostly comes down to trigonometry. Here is where I'm at currently (this is before the tangential direction is applied to the final velocity vector):
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);
}
Logic behind this
The result is very inconsistent based on xdir and V_BallForce, sometimes travels further, sometimes barely at all. This has been a pretty sobering adventure in discovering that I'm pretty bad at math.
If anyone has any advice for this issue I would forever be in your debt.
Update: Here is some visualization of the issue:
visualization
Update: I figured I should include a code sample of the function GetMagnusTorque is called from, to better put things in context:
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);
}
Update 11/21: I'm currently in the process of faking it through trial and error. But for those still interested in solving this anomaly, I may have found in issue in how I'm calculating the direction to apply the side-spin derived force to the ball. Hitting the ball with a lob wedge, which has a maximum distance of 70 yards and a loft angle of 60 deg, the desired curve looks something like this: Lob Wedge This obviously makes no sense, because the ball flies behind the golfer for a short period of time. I'll report back with the final numbers and calculations, though it will not answer the question it could help point it in the correct direction.
c# unity3d physics trigonometry
1
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44
|
show 10 more comments
up vote
0
down vote
favorite
up vote
0
down vote
favorite
Aight so I've been at this for several days and with how much it's slowing the project down I've made the hard decision to come beg the internet.
I'm working on a physics-based golf game in Unity and am working on implementing the magnus effect. This is my calculation for tangential force based on torque:
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);
}
This works well enough, but now I need to figure out the correct amount to give the ball to get this result:
Diagram of Desired Curve
I've tried several different approaches, and I've come to the conclusion that this is mostly comes down to trigonometry. Here is where I'm at currently (this is before the tangential direction is applied to the final velocity vector):
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);
}
Logic behind this
The result is very inconsistent based on xdir and V_BallForce, sometimes travels further, sometimes barely at all. This has been a pretty sobering adventure in discovering that I'm pretty bad at math.
If anyone has any advice for this issue I would forever be in your debt.
Update: Here is some visualization of the issue:
visualization
Update: I figured I should include a code sample of the function GetMagnusTorque is called from, to better put things in context:
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);
}
Update 11/21: I'm currently in the process of faking it through trial and error. But for those still interested in solving this anomaly, I may have found in issue in how I'm calculating the direction to apply the side-spin derived force to the ball. Hitting the ball with a lob wedge, which has a maximum distance of 70 yards and a loft angle of 60 deg, the desired curve looks something like this: Lob Wedge This obviously makes no sense, because the ball flies behind the golfer for a short period of time. I'll report back with the final numbers and calculations, though it will not answer the question it could help point it in the correct direction.
c# unity3d physics trigonometry
Aight so I've been at this for several days and with how much it's slowing the project down I've made the hard decision to come beg the internet.
I'm working on a physics-based golf game in Unity and am working on implementing the magnus effect. This is my calculation for tangential force based on torque:
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);
}
This works well enough, but now I need to figure out the correct amount to give the ball to get this result:
Diagram of Desired Curve
I've tried several different approaches, and I've come to the conclusion that this is mostly comes down to trigonometry. Here is where I'm at currently (this is before the tangential direction is applied to the final velocity vector):
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);
}
Logic behind this
The result is very inconsistent based on xdir and V_BallForce, sometimes travels further, sometimes barely at all. This has been a pretty sobering adventure in discovering that I'm pretty bad at math.
If anyone has any advice for this issue I would forever be in your debt.
Update: Here is some visualization of the issue:
visualization
Update: I figured I should include a code sample of the function GetMagnusTorque is called from, to better put things in context:
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);
}
Update 11/21: I'm currently in the process of faking it through trial and error. But for those still interested in solving this anomaly, I may have found in issue in how I'm calculating the direction to apply the side-spin derived force to the ball. Hitting the ball with a lob wedge, which has a maximum distance of 70 yards and a loft angle of 60 deg, the desired curve looks something like this: Lob Wedge This obviously makes no sense, because the ball flies behind the golfer for a short period of time. I'll report back with the final numbers and calculations, though it will not answer the question it could help point it in the correct direction.
c# unity3d physics trigonometry
c# unity3d physics trigonometry
edited Nov 21 at 17:07
asked Nov 10 at 23:59
Jacob Sirotta
12
12
1
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44
|
show 10 more comments
1
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44
1
1
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44
|
show 10 more comments
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244613%2fcalculating-angular-velocity-needed-to-travel-a-certain-distance-via-the-magnus%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
This question eventually comes down to a coding problem. All of the 'physics' could have been easily abstracted while retaining the message.
– Taslim
Nov 11 at 0:22
I could be misinterpreting what you mean, but this seems to be the opposite to me. Given a formula for force over time based on torque, an initial torque must be set such that by the end of a time calculated from horizontal range and velocity, the projectile's velocity in the tangent direction is equal to negative its tangent velocity at the start.
– Jacob Sirotta
Nov 11 at 1:22
Is the problem 2D or 3D? It currently looks like a mixture of both, because although the velocity's Y-component is assumed to be zero, so is the angular velocity's Y-component. A 3D simulation has no such constraints, but the angular velocity should only have an effective Y-component in the 2D case.
– meowgoesthedog
Nov 11 at 19:03
Vertical spin is done separately, this is purely for side spin. angularVelocity.y is used because that is the axis for the side spin. Oh I see though, angularVelocity.z shouldn't be factored into the side-spin calculation. I'll update the code with this fix, but the main issue should persist since angularVelocity.z isn't applied on hit.
– Jacob Sirotta
Nov 11 at 21:34
The 2D top-down case is fairly simple - the ball travels in a circular arc; the 3D case, when gravity is taken into account, might not be analytical (you might need numerical integration).
– meowgoesthedog
Nov 12 at 10:44