2016-09-07 2 views
0

J'essaie de créer un cylindre plat dans SceneKit en utilisant SCNCylinder. Je veux que le cylindre soit placé dans la scène à la position où l'utilisateur appuie sur l'écran.La création de SCNCylinder dans SceneKit au niveau de la position tactile n'est pas précise

Mon approche actuelle fonctionne, mais pour une raison quelconque, le vérin n'est pas positionné avec précision à la position tactile. En fonction de la partie de l'écran, le cylindre est parfois au milieu de la position tactile et parfois de manière significative. J'espère que la capture d'écran illustre assez bien le problème.

Offset when creating SCNCylinder at screenpos

J'ai actuellement un SCNSphere dans lequel se trouve la caméra. En arrêtant le point de contact de l'écran avec la sphère, je récupère un rayon vers le hit-test. Je prends alors le vecteur normal du rayon et positionne le Cylindre le long du vecteur multiplié par 6.

Est-ce que quelqu'un a une idée du problème avec cette approche et pourquoi j'ai ce comportement de décalage?

Ce que je crée actuellement le 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]; 
} 

Répondre

0

Chaque SCNSphere à SceneKit est créé à partir de polygones. Le nombre de polygones et donc la granularité est déterminé par la propriété segmentCount.

Documentation of SCNSphere

Par défaut la valeur segmentCount est réglé sur 48, ce qui est pas très finement grainée. Si vous exécutez un hitTest: sur un SCNSphere avec un segment de segment faible, les polygones ayant un décalage par rapport au point de contact réel seront récupérés. En augmentant le segmentCount (par exemple 96), les segments dans les directions horizontale et verticale sont augmentés et le décalage diminue. Gardez à l'esprit que l'augmentation de segmentCount aura un impact sur les performances.