0

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)
jomaw0
  • 1
  • 4
  • 1
    Thank you, for your answer. The example in the post shows how to move a Node following a certain path but the way I understand the particles they are not treated as a Node object. I want the particles to fly around the tube. – jomaw0 Apr 22 '22 at 06:14
  • Particle system in SceneKit is always inside a node (transform's container). SceneKit is a node editor. https://stackoverflow.com/questions/60505755/high-quality-rendering-realitykit-vs-scenekit-vs-metal/60513052#60513052 – Andy Jazz Apr 22 '22 at 06:25
  • Particle systems in SceneKit are not as cool as in Autodesk Maya or SideFX Houdini, and there is no "per particle" management system, rather "per whole particle system". And SceneKit particles are 2D sprites that look at camera, not 3D objects. – Andy Jazz Apr 22 '22 at 06:39
  • By correcting your question after it has been answered, you distort the answers and make those answers irrelevant. – Andy Jazz Apr 22 '22 at 12:57

1 Answers1

0

Build an array of SCNVector3s along an imaginary motion path of your particle system (through pipe model) and implement an animation approach posted here. The SCNAction.move(...) method will help you move from one point to another.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
  • 1
    That already helps a lot. But how do I get the SCNVector3 Array from a SCNNode or from its geometry. Then I just can create multiple single points with a particle system and iterate over the array to move them along the "path", right? – jomaw0 Apr 22 '22 at 07:01
  • You're correct, create a motion path from scratch. For simplicity, use SCNSpheres as reference objects for positioning points. Nodes' positions are SCNVectors3(x,y,z). – Andy Jazz Apr 22 '22 at 07:15
  • But where do I access the positioning points of the Node which I would like to animate around? with `let elemtns = child.geometry?.elements` or `let sources = child.geometry?.sources`? how do I convert them to a vector? – jomaw0 Apr 22 '22 at 07:24
  • Just `node.position`. – Andy Jazz Apr 22 '22 at 07:28
  • My Form looks something likes this [Node Form](https://i.stack.imgur.com/J2LSv.jpg) if I just access the `position` only the position of the node in the space will be used. I think it would not be very handy if I have to model every path for every shape by hand or am I missing something? – jomaw0 Apr 22 '22 at 07:35
  • Of course, you can use the vertices' coordinates from your model geometry, but, in my opinion, it will take much more time to retrieve them than placing 15 spheres in the SceneKit editor. – Andy Jazz Apr 22 '22 at 07:40
  • You don't have to remove these reference spheres afterwards - you can just make them invisible. – Andy Jazz Apr 22 '22 at 07:43