我正在尝试建立一个应用程序,你可以把骰子放在桌子上,如果应用程序检测到了水平平面,就会自动产生。我将在代码之后解释这个问题:
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
var isTableAdded = false
var diceArray = [SCNNode]()
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
self.sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints]
sceneView.autoenablesDefaultLighting = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
// MARK: - ADDS DICE
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Tapped")
if let touch = touches.first {
let touchLocation = touch.location(in: sceneView)
let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
if let hitResults = results.first {
// Create a new scene
let diceScene = SCNScene(named: "art.scnassets/diceCollada.scn")!
if let diceNode = diceScene.rootNode.childNode(withName: "Dice", recursively: true) {
diceNode.position = SCNVector3(
x: hitResults.worldTransform.columns.3.x,
y: hitResults.worldTransform.columns.3.y,
z: hitResults.worldTransform.columns.3.z)
diceArray.append(diceNode)
sceneView.scene.rootNode.addChildNode(diceNode)
}
}
}
}
// MARK: - RENDERS TABLE AT THE HORIZONTAL PLANE
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
print("plane detected")
if isTableAdded == false {
let planeAnchor = anchor
// let planeNode = SCNNode()
let x = planeAnchor.transform.columns.3.x
let y = planeAnchor.transform.columns.3.y
let z = planeAnchor.transform.columns.3.z
//planeNode!.position = SCNVector3(x: x, y: y, z: z)
let idleScene = SCNScene(named: "art.scnassets/Table.scn")!
let node = SCNNode()
for child in idleScene.rootNode.childNodes{
node.addChildNode(child)
}
node.position = SCNVector3(x,y,z)
node.scale = SCNVector3(0.001,0.001,0.001)
sceneView.scene.rootNode.addChildNode(node)
isTableAdded = true
}
print("Model placed")
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
print("plane updated")
}
}问题是这里。(伊姆古尔的视频)。正如您所看到的,表是放置的,但我不太明白如何将SCNScene直接放在另一个表上。我所做的唯一的事情就是在水龙头上建立一个模型,它只放在水平线上。
我怎样才能在另一个模型上产生模型呢?
发布于 2022-12-01 13:35:09
你可以用这个小小的extension来实现你想要的东西。它基本上是一个帮助函数,允许您从任何场景文件(.scn)中抓取所有的几何对象,并且您可以将它们放置在任何您想要的位置。我使用这个函数从大量其他场景文件中构建一个场景(默认),这些文件包含单个的几何图形。它将返回一个SCNNode而不是一个新的SCNScene。告诉我,如果你需要更多的信息,或者如果我想要你。
extension SCNNode {
convenience init(named name: String) {
self.init()
guard let scene = SCNScene(named: name) else {return}
for childNode in scene.rootNode.childNodes {addChildNode(childNode)}
}
}(将此代码片段放置在ViewController__之外的某个地方)
然后你可以像这样使用它:
let objectNode = SCNNode(named:"art.scnassets/some_directory/some_scene.scn").flattenedClone()如果要将信号flattenedClone中的所有几何图形合并到一个对象中,则该SCNNode非常有用。如果您不使用flattenedClone,您将发现您的几何形状是objectNode的单个childNodes。
记住要将静态physicsBody添加到表(可能是地板)和动态physicsBodies到您的骰子,如果您想将它们保持在桌面上,并防止它们掉进地面(地板)。
https://stackoverflow.com/questions/74631408
复制相似问题