Разыменование UnsafeMutablePointer<UnsafeMutableRawPointer>
У меня есть блок, который передает данные, которые я хотел бы преобразовать в массив массивов с плавающей точкой - например, [[0,1,0,2,0,3, 1,0], [0,3, 0,4, 0,5, 1,0], [0,5, 0,6, 0,7, 1,0]. Эти данные передаются мне в виде data:UnsafeMutablePointer<UnsafeMutableRawPointer>
(Внутренние массивы являются значениями RGBA)
fwiw - параметры блока взяты из SCNParticleEventBlock
Как я могу разыменовать данные в [[Float]]? Когда у меня есть массив, содержащий внутренние массивы, я могу ссылаться на данные внутреннего массива (colorArray) с помощью:
let rgba: UnsafeMutablePointer<Float> = UnsafeMutablePointer(mutating: colorArray)
let count = 4
for i in 0..<count {
print((rgba+i).pointee)
}
fwiw - это пример кода Apple Objective-C для ссылки на данные ( из дескриптора SCNParticleSystem (_: forProperties: handler:))
[system handleEvent:SCNParticleEventBirth
forProperties:@[SCNParticlePropertyColor]
withBlock:^(void **data, size_t *dataStride, uint32_t *indices , NSInteger count) {
for (NSInteger i = 0; i < count; ++i) {
float *color = (float *)((char *)data[0] + dataStride[0] * i);
if (rand() & 0x1) { // Switch the green and red color components.
color[0] = color[1];
color[1] = 0;
}
}
}];
2 ответа
Вы можете подписать набранные UnsafeMutablePointer
без необходимости создавать UnsafeMutableBufferPointer
, как в:
let colorsPointer:UnsafeMutableRawPointer = data[0] + dataStride[0] * i
let rgbaBuffer = colorsPointer.bindMemory(to: Float.self, capacity: dataStride[0])
if(arc4random_uniform(2) == 1) {
rgbaBuffer[0] = rgbaBuffer[1]
rgbaBuffer[1] = 0
}
Удалось ли вам заставить ваше решение работать? Похоже, только горстка SCNParticleProperties
может быть использован в SCNParticleEventBlock
блок.
Основываясь на этом ответе, я написал функцию-обработчик системы частиц в swift как:
ps.handle(SCNParticleEvent.birth, forProperties [SCNParticleSystem.ParticleProperty.color]) {
(data:UnsafeMutablePointer<UnsafeMutableRawPointer>, dataStride:UnsafeMutablePointer<Int>, indicies:UnsafeMutablePointer<UInt32>?, count:Int) in
for i in 0..<count {
// get an UnsafeMutableRawPointer to the i-th rgba element in the data
let colorsPointer:UnsafeMutableRawPointer = data[0] + dataStride[0] * i
// convert the UnsafeMutableRawPointer to a typed pointer by binding it to a type:
let floatPtr = colorsPointer.bindMemory(to: Float.self, capacity: dataStride[0])
// convert that to a an UnsafeMutableBufferPointer
var rgbaBuffer = UnsafeMutableBufferPointer(start: floatPtr, count: dataStride[0])
// At this point, I could convert the buffer to an Array, but doing so copies the data into the array and any changes made in the array are not reflected in the original data. UnsafeMutableBufferPointer are subscriptable, nice.
//var rgbaArray = Array(rgbaBuffer)
// about half the time, mess with the red and green components
if(arc4random_uniform(2) == 1) {
rgbaBuffer[0] = rgbaBuffer[1]
rgbaBuffer[1] = 0
}
}
}
Я действительно не уверен, что это самый прямой способ сделать это и кажется довольно громоздким по сравнению с кодом Objective-C (см. Вопрос выше). Я, конечно, открыт для других решений и / или комментариев к этому решению.