One Logo Pool Ball
RealityFoundation · IOS API REFERENCE

LowLevelMesh

class · iOS 18.0+ · SDK 27.1

@MainActor class LowLevelMesh

A container for vertex data that you can use to create and update meshes using your own format. Use `LowLevelMesh` when you want to bring your own vertex format to RealityKit or update your data frequently. To update your data in `LowLevelMesh`, you can either use Swift for CPU processing, or Metal Compute Shaders for GPU processing. - Note: Use ``MeshDescriptor`` for a simpler alternative to `LowLevelMesh`. For information on loading a model from a USD or Reality file, see <doc:loading-entities-from-a-file>. Express your vertex by creating a ``LowLevelMesh/Descriptor-swift.struct`` that describes your layout, along with the required index and vertex capacities. This descriptor is similar to <doc://com.apple.documentation/documentation/metal/mtlvertexdescriptor>, with additional semantics that make the data available in your shaders. To use `LowLevelMesh`, first define your own vertex structure, either in a Metal header or using a Swift structure: ```swift struct MyVertex { var position: SIMD3<Float> = .zero var color: UInt32 = .zero } ``` Next, describe your structure to `LowLevelMesh` by creating a list of vertex attributes and a vertex layout. This description informs `LowLevelMesh` how to represent the vertex data in memory: ```swift extension MyVertex { static var vertexAttributes: [LowLevelMesh.Attribute] = [ .init(semantic: .position, format: .float3, offset: MemoryLayout<Self>.offset(of: \.position)!), .init(semantic: .color, format: .uchar4Normalized_bgra, offset: MemoryLayout<Self>.offset(of: \.color)!) ] static var vertexLayouts: [LowLevelMesh.Layout] = [ .init(bufferIndex: 0, bufferStride: MemoryLayout<Self>.stride) ] static var descriptor: LowLevelMesh.Descriptor { var desc = LowLevelMesh.Descriptor() desc.vertexAttributes = MyVertex.vertexAttributes desc.vertexLayouts = MyVertex.vertexLayouts desc.indexType = .uint32 return desc } } ``` Create a ``LowLevelMesh/Descriptor-swift.struct`` and `LowLevelMesh`, and assign your mesh data and parts: ```swift func triangleMesh() throws -> LowLevelMesh { var desc = MyVertex.descriptor desc.vertexCapacity = 3 desc.indexCapacity = 3 let mesh = try LowLevelMesh(descriptor: desc) mesh.withUnsafeMutableBytes(bufferIndex: 0) { rawBytes in let vertices = rawBytes.bindMemory(to: MyVertex.self) vertices[0] = MyVertex(position: [-1, -1, 0], color: 0xFF00FF00) vertices[1] = MyVertex(position: [ 1, -1, 0], color: 0xFFFF0000) vertices[2] = MyVertex(position: [ 0, 1, 0], color: 0xFF0000FF) } mesh.withUnsafeMutableIndices { rawIndices in let indices = rawIndices.bindMemory(to: UInt32.self) indices[0] = 0 indices[1] = 1 indices[2] = 2 } let meshBounds = BoundingBox(min: [-1, -1, 0], max: [1, 1, 0]) mesh.parts.replaceAll([ LowLevelMesh.Part( indexCount: 3, topology: .triangle, bounds: meshBounds ) ]) return mesh } ``` To finish, create a ``MeshResource`` from the `LowLevelMesh`, and add it to a ``ModelComponent``. You can then add this model to any ``Entity`` in your scene: ```swift func triangleEntity() throws -> Entity { let lowLevelMesh = try triangleMesh() let resource = try MeshResource(from: lowLevelMesh) let modelComponent = ModelComponent(mesh: resource, materials: [UnlitMaterial()]) let entity = Entity() entity.name = "Triangle" entity.components.set(modelComponent) entity.scale *= 0.1 return entity } ``` The low-level mesh creates a triangular shape in your RealityKit scene: ![A screenshot of an isosceles triangle, floating in a kitchen scene. The triangle appears light gray in color.](lowlevelmesh-triangle-unlit) The ``MeshResource`` retains a reference to the `LowLevelMesh`, reflecting any changes when the renderer updates.

Members (16)

init · iOS 18.0+

init

TypeScript
static init(descriptor: LowLevelMesh_Descriptor): Promise<LowLevelMesh>
Swift declaration
@MainActor init(descriptor: LowLevelMesh.Descriptor) throws

Constructs a low-level mesh from a descriptor. - Parameter descriptor: An object that defines the structure of the low-level mesh. - Throws: If the descriptor is invalid or if you do not successfully allocate its memory.

get · iOS 18.0+

descriptor

TypeScript
get descriptor(): Promise<LowLevelMesh_Descriptor>
Swift declaration
@MainActor final let descriptor: LowLevelMesh.Descriptor

The definition of the structure of this low-level mesh.

method · iOS 18.0+

readIndices

TypeScript
readIndices(commandBuffer: SDKHandle): Promise<SDKHandle>
Swift declaration
@MainActor func readIndices(using commandBuffer: any MTLCommandBuffer) -> any MTLBuffer

Retrieves the Metal index buffer for GPU reading. - Parameter commandBuffer: The <doc://com.apple.documentation/documentation/metal/mtlcommandbuffer> you intend to use for reading. RealityKit waits for the command buffer to complete before discarding the buffer.

get · iOS 18.0+

indexCapacity

