Libor Zapletal
Libor Zapletal

Reputation: 14102

RealityKit - Hiding and showing parts (meshes) of usdz model

I need an advice. I am using RealityKit for showing models of fences. I have models which has several meshes that shouldn't be shown at once. For example filling of the fence. There are different options and I have it all in my model:

3D usdz model showing in Xcode

I would like to show always one at the time. How can I do that? I can't edit meshes at runtime, can I? I was thinking about changing material for each mesh but when I tried to set clear color with SimpleMaterial it shows mesh in black and when I tried OcclusionMateril I get this result:

Apply OcclusionMaterial in real app

Example how I tried hide material with SimpleMaterial:

var material = SimpleMaterial()
material.baseColor = MaterialColorParameter.color(UIColor.clear)
material.tintColor = .clear
clonedEntity.model?.materials[index] = material

Or with OcclusionMaterial (in screenshot from app above):

let occlusion = OcclusionMaterial()
clonedEntity.model?.materials[index] = occlusion

Is it possible to somehow hide parts of 3D model? Or do I have to several models and when I want to change filling for example I must change whole model? Or should I somehow composite one object from multiple models (for example filling and rest of fence)? Thanks for any advice.

Upvotes: 2

Views: 1514

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58563

The most robust way is to create a component USDZ model (containing separate parts) and then use .isEnabled instance property in RealityKit 2.0 to turn any part On or Off.

enter image description here

import UIKit
import RealityKit

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!
    let shelf = try! ModelEntity.load(named: "Shelf")
    var counter: Int = 0

    override func touchesBegan(_ touches: Set<UITouch>, 
                              with event: UIEvent?) {
        self.counter += 1

        let metal = shelf.children[0].children[0].children[0]
                         .children[0].children[0].children[0] as! ModelEntity
        let wood = shelf.children[0].children[0].children[0]
                        .children[0].children[0].children[1] as! ModelEntity

        if counter % 3 == 1 {
            metal.isEnabled = false
            wood.isEnabled = true
        } else if counter % 3 == 2 {
            metal.isEnabled = true
            wood.isEnabled = false
        } else if counter % 3 == 0 {
            metal.isEnabled = true
            wood.isEnabled = true
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        let anchor = AnchorEntity()
        anchor.addChild(shelf)
        arView.scene.anchors.append(anchor)
    }
}

If you do not like using .children[i] chaining, look at this answer,

enter image description here

Upvotes: 3

Related Questions