15

ARKit用来显示 3D 对象。我设法将现实世界中的节点放置在用户面前(也就是相机)。但是当我放下它们时,我无法让它们面对镜头。

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)

节点很好地定位在平面上,在相机前面。但他们都在朝着同一个方向看。我想我应该轮换SCNNode但我没能做到这一点。

4

6 回答 6

8

首先,得到相机的旋转矩阵:

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)
于 2018-01-08T03:24:47.900 回答
4
guard let frame = self.sceneView.session.currentFrame else {
    return
}
node.eulerAngles.y = frame.camera.eulerAngles.y
于 2019-03-01T11:05:19.790 回答
3

这是我面向相机的 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
    }
于 2018-06-27T12:31:36.010 回答
2

您是否希望节点始终面向相机,即使相机移动?这就是 SceneKit约束的用途。要么 要么SCNLookAtConstraint可以SCNBillboardConstraint保持节点始终指向相机。

您是否希望节点在放置时面向相机,然后保持静止(这样您就可以移动相机并看到它的背面)?有几种方法可以做到这一点。有些涉及有趣的数学,但处理它的更简单方法可能只是设计您的 3D 资产,使“正面”始终位于 Z 轴正方向。根据相机变换设置放置对象的变换,其初始方向将与相机匹配。

于 2017-09-13T15:49:17.480 回答
1

我希望节点在放置时面向相机,然后将其保留在此处(并且能够四处移动)。– Marie Dm Blockquote

您可以使用以下方法将对象面向相机:

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

此代码将使您免于万向节锁定和其他麻烦。

四分量旋转向量在前三个分量中指定旋转轴的方向,在第四分量中指定旋转角度(以弧度为单位)。默认旋转是零向量,指定不旋转。相对于节点的 simdPivot 属性应用旋转。

simdRotation、simdEulerAngles 和 simdOrientation 属性都会影响节点的 simdTransform 属性的旋转方面。对这些属性之一的任何更改都会反映在其他属性中。

https://developer.apple.com/documentation/scenekit/scnnode/2881845-simdrotation https://developer.apple.com/documentation/scenekit/scnnode/2881843-simdtransform

于 2019-01-28T17:06:58.837 回答
1

我是这样做的:

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

如前所述,aSCNBillboardConstraint将使节点始终看着相机。我正在对其进行动画处理,因此节点不会立即卡入到位,这是可选的。在SCNTransaction.completionBlockI 中删除约束,也是可选的。

我还设置了SCNBillboardConstraint's freeAxes,它自定义了节点跟随相机的轴,这也是可选的。

于 2018-06-27T12:17:31.683 回答