user1150393
user1150393

Reputation: 139

Programmatically setting texture in Scene generated by Reality Composer

I am creating a cylinder object using Reality Composer. My requirement is to wrap the cylinder with custom image. Image is dynamically created by the app.

I have tried following approach and so far it's not working.

Code:

// Load the "anchor" scene from the "Experience" Reality File
let anchor = try! Experience.loadAnchor()

// Add the anchor to the scene
arView.scene.anchors.append(anchor)

let cylinderEntity : Entity = anchor.cylinder!

let cylinderModelEntity = cylinderEntity.children[0]

var cylinderModelComponent : ModelComponent = cylinderModelEntity.components[ModelComponent.self]!

let paths : NSArray = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
let path : NSString = paths.object(at: 0) as! NSString
let filePath : NSString = path.strings(byAppendingPaths: ["Image.png"])[0] as NSString
let url = URL.init(fileURLWithPath: filePath as String)

// Save image.
let image : UIImage = createImage()
try! image.pngData()?.write(to: url)
let data = NSData.init(contentsOf: url)
print(data!)

var material = SimpleMaterial()
material.tintColor = UIColor.yellow
material.baseColor = try! MaterialColorParameter.texture(TextureResource.load(contentsOf: url))
material.roughness = MaterialScalarParameter(floatLiteral: 0.1)
material.metallic = MaterialScalarParameter(floatLiteral: 1.0)

cylinderModelComponent.materials[0] = material

Any help is really appreciated.

Upvotes: 1

Views: 1311

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58043

You forgot to set a boxComponent which need to be stored on the entity.

For this use set() instance method.

In your code it should look like this:

anchor.cylinder!.components.set(cylinderModelComponent)

In my code it looks like this:

anchor.steelBox!.components.set(boxComponent)

Here are my full code version (I tested it in macOS app):

import AppKit
import RealityKit

class GameViewController: NSViewController {

    @IBOutlet var arView: ARView!

    override func awakeFromNib() {

        let anchor = try! Experience.loadBox()
        anchor.steelBox?.scale = SIMD3(x: 9, y: 9, z: 9)
        anchor.steelBox?.orientation = simd_quatf(angle: -Float.pi/4,
                                                   axis: SIMD3(x: 1, y: 1, z: 0))      

        let boxEntity: Entity = anchor.steelBox!.children[0]
        var boxComponent: ModelComponent = boxEntity.components[ModelComponent].self!

        let paths: NSArray = NSSearchPathForDirectoriesInDomains(.documentDirectory, 
                                                                 .userDomainMask, 
                                                                  true) as NSArray

        // If you're testing it in macOS app – place your Image.png here:
        // /Users/<UserName>/Library/Containers/<ApplicationName>/Data/Documents/

        let path: NSString = paths.object(at: 0) as! NSString
        let filePath: NSString = path.strings(byAppendingPaths: ["Image.png"])[0] as NSString
        let url = URL(fileURLWithPath: filePath as String)

        var material = SimpleMaterial()
        material.tintColor = NSColor.yellow
        material.baseColor = try! MaterialColorParameter.texture(TextureResource.load(contentsOf: url))
        material.roughness = MaterialScalarParameter(floatLiteral: 0.1)
        material.metallic = MaterialScalarParameter(floatLiteral: 0.1)    
        boxComponent.materials = [material]

        anchor.steelBox!.components.set(boxComponent)
        arView.scene.anchors.append(anchor)
    }
}

enter image description here

Upvotes: 6

Related Questions