Set UIView as SCNMaterial content

孤人 提交于 2020-06-17 15:58:10

问题


I'm trying to use a UIView with Arkit 3D space. I've seen a few examples which requires the UIView or UIView's layer is set as the diffuse content of the SCNMaterial object. That's not working as I've expected so far. I only see the frame of the view but the subviews within it are not added neither is a corner radius on the layer visible.

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
}

View Extension to convert UIView to image capture

    extension UIView {
        func asImage() -> UIImage {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        }
    }

So far I get only a red square shaped view in the scene and nothing more

Custom class code here: https://www.paste.org/106551 Xib in attached image


回答1:


Here's the way i set mines up and it works fine. You should be able to copy and paste the function inside viewDidLoad and you will see a red circle. You can also use an UIImageView instead of a UIView.

After you create you custom UIView call yourView.layoutIfNeeded() before adding it to the SCNMaterial.

You can also set the corner radius on a geometry: plane.cornerRadius = 0.015 like I did in 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)
        }
    }
}


来源:https://stackoverflow.com/questions/62286757/set-uiview-as-scnmaterial-content

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!