Tôi gặp phải vấn đề giống hệt nhau khi triển khai trực quan hóa máy bay trong ARKit. Tôi muốn hình dung mặt phẳng được phát hiện như một mẫu bàn cờ. Tôi đã sửa nó bằng cách tạo một tùy chỉnh SCNNode được gọi là "PlaneNode" với cấu hình chính xác SCNMaterial. Vật liệu sử dụng wrapS, wrapT = .repeat và tính toán tỉ lệ chính xác dựa trên kích thước của bản thân mặt phẳng.
Trông như thế này:
Hãy nhìn vào mã bên dưới, các ý kiến inline chứa lời giải thích.
class PlaneNode : SCNNode {
init(planeAnchor: ARPlaneAnchor) {
super.init()
// Create the 3D plane geometry with the dimensions reported
// by ARKit in the ARPlaneAnchor instance
let planeGeometry = SCNPlane(width:CGFloat(planeAnchor.extent.x), height:CGFloat(planeAnchor.extent.z))
// Instead of just visualizing the grid as a gray plane, we will render
// it in some Tron style colours.
let material = SCNMaterial()
material.diffuse.contents = PaintCode.imageOfViewARPlane
//the scale gives the number of times the image is repeated
//ARKit givest the width and height in meters, in this case we want to repeat
//the pattern each 2cm = 0.02m so we divide the width/height to find the number of patterns
//we then round this so that we always have a clean repeat and not a truncated one
let scaleX = (Float(planeGeometry.width)/0.02).rounded()
let scaleY = (Float(planeGeometry.height)/0.02).rounded()
//we then apply the scaling
material.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
//set repeat mode in both direction otherwise the patern is stretched!
material.diffuse.wrapS = .repeat
material.diffuse.wrapT = .repeat
//apply material
planeGeometry.materials = [material];
//make a node for it
self.geometry = planeGeometry
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
// Planes in SceneKit are vertical by default so we need to rotate
// 90 degrees to match planes in ARKit
transform = SCNMatrix4MakeRotation(-Float.pi/2.0, 1.0, 0.0, 0.0);
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(planeAnchor: ARPlaneAnchor) {
guard let planeGeometry = geometry as? SCNPlane else {
fatalError("update(planeAnchor: ARPlaneAnchor) called on node that has no SCNPlane geometry")
}
//update the size
planeGeometry.width = CGFloat(planeAnchor.extent.x)
planeGeometry.height = CGFloat(planeAnchor.extent.z)
//and material properties
let scaleX = (Float(planeGeometry.width)/0.02).rounded()
let scaleY = (Float(planeGeometry.height)/0.02).rounded()
planeGeometry.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(scaleX, scaleY, 0)
// Move the plane to the position reported by ARKit
position.x = planeAnchor.center.x
position.y = 0
position.z = planeAnchor.center.z
}
}
tìm cách để thực hiện việc này trong GUI? – jfisk
@jfisk Thật không may là không. Đoán tốt nhất của tôi là sử dụng sprites theo một cách nào đó, nhưng tôi đã không xem xét nó đủ để đưa ra một câu trả lời hay. – krntz