How do I find my mouse point in a scene using SceneKit?

后端 未结 3 687
借酒劲吻你
借酒劲吻你 2020-12-01 04:11

I have set up a scene in SceneKit and have issued a hit-test to select an item. However, I want to be able to move that item along a plane in my scene. I continue to receive

3条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-01 04:33

    As an experiment I implemented Mr Bishop's helpful answer. The drag doesn't quite work (the object - a chess piece - jumps off screen) because of differences in the coordinate magnitudes between the mouse click and the 3-D world. I've inserted log outputs here and there among the code.

    I asked on the Apple forums if anyone knew the secret sauce to homogenize the coordinates but didn't get a decisive answer. One thing, I had made some experimental changes to Mr Bishop's method and the forum members advised me to return to his technique.

    Despite my code's failings, I thought someone might find it a useful starting point. I suspect there are only one or two small problems with the code.

    Note that the log of the world transform matrix of the object (chess piece) is not part of the process but one Apple forum member advised me that the matrix often offers a useful 'sanity check' - which indeed it did.

    - (NSPoint)
    viewPointForEvent: (NSEvent *) event_
    {
        NSPoint   windowPoint    = [event_ locationInWindow];
        NSPoint   viewPoint        = [self.view convertPoint: windowPoint
                                                 fromView: nil];
        return viewPoint;
    }
    
    - (SCNHitTestResult *)
    hitTestResultForEvent: (NSEvent *) event_
    {
        NSPoint      viewPoint        = [self viewPointForEvent: event_];
        CGPoint      cgPoint        = CGPointMake (viewPoint.x, viewPoint.y);
        NSArray * points        = [(SCNView *) self.view hitTest: cgPoint
                                                         options: @{}];
        return points.firstObject;
    }
    
    - (void)
    mouseDown: (NSEvent *) theEvent
    {
        SCNHitTestResult * result = [self hitTestResultForEvent: theEvent];
    
        SCNVector3 clickWorldCoordinates = result.worldCoordinates;
        log output: clickWorldCoordinates x 208.124578, y -12827.223365, z 3163.659073
        SCNVector3 screenCoordinates = [(SCNView *) self.view projectPoint: clickWorldCoordinates];
        log output: screenCoordinates x 245.128906, y 149.335938, z 0.985565
        // save the z coordinate for use in mouseDragged
        mouseDownClickOnObjectZCoordinate = screenCoordinates.z;
    
        selectedPiece = result.node;  // save selected piece for use in mouseDragged
    
        SCNVector3    piecePosition = selectedPiece.position;
        log output: piecePosition x -18.200000, y 6.483060, z 2.350000
    
        offsetOfMouseClickFromPiece.x = clickWorldCoordinates.x - piecePosition.x;
        offsetOfMouseClickFromPiece.y = clickWorldCoordinates.y - piecePosition.y;
        offsetOfMouseClickFromPiece.z = clickWorldCoordinates.z - piecePosition.z;
        log output: offsetOfMouseClickFromPiece x 226.324578, y -12833.706425, z 3161.309073  
    }
    
    - (void)
    mouseDragged: (NSEvent *) theEvent;
    {
        NSPoint   viewClickPoint        = [self viewPointForEvent: theEvent];
    
        SCNVector3 clickCoordinates;
        clickCoordinates.x = viewClickPoint.x;
        clickCoordinates.y = viewClickPoint.y;
        clickCoordinates.z = mouseDownClickOnObjectZCoordinate;
        log output:  clickCoordinates x 246.128906, y 0.000000, z 0.985565
    
        log output:  pieceWorldTransform: 
          m11 = 242.15889219510001, m12 = -0.000045609300002524833, m13 = -0.00000721691076126, m14 = 0, 
          m21 = 0.0000072168760805499971, m22 = -0.000039452697396149999, m23 = 242.15890446329999, m24 = 0, 
          m31 = -0.000045609300002524833, m32 = -242.15889219510001, m33 = -0.000039452676995750002, m34 = 0, 
          m41 = -4268.2349924762348, m42 = -12724.050221935429, m43 = 4852.6652710104272, m44 = 1)
    
        SCNVector3 newPiecePosition;
        newPiecePosition.x = offsetOfMouseClickFromPiece.x + clickCoordinates.x;
        newPiecePosition.y = offsetOfMouseClickFromPiece.y + clickCoordinates.y;
        newPiecePosition.z = offsetOfMouseClickFromPiece.z + clickCoordinates.z;
        log output: newPiecePosition x 472.453484, y -12833.706425, z 3162.294639
    
        selectedPiece.position = newPiecePosition;
    }
    

提交回复
热议问题