Смущает порядок работы при использовании Matrix в XNA, C # - PullRequest
5 голосов
/ 29 января 2012

Вот два разных куска кода

Это то, с чего я начал

Vector2 hold = Vector2.Transform(pos1, mat1);
Matrix inv = Matrix.Invert(mat2);
Vector2 pos2 = Vector2.Transform(hold, inv);

И мне говорят, что это упрощенная версия

Matrix matrix1to2 = mat1 * Matrix.Invert(mat2);
Vector2 pos2 = Vector2.Transform(pos1, matrix1to2);

Чего я не понимаю, так это почему не первая строка в упрощенной версии

Matrix matrix1to2 = Matrix.Invert(mat2)*mat1;

Так как в матричном порядке вещь справа вступит в силу первой, а в оригинале мы умножим mat1 на первую

Edit: На следующем изображении показан порядок требуемых операций

http://www.riemers.net/images/Tutorials/XNA/Csharp/Series2D/mat1.png

В учебнике сказано, что для создания этого преобразования вы используете;

Matrix carriageMat = Matrix.CreateTranslation(0, -carriage.Height, 0) * Matrix.CreateScale(playerScaling) 
* Matrix.CreateTranslation(xPos, yPos, 0) * Matrix.Identity;

Почему это работает, если порядок слева направо?

1 Ответ

3 голосов
/ 29 января 2012

Так как в матричном порядке вещь справа вступит в силу первым и в оригинале мы имеем mat1, умноженный на первый

На самом деле, «вещь на слева » вступает в силу первой. Матрицы применяются к вершине в том же порядке, в котором вы их читали (при условии, что вы привыкли к латинскому языку).

В XNA вы обычно выполняете преобразования в порядке SRT (Scale, Rotate, Translate). Таким образом, объект будет масштабироваться и вращаться вокруг своего собственного источника (вращение на собственной оси) перед перемещением в мировое пространство.

Например: если бы я хотел повернуть объект на Pi / 2, переместить его на 100 единиц вдоль оси X, я мог бы использовать:

var rotate = Matrix.CreateRotationY(MathHelper.PiOver2);
var translate = Matrix.CreateTranslation(new Vector3(100,0,0));

var worldMatrix = rotate * translate;

Если вместо этого я хотел переместить объект на 100 единиц вправо, то поверните его вокруг начала координат мира (0,0,0), чтобы получить своего рода эффект орбиты (вместо вращения, как это было сделано в первом пример), я бы использовал

var worldMatrix = translate * rotate;

Вы также можете вращать объект вокруг своей оси, перемещать его на 100 единиц вдоль мировой оси X, вращать его вокруг начала мира с помощью:

var worldMatrix = rotateSpin * translate * rotateOrbit;

, где rotateSpin и rotateOrbit - матрицы вращения, определяющие ваше вращение (вращение вокруг источника объекта) и орбиту (вращение вокруг мира после перевода), соответственно. Обратите внимание, что порядок, в котором операции влияют на ваши сервисные вершины, слева направо.

...