本文主要是介绍U3D——刀光轨迹插件的改进,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原文地址:http://www.cnblogs.com/hellohuan/p/3478907.html
U3D——刀光轨迹插件的改进
之前在PC端的游戏中实现过轨迹,算法喜闻乐见,收集每帧的控制点,对其进行B样条插值,生成D3DTriStrip。
这两天刚刚接触U3D,美术给了一个轨迹的插件,要求我扩展脚本,支持锁链刀弯刀的刀光计算,暂且命名多控制点的轨迹。
算是U3D的第一个纯技术需求吧,记录一下。
新增加了一个脚本:Hello_MeleeWeaponTrail.cs,增加了多控制点编辑,调整使用了NewCatmullRom差值算法(使用线性和NewBezier效果不好)。
刀光的效果如下:
根据前东家的规范,写了一下方案的非功能性评估:
通过Unity的stat面板并未发现与之前性能明显的区别。
不过算法会动态生成TriangleMesh,控制点越多生成顶点和三角形数会增加,影响内存显存和显卡带宽填充。
空间:
内存
单个顶点position+uv+vcColor大约32字节。下表展示增加控制点增加的内存消耗。
控制点数量 | 2 | 3 | n |
顶点数量 | 2X | 3X | nX |
三角形数量 | X | 2X | (N-1)X |
显存:
顶点和索引会增加相应空间的显存。
时间:
CPU:与控制点数量的时间复杂度为O(n)。
GPU:随着顶点数量的增加,VS阶段带宽增加,绘制的三角形数量变多。
总体来讲,效率影响不是太大,场景中刀光数量不多的话,使用无大问题。
建议:
逻辑来控制刀光的Emit,即,只在挥刀的时候置成true,其他时候是false,再精致点就要用动画的时间控制刀光的显示和隐藏,比如只有当刀砍下时有刀光,抬起时没有刀光等。
代码1:
#define USE_INTERPOLATION//
// By Anomalous Underdog, 2011
//
// Based on code made by Forest Johnson (Yoggy) and xyber
// 修正致命内存错误么
//using UnityEngine;
using System.Collections;
using System.Collections.Generic;public class Hello_MeleeWeaponTrail : MonoBehaviour
{[SerializeField]bool _emit = true;public bool Emit { set{_emit = value;} }bool _use = true;public bool Use { set{_use = value;} }[SerializeField]float _emitTime = 0.0f;[SerializeField]Material _material;[SerializeField]float _lifeTime = 1.0f;[SerializeField]Color[] _colors;[SerializeField]float[] _sizes;[SerializeField]float _minVertexDistance = 0.1f;[SerializeField]float _maxVertexDistance = 10.0f;float _minVertexDistanceSqr = 0.0f;float _maxVertexDistanceSqr = 0.0f;[SerializeField]float _maxAngle = 3.00f;[SerializeField]bool _autoDestruct = false;#if USE_INTERPOLATION[SerializeField]int subdivisions = 4;
#endif[SerializeField]Transform[] _transforms;List<Point> _points = new List<Point>();
#if USE_INTERPOLATIONList<Point> _smoothedPoints = new List<Point>();
#endifGameObject _trailObject;Mesh _trailMesh;Vector3 _lastPosition;[System.Serializable]public class Point{public float timeCreated = 0.0f;public List<Vector3> allVectors= new List<Vector3>(); public void RemoveVectors(){allVectors.Clear ();}}void Start(){_lastPosition = transform.position;_trailObject = new GameObject("Trail");_trailObject.transform.parent = null;_trailObject.transform.position = Vector3.zero;_trailObject.transform.rotation = Quaternion.identity;_trailObject.transform.localScale = Vector3.one;_trailObject.AddComponent(typeof(MeshFilter));_trailObject.AddComponent(typeof(MeshRenderer));_trailObject.renderer.material = _material;_trailMesh = new Mesh();_trailMesh.name = name + "TrailMesh";_trailObject.GetComponent<MeshFilter>().mesh = _trailMesh;_minVertexDistanceSqr = _minVertexDistance * _minVertexDistance;_maxVertexDistanceSqr = _maxVertexDistance * _maxVertexDistance;}void OnDisable(){Destroy(_trailObject);}void Update(){if (!_use){return;}if (_transforms.Length < 2) {return ;}if (_emit && _emitTime != 0){_emitTime -= Time.deltaTime;if (_emitTime == 0) _emitTime = -1;if (_emitTime < 0) _emit = false;}if (!_emit && _points.Count == 0 && _autoDestruct){Destroy(_trailObject);Destroy(gameObject);}// early out if there is no cameraif (!Camera.main) return;// if we have moved enough, create a new vertex and make sure we rebuild the meshfloat theDistanceSqr = (_lastPosition - transform.position).sqrMagnitude;if (_emit){if (theDistanceSqr > _minVertexDistanceSqr){bool make = false;if (_points.Count < 3){make = true;}else{//Vector3 l1 = _points[_points.Count - 2].basePosition - _points[_points.Count - 3].basePosition;//Vector3 l2 = _points[_points.Count - 1].basePosition - _points[_points.Count - 2].basePosition;Vector3 l1 = _points[_points.Count - 2].allVectors[0] - _points[_points.Count - 3].allVectors[0];Vector3 l2 = _points[_points.Count - 1].allVectors[0] - _points[_points.Count - 2].allVectors[0];if (Vector3.Angle(l1, l2) > _maxAngle || theDistanceSqr > _maxVertexDistanceSqr) make = true;}if (make){Point p = new Point();//p.allVectors.Clear();for(int i = 0; i < _transforms.Length; ++i){p.allVectors.Add(_transforms[i].position);}p.timeCreated = Time.time;_points.Add(p);_lastPosition = transform.position;#if USE_INTERPOLATIONif (_points.Count == 1){_smoothedPoints.Add(p);}else if (_points.Count > 1){// add 1+subdivisions for every possible pair in the _pointsfor (int n = 0; n < 1+subdivisions; ++n)_smoothedPoints.Add(p);}// we use 4 control points for the smoothingif (_points.Count >= 4){List<List<Vector3> > vecsmooths = new List< List<Vector3> >();int transformsSize = _points[_points.Count - 4].allVectors.Count;int smoothTipListCount = 0 ;for(int i = 0 ; i < transformsSize; ++i){//Debug.LogError( "transformsSize" + transformsSize );Vector3[] tipPoints = new Vector3[4];tipPoints[0] = _points[_points.Count - 4].allVectors[i];tipPoints[1] = _points[_points.Count - 3].allVectors[i];tipPoints[2] = _points[_points.Count - 2].allVectors[i];tipPoints[3] = _points[_points.Count - 1].allVectors[i];/// donot use Bezier HelloHuan;//IEnumerable<Vector3> smoothTip = Interpolate.NewBezier(Interpolate.Ease(Interpolate.EaseType.Linear), tipPoints, subdivisions);IEnumerable<Vector3> smoothTip = Interpolate.NewCatmullRom(tipPoints, subdivisions, false);List<Vector3> Tmp = new List<Vector3>(smoothTip);smoothTipListCount = Tmp.Count;//Debug.LogError( "smoothTipListCount\t\t" + smoothTipListCount ); vecsmooths.Add( Tmp );}float firstTime = _points[_points.Count - 4].timeCreated;float secondTime = _points[_points.Count - 1].timeCreated;//Debug.Log(" smoothTipList.Count: " + smoothTipList.Count);for (int n = 0; n <smoothTipListCount; ++n){int idx = _smoothedPoints.Count - (smoothTipListCount-n);// there are moments when the _smoothedPoints are lesser// than what is required, when elements from it are removedif (idx > -1 && idx < _smoothedPoints.Count){Point sp = new Point();for(int i = 0; i < transformsSize; ++i ){sp.allVectors.Add( vecsmooths[i][n] );}sp.timeCreated = Mathf.Lerp(firstTime, secondTime, (float)n/ smoothTipListCount);_smoothedPoints[idx] = sp;}//else//{// Debug.LogError(idx + "/" + _smoothedPoints.Count);//}}}
#endif}else{if(_points[_points.Count - 1].allVectors.Count == _transforms.Length){for(int i = 0; i < _transforms.Length; ++i){_points[_points.Count - 1].allVectors[i] = (_transforms[i].position);}}else{_points[_points.Count - 1].RemoveVectors();for(int i = 0; i < _transforms.Length; ++i){_points[_points.Count - 1].allVectors.Add(_transforms[i].position);}}//_points[_points.Count - 1].timeCreated = Time.time;#if USE_INTERPOLATION
// _smoothedPoints[_smoothedPoints.Count - 1].RemoveVectors();
// for(int i = 0; i < _transforms.Length; ++i)
// {
// _smoothedPoints[_smoothedPoints.Count - 1].allVectors.Add(_transforms[i].position);
// }if(_smoothedPoints[_smoothedPoints.Count - 1].allVectors.Count == _transforms.Length){for(int i = 0; i < _transforms.Length; ++i){_smoothedPoints[_smoothedPoints.Count - 1].allVectors[i] = (_transforms[i].position);}}else{_smoothedPoints[_smoothedPoints.Count - 1].RemoveVectors();for(int i = 0; i < _transforms.Length; ++i){_smoothedPoints[_smoothedPoints.Count - 1].allVectors.Add(_transforms[i].position);}}#endif}}else{if (_points.Count > 0){
// for(int i = 0; i < _transforms.Length; ++i)
// {
// _points[_points.Count - 1].allVectors.Add(_transforms[i].position);
// }if(_points[_points.Count - 1].allVectors.Count == _transforms.Length){for(int i = 0; i < _transforms.Length; ++i){_points[_points.Count - 1].allVectors[i] = (_transforms[i].position);}}else{_points[_points.Count - 1].RemoveVectors();for(int i = 0; i < _transforms.Length; ++i){_points[_points.Count - 1].allVectors.Add(_transforms[i].position);}}//_points[_points.Count - 1].timeCreated = Time.time;}#if USE_INTERPOLATIONif (_smoothedPoints.Count > 0){
// for(int i = 0; i < _transforms.Length; ++i)
// {
// _smoothedPoints[_smoothedPoints.Count - 1].allVectors.Add(_transforms[i].position);
// }if(_smoothedPoints[_smoothedPoints.Count - 1].allVectors.Count == _transforms.Length){for(int i = 0; i < _transforms.Length; ++i){_smoothedPoints[_smoothedPoints.Count - 1].allVectors[i] = (_transforms[i].position);}}else{_smoothedPoints[_smoothedPoints.Count - 1].RemoveVectors();for(int i = 0; i < _transforms.Length; ++i){_smoothedPoints[_smoothedPoints.Count - 1].allVectors.Add(_transforms[i].position);}}}
#endif}}RemoveOldPoints(_points);if (_points.Count == 0){_trailMesh.Clear();}#if USE_INTERPOLATIONRemoveOldPoints(_smoothedPoints);if (_smoothedPoints.Count == 0){_trailMesh.Clear();}
#endif#if USE_INTERPOLATIONList<Point> pointsToUse = _smoothedPoints;
#elseList<Point> pointsToUse = _points;
#endifif (pointsToUse.Count > 1){int sectionPointSize = _transforms.Length;Vector3[] newVertices = new Vector3[pointsToUse.Count * sectionPointSize];Vector2[] newUV = new Vector2[pointsToUse.Count * sectionPointSize];int[] newTriangles = new int[(pointsToUse.Count - 1) * 6*(sectionPointSize - 1)];Color[] newColors = new Color[pointsToUse.Count * sectionPointSize];for (int n = 0; n < pointsToUse.Count; ++n){Point p = pointsToUse[n];float time = (Time.time - p.timeCreated) / _lifeTime;Color color = Color.Lerp(Color.white, Color.clear, time);if (_colors != null && _colors.Length > 0){float colorTime = time * (_colors.Length - 1);float min = Mathf.Floor(colorTime);float max = Mathf.Clamp(Mathf.Ceil(colorTime), 1, _colors.Length - 1);float lerp = Mathf.InverseLerp(min, max, colorTime);if (min >= _colors.Length) min = _colors.Length - 1; if (min < 0) min = 0;if (max >= _colors.Length) max = _colors.Length - 1; if (max < 0) max = 0;color = Color.Lerp(_colors[(int)min], _colors[(int)max], lerp);}float size = 0f;if (_sizes != null && _sizes.Length > 0){float sizeTime = time * (_sizes.Length - 1);float min = Mathf.Floor(sizeTime);float max = Mathf.Clamp(Mathf.Ceil(sizeTime), 1, _sizes.Length - 1);float lerp = Mathf.InverseLerp(min, max, sizeTime);if (min >= _sizes.Length) min = _sizes.Length - 1; if (min < 0) min = 0;if (max >= _sizes.Length) max = _sizes.Length - 1; if (max < 0) max = 0;size = Mathf.Lerp(_sizes[(int)min], _sizes[(int)max], lerp);}Vector3 lineDirection = p.allVectors[sectionPointSize-1] - p.allVectors[0] ;//newVertices[n * 2] = p.basePosition - (lineDirection * (size * 0.5f));//newVertices[(n * 2) + 1] = p.tipPosition + (lineDirection * (size * 0.5f));float deltaRatioxx = 1.0F/(sectionPointSize-1);float uvRatio = (float)n/pointsToUse.Count;for(int i = 0; i < sectionPointSize; ++i){newVertices[n * sectionPointSize + i] = p.allVectors[i] + (lineDirection * (size * ((deltaRatioxx*i) - 0.5f) ));newColors[(n * sectionPointSize) + i] = color;newUV[(n * sectionPointSize) + i] = new Vector2(uvRatio, deltaRatioxx * i);}if (n > 0){int triCount = (sectionPointSize-1)*2;int indexCount = triCount * 3;for(int k = 0; k < sectionPointSize - 1; ++k){newTriangles[(n - 1) * indexCount + 0+6*k] = ( (n-1) * sectionPointSize) + k;newTriangles[((n - 1) * indexCount) + 1+6*k] = ((n-1) * sectionPointSize) +1 +k;newTriangles[((n - 1) * indexCount) + 2+6*k] = (n * sectionPointSize) + k;newTriangles[((n - 1) * indexCount) + 3+6*k] = (n * sectionPointSize) + 1 + k;newTriangles[((n - 1) * indexCount) + 4+6*k] = (n * sectionPointSize) + 0 + k;newTriangles[((n - 1) * indexCount) + 5+6*k] =((n-1) * sectionPointSize) + 1+k;}}}_trailMesh.Clear();_trailMesh.vertices = newVertices;_trailMesh.colors = newColors;_trailMesh.uv = newUV;_trailMesh.triangles = newTriangles;}}void RemoveOldPoints(List<Point> pointList){List<Point> remove = new List<Point>();foreach (Point p in pointList){// cull old points firstif (Time.time - p.timeCreated > _lifeTime){remove.Add(p);}}foreach (Point p in remove){p .RemoveVectors();pointList.Remove(p);}}
}
代码2:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*** Interpolation utility functions: easing, bezier, and catmull-rom.* Consider using Unity's Animation curve editor and AnimationCurve class* before scripting the desired behaviour using this utility.** Interpolation functionality available at different levels of abstraction.* Low level access via individual easing functions (ex. EaseInOutCirc),* Bezier(), and CatmullRom(). High level access using sequence generators,* NewEase(), NewBezier(), and NewCatmullRom().** Sequence generators are typically used as follows:** IEnumerable<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);* foreach (Vector3 newPoint in sequence) {* transform.position = newPoint;* yield return WaitForSeconds(1.0f);* }** Or:** IEnumerator<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration).GetEnumerator();* function Update() {* if (sequence.MoveNext()) {* transform.position = sequence.Current;* }* }** The low level functions work similarly to Unity's built in Lerp and it is* up to you to track and pass in elapsedTime and duration on every call. The* functions take this form (or the logical equivalent for Bezier() and CatmullRom()).** transform.position = ease(start, distance, elapsedTime, duration);** For convenience in configuration you can use the Ease(EaseType) function to* look up a concrete easing function:* * [SerializeField]* Interpolate.EaseType easeType; // set using Unity's property inspector* Interpolate.Function ease; // easing of a particular EaseType* function Awake() {* ease = Interpolate.Ease(easeType);* }** @author Fernando Zapata (fernando@cpudreams.com)* @Traduzione Andrea85cs (andrea85cs@dynematica.it)*/public class Interpolate {/*** Different methods of easing interpolation.*/public enum EaseType {Linear,EaseInQuad,EaseOutQuad,EaseInOutQuad,EaseInCubic,EaseOutCubic,EaseInOutCubic,EaseInQuart,EaseOutQuart,EaseInOutQuart,EaseInQuint,EaseOutQuint,EaseInOutQuint,EaseInSine,EaseOutSine,EaseInOutSine,EaseInExpo,EaseOutExpo,EaseInOutExpo,EaseInCirc,EaseOutCirc,EaseInOutCirc}/*** Sequence of eleapsedTimes until elapsedTime is >= duration.** Note: elapsedTimes are calculated using the value of Time.deltatTime each* time a value is requested.*/static Vector3 Identity(Vector3 v) {return v;}static Vector3 TransformDotPosition(Transform t) {return t.position;}static IEnumerable<float> NewTimer(float duration) {float elapsedTime = 0.0f;while (elapsedTime < duration) {yield return elapsedTime;elapsedTime += Time.deltaTime;// make sure last value is never skippedif (elapsedTime >= duration) {yield return elapsedTime;}}}public delegate Vector3 ToVector3<T>(T v);public delegate float Function(float a, float b, float c, float d);/*** Generates sequence of integers from start to end (inclusive) one step* at a time.*/static IEnumerable<float> NewCounter(int start, int end, int step) {for (int i = start; i <= end; i += step) {yield return i;}}/*** Returns sequence generator from start to end over duration using the* given easing function. The sequence is generated as it is accessed* using the Time.deltaTime to calculate the portion of duration that has* elapsed.*/public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float duration) {IEnumerable<float> timer = Interpolate.NewTimer(duration);return NewEase(ease, start, end, duration, timer);}/*** Instead of easing based on time, generate n interpolated points (slices)* between the start and end positions.*/public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, int slices) {IEnumerable<float> counter = Interpolate.NewCounter(0, slices + 1, 1);return NewEase(ease, start, end, slices + 1, counter);}/*** Generic easing sequence generator used to implement the time and* slice variants. Normally you would not use this function directly.*/static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float total, IEnumerable<float> driver) {Vector3 distance = end - start;foreach (float i in driver) {yield return Ease(ease, start, distance, i, total);}}/*** Vector3 interpolation using given easing method. Easing is done independently* on all three vector axis.*/static Vector3 Ease(Function ease, Vector3 start, Vector3 distance, float elapsedTime, float duration) {start.x = ease(start.x, distance.x, elapsedTime, duration);start.y = ease(start.y, distance.y, elapsedTime, duration);start.z = ease(start.z, distance.z, elapsedTime, duration);return start;}/*** Returns the static method that implements the given easing type for scalars.* Use this method to easily switch between easing interpolation types.** All easing methods clamp elapsedTime so that it is always <= duration.** var ease = Interpolate.Ease(EaseType.EaseInQuad);* i = ease(start, distance, elapsedTime, duration);*/public static Function Ease(EaseType type) {// Source Flash easing functions:// http://gizma.com/easing/// http://www.robertpenner.com/easing/easing_demo.html//// Changed to use more friendly variable names, that follow my Lerp// conventions:// start = b (start value)// distance = c (change in value)// elapsedTime = t (current time)// duration = d (time duration)Function f = null;switch (type) {case EaseType.Linear: f = Interpolate.Linear; break;case EaseType.EaseInQuad: f = Interpolate.EaseInQuad; break;case EaseType.EaseOutQuad: f = Interpolate.EaseOutQuad; break;case EaseType.EaseInOutQuad: f = Interpolate.EaseInOutQuad; break;case EaseType.EaseInCubic: f = Interpolate.EaseInCubic; break;case EaseType.EaseOutCubic: f = Interpolate.EaseOutCubic; break;case EaseType.EaseInOutCubic: f = Interpolate.EaseInOutCubic; break;case EaseType.EaseInQuart: f = Interpolate.EaseInQuart; break;case EaseType.EaseOutQuart: f = Interpolate.EaseOutQuart; break;case EaseType.EaseInOutQuart: f = Interpolate.EaseInOutQuart; break;case EaseType.EaseInQuint: f = Interpolate.EaseInQuint; break;case EaseType.EaseOutQuint: f = Interpolate.EaseOutQuint; break;case EaseType.EaseInOutQuint: f = Interpolate.EaseInOutQuint; break;case EaseType.EaseInSine: f = Interpolate.EaseInSine; break;case EaseType.EaseOutSine: f = Interpolate.EaseOutSine; break;case EaseType.EaseInOutSine: f = Interpolate.EaseInOutSine; break;case EaseType.EaseInExpo: f = Interpolate.EaseInExpo; break;case EaseType.EaseOutExpo: f = Interpolate.EaseOutExpo; break;case EaseType.EaseInOutExpo: f = Interpolate.EaseInOutExpo; break;case EaseType.EaseInCirc: f = Interpolate.EaseInCirc; break;case EaseType.EaseOutCirc: f = Interpolate.EaseOutCirc; break;case EaseType.EaseInOutCirc: f = Interpolate.EaseInOutCirc; break;}return f;}/*** Returns sequence generator from the first node to the last node over* duration time using the points in-between the first and last node* as control points of a bezier curve used to generate the interpolated points* in the sequence. If there are no control points (ie. only two nodes, first* and last) then this behaves exactly the same as NewEase(). In other words* a zero-degree bezier spline curve is just the easing method. The sequence* is generated as it is accessed using the Time.deltaTime to calculate the* portion of duration that has elapsed.*/public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, float duration) {IEnumerable<float> timer = Interpolate.NewTimer(duration);return NewBezier<Transform>(ease, nodes, TransformDotPosition, duration, timer);}/*** Instead of interpolating based on time, generate n interpolated points* (slices) between the first and last node.*/public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, int slices) {IEnumerable<float> counter = NewCounter(0, slices + 1, 1);return NewBezier<Transform>(ease, nodes, TransformDotPosition, slices + 1, counter);}/*** A Vector3[] variation of the Transform[] NewBezier() function.* Same functionality but using Vector3s to define bezier curve.*/public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, float duration) {IEnumerable<float> timer = NewTimer(duration);return NewBezier<Vector3>(ease, points, Identity, duration, timer);}/*** A Vector3[] variation of the Transform[] NewBezier() function.* Same functionality but using Vector3s to define bezier curve.*/public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, int slices) {IEnumerable<float> counter = NewCounter(0, slices + 1, 1);return NewBezier<Vector3>(ease, points, Identity, slices + 1, counter);}/*** Generic bezier spline sequence generator used to implement the time and* slice variants. Normally you would not use this function directly.*/static IEnumerable<Vector3> NewBezier<T>(Function ease, IList nodes, ToVector3<T> toVector3, float maxStep, IEnumerable<float> steps) {// need at least two nodes to spline betweenif (nodes.Count >= 2) {// copy nodes array since Bezier is destructiveVector3[] points = new Vector3[nodes.Count];foreach (float step in steps) {// re-initialize copy before each destructive call to Bezierfor (int i = 0; i < nodes.Count; i++) {points[i] = toVector3((T)nodes[i]);}yield return Bezier(ease, points, step, maxStep);// make sure last value is always generated}}}/*** A Vector3 n-degree bezier spline.** WARNING: The points array is modified by Bezier. See NewBezier() for a* safe and user friendly alternative.** You can pass zero control points, just the start and end points, for just* plain easing. In other words a zero-degree bezier spline curve is just the* easing method.** @param points start point, n control points, end point*/static Vector3 Bezier(Function ease, Vector3[] points, float elapsedTime, float duration) {// Reference: http://ibiblio.org/e-notes/Splines/Bezier.htm// Interpolate the n starting points to generate the next j = (n - 1) points,// then interpolate those n - 1 points to generate the next n - 2 points,// continue this until we have generated the last point (n - (n - 1)), j = 1.// We store the next set of output points in the same array as the// input points used to generate them. This works because we store the// result in the slot of the input point that is no longer used for this// iteration.for (int j = points.Length - 1; j > 0; j--) {for (int i = 0; i < j; i++) {points[i].x = ease(points[i].x, points[i + 1].x - points[i].x, elapsedTime, duration);points[i].y = ease(points[i].y, points[i + 1].y - points[i].y, elapsedTime, duration);points[i].z = ease(points[i].z, points[i + 1].z - points[i].z, elapsedTime, duration);}}return points[0];}/*** Returns sequence generator from the first node, through each control point,* and to the last node. N points are generated between each node (slices)* using Catmull-Rom.*/public static IEnumerable<Vector3> NewCatmullRom(Transform[] nodes, int slices, bool loop) {return NewCatmullRom<Transform>(nodes, TransformDotPosition, slices, loop);}/*** A Vector3[] variation of the Transform[] NewCatmullRom() function.* Same functionality but using Vector3s to define curve.*/public static IEnumerable<Vector3> NewCatmullRom(Vector3[] points, int slices, bool loop) {return NewCatmullRom<Vector3>(points, Identity, slices, loop);}/*** Generic catmull-rom spline sequence generator used to implement the* Vector3[] and Transform[] variants. Normally you would not use this* function directly.*/static IEnumerable<Vector3> NewCatmullRom<T>(IList nodes, ToVector3<T> toVector3, int slices, bool loop) {// need at least two nodes to spline betweenif (nodes.Count >= 2) {// yield the first point explicitly, if looping the first point// will be generated again in the step for loop when interpolating// from last point back to the first pointyield return toVector3((T)nodes[0]);int last = nodes.Count - 1;for (int current = 0; loop || current < last; current++) {// wrap around when loopingif (loop && current > last) {current = 0;}// handle edge cases for looping and non-looping scenarios// when looping we wrap around, when not looping use start for previous// and end for next when you at the ends of the nodes arrayint previous = (current == 0) ? ((loop) ? last : current) : current - 1;int start = current;int end = (current == last) ? ((loop) ? 0 : current) : current + 1;int next = (end == last) ? ((loop) ? 0 : end) : end + 1;// adding one guarantees yielding at least the end pointint stepCount = slices + 1;for (int step = 1; step <= stepCount; step++) {yield return CatmullRom(toVector3((T)nodes[previous]),toVector3((T)nodes[start]),toVector3((T)nodes[end]),toVector3((T)nodes[next]),step, stepCount);}}}}/*** A Vector3 Catmull-Rom spline. Catmull-Rom splines are similar to bezier* splines but have the useful property that the generated curve will go* through each of the control points.** NOTE: The NewCatmullRom() functions are an easier to use alternative to this* raw Catmull-Rom implementation.** @param previous the point just before the start point or the start point* itself if no previous point is available* @param start generated when elapsedTime == 0* @param end generated when elapsedTime >= duration* @param next the point just after the end point or the end point itself if no* next point is available*/static Vector3 CatmullRom(Vector3 previous, Vector3 start, Vector3 end, Vector3 next, float elapsedTime, float duration) {// References used:// p.266 GemsV1//// tension is often set to 0.5 but you can use any reasonable value:// http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf//// bias and tension controls:// http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/float percentComplete = elapsedTime / duration;float percentCompleteSquared = percentComplete * percentComplete;float percentCompleteCubed = percentCompleteSquared * percentComplete;return previous * (-0.5f * percentCompleteCubed +percentCompleteSquared -0.5f * percentComplete) +start * ( 1.5f * percentCompleteCubed +-2.5f * percentCompleteSquared + 1.0f) +end * (-1.5f * percentCompleteCubed +2.0f * percentCompleteSquared +0.5f * percentComplete) +next * ( 0.5f * percentCompleteCubed -0.5f * percentCompleteSquared);}/*** Linear interpolation (same as Mathf.Lerp)*/static float Linear(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime to be <= durationif (elapsedTime > duration) { elapsedTime = duration; }return distance * (elapsedTime / duration) + start;}/*** quadratic easing in - accelerating from zero velocity*/static float EaseInQuad(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return distance * elapsedTime * elapsedTime + start;}/*** quadratic easing out - decelerating to zero velocity*/static float EaseOutQuad(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return -distance * elapsedTime * (elapsedTime - 2) + start;}/*** quadratic easing in/out - acceleration until halfway, then deceleration*/static float EaseInOutQuad(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime + start;elapsedTime--;return -distance / 2 * (elapsedTime * (elapsedTime - 2) - 1) + start;}/*** cubic easing in - accelerating from zero velocity*/static float EaseInCubic(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return distance * elapsedTime * elapsedTime * elapsedTime + start;}/*** cubic easing out - decelerating to zero velocity*/static float EaseOutCubic(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;elapsedTime--;return distance * (elapsedTime * elapsedTime * elapsedTime + 1) + start;}/*** cubic easing in/out - acceleration until halfway, then deceleration*/static float EaseInOutCubic(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime + start;elapsedTime -= 2;return distance / 2 * (elapsedTime * elapsedTime * elapsedTime + 2) + start;}/*** quartic easing in - accelerating from zero velocity*/static float EaseInQuart(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;}/*** quartic easing out - decelerating to zero velocity*/static float EaseOutQuart(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;elapsedTime--;return -distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1) + start;}/*** quartic easing in/out - acceleration until halfway, then deceleration*/static float EaseInOutQuart(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;elapsedTime -= 2;return -distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2) + start;}/*** quintic easing in - accelerating from zero velocity*/static float EaseInQuint(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;}/*** quintic easing out - decelerating to zero velocity*/static float EaseOutQuint(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;elapsedTime--;return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1) + start;}/*** quintic easing in/out - acceleration until halfway, then deceleration*/static float EaseInOutQuint(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2f);if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;elapsedTime -= 2;return distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2) + start;}/*** sinusoidal easing in - accelerating from zero velocity*/static float EaseInSine(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime to be <= durationif (elapsedTime > duration) { elapsedTime = duration; }return -distance * Mathf.Cos(elapsedTime / duration * (Mathf.PI / 2)) + distance + start;}/*** sinusoidal easing out - decelerating to zero velocity*/static float EaseOutSine(float start, float distance, float elapsedTime, float duration) {if (elapsedTime > duration) { elapsedTime = duration; }return distance * Mathf.Sin(elapsedTime / duration * (Mathf.PI / 2)) + start;}/*** sinusoidal easing in/out - accelerating until halfway, then decelerating*/static float EaseInOutSine(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime to be <= durationif (elapsedTime > duration) { elapsedTime = duration; }return -distance / 2 * (Mathf.Cos(Mathf.PI * elapsedTime / duration) - 1) + start;}/*** exponential easing in - accelerating from zero velocity*/static float EaseInExpo(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime to be <= durationif (elapsedTime > duration) { elapsedTime = duration; }return distance * Mathf.Pow(2, 10 * (elapsedTime / duration - 1)) + start;}/*** exponential easing out - decelerating to zero velocity*/static float EaseOutExpo(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime to be <= durationif (elapsedTime > duration) { elapsedTime = duration; }return distance * (-Mathf.Pow(2, -10 * elapsedTime / duration) + 1) + start;}/*** exponential easing in/out - accelerating until halfway, then decelerating*/static float EaseInOutExpo(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);if (elapsedTime < 1) return distance / 2 * Mathf.Pow(2, 10 * (elapsedTime - 1)) + start;elapsedTime--;return distance / 2 * (-Mathf.Pow(2, -10 * elapsedTime) + 2) + start;}/*** circular easing in - accelerating from zero velocity*/static float EaseInCirc(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;return -distance * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;}/*** circular easing out - decelerating to zero velocity*/static float EaseOutCirc(float start, float distance, float elapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;elapsedTime--;return distance * Mathf.Sqrt(1 - elapsedTime * elapsedTime) + start;}/*** circular easing in/out - acceleration until halfway, then deceleration*/static float EaseInOutCirc(float start, float distance, floatelapsedTime, float duration) {// clamp elapsedTime so that it cannot be greater than durationelapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);if (elapsedTime < 1) return -distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;elapsedTime -= 2;return distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) + 1) + start;}
}
这篇关于U3D——刀光轨迹插件的改进的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!