TypeScript
get indexCapacity(): Promise<number>
Swift declaration
@MainActor var indexCapacity: Int { get }

The capacity of the index buffer, measured in indices. This value is equivalent to ``LowLevelMesh/Descriptor-swift.struct/indexCapacity``.

method · iOS 18.0+

replaceIndices

TypeScript
replaceIndices(commandBuffer: SDKHandle): Promise<SDKHandle>
Swift declaration
@MainActor func replaceIndices(using commandBuffer: any MTLCommandBuffer) -> any MTLBuffer

Retrieves a Metal index buffer that you can use to replace the indices of this low-level mesh. The buffer's contents are in an uninitialized state. - Parameter commandBuffer: The <doc://com.apple.documentation/documentation/metal/mtlcommandbuffer> you intend to use for reading. RealityKit waits for the command buffer to complete before discarding the buffer.

get · iOS 18.0+

vertexCapacity

TypeScript
get vertexCapacity(): Promise<number>
Swift declaration
@MainActor var vertexCapacity: Int { get }

The capacity of the vertex buffer, measured in vertices. This value is equivalent to ``LowLevelMesh/Descriptor-swift.struct/vertexCapacity``.

method · iOS 18.0+

withUnsafeBytes

TypeScript
withUnsafeBytes(bufferIndex: number, callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func withUnsafeBytes(bufferIndex: Int, _ callback: (UnsafeRawBufferPointer) -> Void)

Reads a Metal vertex buffer synchronously on the CPU. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

withUnsafeIndices

TypeScript
withUnsafeIndices(callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func withUnsafeIndices(_ callback: (UnsafeRawBufferPointer) -> Void)

Reads the index buffer synchronously on the CPU. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

withUnsafeMutableBytes

TypeScript
withUnsafeMutableBytes(bufferIndex: number, callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func withUnsafeMutableBytes(bufferIndex: Int, _ callback: (UnsafeMutableRawBufferPointer) -> Void)

Updates a Metal vertex buffer synchronously on the CPU. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

withUnsafeMutableIndices

TypeScript
withUnsafeMutableIndices(callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func withUnsafeMutableIndices(_ callback: (UnsafeMutableRawBufferPointer) -> Void)

Updates the index buffer synchronously on the CPU. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

replaceUnsafeMutableBytes

TypeScript
replaceUnsafeMutableBytes(bufferIndex: number, callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func replaceUnsafeMutableBytes(bufferIndex: Int, _ callback: (UnsafeMutableRawBufferPointer) -> Void)

Replaces a Metal vertex buffer synchronously on the CPU. The buffer's contents are unspecified, and it is the caller's responsibility to populate the buffer with valid data. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

replaceUnsafeMutableIndices

TypeScript
replaceUnsafeMutableIndices(callback: ((arg0: ArrayBuffer) => void)): Promise<void>
Swift declaration
@MainActor func replaceUnsafeMutableIndices(_ callback: (UnsafeMutableRawBufferPointer) -> Void)

Replaces the index buffer synchronously on the CPU. The buffer's contents are unspecified, and it is the caller's responsibility to populate the buffer with valid data. The buffer is only valid for the lifetime of the callback.

method · iOS 18.0+

read

TypeScript
read(index: number, commandBuffer: SDKHandle): Promise<SDKHandle>
Swift declaration
@MainActor func read(bufferIndex index: Int, using commandBuffer: any MTLCommandBuffer) -> any MTLBuffer

Retrieves a Metal vertex buffer at the specified index, for GPU reading. - Parameters: - index: The index of the buffer to read. Use a value that is less than ``LowLevelMesh/Descriptor/vertexBufferCount``. - commandBuffer: The <doc://com.apple.documentation/documentation/metal/mtlcommandbuffer> you intend to use for reading. RealityKit waits for the command buffer to complete before discarding the buffer.

get · iOS 18.0+

parts

TypeScript
get parts(): Promise<LowLevelMesh_PartsCollection>
Swift declaration
@MainActor var parts: LowLevelMesh.PartsCollection { get set }

A mutable collection of parts. The parts of a ``LowLevelMesh`` object specify how to interpret the index buffer. You can also use `parts` to customize the material index and primitive type.

set · iOS 18.0+

parts

TypeScript
setParts(value: LowLevelMesh_PartsCollection): Promise<void>
Swift declaration
@MainActor var parts: LowLevelMesh.PartsCollection { get set }

A mutable collection of parts. The parts of a ``LowLevelMesh`` object specify how to interpret the index buffer. You can also use `parts` to customize the material index and primitive type.

method · iOS 18.0+

replace

TypeScript
replace(index: number, commandBuffer: SDKHandle): Promise<SDKHandle>
Swift declaration
@MainActor func replace(bufferIndex index: Int, using commandBuffer: any MTLCommandBuffer) -> any MTLBuffer

Retrieves a Metal vertex buffer you can use to replace the contents of the specified buffer on the GPU using Metal. The buffer's contents are in an uninitialized state. - Parameters: - index: The index of the buffer to modify. Use a value that is less than ``LowLevelMesh/Descriptor/vertexBufferCount``. - commandBuffer: The <doc://com.apple.documentation/documentation/metal/mtlcommandbuffer> you intend to use for buffer modifications. RealityKit waits for the command buffer to complete before utilizing the buffer for rendering.

Skipped declarations

No declarations were skipped in this snapshot.

All RealityFoundation types →