I'm building a test app using the SceneKit's SCNParticleSystem
. It has a callback which lets you modify the particles' properties on each frame. The signature of this callback is
typealias SCNParticleModifierBlock = (UnsafeMutablePointer<UnsafeMutablePointer<Void>>, UnsafeMutablePointer<Int>, Int, Int, Float) -> Void
Reference from apple developer site - SCNParticleSystem_Class
I don't know how to access and modify this reference from Swift. If this was C it would be a **
that I could dereference like an array.
After some futzing I've gotten as far as this:
.....
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)
}
}¸
This works for the first particle but crashes on the second. The first time the function is called there are 0 particles, so it skips the loop. The second time there are three particles, so it tries to print them out. The first size value is 0.9 which seams reasonable. The second size value is clearly bogus, and then it crashes and I drop into the debugger.
indexes 0 0
indexes 0 3
0 0.929816
1 1.51296e-39
(lldb)
As near as I can tell no one on the internet uses this function. The only references I find are Apple's docs which provide only ObjC examples for it, not Swift.
Help me!
for 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]
i think that in your code, the declaration of myptr is wrong
let myptr = UnsafeMutablePointer<UnsafeMutablePointer<Foos>>(data)
dataStride.count in your example should be 1 (number of properties) and value of its element should be size of float (size of the property).
also be careful! your loop should be something like
for i in start..<end {
...
}
are you sure the start is 0 ???
Working with the very similar SCNParticleEventBlock, I wrote the handler in Swift3 as
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
}
}
}
A little more detail in my SO asked and answered question here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.