Attaching environment information: macOS Catalina 10.15.7 (MacBook Pro 16-inch 2019)
XCode 12.3
iPadOS 14.2 (iPad Pro 11-inch 2nd gen)
Post
Replies
Boosts
Views
Activity
Hi, I'm having the same problem here. I'd appreciate it if anyone has an example.
I sorta figured out a way to do this. The key is to use SCNGeometrySource's proper initializer that takes an MTLBuffer as input: https://developer.apple.com/documentation/scenekit/scngeometrysource/1522873-init.
I'm posting my pseudo code here in case anyone comes across the same issue.
swift
/* initialize color buffer, similarly for vertex buffer */
var color_buffer_array : [UInt8] = []
/* appending rgba values (0...1) to the color buffer */
color_buffer_array.append(contentsOf: withUnsafeBytes(of: Float(UInt8(xyzrgb[6])!) / 255.0, Array.init))
color_buffer_array.append(contentsOf: withUnsafeBytes(of: Float(UInt8(xyzrgb[7])!) / 255.0, Array.init))
color_buffer_array.append(contentsOf: withUnsafeBytes(of: Float(UInt8(xyzrgb[8])!) / 255.0, Array.init))
color_buffer_array.append(contentsOf: withUnsafeBytes(of: Float(1.0), Array.init))
curr_point_cloud.color_buffer = Data(color_buffer_array)
/* NOTE: use 4 UInt8's for rgba in Data, use 4 Floats for rgba in MTLBuffer
below is an example of not using MTLBuffer, so color cannot be updated in real time
// curr_point_cloud.color_source = SCNGeometrySource(data: curr_point_cloud.color_buffer!,
// semantic: .color,
// vectorCount: curr_point_cloud.points.count, // number of vertices
// usesFloatComponents: true, // this has to be true in order to display correct color
// componentsPerVector: 4, // 4 UInt8's: r, g, b, a
// bytesPerComponent: 1, // 1 UInt8 == 1 byte
// dataOffset: 0,
// dataStride: 4) // 4 * 1/
/* below is an example of using MTLBuffer, so color can be updated in real time */
curr_point_cloud.color_buffer!.withUnsafeBytes { rawBufferPointer in
let rawPtr = rawBufferPointer.baseAddress!
curr_point_cloud.color_mtl_buffer = mtl_device!.makeBuffer(bytes: rawPtr, length: curr_point_cloud.color_buffer!.count, options: [])
curr_point_cloud.tmp_color_mtl_buffer = mtl_device!.makeBuffer(bytes: rawPtr, length: curr_point_cloud.color_buffer!.count, options: [])
curr_point_cloud.color_source = SCNGeometrySource(buffer: curr_point_cloud.color_mtl_buffer!, vertexFormat: .float4, semantic: .color, vertexCount: curr_point_cloud.points.count, dataOffset: 0, dataStride: 16)
}
/* update MTLBuffer
// NOTE: two options, change color_mtl_buffer directly, or change tmp_color_mtl_buffer and use blit command
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
if DataModel.shared.point_cloud_objects.count == 0 { return }
// https://stackoverflow.com/questions/40476426/scenekit-metal-depth-buffer
let commandBuffer = DataModel.shared.mtl_command_queue!.makeCommandBuffer()!
let blitCommandEncoder: MTLBlitCommandEncoder = commandBuffer.makeBlitCommandEncoder()!
blitCommandEncoder.copy(from: DataModel.shared.point_cloud_objects[0].tmp_color_mtl_buffer!, sourceOffset: 0, to: DataModel.shared.point_cloud_objects[0].color_mtl_buffer!, destinationOffset: 0, size: DataModel.shared.point_cloud_objects[0].color_buffer!.count)
blitCommandEncoder.endEncoding()
commandBuffer.commit()
}/