You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D仿射变换(TRS)组合计算:无需极分解的实现问询

无需极分解直接组合3D TRS变换的方法

当然可以不用显式构造矩阵做极分解,直接通过向量和四元数运算得到组合后的TRS参数。以下是具体步骤,先明确TRS变换的定义:我们默认每个TRS变换的顺序是先缩放,再旋转,最后平移,即对任意点v,变换公式为:
T(v) = r.rotate(s.component_multiply(v)) + t
其中r.rotate(v)表示用四元数r旋转向量v,component_multiply是分量-wise乘法。

1. 计算组合后的平移向量t_total

这一步很直接,先把T0的平移向量t0经过T1的线性变换(缩放+旋转),再加上T1的平移t1:

t_total = r1.rotate( s1.component_multiply(t0) ) + t1

2. 计算组合后的旋转四元数r_total和缩放向量s_total

我们需要从两个变换的线性组合中提取旋转和缩放,核心是利用标准正交基的变换,再通过正交化得到旋转基,同时提取缩放因子:

步骤2.1 计算三个标准基向量的变换结果

取x/y/z轴的单位向量e_x=(1,0,0)、e_y=(0,1,0)、e_z=(0,0,1),分别计算它们经过T0和T1线性变换后的结果:

v_x = r1.rotate( s1.component_multiply( r0.rotate( s0.component_multiply(e_x) ) ) )
v_y = r1.rotate( s1.component_multiply( r0.rotate( s0.component_multiply(e_y) ) ) )
v_z = r1.rotate( s1.component_multiply( r0.rotate( s0.component_multiply(e_z) ) ) )

这三个向量构成了组合线性变换的矩阵列。

步骤2.2 对变换后的基向量做Gram-Schmidt正交化

由于各向异性缩放的存在,v_x/v_y/v_z不一定正交,我们需要将它们正交化得到正交单位基,这就是组合后旋转矩阵的列:

  1. 处理第一个向量:
    u1 = v_x.normalize()  # 归一化得到第一个正交基
    s_x = v_x.magnitude() # 第一个缩放分量
    
  2. 处理第二个向量:
    proj_y = v_y.dot(u1) * u1  # 计算v_y在u1上的投影
    v_y_ortho = v_y - proj_y   # 去除投影得到正交分量
    u2 = v_y_ortho.normalize() # 归一化得到第二个正交基
    s_y = v_y_ortho.magnitude()# 第二个缩放分量
    
  3. 处理第三个向量:
    proj_z1 = v_z.dot(u1) * u1
    proj_z2 = v_z.dot(u2) * u2
    v_z_ortho = v_z - proj_z1 - proj_z2
    u3 = v_z_ortho.normalize()
    s_z = v_z_ortho.magnitude()
    

步骤2.3 得到最终的旋转和缩放

  • 缩放向量s_total就是(s_x, s_y, s_z)
  • 正交基u1/u2/u3构成了组合后的旋转矩阵,将这个矩阵转换为四元数就是r_total

关键说明

  • 这种方法本质上是通过Gram-Schmidt正交化完成了极分解中正交部分的计算,避免了显式构造大矩阵和完整的极分解运算,计算量更低。
  • 如果两个变换的缩放都是各向同性(即s0.x=s0.y=s0.z且s1.x=s1.y=s1.z),那么v_x/v_y/v_z会天然正交,此时正交化步骤可以简化为直接归一化,旋转四元数就是r1 * r0(四元数乘法),缩放向量就是s0.component_multiply(s1)。

内容的提问来源于stack exchange,提问作者Xaldew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:15:02