我正在努力了解Scene Kit对节点使用与变换相关的属性的语义。特别是,节点上的支点属性不是单点,而是完整的变换矩阵,在Collada规范或其他文档中,我还没有找到任何可比的参考。
有没有人有使用场景工具箱中的枢轴矩阵或具有类似语义的属性的经验?有人可以提供有关其用法的简短说明/示例或指向相关文档的指针吗?看来这是一种潜在有用的方法,但如果可以避免的话,我宁可不必对其进行反向工程。
编辑:根据OMZ的响应,似乎枢轴可能只是变换树中的另一层。但是,如果是这样,它与仅添加一个中间节点有何不同?确定在哪里应用哪种转换的方法将是什么?
最佳答案
我尝试了@omz的想法。但是会有一些矛盾的结果,所以我进一步研究了一些有趣的结果。
答案是将枢轴的倒数用作主要变换的子级。与提供中间父节点相比,这提供了截然不同的语义。
具体来说,如果我从具有转换P的父节点开始,到具有转换C的子节点开始,它们结合在一起将构成世界转换W = CATransform3DConcat(C,P)。通过将父节点的轴点设置为C的倒数,而不是在子节点上设置变换,可以获得相同的世界变换W。
这种方法确实提供了一些附加的实用程序,因为它不能通过插入中间节点来复制,并且在应用之前是反向的。正如哈尔·穆勒(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;
}
欢迎评论!