在触摸位置在SceneKit中创建SCNCylinder并不准确

时间:2016-09-07 19:11:36

标签: ios objective-c scenekit scnscene

我尝试使用SCNCylinder在SceneKit中创建一个平面圆柱体。我希望将圆柱放置在用户点击屏幕的位置的场景中。

我当前的方法有效,但由于某种原因,气缸未准确放置在触摸位置。取决于屏幕的部分,圆柱体有时处于触摸位置的中间并且有时偏离相当大的量。我希望截图能很好地说明这个问题。

Offset when creating SCNCylinder at screenpos

我目前有一个SCNSphere相机所在的位置。通过使用球体测试屏幕触摸点,我将检索射线朝向命中测试。然后,我获取光线的法向矢量,并沿着矢量乘以6来定位圆柱体。

有没有人知道这种方法的问题是什么以及为什么我会遇到这种偏移行为?

这是我目前如何创建SCNCylinder

- (IBAction)longPressGesture:(UILongPressGestureRecognizer *)sender {
    if (sender.state == UIGestureRecognizerStateBegan) {
        CGPoint location = [sender locationInView:self.sceneView];
        NSArray *hitTestResult = [self.sceneView hitTest:location  options:nil];

        if (hitTestResult.count == 1) {
            SCNHitTestResult *sphereHit = hitTestResult.firstObject;
            // Get ray coordinates from local camera position
            SCNVector3 localCoordinates = sphereHit.worldNormal;
            localCoordinates = SCNVector3Make(localCoordinates.x * 6, localCoordinates.y * 6, localCoordinates.z * 6);
            [self addCylinder:SCNVector3Make(localCoordinates.x, localCoordinates.y, localCoordinates.z)];
        }
    }
}

- (void)addCylinder:(SCNVector3)position {
    SCNCylinder *cylinder = [SCNCylinder cylinderWithRadius:0.5 height:0.01];
    SCNNode *cylinderNode = [SCNNode nodeWithGeometry:cylinder];

    // Create LookAt Contstraint
    NSMutableArray *constraints = [NSMutableArray new];
    SCNLookAtConstraint *lookAtCameraConstraint = [SCNLookAtConstraint lookAtConstraintWithTarget:cameraNode];
    lookAtCameraConstraint.gimbalLockEnabled = YES;
    [constraints addObject:lookAtCameraConstraint];

    // Turn 90° Constraint
    SCNTransformConstraint *turnConstraint = [SCNTransformConstraint transformConstraintInWorldSpace:NO withBlock:^SCNMatrix4(SCNNode * _Nonnull node, SCNMatrix4 transform) {
        transform = SCNMatrix4Mult(SCNMatrix4MakeRotation(M_PI_2, 1, 0, 0), transform);
        return transform;
    }];
    [constraints addObject:turnConstraint];

    cylinderNode.constraints = constraints;

    cylinderNode.position = position;

    SCNNode *rootNode = self.sceneView.scene.rootNode;
    [rootNode addChildNode:cylinderNode];
}

1 个答案:

答案 0 :(得分:0)

SceneKit中的每个SCNSphere都是由多边形创建的。多边形的数量以及SCNSphere网格的粒度由segmentCount属性确定。

Documentation of SCNSphere

默认情况下,segmentCount值设置为48,这不是非常细粒度。在具有低segmentCount的hitTest:上执行SCNSphere将导致检索与实际触摸点相比具有偏移的多边形。 通过增加segmentCount(例如,增加到96),水平和垂直方向上的段都会增加,偏移量也会减少。

请注意,增加segmentCount会对效果产生影响。