Масштабирование пользовательского класса матрицы по вектору - PullRequest
0 голосов
/ 28 ноября 2010

У меня ужасно с математикой, но у меня есть ситуация, когда мне нужно масштабировать один.Матрица является экземпляром пользовательского класса , определенного здесь , а мой масштабирующий объект - это вектор, содержащий 3 числа с плавающей запятой (x, y, z).Я хотел бы получить нужный мне код, а не общее объяснение, потому что я уже пошел по этому пути и просто не понимаю математики.К счастью, то, что я пытаюсь выполнить, достаточно тривиально, когда я могу масштабировать матрицу.

Чтобы пояснить, вот код, который я обновляю.Он выполняет итерацию по иерархии связанных объектов с относительными преобразованиями и обновляет их в соответствии с абсолютным преобразованием:

void LocalModelPiece::GetPiecePosIter(CMatrix44f* mat) const
{
if (parent) {
    parent->GetPiecePosIter(mat);
}

if (pos.x || pos.y || pos.z) { mat->Translate(pos.x, pos.y, pos.z); }
// --> My problem is here. There is no Scale() method, I need one. <--
if (scale.x!=1.0f || scale.y!=1.0f || scale.z!=1.0f) { mat->Scale(scale.x, scale.y, scale.z); }
if (rot[1]) { mat->RotateY(-rot[1]); }
if (rot[0]) { mat->RotateX(-rot[0]); }
if (rot[2]) { mat->RotateZ(-rot[2]); }

}

Ответы [ 2 ]

2 голосов
/ 28 ноября 2010

Мне не понятно, что вы хотите масштабировать. Это сама матрица или вы собираетесь использовать ее для масштабирования другого вектора?

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

Вы путаете меня, когда ссылаетесь на матрицу 4x4. Вы уверены, что это то, что вы хотите?

Я думаю, вы хотите это:

alt text

Вот некоторый псевдокод, чтобы показать, как это делается:

for (int i = 0; i < 3; ++i)
{
    v_prime[i] = c[i]*v[i];
}

Если вы хотите масштабировать матрицу 3x3, она будет выглядеть так:

alt text

Вот некоторый псевдокод, чтобы показать, как это делается:

for (int i = 0; i < 3; ++i)
{
    for (int j = 0; j < 3; ++j)
    {
        m_prime[i][j] = c[i]*m[i][j];
    }
}

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

0 голосов
/ 28 ноября 2010

Я посмотрел на предоставленную вами ссылку API, и, исходя из этого, я бы реализовал метод масштабирования для класса матрицы, чтобы он соответствовал существующим методам Translate () и Rotate (). То есть он выполняет умножение в правой части с масштабирующей матрицей.

Хотя лично я нахожу это немного странным, потому что API использует матрицы стилей OpenGL. Это означает, что умножение в правой части применяет новое преобразование перед всеми другими преобразованиями, существующими в матрице, тогда как умножение в левой части применяет его после других преобразований. Так что я не уверен, что ты здесь этого хочешь. Возможно, вам придется выполнить все преобразования в обратном порядке или выполнить умножение влево самостоятельно.

void CMatrix44f::Scale(float scalex, float scaley, float scaley) 
{
  /* the function should be equivalent to doing this:
  CMatrix44f scalemat;
  scalemat[0] = scalex;
  scalemat[5] = scaley;
  scalemat[10] = scalez;
  *this = Mul(scalemat);
  */

  m[0] *= scalex;
  m[1] *= scalex;
  m[2] *= scalex;
  m[3] *= scalex;

  m[4] *= scaley;
  m[5] *= scaley;
  m[6] *= scaley;
  m[7] *= scaley;

  m[8] *= scalez;
  m[9] *= scalez;
  m[10] *= scalez;
  m[11] *= scalez;
}
...