Scene Set - Drag and Drop

I am trying to drag a shape with the mouse / trackpad using the Scene Kit. All objects (board and pieces) are children of the root node loaded from the Collada file.

I found a useful description of the process elsewhere in the stack overflow . Using this description, I wrote the original version of the code below. My problem is the discrepancy between the click coordinates and the node position - their coordinates are in different orders. I remain unclear how to match them - put them in the "same universe." Ive tried a number of suggestions from the Apple forums, as well as fantasy flights of my own.

Here is my current attempt, basically reverting to the original version based on the link above, along with the registered coordinate values ​​along the way. The result is that dragging a chess piece makes it jump sharply from the screen:

- (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;
}

Until that moment, I had a lot of interesting and useful comments and tips. But I realized that in order to move forward, I probably would need a sample working code that shows a secret sauce that allows clicks and vectors to exist in the "same universe."

+4
source share
2 answers

You do not need to “play” to find the source. You can make the code as follows:

let originZ = sceneView.projectPoint(SCNVector3Zero).z
let viewLocation = /* Location in SCNView coordinate system */
let viewLocationWithOriginZ = SCNVector3(
  x: Float(viewLocation.x), // X & Y are in view coordinate system
  y: Float(viewLocation.y),
  z: originZ                // Z is in scene coordinate system
)
var position = sceneView.unprojectPoint(viewLocationWithOriginZ)
/* "position" is in the scene coordinate system with z of 0 */
+1

unprojectPoint. , z-, ( , , ). , touch- iOS. , :

let convertedTranslation = scnView.unprojectPoint(SCNVector3Make(Float(translation.x), Float(translation.y), 1.0))

, z 1. , -1 1. -1 0 , .

0

Source: https://habr.com/ru/post/1540933/


All Articles