1

I am beginner in Scenekit development, I am trying to add UIView as diffuse content of SCNPlane node but getting some weird crash.

Code:

   override func viewDidLoad() {
        super.viewDidLoad()
        let scene = SCNScene()
        let plane = SCNPlane(width: 0.1, height: 0.1)
        plane.firstMaterial?.diffuse.contents = getCustomView()
        let planeNode = SCNNode(geometry: plane)
        planeNode.position = SCNVector3(0, 0, 0)
        scene.rootNode.addChildNode(planeNode)
        sceneView.scene = scene
    }

    func getCustomView() -> UIView {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }

Crash :

enter image description here

I am trying to achieve following output with designing UIView

enter image description here

enter image description here

Please let me know how I can add UIView as SCNNode's diffuse content.

Jarvis The Avenger
  • 2,750
  • 1
  • 19
  • 37

3 Answers3

2

Use this extension to get the image representation from the UIView

public extension UIView {
 @available(iOS 10.0, *)
 var image: UIImage {
    let renderer = UIGraphicsImageRenderer(bounds: bounds)
    return renderer.image { rendererContext in
        layer.render(in: rendererContext.cgContext)
    }
  }
}

And call it on your custom View like the following :

getCustomView().image

And finally on your SCNNode's Plane like the following :

plane.firstMaterial?.diffuse.contents = getCustomView().image
ashif-ismail
  • 1,037
  • 17
  • 34
1

You are mixing Legos and K'Nex here.

Let's go to the documentation and see what is a valid diffuse content for SCNMaterial:

You can set a value for this property using any of the following types:

A color (NSColor/UIColor or CGColor), specifying a uniform color for the material’s surface

A number (NSNumber), specifying a uniform scalar value for the material's surface (useful for physically based properties such as metalness)

An image (NSImage/UIImage or CGImage), specifying a texture to be mapped across the material’s surface

An NSString or NSURL object specifying the location of an image file

A video player (AVPlayer) or live video capture preview (AVCaptureDevice, in iOS only)

A Core Animation layer (CALayer)

A texture (SKTexture, MDLTexture, MTLTexture, or GLKTextureInfo)

A SpriteKit scene (SKScene)

A specially formatted image or array of six images, specifying the faces of a cube map

When you examine elements of a scene loaded from a file, this value is always either a color object (of the NSColor or UIColor class, according to platform) or an image object (of the NSImage or UIImage class, according to platform). You can therefore use type introspection (the isKind(of:) method in Objective-C, or the is operator or let-as matching in Swift) to determine the type of the material property’s contents. https://developer.apple.com/documentation/scenekit/scnmaterialproperty/1395372-contents

Let us look at what UIView is:

class UIView : UIResponder
class UIResponder : NSObject
https://developer.apple.com/documentation/uikit/uiview
https://developer.apple.com/documentation/uikit/uiresponder

As you can see, UIView is not a valid type.

However, UIView does contain a CALayer

https://developer.apple.com/documentation/uikit/uiview/1622436-layer

So you should be able to use that to get what you need from your view:

func getCustomViewLayer() -> CALayer {
    let view = UIView()
    view.backgroundColor = .red
    return view.layer
}
Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44
0

To put a UIView on a SCNNode:

Superficially, it's very simple.

@IBOutlet var anyUIView: UIView!

and then ...

You have to use the layer ...

func test() {
  somePictureNode.geometry!.firstMaterial!.diffuse.contents = anyUIView.layer
}

It's that easy.

It's very difficult to get good quality though, and drawing order and layout can be strange.

Re-warning ... !

Just to repeat, you will find the layout EXTREMELY strange moving from UIKit to SceneKit! You CAN use the constraint layout engine if you are truly on your toes! My guess is that in a couple yrs (say, by 2025) Apple will put some time in to rationalize the UIKit-like layout engine in SceneKit. Keeping track of / making layout happen is also hell! But for simple UIView, you are all set.

Fattie
  • 27,874
  • 70
  • 431
  • 719