基于变换重新计算 SCNNode 几何

Recalculate SCNNode geometry based on transformation

有没有办法通过重新计算其几何结构来固定 SCNNode 的比例和方向?

基本上,我从一个 scn 文件中加载一个 SCNNode,该文件是从导出到 DAE 文件的 sketchup 文件转换而来的。因为 ARKit 以米为单位工作并且轴方向不同,所以我必须设置加载的 SCNNode 的比例(到 0.0254)和欧拉角(x -90deg)才能正确显示它。这一切都很好,但是因此缩放和旋转弄乱了一些逻辑,因为这个逻辑也使用旋转从而覆盖了前一个......:(

我认为如果我可以简单地告诉 SCNNode 根据它的当前比例、方向重新计算它的几何形状会很棒...(基本上是它的变换矩阵)这将导致 SCNNode 的变换矩阵为零矩阵....

如果您“只是”想告诉节点永久缩放其顶点,您将不得不编写一个函数来执行此操作,因为没有标准选项。

该函数应将节点几何体的顶点源读取到向量数组中,然后使用 GLKMatrix4MultiplyAndProjectVector3 将变换应用到每个向量,然后创建一个新的 SCNGeometry 并将新的顶点作为源。

GLKMatrix4 scalemat = GLKMatrix4MakeScale(aNode.scale.x, aNode.scale.y, aNode.scale.z);

for (HEVertex* vert in toBeTransformedVerts) {
     vert.pos = SCNVector3FromGLKVector3(GLKMatrix4MultiplyAndProjectVector3(scalemat, SCNVector3ToGLKVector3(vert.pos)) );
}

//reset node scale property.
aNode.scale = SCNVector3Make(1.0, 1.0, 1.0);

HEVertex是一个class我用来存储顶点,pos属性是一个SCNVector3。在您的情况下,您必须将 SCNNode 的 .geometry 的顶点源读取到 SCNVector3 的数组中,然后循环遍历它们。

变换每个顶点的位置后,您需要更新节点的几何形状。 IE。像这样:

SCNGeometrySource *_vertexSource =
        [SCNGeometrySource geometrySourceWithVertices:_meshVertices count:_vertexCount];

aNode.geometry = [SCNGeometry geometryWithSources:@[_vertexSource, _aNode.geometry.geometrySources[1], _aNode.geometry.geometrySources[2]] elements:@[_aNode.geometry.geometryElements.firstObject]];

这只是一个粗略的例子,它只更新顶点源,并重复使用法线和彩色几何源以及几何元素,每个模型可能会有很大差异。

非常可行,但不像重新导出具有适当大小的模型那么简单。

如果该节点没有任何子节点,您可以简单地将您的节点作为一个空节点的父节点,在您的节点上执行所需的转换,然后在空父节点上调用展平。您的节点的中心和方向将与空父节点相匹配。如果您的节点有一个子节点树,您将需要递归地执行此操作。

作为更复杂方法的替代方法,您可以使用简单的子节点轻松完成此操作...

  1. 创建一个新节点
  2. 将几何图形(以及您希望的任何其他节点属性)从原始节点移动到新节点
  3. 将新节点添加为原始节点的子节点
  4. 将缩放变换应用于子节点。

基本上,在第 3 步之后,您应该完全回到执行任何操作之前的位置,除了您现在有一个新的子节点可以应用您的比例变换,让父节点保持独立,以便它可以使用单位矩阵(或者你想要的任何矩阵。)

类似的方法是按原样使用现有节点...

  1. 创建新的父节点
  2. 将其添加到与现有节点相同的父节点
  3. 将现有节点从旧父节点移动到这个新父节点
  4. 将现有子节点的转换复制到新的父节点
  5. 仅用缩放变换替换子节点上的变换

在这两者之间做出选择实际上取决于您的节点上有多少您想要移动的东西,以及它最初对它进行的转换。 (即,如果您缩放节点,它可能会偏离其相对于模型的原始位置。)您可以根据该信息选择您希望执行的上述操作。

就是说,如果它只是几何体本身并且可以就地缩放它,那么选择第一个。如果有很多节点属性,则选择第二个。重点是,您正在添加一个新节点,专门用于将缩放应用到现有节点,不需要直接修改几何形状。