3

我正在努力理解 Scene Kit 使用节点的变换相关属性的语义。特别是,节点上的 pivot 属性不是一个点,而是一个完整的变换矩阵,我在 Collada 规范或其他文档中没有找到任何可比较的参考。

有没有人有使用 Scene Kit 中的枢轴矩阵或具有类似语义的属性的经验?有人可以提供有关如何使用它的简要说明/示例或指向相关文档的指针吗?它看起来像是一种潜在有用的方法,但如果我可以避免它,我宁愿不必对它进行逆向工程。

编辑:根据 OMZ 的响应,看起来枢轴可能只是变换树中的另一层。但是,如果是这样的话,它与仅仅添加一个中间节点有什么不同呢?确定在哪里应用哪些转换的依据是什么?

4

3 回答 3

3

我尝试了@omz 的想法。但是得到一些相互矛盾的结果,所以我用一些有趣的结果进一步研究了这个。

答案是枢轴的倒数作为主变换的子级应用。这提供了与提供中间父节点完全不同的语义。

具体来说,如果我从一个带有变换 P 的父节点和一个带有变换 C 的子节点开始,它们组合起来形成一个世界变换 W = CATransform3DConcat(C, P)。相同的世界变换 W 是通过将父节点的枢轴设置为 C 的倒数,而不是对子节点设置变换来获得的。

这种方法似乎确实提供了一些额外的实用程序,因为它不能通过插入中间节点来复制,也不能在应用之前被反转。正如 Hal Mueller 指出的那样,文档确实说枢轴会影响旋转和缩放以及位置,但对影响的性质保持沉默。

以下是测试此结论的结果:

Set parent rotation and node position.

Transform:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  1.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  1.00,  2.00,  3.00,  1.00 }

Pivot:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  1.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00,  0.00,  0.00,  1.00 }

World Transform:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00, -1.00,  0.00,  0.00 }
{  1.00, -3.00,  2.00,  1.00 }
2013-04-04 13:49:55.453 Model Importer[43504:303] 

CATransform3DConcat(node.transform, node.parentNode.transform)]
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00, -1.00,  0.00,  0.00 }
{  1.00, -3.00,  2.00,  1.00 }
2013-04-04 13:49:55.454 Model Importer[43504:303] 

Set parent rotation and parent.pivot to inverse position.

Transform:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  1.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00,  0.00,  0.00,  1.00 }

Pivot:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  1.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00,  0.00,  0.00,  1.00 }

World Transform:
{  1.00,  0.00,  0.00,  0.00 }
{  0.00,  0.00,  1.00,  0.00 }
{  0.00, -1.00,  0.00,  0.00 }
{  1.00, -3.00,  2.00,  1.00 }

这是代码:

    // Verification
    SCNVector3 v3 = {1.0, 2.0, 3.0};
    SCNVector4 v4 = {1.0, 0, 0, M_PI/2.0};
    node.parentNode.rotation = v4;
    node.position = v3;
    NSLog(@"\n\nSet parent rotation and node position.%@",
          [self transformsForNodeToString:node]);
    //
    // Verify match with CATransform3DConcat
    NSLog(@"\n\nCATransform3DConcat(node.transform, node.parentNode.transform)]%@",
          [self transformToString:CATransform3DConcat(node.transform, node.parentNode.transform)]);
    //
    // Clear the child node transform and put the inverse in the parent's pivot.
    CATransform3D position = node.transform;
    CATransform3D inversePosition = CATransform3DInvert(position);

    node.transform = CATransform3DIdentity;
    node.parentNode.pivot = inversePosition;
    NSLog(@"\n\nSet parent rotation and parent.pivot to inverse position.%@",
          [self transformsForNodeToString:node]);
    node.parentNode.pivot = CATransform3DIdentity;
    node.parentNode.transform = CATransform3DIdentity;


+ (NSString*)transformsForNodeToString: (SCNNode*)node {
    NSString* result = @"\n";
    result = [result stringByAppendingFormat:
          @"\nTransform:%@\nPivot:%@\nWorld Transform:%@",
          [self transformToString:node.transform],
          [self transformToString:node.pivot],
          [self transformToString:[node worldTransform]]];
    return result;
}

+ (NSString*)transformToString: (CATransform3D)transform {
    NSString* result = @"\n";
    result = [result stringByAppendingFormat:
              @"{ % .2f, % .2f, % .2f, % .2f }\n", transform.m11, transform.m12, transform.m13, transform.m14];
    result = [result stringByAppendingFormat:
              @"{ % .2f, % .2f, % .2f, % .2f }\n", transform.m21, transform.m22, transform.m23, transform.m24];
    result = [result stringByAppendingFormat:
              @"{ % .2f, % .2f, % .2f, % .2f }\n", transform.m31, transform.m32, transform.m33, transform.m34];
    result = [result stringByAppendingFormat:
              @"{ % .2f, % .2f, % .2f, % .2f }\n", transform.m41, transform.m42, transform.m43, transform.m44];
    return result;
}

欢迎评论!

于 2013-04-04T21:44:07.383 回答
2

我对 SceneKit 没有太多经验,但在 3D 建模应用程序中,枢轴是一个可以旋转的点(有时称为定位器)是很常见的。例如,这使您可以更轻松地使对象围绕自己的轴旋转(不一定对应于世界轴)。

对于未旋转的枢轴,矩阵将只是CATransform3DMakeTranslation(x, y, z).

编辑:我认为枢轴被指定为完整矩阵的事实仅仅是因为它是一种方便的数据结构并且与模型的其余部分一致。我想不出您想要缩放枢轴的情况,但是将其表示为矩阵可以很容易地使用通常的矩阵操作函数对其进行操作。

您当然可以将枢轴表示为另一个中间节点并获得相同的结果,但枢轴是表达对象中心的一种更“语义”的方式,更适合交互式编辑。当您在建模应用程序中选择对象时,通常会将转换工具手柄定位在枢轴所在的位置,以便您可以围绕其“自然”中心旋转/缩放对象,而无需在节点层次结构中向上导航。

我真的找不到任何好的参考资料。出现的大多数事情似乎都涉及各种软件包中的具体实现细节。

于 2013-04-01T04:26:16.930 回答
1

我想你会在 Core Animation 材料中找到一些相关的示例。的pivotof anSCNNode被定义为 a CATransform3D,它在 Mac 和 iOS 上的 Core Animation 中使用。

我自己对 Scene Kit 的研究还不够权威。但是我发现了 Brad Larson 的这篇文章:“Core Animation 提供的用于操作 CALayers 的 CATransform3D 结构在结构上与 OpenGL 中的模型视图矩阵相同”。

GitHub 上还有一个很酷的可视化工具,https://github.com/honcheng/CATransform3D-Test。Honcheng 的演示仅适用于 iPad,但我认为仍然很有帮助。

于 2013-04-02T01:00:51.953 回答