- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 SCNPlane,当检测到水平表面有足够的区域时,它会添加到场景中。根据放置的地板/ table ,飞机似乎放置在正确的位置。问题是当我将一个 SCNNode(无论它是一个盒子、金字塔、3D 模型等,这一直是一致的)放到平面上时,它最终会找到一个着陆点并且 99% 的节点开始疯狂地摇晃。很少有几次它只是着陆而根本没有移动。我还认为这可能是由于节点掉落并稍微低于平面表面造成的。它既不在平面的“顶部”,也不在平面的“下方”。也许节点正在崩溃,因为它在两个级别之间摇摆不定?
这是一段视频,您可以在开始时看到盒子在平面下方和上方,橙色盒子在与深蓝色盒子碰撞时确实停止了,但又回到了摇晃的方式当绿色盒子最后与它碰撞时:
代码在github 上
我还将展示一些嵌入代码中的相关部分:
我只是创建一个 Plane 类以在需要时添加到场景中
class Plane: SCNNode {
var anchor :ARPlaneAnchor
var planeGeometry :SCNPlane!
init(anchor :ARPlaneAnchor) {
self.anchor = anchor
super.init()
setup()
}
func update(anchor: ARPlaneAnchor) {
self.planeGeometry.width = CGFloat(anchor.extent.x)
self.planeGeometry.height = CGFloat(anchor.extent.z)
self.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z)
let planeNode = self.childNodes.first!
planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: self.planeGeometry, options: nil))
}
private func setup() {
//plane dimensions
self.planeGeometry = SCNPlane(width: CGFloat(self.anchor.extent.x), height: CGFloat(self.anchor.extent.z))
//plane material
let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "tronGrid.png")
self.planeGeometry.materials = [material]
//plane geometry and physics
let planeNode = SCNNode(geometry: self.planeGeometry)
planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(geometry: self.planeGeometry, options: nil))
planeNode.physicsBody?.categoryBitMask = BodyType.plane.rawValue
planeNode.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z)
planeNode.transform = SCNMatrix4MakeRotation(Float(-Double.pi / 2.0), 1, 0, 0)
//add plane node
self.addChildNode(planeNode)
}
这是 View Controller
enum BodyType: Int {
case box = 1
case pyramid = 2
case plane = 3
}
class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate {
//outlets
@IBOutlet var sceneView: ARSCNView!
//globals
var planes = [Plane]()
var boxes = [SCNNode]()
//life cycle
override func viewDidLoad() {
super.viewDidLoad()
//set sceneView's frame
self.sceneView = ARSCNView(frame: self.view.frame)
//add debugging option for sceneView (show x, y , z coords)
self.sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
//give lighting to the scene
self.sceneView.autoenablesDefaultLighting = true
//add subview to scene
self.view.addSubview(self.sceneView)
// Set the view's delegate
sceneView.delegate = self
//subscribe to physics contact delegate
self.sceneView.scene.physicsWorld.contactDelegate = self
//show statistics such as fps and timing information
sceneView.showsStatistics = true
//create new scene
let scene = SCNScene()
//set scene to view
sceneView.scene = scene
//setup recognizer to add scooter to scene
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
sceneView.addGestureRecognizer(tapGestureRecognizer)
}
//MARK: helper funcs
@objc func tapped(recognizer: UIGestureRecognizer) {
let scnView = recognizer.view as! ARSCNView
let touchLocation = recognizer.location(in: scnView)
let touch = scnView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
//take action if user touches box
if !touch.isEmpty {
guard let hitResult = touch.first else { return }
addBox(hitResult: hitResult)
}
}
private func addBox(hitResult: ARHitTestResult) {
let boxGeometry = SCNBox(width: 0.1,
height: 0.1,
length: 0.1,
chamferRadius: 0)
let material = SCNMaterial()
material.diffuse.contents = UIColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1.0)
boxGeometry.materials = [material]
let boxNode = SCNNode(geometry: boxGeometry)
//adding physics body, a box already has a shape, so nil is fine
boxNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
//set bitMask on boxNode, enabling objects with diff categoryBitMasks to collide w/ each other
boxNode.physicsBody?.categoryBitMask = BodyType.plane.rawValue | BodyType.box.rawValue
boxNode.position = SCNVector3(hitResult.worldTransform.columns.3.x,
hitResult.worldTransform.columns.3.y + 0.3,
hitResult.worldTransform.columns.3.z)
self.sceneView.scene.rootNode.addChildNode(boxNode)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
//track objects in ARWorld and start session
sceneView.session.run(configuration)
}
//MARK: - ARSCNViewDelegate
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//if no anchor found, don't render anything!
if !(anchor is ARPlaneAnchor) {
return
}
DispatchQueue.main.async {
//add plane to scene
let plane = Plane(anchor: anchor as! ARPlaneAnchor)
self.planes.append(plane)
node.addChildNode(plane)
//add initial scene object
let pyramidGeometry = SCNPyramid(width: CGFloat(plane.planeGeometry.width / 8), height: plane.planeGeometry.height / 8, length: plane.planeGeometry.height / 8)
pyramidGeometry.firstMaterial?.diffuse.contents = UIColor.white
let pyramidNode = SCNNode(geometry: pyramidGeometry)
pyramidNode.name = "pyramid"
pyramidNode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)
pyramidNode.physicsBody?.categoryBitMask = BodyType.pyramid.rawValue | BodyType.plane.rawValue
pyramidNode.physicsBody?.contactTestBitMask = BodyType.box.rawValue
pyramidNode.position = SCNVector3(-(plane.planeGeometry.width) / 3, 0, plane.planeGeometry.height / 3)
node.addChildNode(pyramidNode)
}
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
let plane = self.planes.filter {
plane in return plane.anchor.identifier == anchor.identifier
}.first
if plane == nil {
return
}
plane?.update(anchor: anchor as! ARPlaneAnchor)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//pause session
sceneView.session.pause()
}
}
最佳答案
我想我遵循了相同的教程。我也有同样的结果。原因是立方体从高处下落时加速,并没有恰好撞在平面上,而是穿过了。如果将立方体缩小到“1 毫米”,您可以看到盒子完全穿过平面并继续下降到平面以下。
您可以尝试将立方体从离平面较近的地方放下,盒子下降得更慢,并且不会发生这种“抖动”。或者您可以尝试使用高度较小的盒子而不是平面。
关于ios - 为什么 SCNNode "jiggling"掉落到 SCNPlane 上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48329115/
抱歉,我不知道如何正确表达标题。但我正在制作一个 Java 游戏,屏幕底部有一个桨,您可以左右移动它以避免小行星坠落。我的桨可以工作,但我不知道如何制作一颗下落的小行星。小行星目前只是一个矩形。我还希
我制作了一个 x=25 & y= 25 的正方形并附加了一个 SKPhysicsBody。我制作了一个标准平台关卡,其中有几个高的下降区域。我希望正方形“破裂”/因从高处坠落而受到损坏。我查了一下维基
我是一名初级游戏程序员,我正在学习如何使用适用于 Android 的 AndEngine。我想让一个 Sprite 从屏幕上掉下来,并在用户触摸时向上跳。关于如何做到这一点的任何想法?如果这样更容易,
我刚刚开始在我的 Ogre 项目中实现 bullet。我按照此处的安装说明进行操作:http://www.ogre3d.org/tikiwiki/OgreBullet+Tutorial+1 剩下的教程
将我的项目升级到 iOS7 后 当我执行 BACK 按钮并且 UINavigationController 返回上一页时,屏幕顶部的 ImageView 会向下移动。 我使用 IB 来做我的布局。这些
我有两个内联 div,其中一个内联 div 有两个彼此下方的 div。 JSFiddle 点击#notLoginStudentBtn 我在做什么我正在切换#notLoginStudentBox 但在切
我有一个移动的对象,它生成由滑动关节连接的 object2 当我按下按钮时,关节被移除,object2 在重力作用下落下 这可行,但只在 x 轴上落下而不会保持其 y 轴速度。 如何让 Object2
如何从购物车中删除商品? 自然地,您希望能够将项目拖放回去。 $(function() { $( "#catalog" ).accordion(); $( "#cata
Swift 标准库中是否有作用于集合、采用谓词并返回从该集合中移除的值的函数? 目前,我必须分两步实现它: guard let idx = allAnnotations.index(where: {$
我真的需要一些关于我的游戏对象的帮助。 我正在开发一款游戏,我想要一个拾取元素来产生物理力爆炸来炸毁敌人。我做了一个简单的炸弹对象来测试这个想法。我添加了一个简单的代码,使用一个循环来收集其半径内的所
平台:iOS (Swift)Mapbox SDK版本:3.6 嗨,我有一个自定义 MGLCalloutView,当我点击 MGLAnnotationView 时,标注会按预期显示在注释上方,但如果我稍
我正在使用 WKWebView 查看自定义 HTML。 无论 HTML 内容如何,在真实设备上进行测试时,我都会在 Could not signal service com.apple.WebKi
我正在使用 WKWebView 查看自定义 HTML。 无论 HTML 内容如何,在真实设备上进行测试时,我都会在 Could not signal service com.apple.WebKi
我是一名优秀的程序员,十分优秀!