对于一组给定的叶子结点_glTF格式详解(场景和结点)

本文翻译自:https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md

由于本人才疏学浅,翻译难免有误,望各位不吝惜指正。


场景

一个glTF文件可以包含了多个场景,但通常来说,只包含了一个场景。每个场景包含了一个nodes数组,这一数组引用了场景的场景图的所有根结点。同样,场景图可以有多个根结点,但通常只有一个根结点。下面代码描述了只包含一个根结点的场景:

"scenes" : [
    {
      "nodes" : [ 0 ]
    }
  ],

  "nodes" : [
    {
      "mesh" : 0
    }
  ],

结点构成场景图

每个node对象包含一个children数组,这一数组引用了node对象的所有子结点。通过孩子结点,构成了整个场景结构。

e76c25d9cb1828108b24f50705c1562f.png
图4a:glTF文件所表示的场景图

通过递归遍历scene中的结点,就可以完成整个场景的处理,伪代码如下:

traverse(node) {
    // Process the meshes, cameras, etc., that are
    // attached to this node - discussed later
    processElements(node);

    // Recursively process all children
    for each (child in node.children) {
        traverse(child);
    }
}

实践中,遍历过程还会需要一些和结点关联的附加信息。比如对结点的累加变换进行处理,就需要额外的附加信息。

局部和全局变换

每个node对象附加有变换操作(平移、旋转或缩放)。附加的变换操作会被应用到node对象本身以及它的所有孩子结点。这使得我们可以对一组结点通过结点层次执行同样得变换操作。

结点的局部变换

对于node对象可以附加不同的局部变换表示。可以将变换直接以node对象的matrix属性给出。matrix属性是一个包含16个浮点数的数组,按照列主序排列矩阵元素。下面代码描述了一个缩放(2,1,0.5),绕x轴旋转30度,平移(10,20,30)的matrix属性:

"node0": {
    "matrix": [
        2.0,    0.0,    0.0,    0.0,
        0.0,    0.866,  0.5,    0.0,
        0.0,   -0.25,   0.433,  0.0,
       10.0,   20.0,   30.0,    1.0
    ]
}

上面代码定义了下图的矩阵:

628254f454051536c0b430259d6e843b.png
图4b:示例矩阵

也可以使用translation,rotation和scale属性来表示变换:

"node0": {
    "translation": [ 10.0, 20.0, 30.0 ],
    "rotation": [ 0.259, 0.0, 0.0, 0.966 ],
    "scale": [ 2.0, 1.0, 0.5 ]
}

每个变换属性可以被用来构造变换矩阵,作为node对象的局部变换,将所有变换属性构成的变换矩阵连乘后就得到了node对象的局部变换矩阵:

  • translation属性包含了x,y和z轴方向的平移。比如(10.0,20.0,30.0)这一平移,可以构造出下面这一矩阵:

6100b8722859a9dce13bd33ff48daf87.png
图4c:一个平移矩阵
  • rotation属性以四元数的形式给出。四元数的数学意义超出了本教程的范围,读者可以自行了解。四元数可以方便地表示绕任意轴旋转任意角度。比如四元数(0.259,0.0,0.0,0.966)表示绕x轴旋转30度。四元数可以转换为旋转变换矩阵,如下图所示:

6100b8722859a9dce13bd33ff48daf87.png
图4d:一个旋转矩阵
  • scale属性包含了x,y和z轴的缩放系数。可以使用这些缩放系数来构造缩放变换矩阵。如下图是使用(2.0,1.0,0.5)作为缩放系数构造的缩放变换矩阵:

9ae1ab39cf5ca3c5a26a36f6b518e280.png
图4e:一个缩放矩阵

我们将translation、rotation和scale属性构造的变换矩阵连乘起来就得到了node对象的局部变换矩阵。连乘的顺序非常重要,局部变换矩阵M=T*R*S。其中T是translation属性构造的变换矩阵,R是rotation属性构造的变换矩阵,S是scale属性构造的变换矩阵。计算局部变换矩阵的伪代码如下所示:

translationMatrix = createTranslationMatrix(node.translation);
rotationMatrix = createRotationMatrix(node.rotation);
scaleMatrix = createScaleMatrix(node.scale);
localTransform = translationMatrix * rotationMatrix * scaleMatrix;

对于上面我们构造的T,R,S变换矩阵连乘后得到的局部变换矩阵M如下图所示:

1b5e574c955b9cccff8b990f50fb0ab2.png
图4f:node对象的局部变换矩阵

node对象的局部变换矩阵会对附着在其上的mesh进行缩放,旋转和平移变换。

如果translation、rotation和scale属性中的某个属性没有给出,则使用单位矩阵作为其构造的变换矩阵。当一个node对象既不包含matrix属性又不包含任何TRS变换属性,那么就会使用单位矩阵作为它的局部变换矩阵。

结点的全局变换

不管在JSON文件中如何表示,node对象的局部变换都能够被作为一个4x4矩阵进行存储。一个node对象的全部变换由从根结点到这一node对象结点路径上的所有局部变换矩阵连乘得到:

Structure:           local transform      global transform
root                 R                    R
 +- nodeA            A                    R*A
     +- nodeB        B                    R*A*B
     +- nodeC        C                    R*A*C

需要注意,由于进行动画时可能会修改一部分node对象的局部变换,我们不能简单地只进行一次全局变换计算。在之后的章节,我们会介绍动画如何修改部分node对象的局部变换。部分node对象的局部变换改变会对它的所有孩子结点的全局变换产生影响。我们可以通过对全局变换进行缓冲,通过检测父亲结点的局部变换是否发生变化,来决定是否更新全局变换的缓冲值,来提高一定的性能表现。


fangcun:glTF格式详解(目录)​zhuanlan.zhihu.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值