4 gltf:scenes 和Nodes(场景和节点)

总目录 >> threejs入门进阶到实战(目前已更新入门篇、基础篇和进阶篇)

4 scenes 和Nodes(场景和节点)

原文:https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md

场景 scenes

一个glTF文件中可能有多个场景scene被存储,但在大多数情况下,只有一个场景,也就是默认场景。每个场景都包含一组节点nodes,这些节点是场景图(scene graph)根节点的索引 indices。同样的,可能有多个根节点,形成不同的层次,但在许多情况下,场景只有一个根节点。最简单的场景描述包含单个节点、单个场景,已在上一节中解释:

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

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

Nodes 节点形成scene graph场景图

每个节点node都可以包含一个名为children的数组,该数组包含其子节点的索引。因此每个节点都是节点层次结构中的一个元素,它们一起定义场景的结构(场景图 scene graph)。
4 gltf:scenes 和Nodes(场景和节点)_第1张图片

可以遍历场景中scene 给定的每个节点,递归地访问其所有子节点,从而能够处理附加到节点上的所有元素。遍历过程中的简化代码如下所示:

traverse(node) {
    // 处理 网格,相机等元素, 这些元素是附着在node节点上的
    //后面再讨论如何处理这些元素:  processElements(node);
    
    // 递归处理所有的子对象。
    for each (child in node.children) {
        traverse(child);
    }
}

实际上,遍历需要一些额外的信息:处理附加到节点的某些元素,需要知道它们附加到哪个节点。此外,在遍历过程中,关于节点的矩阵变换(transform)信息需要被逐步积累(accumulated)

局部和全局矩阵变换

每个节点都可以有一个矩阵(或者成为 变换矩阵)。这样的矩阵定义了平移(translation)、旋转(rotation)和缩放(scale)。此矩阵将应用于附加到节点本身及其所有子节点的所有元素之上。因此,节点的层次结构(hierarchy of nodes)允许构造应用于场景元素的平移、旋转和缩放。

节点的局部矩阵(变换)

节点的局部矩阵变换有不同的表示方法。该变换可由节点的矩阵matrix直接给出。这是一个由16个浮点数组成的数组,按列的主顺序描述矩阵。例如,下面的矩阵描述了围绕(2,1,0.5)的缩放、围绕x轴大约30度的旋转和围绕(10,20,30)的平移:

"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
    ]
}

这里定义的矩阵如图4b所示。

图 4b: 示例矩阵

节点的矩阵转换也可以使用节点的平移translation,、旋转rotation和缩放scale属性(有时缩写为TRS):

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

这些属性中的每一个都可以用来创建一个矩阵,然后这些矩阵的乘积(product:矩阵乘积)就是节点的局部变换:

  • translation平移 只包含了 x-, y-和 z方向的平移. 例如,从vector3 [10.0,20.0,30.0]的平移中,可以创建一个平移矩阵,体现在矩阵中的最后一列,如图4c所示。


图 4c: 平移矩阵

  • rotation是以四元数的形式给出的。四元数的数学背景超出了本教程的范围。目前,最重要的不部分是四元数是围绕任意角度和任意轴旋转的表示。例如,四元数vector4[0.259,0.0,0.0,0.966]描述绕x轴旋转约30度。这个四元数可以被转换成旋转矩阵,如图4d所示。-> 此处给出了 四元数到旋转矩阵的转换方式: https://blog.csdn.net/loongkingwhat/article/details/88427828

4 gltf:scenes 和Nodes(场景和节点)_第2张图片
图 4d: 旋转矩阵

  • scale 包含了沿着x,y,z轴的放缩系数 ;通过使用这些比例因子作为矩阵对角线上的数字,可以创建相应的矩阵。例如,缩放因子vector3[2.0、1.0、0.5]的缩放矩阵如图4e所示。


图 4e: 放缩矩阵

计算节点的最终局部变换矩阵时,需要将各自的矩阵相乘在一起,并且必须按正确的顺序对这些矩阵进行乘法运算。局部变换矩阵公式为M=T*R*S,其中T是平移部分的矩阵,R是旋转部分的矩阵,S是缩放部分的矩阵。计算代码示意为:

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

对于上面给出的示例矩阵,节点的最终局部变换矩阵如图4f所示。

图4f: 根据TRS属性计算的最终局部变换矩阵。

此矩阵将使得网格的顶点先 缩放、再旋转,最后再平移(注意与乘法法则正好倒过来
当这三个性质中的任何一个没有给出时,将使用单位矩阵(identity matrix)。类似地,当一个节点既不包含矩阵matrix属性也不包含TRS属性时,它的局部变换也将是单位矩阵(identity matrix)。

节点的全局变换(矩阵变换)

无论JSON文件中的表示形式如何,节点的局部矩阵转换都可以存储为4×4矩阵。节点的全局变换由根到相应节点路径上所有局部变换的乘积给出:

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

必须指出的是,加载文件后,这些全局转换不能只计算一次。稍后,将演示动画中(animation)如何修改单个节点的局部变换。这些修改将影响所有子节点的全局转换。因此,当需要节点的全局变换时,必须直接从所有节点的当前局部变换计算。或者,作为潜在的性能改进,实现可以缓存全局转换,检测祖节点(ancestor node)的局部转换中的更改,并仅在必要时更新全局转换。这方面的不同实现选项将取决于编程语言和客户机应用程序的要求,因此超出了本教程的范围。

你可能感兴趣的:(gltf,threejs)