swiftrealitykit

In RealiktKit we are creating objects with MeshResource but we are unable to set different materials for different faces


Using following blocks we are creating front and back of an entity. They are same polygons with some -z distance between them.

We see both side of it when we rotate entity in scene.

Looks like both side is applidedMaterial.

// FRONT
    var frontDesc = MeshDescriptor(name: "Front")
    frontDesc.positions = .init(frontPos)
    frontDesc.textureCoordinates = .init(uvs)
    frontDesc.primitives = .triangles(frontIndices.map(UInt32.init))

    // BACK (reverse winding)
    var backDesc = MeshDescriptor(name: "Back")
    backDesc.positions = .init(backPos)
    backDesc.textureCoordinates = .init(uvs)
    backDesc.primitives = .triangles(frontIndices.reversed().map(UInt32.init))

    let meshResource = try! MeshResource.generate(from: [frontDesc, backDesc])
    let entity = ModelEntity(mesh: meshResource, materials: [applidedMaterial, menuMaterial])

ModelEntity(mesh: meshResource, materials: [applidedMaterial, menuMaterial]) does not work but why?

Also, when we change materials later like this

       var frontMat = PhysicallyBasedMaterial()
        frontMat.baseColor = .init(texture: .init(globalSimpTexture[0]))
        frontMat.faceCulling = .none

        var backMat = PhysicallyBasedMaterial()
        backMat.baseColor = .init(texture: .init(globalSimpTexture[1]))
        backMat.faceCulling = .none

        piece.model?.materials = [frontMat, backMat]

both front and back have been set with frontMat


Solution

  • You’re passing two MeshDescriptors, but without assigning material indices both parts end up using the default material index 0, which means both sides render with materials[0] (your applidedMaterial / frontMat) of the ModelComponent.

    To use the second material, the back part must reference index 1.

    // FRONT
    var frontDesc = MeshDescriptor(name: "Front")
    frontDesc.positions = .init(frontPos)
    frontDesc.textureCoordinates = .init(uvs)
    frontDesc.primitives = .triangles(frontIndices.map(UInt32.init))
    frontDesc.materials = .allFaces(0)   // optional, 0 is the default
    
    // BACK
    var backDesc = MeshDescriptor(name: "Back")
    backDesc.positions = .init(backPos)
    backDesc.textureCoordinates = .init(uvs)
    backDesc.primitives = .triangles(frontIndices.reversed().map(UInt32.init))
    backDesc.materials = .allFaces(1)    // <- key change: assign "back" material index here
    
    let mesh = try MeshResource.generate(from: [frontDesc, backDesc])
    let entity = ModelEntity(mesh: mesh, materials: [frontMat, backMat]) // the order of the passed materials define their index