按向量缩放自定义矩阵类

发布于 2024-10-05 12:42:07 字数 831 浏览 0 评论 0原文

我对矩阵数学很糟糕,但我遇到了需要缩放矩阵的情况。该矩阵是此处定义的自定义类的实例,我的缩放对象是包含 3 个浮点数 (x,y,z) 的向量。我想要我需要的实际代码,而不是通用的解释,因为我已经走上了这条路,只是不理解所涉及的数学。幸运的是,一旦我可以扩展矩阵,我想要完成的事情就相当微不足道了。

为了澄清这里是我正在更新的代码。它通过相对变换迭代链接对象的层次结构并更新 mat&到绝对变换:

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]); }

}

I'm terrible with matrix maths but I have a situation where I need to scale one. The matrix is an instance of a custom class defined here and my scaling object is a vector containing 3 floats (x,y,z). I'd like the actual code I need rather than a generic explanation because I've already gone down that path and just don't understand the maths involved. Fortunately what I'm trying to accomplish is reasonably trivial once I can scale the matrix.

To clarify here is the code I'm updating. It iterates over a hierarchy of linked objects with relative transforms and updates mat& to an absolute transform:

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]); }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末骤雨初歇 2024-10-12 12:42:07

我不清楚你想要扩展什么。是矩阵本身,还是打算用它来缩放另一个向量?

如果你谈论的是 3D 空间中的向量,我不明白 4x4 矩阵如何能成为你想要的。使用矩阵在 3D 空间中缩放向量意味着将缩放因子放在矩阵的对角线上;非对角线元素为零。

当你链接到 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];
    }
}

请注意,这些解决方案是根据您的声明得出的,您的缩放向量具有三个组成部分。如果情况并非如此,那么一切都将失败。

It's not clear to me what you wish to scale. Is it the matrix itself, or do you intend to use it to scale another vector?

If you're talking about a vector in 3D space, I don't see how a 4x4 matrix can be what you want. Scaling a vector in 3D space using a matrix would mean putting the scaling factors on the diagonal of the matrix; off-diagonal elements are zero.

You confuse me when you link to a 4x4 matrix. Are you sure that's what you want?

I think you want this:

alt text

Here's some pseudo-code to show how it's done:

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

If you want to scale a 3x3 matrix, it'd look like this:

alt text

Here's some pseudo-code to show how it's done:

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

Note that both of these solutions follow from your statement that your scaling vector has three components. If that's not the case, all bets are off.

烟火散人牵绊 2024-10-12 12:42:07

我查看了您提供的 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;
}

I looked at the API link you provided, and based on that, this is how I would implement a scaling method for the matrix class so that it's consistent with the existing Translate() and Rotate() methods. That is, it does a right side multiplication with a scaling matrix.

Though personally I find it a bit weird, because the API uses OpenGL style matrices. That means that a right side multiplication applies the new transformation before all the other transformations that exist in the matrix, where as left side multiplication would apply it after the other transformations. So I'm not sure if that's what you want here. You might have to do all the transformations in the reverse order or do a left side multiplication yourself.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文