Vector3.magnitude and vector3.normalized explanation - c#

I am looking at this code and do not know what is this magnitude and normalizeddoing and how is this guy using them. In documentation there is only few thing but it doesn't explain much.
Code i am looking at is:
public float minDistance = 1.0f;
public float maxDistance = 4.0f;
public float smooth = 10.0f;
Vector3 dollyDir;
public Vector3 dollyDirAdjusted;
public float distance;
void Awake()
{
dollyDir = transform.localPosition.normalized;
//What has he got with this? Documentation says Returns this vector with
//a magnitude of 1 so if i get it it return's it's length as 1. So what is the point?
distance = transform.localPosition.magnitude;
//Have no idea what he got with this
}
void Update()
{
Vector3 desiredPos = transform.parent.TransformPoint(dollyDir * maxDistance);
//I know what TransfromPoint does but what is he getting with this dollyDir * maxDistance
//Some other code which i understand
}
And while i am here if someone could explain me Mathf.Clamp
Documentation for clamp is so unclear and how i got it is that i give top and bottom value 1 and 5 and if i set value = 3 it will return 3, but if i set value > 5 it will return 5 and if i set value < 1 it will return 1?
Thanks.

Vector3.magnitude returns a float, its a single dimensional value expressing vector length (so it looses directional information)
Vector3.normalized is a bit of an opposite operation - it returns vector direction, guaranteeing that the magnitude of the resulting vector is one, (it preserves the direction information but looses the magnitude information).
The two are often useful for when you want to seperate those two ways of looking at a vector, for example if you need to have an influcence between two bodies where the influence is inversly proportional to the distance between them, you can do
float mag=(targetpos-mypos).magnitude;
if (mag<maxRange)
{
Vector3 dir=(targetpos-mypos).normalized;
Vector3 newVector=dir*(maxRange-mag);
}
this is the most typical use case for me, I am not sure what the author of the original code meant by his as it does seem he could just use a vector difference without using the two extra calls
Mathf.Clamp returns value of value lies between min and max, returns min if its lower and max if is greater.
Another interesting feature of Vector3 is sqrMagnitude which returns a^2+b^2+c^c without computhing the square root. While it adds a bit to the complexity to the code (you need to compare it with squared distance), it saves a relatively expensive root computation; The slightly optimised but a tiny bit harder to read version would look like this
Vectior3 delta=targetpos-mypos;
if (delta.sqrMagnitude<maxRange*maxRange)
{
Vector3 dir=delta.normalized;
Vector3 newVector=dir*(maxRange-delta.magnitude);
}

A vector can be thought of as a direction and distance (although it is normally expressed as an amount in each axis; for example, +3 on x and -4 on y would have a magnitude of 5). A normalized vector has magnitude 1, so it is just the direction (+0.6,-0.8 for the +3,-4 example); the magnitude tells you the original distance part. You can then multiply a normalized vector (the direction) by any magnitude to express "go this far in that direction". In this case, they seem to be moving 4 units (maxDistance) in the same direction as the original vector.

A magnitude is the length of a vector from the origin. It is like using a tape measure from (0,0,0) to wherever your point is. A normalized vector is that same vector, but its length is exactly 1.
An important note is that the normalized vector is calculated is by dividing by its magnitude.

Related

Calculating the speed a sprite changes size based on the distance it needs to travel and speed it is travelling

