c++ 如何沿着任意轴缩放对象(在三维空间中)

qyzbxkaa  于 2023-03-05  发布在  其他
关注(0)|答案(3)|浏览(234)

我正尝试用opengl编写一个c++物理模拟器,我需要能够沿着摄像机所面对的轴缩放物体(现在大多数是立方体)。
我可以用这个模型矩阵完美地画出物体:

mat4 Model = Translate(cube.Position - float3(gl.Position.x, gl.Position.y, -gl.Position.z)) * Rotate(cube.Rotation) * Scale(cube.Scale);

其中gl.Position是凸轮的位置,float 3是一个vec 3,类似于我写的类,等等...
所以我试着修改那一行,在所有其他内容之前包含一个缩放因子(其中最后的内容首先应用):

mat4 Model = Translate(cube.Position - float3(gl.Position.x, gl.Position.y, -gl.Position.z)) * Rotate(cube.Rotation) * Scale(cube.Scale) * (Rotate(float3(gl.Rotation.x, gl.Rotation.y, gl.Rotation.z)) * Scale(float3(1.0f, 1.0f, sqrt(1 - (velocity * velocity)))) * Rotate(float3(tau - gl.Rotation.x, tau - gl.Rotation.y, tau - gl.Rotation.z)));

这是最后一个重要的部分,在这里我旋转对象,缩放它,然后旋转回来。(1 -(速度 * 速度))是物理部分(洛伦兹收缩)和gl。旋转是一个vec 3,其中每个轴都以弧度表示凸轮的俯仰、偏航和滚转。我的translate、rotate等函数工作正常,但我需要创建按比例缩放的矩阵的理论帮助。

wztqucjr

wztqucjr1#

比例矩阵的形式为:

{{s_x, 0, 0, 0},
 {0, s_y, 0, 0},
 {0, 0, s_z, 0},
 {0,  0,  0, 1}}

假设坐标一致。
要应用它们,你需要缩放,然后旋转,然后平移。我推荐使用gl函数来实现这一点。假设你希望你的对象位于x,y,z位置,并且它的旋转是在四元数{theta,r_x,r_y,r_z}中。缩放和旋转需要发生在模型坐标系中。GL以适当的顺序应用变换,所以它的代码看起来像这样:

glTranslatef(x, y, z);
glRotatef(theta, r_x, r_y, r_z);
glScalef(s_x, s_y, s_z);

//draw my model
9njqaruj

9njqaruj2#

我根据pippin1289的解编写了这个函数

mat4 ScaleOnAxis(float3 a)
{
    a = Norm3f(a);

    if(a == x || (a.x == -1.0f && a.y == 0.0f && a.z == 0.0f))
        return Scale(0.2f, 1.0f, 1.0f);

    float3 axis = Cross(a, x);
    float theta = acos(Dot(a, x));

    if(theta > pi / 2)
    {
        axis = axis * -1.0f;
        theta = pi - theta;
    }

    Quaternion ToRotation(axis.x, axis.y, axis.z, theta);
    Quaternion FromRotation(axis.x, axis.y, axis.z, tau - theta);

    return mat4(FromRotation) * (Scale(float3(0.2f, 1.0f, 1.0f)) * mat4(ToRotation));
}

它返回一个在轴上缩放0.2的矩阵

3wabscal

3wabscal3#

我还没有在网上找到任何使用GLM库解决这个问题的资源,多亏了@pippin1289的评论帖子,我终于找到了这个问题的答案,我写这篇文章是希望它能在未来帮助到别人,尽管事实上这个帖子已经有10年的历史了。
例如,如果要在3维空间中的x轴和z轴之间成45度角且经过点(1,0,0)的轴上将对象缩放3x,则应编写:

M = glm::mat4(1);
M = glm::translate(M, glm::vec3(1, 0, 0));
M = glm::rotate(M, glm::radians(45.0f), glm::vec3(0, 1, 0));
M = glm::scale(M, glm::vec3(3, 1, 1));
M = glm::rotate(M, glm::radians(-45.0f), glm::vec3(0, 1, 0));
M = glm::translate(M, glm::vec3(-1, 0, 0));

实际上,您需要首先将对象定位在任意轴通过的点上,执行所需的旋转,然后仅沿着其中一个维度执行缩放,然后再反转之前执行的缩放和平移。
如@pippin1289所示,* 您可以通过沿着x轴放置任意向量的旋转来旋转模型 *。
希望这是有用的任何人挣扎什么似乎是一个简单的问题!

相关问题