Когда нормализовать вектор?
Я изучаю XNA и почти во всех обучающих наборах, найденных на http://creators.xna.com/en-US/. Я всегда вижу вызов Normalize() для вектора. Я понимаю, что нормализация в основном преобразует вектор в единицу длины, поэтому все это дает направление.
Теперь мой вопрос: когда нормализовать и что именно мне это помогает. Я занимаюсь 2D-программированием, поэтому, пожалуйста, объясните в 2D-концепциях, а не в 3D.
EDIT: вот код в наборе XNA, так почему называется Normalize?
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;
}
Ответы
Ответ 1
В вашем примере нажатия клавиш дают вам движение в X или Y, или и то, и другое. В случае как X, так и Y, как при одновременном нажатии вправо и влево, ваше движение диагонально. Но когда движение только в X или Y дает вам вектор длины 1, диагональный вектор длиннее одного. То есть около 1,4 (квадратный корень из 2).
Без нормализации вектора движения, диагональное движение будет быстрее, чем просто движение X или Y. При нормализации скорость одинакова во всех 8 направлениях, и я думаю, это то, что требует игра.
Ответ 2
Один общий вариант использования векторной нормализации, когда вам нужно что-то переместить на несколько единиц в направлении. Например, если у вас есть игра, в которой объект A перемещается к объекту B со скоростью 5 единиц в секунду, вы получите вектор от A до B (который равен B - A
), вы нормализуете его так вы только сохраняете направление к объекту B с точки зрения, а затем умножаете его на 5 единиц в секунду. Результирующим вектором будет скорость A, и вы можете просто умножить его на прошедшее время, чтобы получить смещение, с помощью которого вы можете перемещать объект.
Ответ 3
Это зависит от того, для чего вы используете вектор, но если вы используете только векторы, чтобы дать направление, то ряд алгоритмов и формул проще, если ваши векторы имеют единую длину.
Например, углы: угол theta
между двумя единичными векторами u
и v
определяется формулой cos(theta) = u.v
(где .
является точечным произведением). Для неединичных векторов вам необходимо вычислить и разделить длины: cos(theta) = (u.v) / (|u| |v|)
.
Несколько более сложный пример: проекция одного вектора на другой. Если v
- единичный вектор, то ортогональная проекция u
на v
задается выражением (u.v) v
, а если v
- неединичный вектор, то формула (u.v / v.v) v
.
Другими словами: нормализовать, если вы знаете, что все, что вам нужно, - это направление, и если вы не уверены, что вектор уже является единичным вектором. Это помогает вам, потому что вы, вероятно, в конечном итоге разделите свои векторы направления по их длине все время, поэтому вы можете просто сделать это один раз, когда вы создадите вектор и перейдете к нему.
EDIT: Я предполагаю, что причина Normalize вызывается в вашем примере, так что направление скорости можно отличить от скорости. В последней строке кода 10 * smoothStop
- скорость объекта, что удобно знать. Чтобы восстановить скорость со скоростью, вам нужно умножить на единичный вектор направления.
Ответ 4
Вы нормализуете любой вектор, разделив каждый компонент на величину вектора, который задается квадратным корнем из суммы квадратов компонентов. Затем каждый компонент имеет величину, которая изменяется между [-1, 1], а величина равна единице. Это определение единичного вектора.