objective-c - 在相机不是场景中心的 3D 空间中对 2D 平面进行广告牌

标签 objective-c macos opengl core-animation scenekit

我在 OpenGL/SceneKit/CoreAnimation 环境中遇到转换问题。我有我的 LED 场景。我还创建了一个与每个 LED 相交的平面。将来这个平面将是透明的,一旦我解决了广告牌问题,它将用于在 LED 周围绘制高亮圆圈。

Default Behavior

我正在尝试将飞机广告牌制作到相机上。我遇到的问题是我找不到确切的转换类型来使其在我构建的场景中发挥作用。

在我的 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-axis goofery

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

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

最佳答案

最简单的方法是使用 SCNConstraint Here it is in the WWDC 2013 session.您应该下载并查看一下才能看到它。无论如何,您都可以使用约束来保持飞机瞄准相机。由于平面是透明的,LED 周围的实际可见光非常少。我认为这是一个非常不错的选择。

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

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

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

关于objective-c - 在相机不是场景中心的 3D 空间中对 2D 平面进行广告牌,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22670065/

相关文章:

linux - 如何在 Linux 上的 OpenGL 中创建一个窗口而不是使用 GLUT?

c++ - 看不到 SpotLight - OpenGL

macos - Bash:以人类可读的格式从 wc 输出行数

c++ - SFML 库未加载错误,未找到图像

ruby-on-rails - Mac OS X 上的 Postgres 权限被拒绝

objective-c - UIAlertView 中的其他按钮标题

c++ - OpenGL:一次只能有一个 FBO 工作

objective-c - 将 1 个字节转换为 int Objective-C

android - 如何在 Objective-C 中将值 BOOL 设置为与 Firebase 中的 Java 相同?

iphone - 方法内创建的变量的内存泄漏