/// <summary> /// Sets the spiral properties yo the curves /// </summary> private void SetSpiralProperties(SplineParticles _target) { AnimationCurve tempCurveFirstAxis = new AnimationCurve(); AnimationCurve tempCurveSecondAxis = new AnimationCurve(); AnimationCurve targetAnimationCurveFirstAxis = new AnimationCurve(); AnimationCurve targetAnimationCurveSecondAxis = new AnimationCurve(); switch (_target.spiralAxis) { case SplineParticles.SPIRAL_AXIS.X: targetAnimationCurveFirstAxis = _target.velocityCurveZ; targetAnimationCurveSecondAxis = _target.velocityCurveY; break; case SplineParticles.SPIRAL_AXIS.Y: targetAnimationCurveFirstAxis = _target.velocityCurveX; targetAnimationCurveSecondAxis = _target.velocityCurveZ; break; case SplineParticles.SPIRAL_AXIS.Z: targetAnimationCurveFirstAxis = _target.velocityCurveX; targetAnimationCurveSecondAxis = _target.velocityCurveY; break; } for (int i = 0; i<targetAnimationCurveFirstAxis.keys.Length; i++) { Keyframe newKey = targetAnimationCurveFirstAxis.keys[i]; newKey.value += Mathf.Sin(newKey.time*6*_target.spiralLoops)*10*_target.spiralAmplitude; tempCurveFirstAxis.AddKey(newKey); } for (int i = 0; i<targetAnimationCurveSecondAxis.keys.Length; i++) { Keyframe newKey = targetAnimationCurveSecondAxis.keys[i]; newKey.value += Mathf.Cos(newKey.time*6*_target.spiralLoops)*10*_target.spiralAmplitude; tempCurveSecondAxis.AddKey(newKey); } //Assign curves switch (_target.spiralAxis) { case SplineParticles.SPIRAL_AXIS.X: _target.velocityCurveZ = tempCurveFirstAxis; _target.velocityCurveY = tempCurveSecondAxis; break; case SplineParticles.SPIRAL_AXIS.Y: _target.velocityCurveX = tempCurveFirstAxis; _target.velocityCurveZ = tempCurveSecondAxis; break; case SplineParticles.SPIRAL_AXIS.Z: _target.velocityCurveX = tempCurveFirstAxis; _target.velocityCurveY = tempCurveSecondAxis; break; } }
/// <summary> /// Simplifies the curve, to reduce noise or to make it eaiser to tweak on the editor /// </summary> private AnimationCurve SimplifyCurve(AnimationCurve _curveToSimplify, SplineParticles _target) { AnimationCurve simplifiedAnimationCurve = new AnimationCurve(); for (int i = 0; i<_curveToSimplify.keys.Length; i++) { if (i == 0 || i == _curveToSimplify.keys.Length-1) simplifiedAnimationCurve.AddKey(_curveToSimplify.keys[i]); else { Keyframe prevKey = _curveToSimplify.keys[i-1]; Keyframe currentKey = _curveToSimplify.keys[i]; float inLineTangent = (currentKey.value - prevKey.value)/(currentKey.time-prevKey.time); // We have to test not only the coordinates but also the tangents if (Mathf.Sign(Mathf.Round(inLineTangent*100)/100) != Mathf.Sign(Mathf.Round(currentKey.inTangent*100)/100) || Mathf.Sign(Mathf.Round(inLineTangent*100)/100) != Mathf.Sign(Mathf.Round(prevKey.outTangent*100)/100) || ( (Mathf.Sign(inLineTangent) == Mathf.Sign(currentKey.inTangent) && Mathf.Abs(Mathf.Abs(inLineTangent)-Mathf.Abs(currentKey.inTangent)) > _target.pathSimplifyError) || (Mathf.Sign(inLineTangent) == Mathf.Sign(currentKey.outTangent) && Mathf.Abs(Mathf.Abs(inLineTangent)-Mathf.Abs(currentKey.outTangent)) > _target.pathSimplifyError) )) simplifiedAnimationCurve.AddKey(_curveToSimplify.keys[i]); } } return simplifiedAnimationCurve; }
private void NormelizeAndSimplify(SplineParticles _target) { //Curve values normalization. To show correctly on the particle velocity curve editor xVelocityCurveScale = NormalizeCurve(ref _target.velocityCurveX); yVelocityCurveScale = NormalizeCurve(ref _target.velocityCurveY); zVelocityCurveScale = NormalizeCurve(ref _target.velocityCurveZ); //Simplify the number of key. This will help to reduce noise or to be easier to tweek the curves on the editor _target.velocityCurveX = SimplifyCurve(_target.velocityCurveX, _target); _target.velocityCurveY = SimplifyCurve(_target.velocityCurveY, _target); _target.velocityCurveZ = SimplifyCurve(_target.velocityCurveZ, _target); }
/// <summary> /// Sets the curve points. /// </summary> private void SetCurvePoints(int _loopNumber, Spline.BaseSpline.SplineIterator _iterator, SplineParticles _target, float _offset) { previousPoint = Vector3.zero; for (float i = 0; i<=1; i += _target.pathQuality) { CalculatePoint(i, _loopNumber, _iterator, _target, _offset); } }
/// <summary> /// Creates the velocity curve. /// </summary> /// <param name='_target'> /// _target. /// </param> private void CreateVelocityCurve(SplineParticles _target) { if (_target.pathQuality <= 0) { Debug.LogWarning("Too much quality on particle follow path"); return; } Spline.BaseSpline.SplineIterator splineIterator; if (_target.splinePath == null) splineIterator = _target.GetComponent<SplineParticles>().Spline.GetIterator(); else splineIterator = _target.splinePath.Spline.GetIterator(); //Clear curve values _target.velocityCurveX = new AnimationCurve(); _target.velocityCurveY = new AnimationCurve(); _target.velocityCurveZ = new AnimationCurve(); if (_target.loopNumber <= 1) //Set the curve points for each loop { SetCurvePoints(1, splineIterator, _target, 0); } else { for (int i = 0; i < _target.loopNumber; i++) SetCurvePoints(_target.loopNumber, splineIterator, _target, (float)i/(float)_target.loopNumber); } //Check if there is any key on the last keyframe, for precision problems if (1 - _target.velocityCurveX.keys[_target.velocityCurveX.keys.Length-1].time >= 0.0001f) { CalculatePoint(1, 1, splineIterator, _target, 0); } }
/// <summary> /// Creates the veocity curves and Assign them to the particle system /// </summary> /// <param name='_target'> /// _target. /// </param> private void CreateAndSetVelocityCurves(SplineParticles _target) { ClearCurves(_target); CreateVelocityCurve(_target); if (_target.useSpiral) SetSpiralProperties(_target); NormelizeAndSimplify(_target); ChangeVelocityCurve(_target); }
private void ClearCurves(SplineParticles _target) { _target.velocityCurveX = AnimationCurve.Linear(0,0,1,0); _target.velocityCurveY = AnimationCurve.Linear(0,0,1,0); _target.velocityCurveZ = AnimationCurve.Linear(0,0,1,0); xVelocityCurveScale = 1; yVelocityCurveScale = 1; zVelocityCurveScale = 1; this.Repaint(); }
/// <summary> /// Apply the changes to the particle system /// </summary> private void ChangeVelocityCurve(SplineParticles _target) { ParticleSystem myParticleSystem = _target.gameObject.GetComponent<ParticleSystem>(); SerializedObject newSerializedObject = new SerializedObject(myParticleSystem); SerializedProperty enableVelocityModule = newSerializedObject.FindProperty("VelocityModule.enabled"); SerializedProperty velocityModuleTypeX = newSerializedObject.FindProperty("VelocityModule.x.minMaxState"); SerializedProperty velocityModuleTypeY = newSerializedObject.FindProperty("VelocityModule.y.minMaxState"); SerializedProperty velocityModuleTypeZ = newSerializedObject.FindProperty("VelocityModule.z.minMaxState"); SerializedProperty velocityModuleInWorldSpace = newSerializedObject.FindProperty("VelocityModule.inWorldSpace"); SerializedProperty speedCurveX = newSerializedObject.FindProperty("VelocityModule.x.maxCurve"); SerializedProperty scalarCurveX = newSerializedObject.FindProperty("VelocityModule.x.scalar"); SerializedProperty speedCurveY = newSerializedObject.FindProperty("VelocityModule.y.maxCurve"); SerializedProperty scalarCurveY = newSerializedObject.FindProperty("VelocityModule.y.scalar"); SerializedProperty speedCurveZ = newSerializedObject.FindProperty("VelocityModule.z.maxCurve"); SerializedProperty scalarCurveZ = newSerializedObject.FindProperty("VelocityModule.z.scalar"); if (_target.autoEnableParticleVelocityCurves == true) { if (!_target.hasCreatedTheCurveOnce) { _target.particleSystem.startSpeed = 0; _target.hasCreatedTheCurveOnce = true; } velocityModuleInWorldSpace.boolValue = false; enableVelocityModule.boolValue = _target.autoEnableParticleVelocityCurves; velocityModuleTypeX.intValue = 1; velocityModuleTypeY.intValue = 1; velocityModuleTypeZ.intValue = 1; _target.particleSystem.startSpeed = 0; } scalarCurveX.floatValue = xVelocityCurveScale; scalarCurveY.floatValue = yVelocityCurveScale; scalarCurveZ.floatValue = zVelocityCurveScale; speedCurveX.animationCurveValue = _target.velocityCurveX; speedCurveY.animationCurveValue = _target.velocityCurveY; speedCurveZ.animationCurveValue = _target.velocityCurveZ; newSerializedObject.ApplyModifiedProperties(); }
/// <summary> /// Calculates the point each animation curve point. /// </summary> private void CalculatePoint(float _point, int _loopNumber, Spline.BaseSpline.SplineIterator _iterator, SplineParticles _target, float _offset) { _iterator.SetOffsetPercent(_point); //Calc modifiers float lifeTimeModifier = _target.particleSystem.startLifetime; float loopsModifier = _target.loopNumber; //Vector3 tangentAtPoint = _target.transform.TransformDirection(_iterator.GetTangent().normalized); Vector3 currentPosition = _target.transform.TransformPoint(_iterator.GetPosition()); Vector3 tangentAtPoint = (_iterator.GetTangent().normalized); //Vector3 currentPosition =(_iterator.GetPosition()); Vector3 velocityAtPoint = Vector3.zero; if (_point == 0 && _target.Spline.WrapMode == Spline.BaseSpline.SplineWrapMode.Loop) { _iterator.SetOffsetPercent(1-_target.pathQuality); previousPoint = _target.transform.TransformPoint(_iterator.GetPosition()); //previousPoint = (_iterator.GetPosition()); } else if (_point == 0 && _target.Spline.WrapMode != Spline.BaseSpline.SplineWrapMode.Loop) { _iterator.SetOffsetPercent(_point+_target.pathQuality); previousPoint = _target.transform.TransformPoint(_iterator.GetPosition()); //previousPoint = (_iterator.GetPosition()); } velocityAtPoint = (currentPosition - previousPoint).magnitude * tangentAtPoint; //velocityAtPoint = tangentAtPoint; previousPoint = currentPosition; velocityAtPoint *= loopsModifier*(1/_target.pathQuality)/lifeTimeModifier; // Debug.Log("Point: " + _point + " " + velocityAtPoint.x + " " +velocityAtPoint.y + " "+velocityAtPoint.z ); _target.velocityCurveX.AddKey(_point/_loopNumber + _offset,velocityAtPoint.x); _target.velocityCurveY.AddKey(_point/_loopNumber + _offset,velocityAtPoint.y); _target.velocityCurveZ.AddKey(_point/_loopNumber + _offset,velocityAtPoint.z); }