gpt4 book ai didi

ios - SceneKit unproject 一个点给出了奇怪的结果

转载 作者:行者123 更新时间:2023-11-28 20:56:48 25 4
gpt4 key购买 nike

首先,我在场景中投影一个特定点。

SCNVector3 topLeft = SCNVector3Make(
-50,
-50,
-UIScreen.mainScreen.bounds.size.width);
SCNVector3 projectedPoint = [self.sceneView projectPoint:topLeft];

当我打印值时,我在屏幕上得到了预期的位置。

(-50 -50 -667) --> (309 212 1)

但是当我取消投影时,基本上是在寻找反向操作。

SCNVector3 point = SCNVector3Make(309, 212, 1);
SCNVector3 unprojectedPoint = [self.sceneView unprojectPoint:point];

我得到了一些非常不同的东西。

(309, 212, 1) --> (-7.544 -7.544 -100)

我错过了什么/做错了什么?

最佳答案

您的 SCNVector3 topLeft 使用屏幕宽度作为 z 坐标,这与世界坐标系无关。

坐标系

SceneKit uses a right-handed coordinate system where (by default) the direction of view is along the negative z-axis, as illustrated below.

https://developer.apple.com/documentation/scenekit/organizing_a_scene_with_nodes

从世界坐标到二维 View 的投影点

项目点(_:)

Projects a point from the 3D world coordinate system of the scene to the 2D pixel coordinate system of the renderer.

https://developer.apple.com/documentation/scenekit/scnscenerenderer/1524089-projectpoint

插图

Illustration

这里我们看到一个维度为 2 的立方体。它位于世界坐标系的原点 (x: 0, y: 0, z: 0)。相机位于 x: 0, y: 0, z: 10。

现在要将立方体的位置 (0/0/0) 投影到 2D View ,可以在 Objective-C 中编写:

SCNVector3 projectedPoint = [self.sceneView projectPoint:SCNVector3Make(0, 0, 0)];

在 iPhone 8 Plus 上,我们知道屏幕尺寸为 414 x 736。因此我们预计结果 x: 207 y: 368。

如果我们使用以下代码记录输出:

NSLog(@"projectedPoint: %f %f %f", projectedPoint.x, projectedPoint.y, projectedPoint.z);

一个人会得到这样的东西:

projectedPoint: 207.000000 368.000000 0.909091

所以现在使用这个 projectedPoint 并取消投影我们应该再次获得原点:

SCNVector3 unprojectedPoint = [self.sceneView unprojectPoint:projectedPoint];
NSLog(@"unprojectedPoint: %f %f %f", unprojectedPoint.x, unprojectedPoint.y, unprojectedPoint.z);

确实输出是

unprojectedPoint: 0.000000 0.000000 0.000000

完整示例

这里是上述场景的完整代码:

@interface GameViewController ()

@property (nonatomic, weak) SCNView *scnView;
@property (nonatomic, strong) SCNNode *cameraNode;
@property (nonatomic, strong) SCNScene *scnScene;
@property (nonatomic, strong) SCNNode *boxNode;

@end

@implementation GameViewController

- (void)viewDidLoad {
[super viewDidLoad];
[self _setupView];
[self _setupScene];
[self _setupCamera];
[self _setupTapping];
[self _addCube];
}

-(void)_setupTapping {
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapHandler:)];
self.scnView.gestureRecognizers = @[tapGestureRecognizer];
}

-(void)_tapHandler:(UIGestureRecognizer *)gestureRecognizer {
NSLog(@"--------------");
SCNVector3 projectedPoint = [self.scnView projectPoint:SCNVector3Make(0, 0, 0)];
NSLog(@"projectedPoint: %f %f %f", projectedPoint.x, projectedPoint.y, projectedPoint.z);

SCNVector3 unprojectedPoint = [self.scnView unprojectPoint:projectedPoint];
NSLog(@"unprojectedPoint: %f %f %f", unprojectedPoint.x, unprojectedPoint.y, unprojectedPoint.z);

CGPoint point = [gestureRecognizer locationInView:self.scnView];
SCNVector3 scenePoint = [self.scnView unprojectPoint:SCNVector3Make(point.x, point.y, projectedPoint.z)];
NSLog(@"point %f %f -> scenePoint: %f %f %f", point.x, point.y, scenePoint.x, scenePoint.y, scenePoint.z);
}

-(void)_setupView {
self.scnView = (SCNView *)self.view;
self.scnView.autoenablesDefaultLighting = YES;
}

-(void)_setupScene {
self.scnScene = [SCNScene new];
self.scnView.scene = self.scnScene;
}

- (void)_setupCamera {
self.cameraNode = [SCNNode new];
self.cameraNode.camera = [SCNCamera camera];
self.cameraNode.position = SCNVector3Make(0, 0, 10);
[self.scnScene.rootNode addChildNode:self.cameraNode];
}

- (void)_addCube {
SCNBox *box = [SCNBox boxWithWidth:2 height:2 length:2 chamferRadius:0];
SCNMaterial *mat = [SCNMaterial new];
mat.diffuse.contents = @"art.scnassets/crosshair.png";
box.materials = @[mat];
self.boxNode = [SCNNode new];
self.boxNode.geometry = box;
self.boxNode.position = SCNVector3Make(0, 0, 0);
[self.scnScene.rootNode addChildNode:self.boxNode];
}

- (BOOL)prefersStatusBarHidden {
return YES;
}

@end

点击立方体的左上角

示例中的立方体具有十字准线纹理。在 iPhone 上看起来像这样:

screenshot

现在您可以点击 View 中的某处。

用下面的代码

CGPoint point = [gestureRecognizer locationInView:self.scnView];
SCNVector3 scenePoint = [self.scnView unprojectPoint:SCNVector3Make(point.x, point.y, projectedPoint.z)];
NSLog(@"point %f %f -> scenePoint: %f %f %f", point.x, point.y, scenePoint.x, scenePoint.y, scenePoint.z);

我们在上图中显示为网格的区域上输出未投影点(世界坐标系)。

由于立方体的维度为 2 且位于原点,因此确切的世界坐标点为 x: -1,y: -1,z: 0。

例如,当我在模拟器中点击立方体的左上角时,我会得到如下信息:

point 141.000000 299.000000 -> scenePoint: -1.035465 1.082531 0.000000

关于ios - SceneKit unproject 一个点给出了奇怪的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51464688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com