I am doing some sprite scaling and have a sprite starting at scale 0.2 on the x+y axis it travels at a constant speed (10) between its start point and end point increasing in scale as it travels.
I need it to scale evenly across that distance so that when it reaches its end point it is at its final scale (0.2 - 1).
Now because the distance changes based on where it spawns the time that it takes to scale in size must also change so that it can scale evenly across the distance, what I need is the calculation to work out the 'scale speed' based on the distance it is traveling and speed the item is moving.
I'm getting the distance between the two points with Vector3.Distance
distance = Vector2.Distance(transform.position, centerScreen);
This scales the object over time
if (transform.localScale.x < 1 && transform.localScale.y < 1)
{
transform.localScale = new Vector3(transform.localScale.x + scaleSpeed * Time.deltaTime, transform.localScale.y + scaleSpeed * Time.deltaTime, 1);
}
and the object moves at a speed of 10
My question is, How do I calculate the scale speed based on the distance and speed the object is traveling?
In Unity, there is a function called InverseLerp, which creates a point from 0 - 1 based on how far the value v is between the values a and b. It is the opposite of the Lerp function. (https://docs.unity3d.com/ScriptReference/Mathf.InverseLerp.html).
Here is example code for your situation: float sizeVal = Mathf.InverseLerp(0, yourSetDistance, distance) * 0.8f + 0.2f;
This changes the range of the inverse lerp to between 0.2 and 1. Use the sizeVal in the size vector. If this isn't what you wanted, please explain in more detail or restate your question.

Find Angle Between Two Vectors

I have read some of the duplicate answers about angle between two vectors, but I'm still stuck with my problem. I have two vectors and I want that the angle between them to always be 90 degrees. To achieve that I need to find the angle between them, so that I can subtract or add the correct amount of degrees so that the angle between them always is 90 degrees.
The picture illustrates a sprite and two vectors. How do I find the angle A between them two? I have tried to use this code to get the angle between two vectors, but I must have missed something out, because I don't get the correct results:
public float GetAngleBetween (Vector2 A, Vector2 B)
{
float DotProd = Vector2.Dot (A, B);
float Length = A.Length () * B.Length ();
return (float)MathHelper.ToDegrees ((float)Math.Acos (DotProd/Length));
}
Any input is welcome and thank you in advance for any answers.
The actual angle in radians is
Math.ACos(Vector2.Dot(a, b));
Make sure that a and b are normalized vectors or the results can get pretty weird.
I think you may be looking for the Vector2.Dot method which is used to calculate the product of two vectors, and can be used for angle calculations.
For example:
// the angle between the two vectors is less than 90 degrees.
Vector2.Dot(vector1.Normalize(), vector2.Normalize()) > 0
// the angle between the two vectors is more than 90 degrees.
Vector2.Dot(vector1.Normalize(), vector2.Normalize()) < 0
// the angle between the two vectors is 90 degrees; that is, the vectors are orthogonal.
Vector2.Dot(vector1.Normalize(), vector2.Normalize()) == 0
// the angle between the two vectors is 0 degrees; that is, the vectors point in the same direction and are parallel.
Vector2.Dot(vector1.Normalize(), vector2.Normalize()) == 1
// the angle between the two vectors is 180 degrees; that is, the vectors point in opposite directions and are parallel.
Vector2.Dot(vector1.Normalize(), vector2.Normalize()) == -1
Is this what you're looking for, or do you need the exact angle?
If I understand your question diagram and comments, the Dot product and Acos are not the only bits of info you need. You also need to account for when the sprite is not located at (0,0).
float angleInRadians = (float) Math.Acos(Vector2.Dot(Vector2.Normalize(vector1 - spritePosition), Vector2.Normalize(vector2 - spritePosition)));
int angleInDegrees = MathHelper.ToDegrees(angleInRadians);

Shortest distance from a point to this curve

I need to find the distance of multiple points to a curve of the form: f(x) = a^(k^(bx))
My first option was using its derivative, using a line of the form with the inverse of the derivative, giving it coordinates of the Point and intersecting it with the original curve. Finally, we calculate the distance between points with simple geometry.
That's the mathematical process that I usually follow. I need to save time (since I'm doing a genetic algorithms program) so I need an efficient way to do this. Ideas?
The distance between a point (c,d) and your curve is the minimum of the function
sqrt((c-x)^2 + (d-a^(k^(bx)))^2)
To find its minimum, we can forget about the sqrt and look at the first derivative. Find out where it's 0 (it has to be the minimal distance, as there's no maximum distance). That gives you the x coordinate of the nearest point on the curve. To get the distance you need to calculate the y coordinate, and then calculate the distance to the point (you can just calculate the distance function at that x, it's the same thing).
Repeat for each of your points.
The first derivative of the distance function, is, unfortunately, a kind of bitch. Using Wolfram's derivator, the result is hopefully (if I haven't made any copying errors):
dist(x)/dx = 2(b * lna * lnk * k^(bx) * a^(k^(bx)) * (a^(k^(bx)) - d) - c + x)
To find distance from point to curve it's not a simple task, for that you need to find the global of function where f(x) is the function which determine your curve.
For that goal you could use:
Simplex method
Nelder_Mead_method
gradient_descent
This methods implemented in many libraries like Solver Foundation, NMath etc.

