2

以下のコードは、タッチ座標を SceneKit シーンのワールド座標に変換する必要があります。

ただし、以下の出力に示されているように、 によってunprojectPoint返されるポイントは、画面のどこをタッチしても事実上同じポイントを返します (iPhone 5s)。

のクラス ドキュメントでunprojectPointは、0 から 1 の間の Z 値を使用することを提案していますが、0.5 などの異なる値を使用しても の出力は変化しませんでしたunprojectPoint

This SO postでは、 の深さの値を設定する方法について説明してunprojectPointいますが、Z 値を 1 より大きい値 (15、20 など) に設定しても、出力は変わりませんでした。

どちらの場合も、から返される X 値と Y 値はunprojectPoint事実上同じままでした。

1) 正しい使い方はunprojectPoint?

unprojectPoint2)カメラの回転はどのように考慮されますか? たとえば、カメラを (0, 20, 0) に移動し、カメラを 90 度下に回転させて地面に向けた場合、回転が確実に考慮されるようにするにはどうすればよいでしょうか? 深さを 20 に設定して原点をタップした場合、目的の戻り値はunprojectPoint(0, 0, 0) になります。

3) カメラの前で値を返すにはどうすればよいですかunprojectPoint(たとえば、Z 値はカメラの Z 値よりも低い)。

コード:

cameraNode.position = SCNVector3(x: 0, y: Float(0), z: Float(8))

func sceneViewTapped(recognizer: UITapGestureRecognizer) {
    let point = recognizer.locationInView(sceneView)
    let unprojectPoint = SCNVector3(x: Float(point.x), y: Float(point.y), z: 0.0)
    let scenePos = sceneView.unprojectPoint(unprojectPoint)
    print("2D point: \(point). 3D point: \(scenePos)")
}

出力:

2D ポイント: (154.5, 169.5)。3D ポイント: SCNVector3(x: -0.00111810782、y: 0.0232769605、z: 7.9000001)

2D ポイント: (280.5, 252.0)。3D ポイント: SCNVector3(x: 0.0244967155、y: 0.00650534919、z: 7.9000001)

2D ポイント: (32.0, 181.0)。3D ポイント: SCNVector3(x: -0.0260214079、y: 0.0209390987、z: 7.9000001)

2D ポイント: (12.0, 505.0)。3D ポイント: SCNVector3(x: -0.0300872531、y: -0.0449275821、z: 7.9000001)

2D ポイント: (311.5, 12.5)。3D ポイント: SCNVector3(x: 0.0307987742、y: 0.0551938377、z: 7.9000001)

2D ポイント: (22.5、88.0)。3D ポイント: SCNVector3(x: -0.0279526841、y: 0.0398452766、z: 7.9000001)

2D ポイント: (313.5, 358.0)。3D ポイント: SCNVector3(x: 0.0312053617、y: -0.0150436237、z: 7.9000001)

2D ポイント: (314.0, 507.0)。3D ポイント: SCNVector3(x: 0.0313070044、y: -0.0453341678、z: 7.9000001)

2D ポイント: (155.0, 360.5)。3D ポイント: SCNVector3(x: -0.00101646129、y: -0.0155518558、z: 7.9000001)

4

1 に答える 1

0

0 と 1 を使用している限り、値は変化しますunprojectPoint.。Z 値に 0 を使用すると近平面上のポイントを表し、1 を使用すると遠平面上のポイントを表します。

そこで、カメラから任意の距離にあるシーン ポイントを返すために、次の関数を開発しました。SceneKit は初めてなので、編集や修正を提供してください!

事実上、近点と遠点の間の光線/線を定義してから、線に沿っていくつかの点を選択します。

private func touchPointToScenePoint(recognizer: UIGestureRecognizer) -> SCNVector3 {
    // Get touch point
    let touchPoint = recognizer.locationInView(sceneView)

    // Compute near & far points
    let nearVector = SCNVector3(x: Float(touchPoint.x), y: Float(touchPoint.y), z: 0)
    let nearScenePoint = sceneView.unprojectPoint(nearVector)
    let farVector = SCNVector3(x: Float(touchPoint.x), y: Float(touchPoint.y), z: 1)
    let farScenePoint = sceneView.unprojectPoint(farVector)

    // Compute view vector
    let viewVector = SCNVector3(x: Float(farScenePoint.x - nearScenePoint.x), y: Float(farScenePoint.y - nearScenePoint.y), z: Float(farScenePoint.z - nearScenePoint.z))

    // Normalize view vector
    let vectorLength = sqrt(viewVector.x*viewVector.x + viewVector.y*viewVector.y + viewVector.z*viewVector.z)
    let normalizedViewVector = SCNVector3(x: viewVector.x/vectorLength, y: viewVector.y/vectorLength, z: viewVector.z/vectorLength)

    // Scale normalized vector to find scene point
    let scale = Float(15)
    let scenePoint = SCNVector3(x: normalizedViewVector.x*scale, y: normalizedViewVector.y*scale, z: normalizedViewVector.z*scale)

    print("2D point: \(touchPoint). 3D point: \(nearScenePoint). Far point: \(farScenePoint). scene point: \(scenePoint)")

    // Return <scenePoint>
    return scenePoint
}
于 2016-09-11T04:27:35.000 に答える