web-dev-qa-db-ja.com

ARKit SCNNodeをカメラに向けて配置します

3Dオブジェクトを表示するためにARKitを使用しています。実世界のノードをユーザー(カメラ)の前に配置することができました。でも、落とすとなんとかカメラを向くことができません。

let tap_point=CGPoint(x: x, y: y)
let results=arscn_view.hitTest(tap_point, types: .estimatedHorizontalPlane)
guard results.count>0 else{
    return
}
guard let r=results.first else{
    return
}

let hit_tf=SCNMatrix4(r.worldTransform)
let new_pos=SCNVector3Make(hit_tf.m41, hit_tf.m42+Float(0.2), hit_tf.m43)

guard let scene=SCNScene(named: file_name) else{
    return
}
guard let node=scene.rootNode.childNode(withName: "Mesh", recursively: true) else{
    return
}
node.position=new_pos
arscn_view.scene.rootNode.addChildNode(node)

ノードは、カメラの前の平面上に適切に配置されています。しかし、彼らは皆同じ​​方向を見ています。 rotate the SCNNodeと思いますが、どうにかできませんでした。

12
Marie Dm

まず、カメラの回転行列を取得します。

let rotate = simd_float4x4(SCNMatrix4MakeRotation(sceneView.session.currentFrame!.camera.eulerAngles.y, 0, 1, 0))

次に、行列を結合します。

let rotateTransform = simd_mul(r.worldTransform, rotate)

最後に、ノードに変換を適用し、SCNMatrix4としてキャストします。

node.transform = SCNMatrix4(rotateTransform)

それが役に立てば幸い

[〜#〜]編集[〜#〜]

ここでは、simd_float4x4からSCNMatrix4を作成する方法を説明します。

   let rotateTransform = simd_mul(r.worldTransform, rotate)

  node.transform =  SCNMatrix4(m11: rotateTransform.columns.0.x, m12: rotateTransform.columns.0.y, m13: rotateTransform.columns.0.z, m14: rotateTransform.columns.0.w, m21: rotateTransform.columns.1.x, m22: rotateTransform.columns.1.y, m23: rotateTransform.columns.1.z, m24: rotateTransform.columns.1.w, m31: rotateTransform.columns.2.x, m32: rotateTransform.columns.2.y, m33: rotateTransform.columns.2.z, m34: rotateTransform.columns.2.w, m41: rotateTransform.columns.3.x, m42: rotateTransform.columns.3.y, m43: rotateTransform.columns.3.z, m44: rotateTransform.columns.3.w)
6
modium

これは、カメラに面しているSCNNodeの私のコードです。誰かの助けを願っています

    let location = touches.first!.location(in: sceneView)

    var hitTestOptions = [SCNHitTestOption: Any]()
    hitTestOptions[SCNHitTestOption.boundingBoxOnly] = true

    let hitResultsFeaturePoints: [ARHitTestResult]  = sceneView.hitTest(location, types: .featurePoint)

    let hitTestResults = sceneView.hitTest(location)
    guard let node = hitTestResults.first?.node else {
        if let hit = hitResultsFeaturePoints.first {
            let rotate = simd_float4x4(SCNMatrix4MakeRotation(sceneView.session.currentFrame!.camera.eulerAngles.y, 0, 1, 0))
            let finalTransform = simd_mul(hit.worldTransform, rotate)
            sceneView.session.add(anchor: ARAnchor(transform: finalTransform))
        }
        return
    }
3
Caleb

カメラが動いているときでも、ノードを常にカメラに向けますか?それがSceneKit constraints の目的です。 SCNLookAtConstraintまたはSCNBillboardConstraintは、ノードを常にカメラに向け続けることができます。

配置時にノードをカメラの方に向けますが、それでも静止させますか(カメラを動かしてその背面を見ることができます)?それにはいくつかの方法があります。いくつかは楽しい数学を含みますが、それを処理するより簡単な方法は、「正面」が常に正のZ軸方向になるように3Dアセットを設計することかもしれません。配置されたオブジェクトの変換をカメラの変換に基づいて設定します。その初期方向はカメラの向きと一致します。

1
rickster

ここに私がそれをした方法があります:

func faceCamera() {
    guard constraints?.isEmpty ?? true else {
        return
    }
    SCNTransaction.begin()
    SCNTransaction.animationDuration = 5
    SCNTransaction.completionBlock = { [weak self] in
        self?.constraints = []
    }
    constraints = [billboardConstraint]
    SCNTransaction.commit()
}

private lazy var billboardConstraint: SCNBillboardConstraint = {
    let constraint = SCNBillboardConstraint()
    constraint.freeAxes = [.Y]
    return constraint
}()

前述のように、SCNBillboardConstraintを指定すると、ノードは常にカメラを見ます。私はそれをアニメーション化して、ノードがすぐに所定の位置にスナップするのではなく、これはオプションです。の中に SCNTransaction.completionBlock制約を削除します。これもオプションです。

また、SCNBillboardConstraintfreeAxesを設定します。これは、ノードがカメラを追跡する軸をカスタマイズしますが、これもオプションです。

1
Quan Vo

配置するときにノードをカメラに向け、ここに保持します(そして移動できるようにします)。 –マリーDm Blockquote

これを使用して、オブジェクトをカメラに向けることができます:

if let rotate = sceneView.session.currentFrame?.camera.transform {
    node.simdTransform = rotate
}

このコードは ジンバルロック およびその他の問題からあなたを救います。

4つのコンポーネントの回転ベクトルは、最初の3つのコンポーネントの回転軸の方向と4番目のコンポーネントの回転角度(ラジアン)を指定します。デフォルトの回転はゼロベクトルで、回転なしを指定します。回転は、ノードのsimdPivotプロパティを基準にして適用されます。

SimdRotation、simdEulerAngles、およびsimdOrientationプロパティはすべて、ノードのsimdTransformプロパティの回転の側面に影響します。これらのプロパティの1つを変更すると、他のプロパティにも反映されます。

https://developer.Apple.com/documentation/scenekit/scnnode/2881845-simdrotationhttps://developer.Apple.com/documentation/scenekit/scnnode/2881843-simdtransform

0
Denis Markov
guard let frame = self.sceneView.session.currentFrame else {
    return
}
node.eulerAngles.y = frame.camera.eulerAngles.y
0
iOS Unit