我在屏幕上定位模型时遇到了一点问题。模型出现了,但它出现在我的上方,而不是我的前面。理想情况下,我希望模型出现在它被点击的地方。请帮帮我!
此函数用于从AWS成功下载模型:
private func dowloadModel(){
let url = URL(string: "url_string")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error{
print(error.localizedDescription)
return
}
if let data = data{
print(data)
let documentDirectories = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
if let documentDirectory = documentDirectories.first{
let fileURL = documentDirectory.appendingPathComponent("Food.scn")
let dataNS : NSData? = data as NSData
try! dataNS?.write(to: fileURL, options: .atomic)
print("Saved!")
}
}
}.resume()
}这里我将模型渲染到屏幕上:
private func registerGestureRecogniser(){
print("Tapped")
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
self.sceneView.addGestureRecognizer(tapGestureRecognizer)
}下面是被点击的函数:
@objc func handleTap(gesture: UITapGestureRecognizer) {
let documentDirectories = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
if let documentDirectory = documentDirectories.first{
let fileURL = documentDirectory.appendingPathComponent("Food.scn")
do{
let scene = try SCNScene(url: fileURL, options: nil)
let node = scene.rootNode.childNode(withName: "Burger", recursively: true)!
node.position = SCNVector3Make(0, 0, 0);
self.sceneView.scene.rootNode.addChildNode(node)
}
catch{
print(error)
}
}
}我也得到了这个错误:
Error: Failed to load <C3DImage发布于 2020-02-19 23:49:09
当你这样做的时候
node.position = SCNVector3Make(0, 0, 0);
self.sceneView.scene.rootNode.addChildNode(node)将模型节点定位在场景的rootNode处,场景启动时,场景的位置由ARKit确定。
如果希望模型出现在摄影机的前面,则需要抓取摄影机变换(session.currentFrame?.camera.transform),修改-z组件,并将其设置为节点的位置。或者,如果要将模型放置在曲面上,请执行光线投射并使用raycastResult simdWorldPosition作为节点的simdWorldPosition。
肯定有raycast的例子,但简而言之,您首先需要定义一个查询:
let bounds = sceneView.bounds
let screenCenter = CGPoint(x: bounds.midX, y: bounds.midY)
let query = sceneView.raycastQuery(from: screenCenter, allowing: .estimatedPlane, alignment: .horizontal)上面定义了从屏幕中心延伸的光线投射,并且只找到水平表面。有关allowing和alignment选项的更多信息,请浏览docs。
然后可以使用session投射光线:
session.raycast(query)这将返回一个ARRaycastResult数组。如果愿意,您可以检查它们并进行选择,但我通常只使用.first one (注意:它可以是空的)。
然后,您需要获取raycastResult转换的转换组件,并将其指定为节点的simdWorldPosition。请注意,可以将整个变换指定给节点simdWorldTransform,但这也会改变节点的方向,您可能希望也可能不希望这样做。
if let raycastResult = session.raycast(query).first {
node.simdWorldPosition = raycastResult.worldTransform.translation
}哦,还有,我发现这个小扩展很方便:
extension float4x4 {
/**
Treats matrix as a (right-hand column-major convention) transform matrix
and factors out the translation component of the transform.
*/
var translation: SIMD3<Float> {
let translation = columns.3
return SIMD3<Float>(translation.x, translation.y, translation.z)
}
}它允许您在上面的代码中执行worldTransform.translation。
https://stackoverflow.com/questions/60303610
复制相似问题