I am trying to achieve an airflow like animation along a custom node (loaded from .usdz
file) but all I can achieve is that the particles flow all around or just stick to the node. How can I achieve that there is some kind of flow along the object?
The Object looks something like this: usdz node object
let particleSystem = SCNParticleSystem()
particleSystem.isLocal = true
particleSystem.birthRate = 100
particleSystem.emitterShape = child.geometry
particleSystem.particleSize = 0.002
particleSystem.particleLifeSpan = 20 //0.14
particleSystem.particleColor = UIColor(red: 118.0/255.0,
green: 146.0/255.0,
blue: 190.0/255.0,
alpha: 1.0)
particleSystem.isAffectedByGravity = false
particleSystem.isAffectedByPhysicsFields = true
particleSystem.birthLocation = .surface
particleSystem.birthDirection = .surfaceNormal
particleSystem.acceleration = SCNVector3(2, 1.8, 0)
particleSystem.particleVelocity = 20
let spring = SCNPhysicsField.drag()
spring.isActive = true
spring.strength = 100
child.physicsField = spring
particleSystem.particleColorVariation = SCNVector4(0, 0, 0.1, 1)
particleSystem.blendMode = .alpha
child.addParticleSystem(particleSystem)
Somehow I can't post the answer so here it is:
I think I found the solution I was looking for.
I found this code on stack overflow (I can not find the link anymore)
extension SCNGeometry {
/**
Get the vertices (3d points coordinates) of the geometry.
- returns: An array of SCNVector3 containing the vertices of the geometry.
*/
func vertices() -> [SCNVector3]? {
let sources = self.sources(for: .vertex)
guard let source = sources.first else{return nil}
let stride = source.dataStride / source.bytesPerComponent
let offset = source.dataOffset / source.bytesPerComponent
let vectorCount = source.vectorCount
return source.data.withUnsafeBytes { (buffer : UnsafePointer<Float>) -> [SCNVector3] in
var result = Array<SCNVector3>()
for i in 0...vectorCount - 1 {
let start = i * stride + offset
let x = buffer[start]
let y = buffer[start + 1]
let z = buffer[start + 2]
result.append(SCNVector3(x, y, z))
}
return result
}
}
}
And here the animation itself.
let moveAround = SCNNode(geometry: SCNSphere(radius: 0.01))
moveAround.geometry?.materials.first?.diffuse.contents = UIColor(red: 30, green: 150, blue: 30, alpha: 1.0)
let particleSystem = SCNParticleSystem()
particleSystem.isLocal = true
particleSystem.birthRate = 20
particleSystem.particleSize = 0.006
particleSystem.particleLifeSpan = 0.14
particleSystem.particleColor = UIColor(red: 118.0/255.0, green: 146.0/255.0, blue: 190.0/255.0, alpha: 1.0)
particleSystem.birthLocation = .surface
particleSystem.birthDirection = .surfaceNormal
particleSystem.acceleration = SCNVector3(1, 0, 0)
moveAround.addParticleSystem(particleSystem)
child.addChildNode(moveAround)
let points = child.geometry?.vertices() ?? []
var actionArray: [SCNAction] = []
for i in points {
let action = SCNAction.move(to: i, duration: 0.01)
actionArray.append(action)
}
let moveSequence = SCNAction.sequence(actionArray)
let moveLoop = SCNAction.repeatForever(moveSequence)
moveAround.runAction(moveLoop)