我在OpenGL / SceneKit / CoreAnimation环境中遇到转换问题。我有我的LED场景。我还创建了一个与每个LED相交的平面。这架飞机将来是透明的,一旦我解决了广告牌问题,它将用于在LED周围画一个高亮圆圈。
我正在尝试将飞机广告牌放到相机上。我遇到的问题是我无法找到确切的转换方式,以便在我构建的场景中完成这项工作。
在我的mouseDragged:方法中,我正在反转X旋转和Y旋转矩阵,将它们连接起来并将其用作最终变换以反转LED的正向旋转,使其看起来始终面向摄像机。
-(void)mouseDragged:(NSEvent *)theEvent
{
NSPoint winp = [theEvent locationInWindow];
NSPoint p = [sceneView convertPoint:winp fromView:nil];
mouseDraggedLocation = p;
//****************** TRANSFROM INIT ****************************************
CATransform3D localProjectionTransform;
CATransform3D translatedProjectionTransformX;
CATransform3D translatedProjectionTransformY;
CATransform3D translatedProjectionTransformFinal;
CATransform3D rotatedProjectionTransformX;
CATransform3D rotatedProjectionTransformY;
CATransform3D rotatedProjectionTransformFinal;
CATransform3D checkedProjectionTransform;
CATransform3D translatedProjectionTransformZ;
CATransform3D translationOnlyMatrix;
CATransform3D tempTransform;
//****************** TRANSFROM INIT ****************************************
// Figure out Angle
angleX = mouseDraggedLocation.x - mouseOldLocation.x;
angleY = mouseDraggedLocation.y - mouseOldLocation.y;
//********************************PLAYING WITH TRANSFORMS****************************
// X transform
rotatedProjectionTransformX = CATransform3DMakeRotation(angleX * ROTATION_FACTOR, 0, 1, 0);
// Y transform
rotatedProjectionTransformY = CATransform3DMakeRotation(angleY * ROTATION_FACTOR, -1.0f, 0.0f, 0.0f);
rotatedProjectionTransformFinal = CATransform3DConcat(rotatedProjectionTransformX, rotatedProjectionTransformY);
translatedProjectionTransformX = CATransform3DMakeTranslation(0, angleX * ROTATION_FACTOR, 0);
translatedProjectionTransformY = CATransform3DMakeTranslation( -1 *(angleY * ROTATION_FACTOR), 0, 0);
translatedProjectionTransformFinal = CATransform3DConcat(translatedProjectionTransformX, translatedProjectionTransformY);
// rootNode
// |
// ledArrayNode
// / \
// outlinePlaneNode (s) LEDGeomNode(s)
// OH GOD PLEASE DON'T HATE ME FOR THIS, it chooses nodes that aren't Outline nodes, just disregard as crap test coding.
for (SCNNode *NodeTemp in [ledArrayNode childNodes]) {
if ( [NodeTemp.name rangeOfString:@"O"].location == NSNotFound) {
localProjectionTransform = NodeTemp.transform;
NodeTemp.transform = CATransform3DConcat(localProjectionTransform, rotatedProjectionTransformFinal);
} else {
}
}
// This is what does the rotation with the outline planes, the previous loop did normal rotations for the LEDGeom Nodes
tempTransform = CATransform3DInvert(rotatedProjectionTransformFinal);
for (SPCLedGeom *LEDTemp1 in LED_Array) {
localProjectionTransform = LEDTemp1.LED_Outline_Plane_Node.transform;
LEDTemp1.LED_Outline_Plane_Node.transform = CATransform3DConcat(localProjectionTransform, tempTransform);
}
mouseOldLocation.x = mouseDraggedLocation.x;
mouseOldLocation.y = mouseDraggedLocation.y;
}
如果我只是将运动锁定到任一轴而不是一起锁定,这通常适用于任何一个轴,
但是当我移动两个轴时,看起来Y轴需要大约2整圈才能“向上”(同样在Y轴上移动时,平面沿x轴顺时针/逆时针旋转),然后x轴“关闭”,不会像以前那样移动。
当我阅读关于billboarding时,要点是从旋转/变换矩阵中拉出平移方面并使用它,但是,在这些例子中,我认为相机被认为是场景的中心,然而,在SceneKit和我正在处理的事情中,中心是LED阵列的中心,当我按照mouseDragged:方法看到的移动LED节点时,摄像机是固定的。
答案 0 :(得分:2)
最直接的方法就是使用SCNConstraint Here it is in the WWDC 2013 session.你应该下载并看一下才能看到它。无论如何,您可以使用约束来保持飞机瞄准相机。由于这些平面是透明的,实际上可见的很少,以围绕LED。我认为这是一个不错的选择。
nodeA.constraints = @[SCNLookAtConstraint lookAtConstraintWithTarget:nodeB];
在这种情况下,nodeB将是cameraNode,而nodeA将是包含所有平面的节点。
谢谢David Rönnqvist对于正确方向的箭头。