2

我在 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;


}

如果我只是将运动锁定到任一轴而不是一起,这通常适用于任一轴本身,

x轴傻瓜

但是当我移动两个轴时,看起来 Y 轴需要大约 2 整圈才能赶上“赶上”(在 Y 轴上移动时,平面沿 x 轴以顺时针/逆时针方向旋转),并且然后 x 轴“关闭”并且不会像以前那样移动。

当我阅读billboard时,主要是从旋转/变换矩阵中提取平移方面并使用它,但是,在这些示例中,我认为相机被认为是场景的中心,而在 SceneKit 和方式中我正在做一些事情,中心是 LED 阵列的中心,当我移动 LED 节点时相机是固定的,正如您在 mouseDragged: 方法中看到的那样。

4

1 回答 1

2

最直接的做法是使用 SCNConstraint ,这是在 WWDC 2013 会议中。您应该下载并查看一下。在任何情况下,您都可以使用约束来保持平面对准相机。由于这些平面将是透明的,围绕 LED 的实际可见度非常低。我认为这是一个相当不错的选择。

nodeA.constraints = @[SCNLookAtConstraint lookAtConstraintWithTarget:nodeB];

在这种情况下,nodeB 将是 cameraNode,nodeA 将是包含所有平面的节点。

谢谢David Rönnqvist为正确方向的箭头。

于 2014-04-11T18:34:46.237 回答