Search code examples
scenekitarkitmeshrealitykit

How can I use a SceneKit Mesh in RealityKit?


I have SceneKit code that generates 3D Meshes stored as SCNGeometry objects:

geometry = SCNGeometry(sources: [vertexSource, normalSource, texCoordSource], elements: elements)

I am porting my code to to use RealityKit. To my amazement I can not find any kind of adapter or converter so I can use SceneKit meshes in RealityKit; e.g., create a MeshResource from a SCNGeometry object with the goal of creating a ModelEntity. The Model I/O framework does not mention RealityKit:

"Model I/O can share data buffers with the MetalKit, GLKit, and SceneKit frameworks to help you load, process, and render 3D assets efficiently."

What about RealityKit?


Solution

  • I also was unable to find any automated tool to port an app from SceneKit to RealityKit. I had to do it manually. Using the most recent version of RealityKit (from WWDC2023), here's my code for generating a Tetrahedron View:

    struct Tetrahedron: View {
        var tetrahedronEntity = TetrahedronEntity()
    
        var body: some View {
            let modelEntity: ModelEntity = tetrahedronEntity.createModelEntity()
    
            RealityView { content in
                modelEntity.scale = [ 0.25, 0.25, 0.25 ]
                content.add(modelEntity)
            }
        }
    }
    
    final class TetrahedronEntity: Entity {
        let vertices: [SIMD3<Float>] = [            // A tetrahedron has 4 vertices.
            SIMD3( x:  1.0, y: -1.0, z:  1.0 ),     // vertex = 0
            SIMD3( x:  1.0, y:  1.0, z: -1.0 ),     // vertex = 1
            SIMD3( x: -1.0, y:  1.0, z:  1.0 ),     // vertex = 2
            SIMD3( x: -1.0, y: -1.0, z: -1.0 )      // vertex = 3
        ]
    
        let counts: [UInt8] = [3,3,3,3] // A tetrahedron has 4 faces, each with 3 corners
        let indices: [UInt32] = [
            0, 1, 2,                    // indices to vertices array for face = 0
            1, 0, 3,                    // indices to vertices array for face = 1
            2, 3, 0,                    // indices to vertices array for face = 2
            3, 2, 1,                    // indices to vertices array for face = 3
        ]
    
        func createModelEntity() -> ModelEntity {
            var meshDescriptor = MeshDescriptor()
            meshDescriptor.positions = MeshBuffers.Positions(vertices)
            meshDescriptor.primitives = .polygons(counts, indices)
            let mesh: MeshResource = try! .generate(from: [meshDescriptor])
            let material = SimpleMaterial(color: .red, isMetallic: false)
            let modelEntity = ModelEntity(mesh: mesh, materials: [material])
            return modelEntity
        }
    }
    

    where I used the more-general .polygons primitive type (instead of the more-specific .triangles) as guidance for creating other polyhedrons.

    Unfortunately, this updated version of RealityKit is currently only supported by visionOS, so you will have to run your Xcode app on a Vision Pro Simulator.