Разыменование 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 (см. Вопрос выше). Я, конечно, открыт для других решений и / или комментариев к этому решению.

Другие вопросы по тегам