将 UIView 设置为 SCNMaterial 内容
Set UIView as SCNMaterial content
我正在尝试将 UIView 与 Arkit 3D space 结合使用。我已经看到一些示例需要将 UIView 或 UIView 的图层设置为 SCNMaterial 对象的漫反射内容。到目前为止,这并不像我预期的那样有效。我只看到视图的框架,但其中的子视图没有添加,图层上的角半径也不可见。
func setupBillBoard() {
let view = PlayerView(frame: CGRect(x: 0, y: 0, width: 70, height: 40))
view.backgroundColor = .red
view.layer.cornerRadius = 14
let material = SCNMaterial()
material.diffuse.contents = view.asImage()
material.isDoubleSided = true
let plane = SCNPlane(width: 1, height: 1)
plane.materials = [material]
let node = SCNNode()
node.geometry = plane
node.position = SCNVector3(box.x, box.y + 0.3, box.z - 0.4)
node.scale = SCNVector3(0.4, 0.4, 0.4)
self.billBoardNode = node
}
将 UIView 转换为图像捕获的视图扩展
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
到目前为止,我在场景中只得到一个红色方形视图,仅此而已
此处自定义 class 代码:https://www.paste.org/106551
附图中的 Xib
这是我设置地雷的方法,效果很好。您应该能够将函数复制并粘贴到 viewDidLoad
中,您会看到一个红色圆圈。您也可以使用 UIImageView
而不是 UIView
.
创建自定义 UIView
后调用 yourView.layoutIfNeeded()
,然后再将其添加到 SCNMaterial
。
您还可以在几何体上设置拐角半径:plane.cornerRadius = 0.015
就像我在 createAndPositionGrayNode()
中所做的那样
override func viewDidLoad() {
super.viewDidLoad()
createAndPositionRedCircleNode()
// or try it with an imageView, comment out the line above
// createAndPositionGrayNode()
}
func createAndPositionRedCircleNode() {
let redImage = UIColor.red.imageRepresentation
let myView = UIView()
myView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
myView.layer.contents = redImage.cgImage
myView.layoutIfNeeded() // <-- myView.layoutIfNeeded() called here
myView.layer.contentsGravity = CALayerContentsGravity.resizeAspectFill
myView.layer.contentsScale = UIScreen.main.scale
myView.layer.masksToBounds = true
myView.layer.cornerRadius = myView.frame.width / 2
let convertedImage = myView.asImage()
let material = SCNMaterial()
material.diffuse.contents = convertedImage
let plane = SCNPlane(width: 0.15, height: 0.15)
plane.materials = [material]
plane.firstMaterial?.isDoubleSided = true
let redNode = SCNNode(geometry: plane)
redNode.name = "redNode"
redNode.position = SCNVector3(0.0, 0.2, -0.7)
sceneView.scene.rootNode.addChildNode(redNode)
}
func createAndPositionGrayNode() {
let lightGrayImage = UIColor.lightGray.imageRepresentation
let imageView = UIImageView()
imageView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
imageView.image = lightGrayImage
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = .clear
imageView.layer.masksToBounds = true
let material = SCNMaterial()
material.diffuse.contents = imageView.image
let plane = SCNPlane(width: 0.4, height: 0.4)
plane.materials = [material]
plane.firstMaterial?.isDoubleSided = true
plane.cornerRadius = 0.015 // <-- geometry cornerRadius set here
let grayNode = SCNNode(geometry: plane)
grayNode.name = "grayNode"
grayNode.position = SCNVector3(0.0, 0.2, -0.7)
sceneView.scene.rootNode.addChildNode(grayNode)
}
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
我正在尝试将 UIView 与 Arkit 3D space 结合使用。我已经看到一些示例需要将 UIView 或 UIView 的图层设置为 SCNMaterial 对象的漫反射内容。到目前为止,这并不像我预期的那样有效。我只看到视图的框架,但其中的子视图没有添加,图层上的角半径也不可见。
func setupBillBoard() {
let view = PlayerView(frame: CGRect(x: 0, y: 0, width: 70, height: 40))
view.backgroundColor = .red
view.layer.cornerRadius = 14
let material = SCNMaterial()
material.diffuse.contents = view.asImage()
material.isDoubleSided = true
let plane = SCNPlane(width: 1, height: 1)
plane.materials = [material]
let node = SCNNode()
node.geometry = plane
node.position = SCNVector3(box.x, box.y + 0.3, box.z - 0.4)
node.scale = SCNVector3(0.4, 0.4, 0.4)
self.billBoardNode = node
}
将 UIView 转换为图像捕获的视图扩展
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}
到目前为止,我在场景中只得到一个红色方形视图,仅此而已
此处自定义 class 代码:https://www.paste.org/106551 附图中的 Xib
这是我设置地雷的方法,效果很好。您应该能够将函数复制并粘贴到 viewDidLoad
中,您会看到一个红色圆圈。您也可以使用 UIImageView
而不是 UIView
.
创建自定义 UIView
后调用 yourView.layoutIfNeeded()
,然后再将其添加到 SCNMaterial
。
您还可以在几何体上设置拐角半径:plane.cornerRadius = 0.015
就像我在 createAndPositionGrayNode()
override func viewDidLoad() {
super.viewDidLoad()
createAndPositionRedCircleNode()
// or try it with an imageView, comment out the line above
// createAndPositionGrayNode()
}
func createAndPositionRedCircleNode() {
let redImage = UIColor.red.imageRepresentation
let myView = UIView()
myView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
myView.layer.contents = redImage.cgImage
myView.layoutIfNeeded() // <-- myView.layoutIfNeeded() called here
myView.layer.contentsGravity = CALayerContentsGravity.resizeAspectFill
myView.layer.contentsScale = UIScreen.main.scale
myView.layer.masksToBounds = true
myView.layer.cornerRadius = myView.frame.width / 2
let convertedImage = myView.asImage()
let material = SCNMaterial()
material.diffuse.contents = convertedImage
let plane = SCNPlane(width: 0.15, height: 0.15)
plane.materials = [material]
plane.firstMaterial?.isDoubleSided = true
let redNode = SCNNode(geometry: plane)
redNode.name = "redNode"
redNode.position = SCNVector3(0.0, 0.2, -0.7)
sceneView.scene.rootNode.addChildNode(redNode)
}
func createAndPositionGrayNode() {
let lightGrayImage = UIColor.lightGray.imageRepresentation
let imageView = UIImageView()
imageView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
imageView.image = lightGrayImage
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = .clear
imageView.layer.masksToBounds = true
let material = SCNMaterial()
material.diffuse.contents = imageView.image
let plane = SCNPlane(width: 0.4, height: 0.4)
plane.materials = [material]
plane.firstMaterial?.isDoubleSided = true
plane.cornerRadius = 0.015 // <-- geometry cornerRadius set here
let grayNode = SCNNode(geometry: plane)
grayNode.name = "grayNode"
grayNode.position = SCNVector3(0.0, 0.2, -0.7)
sceneView.scene.rootNode.addChildNode(grayNode)
}
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
}
}