代码之家  ›  专栏  ›  技术社区  ›  ngngngn

如何使用SceneKit漩涡场创建tornato效果

  •  3
  • ngngngn  · 技术社区  · 6 年前

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

    enter image description here

    粒子系统看起来很像一个tornato,因为它以空心中心向内旋转。

    然而,有关涡旋场的文件没有关于如何实现这种效果的信息。现在,我有这个:

    // 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 回复  |  直到 6 年前
        1
  •  1
  •   rickster    6 年前

    你说tornato,我说tornado,让我们把一切都取消。。。

    SceneKit WWDC 2014演示/幻灯片是 sample code project ,所以你可以亲眼看到他们是如何产生你在其中看到的任何效果的。在这种情况下,vortex演示似乎没有实际使用 vortexField API,而是自定义字段API,允许您在计算器块中提供自己的数学。(请参见该块中代码的链接。)

    通过将漩涡(仅导致旋转)、径向重力(向内吸引)和线性重力(向下吸引)或其他组合(可能涉及电荷)组合在一起,您可能可以在没有自定义场的情况下获得类似的行为。但您可能需要对参数进行多次调整。

        2
  •  0
  •   ZAY    3 年前

    如果还有人对这个话题感兴趣的话,这里有一个传奇龙卷风效应的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 .