public Vector3 ApplyField(Vector3 position, ref ParticleCustomData cdata, float influence, int particleIdx)
        {
            var acc  = force(position);
            var xn_1 = cdata.Xn_1[customDataIdx];
            var xn   = cdata.Xn[customDataIdx];

            var dt  = Time.deltaTime;
            var dt2 = dt * dt;

            Vector3 newPos;

            if (cdata.NumTimestep == 0)
            {
                newPos = xn + (velocity(xn) * dt) + (influence * 0.5f * dt2 * force(xn));
            }
            else
            {
                newPos = (2 * xn) - xn_1 + (influence * dt2 * force(xn));
            }

            cdata.Xn[customDataIdx]   = newPos;
            cdata.Xn_1[customDataIdx] = xn;

            return(newPos);
        }
예제 #2
0
        void FixedUpdate()
        {
            int particleCount = ps.particleCount;

            if (!ps.isPlaying || particleCount == 0)
            {
                return;
            }

            dt  = Time.deltaTime;
            dt2 = dt * dt;

            ParticleSystem.Particle[] particles = new ParticleSystem.Particle[particleCount];
            ps.GetParticles(particles);

            ps.GetCustomParticleData(customData, ParticleSystemCustomData.Custom1);

            DateTime curTime = DateTime.Now;

            for (int i = 0; i < particles.Length; ++i)
            {
                int particleIdx = Mathf.RoundToInt(customData[i].x);

                // Init custom data for new particle
                if (particleIdx <= 0)
                {
                    particleIdx        = ++uniqueID;
                    customData[i]      = new Vector4(particleIdx, 0, 0, 0);
                    cdata[particleIdx] = new ParticleCustomData(forceFields.Count);
                }

                var temp = cdata[particleIdx];
                AdvectParticleDirect(ref particles[i], ref temp, particleIdx);
                temp.NumTimestep++;
                temp.LastTime      = curTime;
                cdata[particleIdx] = temp;

                var lifetime = cdata[particleIdx].NumTimestep * dt + cdata[particleIdx].ParamPhase;
                particles[i].remainingLifetime = MaxParticleLifetime - lifetime - dt;
            }


            ps.SetCustomParticleData(customData, ParticleSystemCustomData.Custom1);
            ps.SetParticles(particles);
        }
예제 #3
0
        private void AdvectParticleDirect(ref ParticleSystem.Particle p, ref ParticleCustomData data, int idx)
        {
            p.velocity = Vector3.zero;

            float              time, normalizedTime;
            Vector3            T, N, B;
            Tuple <int, float> splineParam;
            float              theta;

            // compute pseudo-random parameters
            if (data.NumTimestep == 0)
            {
                data.ParamPhase = dt * UnityEngine.Random.value;

                data.PositionNoiseSeed[0] = UnityEngine.Random.value * 50;
                data.PositionNoiseSeed[1] = UnityEngine.Random.value * 50;
                data.RotationNoiseSeed[0] = UnityEngine.Random.value * 50;
                data.RotationNoiseSeed[1] = UnityEngine.Random.value * 50;
            }

            // find Bishop frame
            time           = data.NumTimestep * dt + data.ParamPhase;
            splineParam    = emissionCurve.GetSplineParamFromTime(time);
            T              = emissionCurve.Tangent(splineParam.Item1, splineParam.Item2);
            N              = emissionCurve.Normal(splineParam.Item1, splineParam.Item2);
            B              = Vector3.Cross(T, N);
            normalizedTime = time / MaxParticleLifetime;

            // compute other init parameters
            if (data.NumTimestep == 0)
            {
                var pos = p.position - Vector3.Dot(p.position, T) * T;
                data.Delta = pos.magnitude / emitterShape.radius;
                if (data.Delta > float.Epsilon)
                {
                    data.Theta0 = Mathf.Atan2(Vector3.Dot(pos, B), Vector3.Dot(pos, N));
                }
                else
                {
                    data.Theta0 = 0;
                }
            }

            theta = data.Theta0 + 2 * Mathf.PI * SpiralFrequency * time;

            var emissionData = GetInterpolatedEmissionData(time);

            p.position = emissionCurve.Evaluate(splineParam.Item1, splineParam.Item2) +
                         data.Delta * emissionData.Radius * (N * Mathf.Cos(theta) + B * Mathf.Sin(theta));


            Vector3 externalForceInfluence = Vector3.zero;

            foreach (var force in forceFields)
            {
                switch (force.EffectType)
                {
                case ParticleCustomForceField.FieldEffectType.Gravity:
                    externalForceInfluence += transform.InverseTransformVector(force.ApplyField(p.position, ref data, GravityInfluence, idx));
                    break;

                case ParticleCustomForceField.FieldEffectType.Wind:
                    externalForceInfluence += transform.InverseTransformVector(force.ApplyField(p.position, ref data, WindInfluence, idx));
                    break;
                }
            }

            p.position += externalForceInfluence;

            data.Xn_1[0] = data.Xn[0];
            data.Xn[0]   = p.position;
            data.Nn_1    = N;

            Vector2 positionNoise = new Vector2(
                -1 + 2 * Mathf.PerlinNoise(data.PositionNoiseSeed[0], PositionNoiseFrequency * time),
                -1 + 2 * Mathf.PerlinNoise(data.PositionNoiseSeed[1], PositionNoiseFrequency * time)
                ) * MaxPositionNoise * normalizedTime;

            Vector2 rotationNoise = new Vector2(
                -1 + 2 * Mathf.PerlinNoise(data.RotationNoiseSeed[0], RotationNoiseFrequency * time),
                -1 + 2 * Mathf.PerlinNoise(data.RotationNoiseSeed[1], RotationNoiseFrequency * time)
                ) * MaxRotationNoise * normalizedTime;

            p.position += N * positionNoise.x + B * positionNoise.y;

            Quaternion rot = Quaternion.LookRotation(T, B);

            rot         *= (Quaternion.AngleAxis(rotationNoise.x, N) * Quaternion.AngleAxis(rotationNoise.y, B));
            p.rotation3D = (rot * InitialParticleRotation).eulerAngles;
        }