如何使用SceneKit涡旋场创建一个tornato效果

时间:2018-03-23 00:58:02

标签: swift scenekit

在SceneKit WWDC 2014中,他们有一个具有此效果的涡旋场示例:

enter image description here

粒子系统看起来很像龙卷风,因为它向内旋转有一个空心。

但是,涡旋字段的文档没有关于如何实现此效果的信息。现在,我有这个:

// create the particle system
let exp = SCNParticleSystem()
exp.loops = true
exp.particleMass = 5
exp.birthRate = 10000
exp.emissionDuration = 10
exp.emitterShape = SCNTorus(ringRadius: 5, pipeRadius: 1)
exp.particleLifeSpan = 15
exp.particleVelocity = 2
exp.particleColor = UIColor.white
exp.isAffectedByPhysicsFields = true
scene.addParticleSystem(exp, transform: SCNMatrix4MakeRotation(0, 0, 0, 0))
// create the field 
let field = SCNPhysicsField.vortex()
field.strength = -5
field.direction = SCNVector3(x: 0, y: 1, z: 0)
let fieldNode = SCNNode()
fieldNode.physicsField = field
scene.rootNode.addChildNode(fieldNode)

这会产生这种效果: enter image description here 在那里我俯视着顺时针旋转的粒子,外面的半径非常大。它看起来不像龙卷风效应。如何创建此效果?

2 个答案:

答案 0 :(得分:1)

你说龙卷风,我说龙卷风,让我们把整个事情搞定......

SceneKit WWDC 2014演示/幻灯片是sample code project,因此您可以亲自了解他们如何制作您在其中看到的任何效果。在这种情况下,看起来“vortex”演示实际上并没有使用vortexField API,而是使用自定义字段API,它允许您在评估程序块中提供自己的数学运算。 (请参阅该块中代码的链接。)

通过将涡旋(仅引起旋转)与径向重力(吸引向内)与线性重力(向下吸引)或其他一些组合(可能涉及电荷的东西)相结合,您可能能够在没有自定义场的情况下获得类似的行为。但是你可能不得不尝试相当多地调整参数。

答案 1 :(得分:0)

如果有人仍然对这个话题感兴趣 - 这是传说中的龙卷风效果的 Swift 5 实现。

这是一个可以创建龙卷风的示例函数。

func addTornadoPhysicsField() {
    
    // Tornado Particles Field Example
    guard let tornadoSystem = SCNParticleSystem(named: "tornado.scnp", inDirectory: nil) else { return }
    
    let emitterGeometry = SCNTorus(ringRadius: 1.0, pipeRadius: 0.2)
    emitterGeometry.firstMaterial?.transparency = 0.0
    
    let fieldAndParticleNode = SCNNode(geometry: emitterGeometry)
    fieldAndParticleNode.position = SCNVector3(0.0, 0.0, -20.0)
    
    tornadoSystem.emitterShape = emitterGeometry
    
    fieldAndParticleNode.addParticleSystem(tornadoSystem)
    
    yourScene.rootNode.addChildNode(fieldAndParticleNode)
    
    // Tornado
    let worldOrigin = SCNVector3Make(fieldAndParticleNode.worldTransform.m41,
                                     fieldAndParticleNode.worldTransform.m42,
                                     fieldAndParticleNode.worldTransform.m43)
    let worldAxis = simd_float3(0.0, 1.0, 0.0) // i.Ex. the Y axis
    
    // Custom Field (Tornado)
    let customVortexField = SCNPhysicsField.customField(evaluationBlock: { position, velocity, mass, charge, time in
        
        let l = simd_float3(worldOrigin.x - position.x, 1.0, worldOrigin.z - position.z)
        let t = simd_cross(worldAxis, l)
        let d2: Float = l.x * l.x + l.z * l.z
        let vs: Float = 27 / sqrt(d2) // diameter, the bigger the value the wider it becomes (Apple Default = 20)
        let fy: Float = 1.0 - Float((min(1.0, (position.y / 240.0)))) // rotations, a higher value means more turn arounds (more screwed, Apple Default = 15.0))
        return SCNVector3Make(t.x * vs + l.x * 10 * fy, 0, t.z * vs + l.z * 10 * fy)
        
    })
    
    customVortexField.halfExtent = SCNVector3Make(100, 100, 100)
    fieldAndParticleNode.physicsField = customVortexField // Attach the Field
    
}

其他配置选项:

Particle File Configuration - Part 1/2

Particle File Configuration - Image Color

Particle File Configuration - Animation Graph

Particle File Configuration - Part 2/2

Smoke Image File from Apple

最后,这一切都会导致这样的结果:

Example Scene with the Tornado

注意:如果您想像真正的龙卷风一样移动静态龙卷风,则必须找到一种方法来为每个渲染帧重新应用物理场。如果你不这样做,评估块中使用的世界原点将不会移动,它会扭曲你的龙卷风。

注意:您还可以将粒子/场节点拆分为两个彼此独立移动的不同节点。将场节点约束到粒子节点的位置,玩转影响因子(每帧还需要重新应用场)

有关自定义字段的更多信息,请查看 here