2015-10-21 7 views
11

Sto costruendo un'app di prova usando il SCNParticleSystem di SceneKit. Ha un callback che ti permette di modificare le proprietà delle particelle su ciascun frame. La firma di questo callback èCome lavoro con un UnsafeMutablePointer <UnsafeMutablePointer <Void>> riferimento da Swift?

typealias SCNParticleModifierBlock = (UnsafeMutablePointer<UnsafeMutablePointer<Void>>, UnsafeMutablePointer<Int>, Int, Int, Float) -> Void 

riferimento dal sito degli sviluppatori di Apple - SCNParticleSystem_Class

Non so come accedere e modificare questo riferimento da Swift. Se questo fosse C sarebbe un ** che potrei dereferenziare come un array.

Dopo qualche futzing ho ottenuto fino a questo:

..... 
      particleSystem?.addModifierForProperties([SCNParticlePropertySize], atStage: SCNParticleModifierStage.PostDynamics, withBlock: doit2) 
} 

struct Foos { 
    var size:float_t 
} 
func doit2(data:UnsafeMutablePointer<UnsafeMutablePointer<Void>>, dataStride: UnsafeMutablePointer<Int>, start:Int, end:Int, deltaTime:Float) -> Void { 
    let myptr = UnsafeMutablePointer<UnsafeMutablePointer<Foos>>(data) 
    print("indexes",start,end) 
    for i in 0 ..< end { 
     print(i,myptr[i].memory.size) 
    } 
}¸ 

Questo funziona per la prima particella, ma si blocca sul secondo. La prima volta che viene chiamata la funzione ci sono 0 particelle, quindi salta il ciclo. La seconda volta ci sono tre particelle, quindi prova a stamparle. Il primo valore di dimensione è 0,9 che sembra ragionevole. Il secondo valore di dimensione è chiaramente fasullo, quindi si blocca e faccio cadere il debugger.

indexes 0 0 
indexes 0 3 
0 0.929816 
1 1.51296e-39 
(lldb) 

Per quanto posso dire nessuno su Internet utilizza questa funzione. Gli unici riferimenti che trovo sono i documenti di Apple che forniscono solo esempi ObjC per questo, non Swift.

Aiutatemi!

+1

Chiamami pazzo, ma dal momento che questo è un puntatore a un puntatore, non dovresti prendere il suo 'memory.memory' per raggiungere la cosa reale? – matt

+0

Buon punto. Passare a 'myptr.memory [i] .size' mi avvicina, ma si blocca ancora ogni tanto. Se imposto le dimensioni, posso vedere alcune ma non tutte le particelle stanno cambiando. E quelli che cambiano si bloccano, smettono di muoversi. Questo suggerisce che sto sbavando un po 'di memoria. E non sono ancora sicuro di cosa sia il dataStride. I documenti dicono che dovrebbe essere: "array che identifica l'offset, in byte, del valore di ogni proprietà nella striscia di dati per ogni particella.L'ordine di offset in questo array corrisponde all'ordine della matrice di proprietà nella chiamata "addModifierForProperties" –

+0

E dovrei menzionare, nel codice di esempio ObjC viene utilizzato dataStride, ma non riesco a vedere come lo utilizzerei in Swift versione –

risposta

1

per examle:

var data = [[0.1, 0.2],[0.3, 0.4],[0.5, 0.6]] 
let pData = UnsafeMutablePointer<UnsafeMutablePointer<Void>>(data) 
// how to reconstruct the original data ?? 

// we need to know how much data we have 
let count = data.count 
// we need to know what type of data we have 
let p2 = UnsafeMutablePointer<Array<Double>>(pData) 
// access the data 
for i in 0..<count { 
    print((p2 + i).memory) 
} 
// [0.1, 0.2] 
// [0.3, 0.4] 
// [0.5, 0.6] 

penso che nel codice, la dichiarazione di myptr è sbagliato

let myptr = UnsafeMutablePointer<UnsafeMutablePointer<Foos>>(data) 

dataStride.count nel tuo esempio dovrebbe essere 1 (numero di proprietà) e di valore del suo elemento dovrebbe essere la dimensione del galleggiante (dimensione della proprietà).

fare attenzione! il tuo loop dovrebbe essere qualcosa come

for i in start..<end { 
... 
} 

sei sicuro che l'inizio è 0 ???

+0

Ti piacerebbe migliorare la tua risposta in modo da poter assegnare premi? Forse sei stato in grado di risolverlo :) –

0

Lavorare con lo SCNParticleEventBlock molto simile, ho scritto il gestore in Swift3 come

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 
     } 
    } 
} 

Un po 'più in dettaglio nella mia interrogazione SO chiesto e ha risposto here

e un paio di GIST here e here

Problemi correlati