How does one know if a normal vector is between two angles?

I have a Max Angle and a Min Angle, and also a unit vector pointing in some direction (2D).
How do I find out if this normal vector is between the two angles?
I don't know c#, but I know math:
Suppose the vector's coordinates are (x,y), and it is a unit vector, so |(x,y)| = 1.
The angle a between the positive x-axis and the vector is
a = atan2(y,x)
where atan2 is the four-quadrant arctangent. You can then check if this angle is between your max and min angles (provided they are also defined with respect to the positive x-axis).
Note that a is in radians; if your angles are given in degrees, you should first compute
a = a*180/pi;
where pi = 3.1415..... of course.
Does this help at all?
Calculate the angle from the dot product (this is easy in 2d) and then compare to your angle range.

When to Normalize a Vector?

I am learning XNA and in almost all of the educational kits found on http://creators.xna.com/en-US/. I always see a call to Normalize() on a vector. I understand that normalize basically converts the vector into unit length, so all it gives is direction.
Now my question is When to normalize and what exactly does it help me in. I am doing 2D programming so please explain in 2D concepts and not 3D.
EDIT: Here is code in the XNA kit, so why is the Normalize being called?
if (currentKeyboardState.IsKeyDown(Keys.Left)
|| currentGamePadState.DPad.Left == ButtonState.Pressed)
{
catMovement.X -= 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Right)
|| currentGamePadState.DPad.Right == ButtonState.Pressed)
{
catMovement.X += 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Up)
|| currentGamePadState.DPad.Up == ButtonState.Pressed)
{
catMovement.Y -= 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Down)
|| currentGamePadState.DPad.Down == ButtonState.Pressed)
{
catMovement.Y += 1.0f;
}
float smoothStop = 1;
if (catMovement != Vector2.Zero)
{
catMovement.Normalize();
}
catPosition += catMovement * 10 * smoothStop;
In your example, the keyboard presses give you movement in X or Y, or both. In the case of both X and Y, as when you press right and down at the same time, your movement is diagonal. But where movement just in X or Y alone gives you a vector of length 1, the diagonal vector is longer than one. That is, about 1.4 (the square root of 2).
Without normalizing the movement vector, then diagonal movement would be faster than just X or Y movement. With normalizing, the speed is the same in all 8 directions, which I guess is what the game calls for.
One common use case of vector normalization when you need to move something by a number of units in a direction. For example, if you have a game where an entity A moves towards an entity B at a speed of 5 units/second, you'll get the vector from A to B (which is B - A), you'll normalize it so you only keep the direction toward the entity B from A's viewpoint, and then you'll multiply it by 5 units/second. The resulting vector will be the velocity of A and you can then simply multiply it by the elapsed time to get the displacement by which you can move the object.
It depends on what you're using the vector for, but if you're only using the vectors to give a direction then a number of algorithms and formulas are just simpler if your vectors are of unit length.
For example, angles: the angle theta between two unit vectors u and v is given by the formula cos(theta) = u.v (where . is the dot product). For non-unit vectors, you have to compute and divide out the lengths: cos(theta) = (u.v) / (|u| |v|).
A slightly more complicated example: projection of one vector onto another. If v is a unit vector, then the orthogonal projection of u onto v is given by (u.v) v, while if v is a non-unit vector then the formula is (u.v / v.v) v.
In other words: normalize if you know that all you need is the direction and if you're not certain the vector is a unit vector already. It helps you because you're probably going to end up dividing your direction vectors by their length all the time, so you might as well just do it once when you create the vector and get it over with.
EDIT: I assume that the reason Normalize is being called in your example is so that the direction of velocity can be distinguished from the speed. In the final line of the code, 10 * smoothStop is the speed of the object, which is handy to know. And to recover velocity from speed, you need to multiply by a unit direction vector.
You normalize any vector by dividing each component by the magnitude of the vector, which is given by the square root of the sum of squares of components. Each component then has a magnitude that varies between [-1, 1], and the magnitude is equal to one. This is the definition of a unit vector.

Categories

Resources