2009-03-11 2 views
8

Хорошо, это то, что должно быть простым матричным вопросом, но мое понимание матриц несколько ограничено. Вот сценарий: у меня есть спрайт 1px на 1px, который я хочу масштабировать на некоторую величину x и y (разные суммы на каждой стороне), а затем я хочу повернуть этот спрайт на какой-то угол, а затем я хочу, чтобы точно позиционируйте все это (из верхнего левого или центра, не имеет для меня никакого значения).Как повернуть, масштабировать и перевести матрицу сразу на C#?

Пока мой код неопределенно близко, но он имеет тенденцию быть смещена на некоторую случайную величину в зависимости от угла я прохожу в

Я думаю, что это будет сделать это:.

 Point center = new Point(50, 50); 
     float width = 60; 
     float height = 100; 
     float angle = 0.5; 
     Vector3 axis = new Vector3(center.X, center.Y, 0); 
     axis.Normalize(); 
     Matrix m = Matrix.Scaling(width, height, 0) * 
      Matrix.RotationAxis(axis, angle) * 
      Matrix.Translation(center.X, center.Y, 0); 

Но он имеет тенденцию уменьшать масштаб повернутой линии вниз, хотя я думаю, что это правильно позиционирует.

Я также попытался это:

Matrix m = Matrix.Transformation2D(new Vector2(center.X, center.Y), 0f, 
     new Vector2(width, height), new Vector2(center.X, center.Y), 
     angle, Vector2.Zero); 

линия выглядит точно так, с точным нужного размера и формы, но я не могу расположить его правильно на всех. Если я использую вектор трансляции в конце вышеперечисленного вызова или если я устанавливаю позицию с помощью Sprite.Draw, то ни один из них не работает правильно.

Это все в SlimDX. Что я делаю не так?

ответ

12

Я просто пережил боль обучения трансформации матрицы, но используя XNA.

Я нашел thesearticlestobevery полезно в понимании того, что происходит. Вызов метода очень похож на XNA, и теория, лежащая в основе всего этого, должна применяться к вам, даже с SlimDX.

От взгляда на ваш код, я думаю, вы должны переводить в начале, в начало координат, а затем снова переводить в конце, в конечную позицию, хотя я все еще немного новичок в этом также.

заказ я хотел бы сделать это в это:

  • Перевести на происхождение
  • Scale
  • Поворот
  • Перевести на нужное место

Причина для перевода в начало координат первое, что вращения основаны на происхождении. Поэтому, чтобы повернуть что-то примерно в определенную точку, поместите эту точку на начало координат перед вращением.

+1

Хм ... это похоже очень близко. Переводы в исходные, масштабные и вращающиеся шаги работают отлично, но затем, когда я пытаюсь перевести в нужное место, он действует очень странно - я меняю x coodinate, и он перемещается как в x, так и в y. Я думаю, что он переводится во вращающееся пространство ... – x4000

+0

Еще одна вещь, которая еще не ясна для меня, - это перевести на начало. У меня есть две точки, плюс одна треть, которая находится в центре их. Я переводил центр в начало, но должен ли я переводить по-другому? – x4000

+1

Вместо того, чтобы переводить туда, где вы хотите, можете ли вы просто изменить положение, где вы рисуете? –

1

Что вам нужно сделать, это сделать каждое преобразование одним шагом за раз. Сначала сделайте масштабирование. Это то, где вы ожидаете этого. Затем бросьте поворот, а затем переведите. Это поможет выявить неверные предположения.

Вы также можете нарисовать временные строки, чтобы помочь определить координаты. Например, если вы делаете свое растяжение и вращение и ожидаете, что ваша конечная точка будет равна 0,0. Рисование другой линии с одной конечной точкой в ​​0,0 будет служить двойной проверкой, чтобы убедиться, что это действительно так.

Для вашей конкретной проблемы проблема может быть связана с вращением. После того, как вы масштабировали и вращали линию, теперь вы находитесь в центре, вызывая проблемы при переводе.

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

ОТВЕТ НА КОММЕНТАРИИ

Если перевод является проблемой, и вы трансформируют систему координат, то вам нужно будет написать функцию преобразования для преобразования между старой системой и новой.

Например, если вы вращаетесь на 45 градусов. Перед вращением вы можете перевести на 0,1 на 1 дюйм. После поворота вам придется перевести примерно -70707, .070707, чтобы подняться на 1 дюйм относительно исходной системы координат.

+0

Я уже пробовал делать каждую часть отдельно - я должен был упомянуть об этом. Масштабирование и перевод работают отлично. Но, как вы говорите, когда я добавляю ротацию, он уходит. И да, у меня есть значки в контрольных точках, поэтому я могу видеть, насколько я близка. Сейчас я попытаюсь компенсировать это. – x4000

+0

Вращение беспорядочно, так как оно вращается вокруг источника. –

+0

Теперь я попытался вернуться к происхождению, а затем перевести обратно туда, где хочу. Кажется, это близко, но перевод выключен, потому что он переводится внутри вращенного координатного пространства. – x4000

1

Вы вращаетесь вокруг правильной оси? Я новичок в матричном материале, но мне кажется, что поскольку спрайт существует в пространстве x, y, ось вращения должна быть Z-осью - то есть (0,0,1).

+0

Хм, это хороший момент, но мой поворот, кажется, отлично работает, когда я просто делаю масштабирование, и это - проблема возникает, когда я затем пытаюсь ее позиционировать. Я могу сделать любые два из этих трех работ, но есть что-то, что я делаю неправильно, когда все это вместе! – x4000

+0

Эй, хороший улов с осью Z - с моим первым примером выше, это весьма актуально. – x4000

3

Хорошо, теперь это работает. Вот мой рабочий код для этого, в случае, если кто-то это нужно:

Point sourceLoc = new Point (50, 50); 
    float length = 60; 
    float thickness = 2; 
    float angle = 0.5; 
    Matrix m = Matrix.Scaling(length, thickness, 0) * 
      Matrix.RotationZ(angle) * 
      Matrix.Translation(sourceLoc.X, sourceLoc.Y, 0); 
    sprite.Transform = m; 

    sprite.Draw(this.tx, Vector3.Zero, Vector3.Zero, Color.Red); 

Это привлечет наклонную линию выбранной длины, с толщиной, равной выбранной толщиной (предполагая текстуру является 1x1 пикселями белого изображения). Место источника - это место, из которого будет излучаться линия, с любым углом, который вы указываете (в радианах). Поэтому, если вы начинаете с нуля и увеличиваете примерно на 0,1, пока не нажмете 2PI, а затем сбросьте на 0, у вас будет линия, которая вращается вокруг центра, например, в руке часов или радаре. Это то, что я искал - благодаря всем, кто внес свой вклад!

Смежные вопросы