swift 在RealityKit中交换ModelEntity上的材质

6jygbczu  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(171)

我有一个3D模型(USDZ)在RealityKit中有一个PBR材质。我可以通过UILongPressGestureRecognizer选择模型。当我选择它时,我需要3D模型改变颜色,这样用户就知道它被选中了。我通过向模型附加一个橙子的UnlitMaterial来让它工作,然后将其分配给材料[0],并将PBR分配给材料[1]。一旦选择了3D模型,用户再次通过LongPress取消选择模型,交换2种材料,并删除最后一种材料。第一次运行正常,如果我再次启动这个过程(2次循环),“UnlitMaterial”是白色的。在第三十三次循环时,它是橙色的?
我试着把var simpleMat = UnlitMaterial(color: .orange)放在“If语句”中的不同位置,因为我认为当不亮的是白色时,它不知何故没有正确地分配橙子,它只是一个没有颜色的UnlitMaterial

@objc func handleLongPress(recognizer: UILongPressGestureRecognizer)  {
    
    
let location = recognizer.location(in: arView)
    
    if let entity = arView.entity(at: location){
     
    
        if let anchorEntity = entity.anchor{
            
            currectAnchorEntity = anchorEntity
          
          
         
            switch recognizer.state {
              case .began:
               
                //if the model/object is not currently selected and nothing assigned to currentModelEntity (when you first start AR session)
                if currentModelEntity != entity && currentModelEntity.children.isEmpty {
                
                  
                    var simpleMat = UnlitMaterial(color: .orange)
      
                    //---   1   making it the current
                    currentModelEntity = entity
                    
                    //---   2  finding the model
                    entModel = (entity.findEntity(named: "model") as? ModelEntity)!
                    
                    //---   3  Adding the unlitmaterial colour materal to material [1]
                    entModel.model?.materials.append(simpleMat)
                
                    //--    4  Assigning Varibles to [0] & [1] for reference
                    let matLastL = entModel.model?.materials.last
                    let matLastF = entModel.model?.materials.first
             
                    //---   5  Swaps the materials on the model, so i can keep the original material
                    entModel.model?.materials[1] = matLastF!
                    entModel.model?.materials[0] = simpleMat
          
                    //---   6  Unhides the menu
                    objectMenu.isHidden = false

                    recognizer.state = .cancelled
                    
                }
                
                
                // not the current model but there is another model that is selcted which is the 'CurrentModelEntity'
                else if currentModelEntity != entity && currentModelEntity.children.count == 1 {
                
               
                    //---   1  finding the model on currently selected model
                    entModel = (currentModelEntity.findEntity(named: "model") as? ModelEntity)!
             
                    //---   2  Assigning Varibles to [0] & [1] for reference
                    let matLastL = entModel.model?.materials.last
                    let matLastF = entModel.model?.materials.first
                    
                    //---   3  Assigning the last material(original) to [0] slot
                    entModel.model?.materials[0] = matLastL!
                     
                    //---   4  Removing the 'UnlitMaterial' from [1]
                    entModel.model?.materials.remove(at: 1)
                    
                    //---   5 Unassigning the currentModel
                    currentModelEntity = Entity()
                    
                    //---   6  Hinding the menu
                    objectMenu.isHidden = true
                    
                    //---   7  stopping the touches
                    recognizer.state = .cancelled
                
                }
                
                
                // is the 'CurrentModelEntity'- at this point the materials are Unlit=[0], Original=[1]
                else if currentModelEntity == entity  && currentModelEntity.children.count == 1{
                  
                    
                    //---    1  finding the model on currently selected model
                    entModel = (entity.findEntity(named: "model") as? ModelEntity)!
                    
                    //---    2  Assigning Varibles to [0] & [1] for reference
                    let matLastL = entModel.model?.materials.last
                    let matLastF = entModel.model?.materials.first
                    
                    //---    3  Swaps the materials on the model
                    entModel.model?.materials[1] = matLastF!
                    entModel.model?.materials[0] = matLastL!
                    
                    //---    4  Remove the simpleMat from slot 1
                    entModel.model?.materials.remove(at: 1)
                  
                    //---    5  Hinding the menu
                    objectMenu.isHidden = true
                    
                    //---    6  Unasigning the current model
                    currentModelEntity = Entity()
                  
                    //---    7  stopping the touches
                    recognizer.state = .cancelled
                    
                }
           
            case .ended, .cancelled: break   
            default: break
               
            }
        }
    } 
}
vlf7wbxs

vlf7wbxs1#

使用以下策略来实现所需的结果。
这个答案也会很有帮助。

import SwiftUI
import RealityKit

struct ARViewContainer : UIViewRepresentable {

    @Binding var index: Int
    let arView = ARView(frame: .zero)
    let teapot = try! Entity.loadModel(named: "teapot.usdz")

    let unlit = UnlitMaterial(color: .systemPink)
    let metal = SimpleMaterial(color: .white, isMetallic: true)
    
    func makeUIView(context: Context) -> ARView {
        let anchor = AnchorEntity()
        anchor.position.z += 1.0
        anchor.position.y = -0.2
        anchor.addChild(teapot)
        arView.scene.anchors.append(anchor)
        return arView
    }
    func updateUIView(_ view: ARView, context: Context) {
        switch index {
            case 0: teapot.model?.materials[0] = metal
            case 1: teapot.model?.materials[0] = unlit
            default: break
        }
    }
}

struct ContentView : View {
    
    @State private var switcher: Bool = false
    @State private var index: Int = 0
    
    var body: some View {
        ARViewContainer(index: $index)
            .ignoresSafeArea()
            .onLongPressGesture {       // Screen Long Press Gesture
                switcher.toggle()
                switcher ? (index = 1) : (index = 0)
            }
    }
}

相关问题