Beispiel #1
0
        private float GetReparam(BezierSplineSegment ss, float u)
        {
            if (u <= 0)
            {
                return(0);
            }
            else if (u >= 1)
            {
                return(1);
            }

            switch (m_reparam)
            {
            case SplineReparamType.Simple:
            {
                int ridx = 0;
                for (int i = 1; i < m_stepcount + 1; ++i)
                {
                    if (ss.m_precomps[i] > u)
                    {
                        ridx = i - 1;
                        break;
                    }
                }
                float uc = (u - ss.m_precomps[ridx]) / (ss.m_precomps[ridx + 1] - ss.m_precomps[ridx]);
                return(Mathf.Lerp(ss.m_params[ridx], ss.m_params[ridx + 1], uc));
            }

            default:
                return(0);
            }
        }
Beispiel #2
0
        private void BuildSegment(BezierSplineSegment ss, BezierSplinePoint pp, BezierSplinePoint sp, BezierSplinePoint ep, BezierSplinePoint np)
        {
            PreparePoint(pp, sp, ep);
            PreparePoint(sp, ep, np);

            ss.m_startpos  = sp.m_point;
            ss.m_endpos    = ep.m_point;
            ss.m_startctrl = ss.m_startpos + sp.m_nextctrl;
            ss.m_endctrl   = ss.m_endpos + ep.m_prevctrl;

            if (sp.m_type == SplinePointType.Corner && ep.m_type == SplinePointType.Corner)
            {
                ss.m_type = SplineSegmentType.Linear;
            }
            else
            {
                ss.m_type = SplineSegmentType.Curve;
            }

            ss.m_startlen = m_length;
            float seglen = GetLength(ss);

            m_length   += seglen;
            ss.m_length = seglen;
            ss.m_endlen = m_length;

            switch (m_reparam)
            {
            case SplineReparamType.None:
                ss.m_params   = null;
                ss.m_precomps = null;
                break;

            case SplineReparamType.Simple:
            {
                m_precompdiv = 1 / (float)m_stepcount;
                float param = 0, length = 0;

                Vector3 prev, next;

                ss.m_params   = new float[m_stepcount + 1];
                ss.m_precomps = new float[m_stepcount + 1];
                for (int i = 1; i < m_stepcount + 1; ++i)
                {
                    prev             = GetPosition(ss, param);
                    param           += m_precompdiv;
                    next             = GetPosition(ss, param);
                    length          += (next - prev).magnitude;
                    ss.m_precomps[i] = length / seglen;
                    ss.m_params[i]   = param;
                }
                ss.m_params[0]             = 0;
                ss.m_params[m_stepcount]   = 1;
                ss.m_precomps[0]           = 0;
                ss.m_precomps[m_stepcount] = 1;
                m_precompdiv = 1 / (float)m_stepcount;
            }
            break;
            }
        }
Beispiel #3
0
        private float GetReparamRungeKutta(BezierSplineSegment ss, float u)
        {
            float t = 0, k1, k2, k3, k4, h = u / (float)m_stepcount, mag;

            for (int i = 1; i <= m_stepcount; i++)
            {
                mag = GetTangent(ss, t).magnitude;
                if (mag == 0)
                {
                    k1 = 0;
                    k2 = 0;
                    k3 = 0;
                    k4 = 0;
                }
                else
                {
                    k1 = h / GetTangent(ss, t).magnitude;
                    k2 = h / GetTangent(ss, t + k1 * 0.5f).magnitude;
                    k3 = h / GetTangent(ss, t + k2 * 0.5f).magnitude;
                    k4 = h / GetTangent(ss, t + k3).magnitude;
                }
                t += (k1 + 2 * (k2 + k3) + k4) * 0.16666666666666666666666666666667f;
            }
            return(t);
        }
Beispiel #4
0
        private float GetLength(BezierSplineSegment ss)
        {
            switch (ss.m_type)
            {
            case SplineSegmentType.Linear:
                return((ss.m_endpos - ss.m_startpos).magnitude);

            case SplineSegmentType.Curve:
            {
                float   len = 0;
                Vector3 start, end;
                float   t = 0, dt = 1 / (float)m_stepcount;
                int     idx = 0;
                start = ss.m_startpos;
                while (idx < m_stepcount)
                {
                    t    += dt;
                    end   = GetPosition(ss, t);
                    len  += (end - start).magnitude;
                    start = end;
                    ++idx;
                }
                return(len);
            }

            default: return(0);
            }
        }
Beispiel #5
0
        public override void Build()
        {
            int idx, count;
            BezierSplinePoint pp, sp, ep, np;

            //
            if (m_points.Count < 2)
            {
                m_segments = null;
                m_length   = 0;
                return;
            }
            if (m_wrapmode == SplineWrapMode.Loop)
            {
                count = m_points.Count;
            }
            else
            {
                count = m_points.Count - 1;
            }
            //
            m_segments = new BezierSplineSegment[count];
            m_length   = 0;
            idx        = 0;
            if (m_wrapmode == SplineWrapMode.Loop)
            {
                while (idx < count)
                {
                    pp = m_points[SplineUtil.WrapIndex(idx - 1, m_points.Count)];
                    sp = m_points[SplineUtil.WrapIndex(idx, m_points.Count)];
                    ep = m_points[SplineUtil.WrapIndex(idx + 1, m_points.Count)];
                    np = m_points[SplineUtil.WrapIndex(idx + 2, m_points.Count)];

                    m_segments[idx] = new BezierSplineSegment();
                    BuildSegment(m_segments[idx], pp, sp, ep, np);
                    ++idx;
                }
            }
            else
            {
                while (idx < count)
                {
                    pp = m_points[SplineUtil.ClampIndex(idx - 1, m_points.Count)];
                    sp = m_points[SplineUtil.ClampIndex(idx, m_points.Count)];
                    ep = m_points[SplineUtil.ClampIndex(idx + 1, m_points.Count)];
                    np = m_points[SplineUtil.ClampIndex(idx + 2, m_points.Count)];

                    m_segments[idx] = new BezierSplineSegment();
                    BuildSegment(m_segments[idx], pp, sp, ep, np);
                    ++idx;
                }
            }

            ++m_buildnum;

            if (OnSplineRebuild != null)
            {
                OnSplineRebuild();
            }
        }
Beispiel #6
0
        protected override Vector3 GetNormal(int segidx, float segpos)
        {
            BezierSplineSegment ss = m_segments[segidx];

            if (m_reparam == BaseSpline.SplineReparamType.None)
            {
                return(GetNormal(ss, segpos / ss.m_length));
            }
            else
            {
                return(GetNormal(ss, GetReparam(ss, segpos / ss.m_length)));
            }
        }
Beispiel #7
0
        public Vector3 GetPosition(BezierSplineSegment ss, float t)
        {
            switch (ss.m_type)
            {
            case SplineSegmentType.Linear:
                return(ss.m_startpos + (ss.m_endpos - ss.m_startpos) * t);

            case SplineSegmentType.Curve:
            {
                // (1 - t) ^ 3 * A + 3 * (1 - t) ^ 2 * t * B + 3 * (1 - t) * t ^ 2 * C + t ^ 3 * D
                float _1mt = 1.0f - t, _1mt2 = _1mt * _1mt, t2 = t * t;
                return(ss.m_startpos * _1mt * _1mt2 +
                       ss.m_startctrl * 3 * _1mt2 * t +
                       ss.m_endctrl * 3 * _1mt * t2 +
                       ss.m_endpos * t2 * t);
            }

            default: return(Vector3.zero);
            }
        }
Beispiel #8
0
        public Vector3 GetTangent(BezierSplineSegment ss, float t)
        {
            switch (ss.m_type)
            {
            case SplineSegmentType.Linear:
                return(ss.m_endpos - ss.m_startpos);

            case SplineSegmentType.Curve:
            {
                // -3 * (A * (t - 1) ^ 2 + B * (-3 * t ^ 2 + 4 * t - 1) + t * (3 * C * t - 2 * C - D * t))
                float _1mt = 1.0f - t, _1mt2 = _1mt * _1mt, t2 = t * t;
                return(ss.m_startpos * -3 * _1mt2 +
                       ss.m_startctrl * (-6 * _1mt * t + 3 * _1mt2) +
                       ss.m_endctrl * (6 * _1mt * t - 3 * t2) +
                       ss.m_endpos * 3 * t2);
            }

            default: return(Vector3.zero);
            }
        }
Beispiel #9
0
        private Vector3 GetNormal(BezierSplineSegment ss, float t)
        {
            switch (ss.m_type)
            {
            case SplineSegmentType.Linear:
                return(Vector3.zero);

            case SplineSegmentType.Curve:
            {
                // -6 * (A * (t - 1) + B * (2 - 3 * t) + 3 * C * t - C - D * t)
                return(-6 * (ss.m_startpos * (1 - t) +
                             ss.m_startctrl * (2 - 3 * t) +
                             3 * ss.m_endctrl * t -
                             ss.m_endctrl -
                             ss.m_endpos * t));
            }

            default: return(Vector3.zero);
            }
        }
			private float GetReparam(BezierSplineSegment ss, float u)
			{
				if(u <= 0)
				{
					return 0;
				}
				else if(u >= 1)
				{
					return 1;
				}
				
				switch(m_reparam)
				{
				case SplineReparamType.Simple:
					{
						int ridx = 0;
						for(int i = 1; i < m_stepcount + 1; ++i)
						{
							if(ss.m_precomps[i] > u)
							{
								ridx = i - 1;
								break;
							}
						}
						float uc = (u - ss.m_precomps[ridx]) / (ss.m_precomps[ridx + 1] - ss.m_precomps[ridx]);
						return Mathf.Lerp(ss.m_params[ridx], ss.m_params[ridx + 1], uc);
					}
					
				default:
					return 0;
				}
			}
			private float GetReparamRungeKutta(BezierSplineSegment ss, float u)
			{
				float t = 0, k1, k2, k3, k4, h = u / (float)m_stepcount, mag;
				for (int i = 1; i <= m_stepcount; i++)
				{
					mag = GetTangent(ss, t).magnitude;
					if(mag == 0)
					{
						k1 = 0;
						k2 = 0;
						k3 = 0;
						k4 = 0;
					}
					else
					{
						k1 = h / GetTangent(ss, t).magnitude;
						k2 = h / GetTangent(ss, t + k1 * 0.5f).magnitude;
						k3 = h / GetTangent(ss, t + k2  * 0.5f).magnitude;
						k4 = h / GetTangent(ss, t + k3).magnitude;
					}
					t += (k1 + 2 * (k2 + k3) + k4) * 0.16666666666666666666666666666667f;
				}
				return t;
			}
			private Vector3 GetNormal(BezierSplineSegment ss, float t)
			{
				switch(ss.m_type)
				{
				case SplineSegmentType.Linear:
					return Vector3.zero;
					
				case SplineSegmentType.Curve:
					{
						// -6 * (A * (t - 1) + B * (2 - 3 * t) + 3 * C * t - C - D * t)
						return	-6 * (ss.m_startpos * (1 - t) +
								ss.m_startctrl * (2 - 3 * t) +
								3 * ss.m_endctrl * t -
								ss.m_endctrl -
								ss.m_endpos * t);
					}
					
				default: return Vector3.zero;
				}
			}
			public Vector3 GetTangent(BezierSplineSegment ss, float t)
			{
				switch(ss.m_type)
				{
				case SplineSegmentType.Linear:
					return (ss.m_endpos - ss.m_startpos);
					
				case SplineSegmentType.Curve:
					{
						// -3 * (A * (t - 1) ^ 2 + B * (-3 * t ^ 2 + 4 * t - 1) + t * (3 * C * t - 2 * C - D * t))
						float _1mt = 1.0f - t, _1mt2 = _1mt * _1mt, t2 = t * t;
						return	ss.m_startpos * -3 * _1mt2 +
								ss.m_startctrl * (-6 * _1mt * t + 3 * _1mt2) +
								ss.m_endctrl * (6 * _1mt * t - 3 * t2) +
								ss.m_endpos * 3 * t2;
					}
					
				default: return Vector3.zero;
				}
			}
			public Vector3 GetPosition(BezierSplineSegment ss, float t)
			{
				switch(ss.m_type)
				{
				case SplineSegmentType.Linear:
					return ss.m_startpos + (ss.m_endpos - ss.m_startpos) * t;
					
				case SplineSegmentType.Curve:
					{
						// (1 - t) ^ 3 * A + 3 * (1 - t) ^ 2 * t * B + 3 * (1 - t) * t ^ 2 * C + t ^ 3 * D
						float _1mt = 1.0f - t, _1mt2 = _1mt * _1mt, t2 = t * t;
						return	ss.m_startpos *_1mt * _1mt2 +
								ss.m_startctrl * 3 * _1mt2 * t +
								ss.m_endctrl * 3 * _1mt * t2 +
								ss.m_endpos * t2 * t;
					}
					
				default: return Vector3.zero;
				}
			}
			private float GetLength(BezierSplineSegment ss)
			{
				switch(ss.m_type)
				{
				case SplineSegmentType.Linear:
					return (ss.m_endpos - ss.m_startpos).magnitude;
					
				case SplineSegmentType.Curve:
					{
						float len = 0;
						Vector3 start, end;
						float t = 0, dt = 1 / (float)m_stepcount;
						int idx = 0;
						start = ss.m_startpos;
						while(idx < m_stepcount)
						{
							t += dt;
							end = GetPosition(ss, t);
							len += (end - start).magnitude;
							start = end;
							++idx;
						}
						return len;
					}
					
				default: return 0;
				}
			}
			private void BuildSegment(BezierSplineSegment ss, BezierSplinePoint pp, BezierSplinePoint sp, BezierSplinePoint ep, BezierSplinePoint np)
			{
				PreparePoint(pp, sp, ep);
				PreparePoint(sp, ep, np);
				
				ss.m_startpos = sp.m_point;
				ss.m_endpos = ep.m_point;
				ss.m_startctrl = ss.m_startpos + sp.m_nextctrl;
				ss.m_endctrl = ss.m_endpos + ep.m_prevctrl;
				
				if(sp.m_type == SplinePointType.Corner && ep.m_type == SplinePointType.Corner)
				{
					ss.m_type = SplineSegmentType.Linear;
				}
				else
				{
					ss.m_type = SplineSegmentType.Curve;
				}
				
				ss.m_startlen = m_length;
				float seglen = GetLength(ss);
				m_length += seglen;
				ss.m_length = seglen;
				ss.m_endlen = m_length;
				
				switch(m_reparam)
				{
				case SplineReparamType.None:			
					ss.m_params = null;
					ss.m_precomps = null;
					break;
					
				case SplineReparamType.Simple:
					{
						m_precompdiv = 1 / (float)m_stepcount;
						float param = 0, length = 0;
					
						Vector3 prev, next;
						
						ss.m_params = new float[m_stepcount + 1];
						ss.m_precomps = new float[m_stepcount + 1];
						for(int i = 1; i < m_stepcount + 1; ++i)
						{
							prev = GetPosition(ss, param);
							param += m_precompdiv;
							next = GetPosition(ss, param);
							length += (next - prev).magnitude;
							ss.m_precomps[i] = length / seglen;
							ss.m_params[i] = param;
						}
						ss.m_params[0] = 0;
						ss.m_params[m_stepcount] = 1;
						ss.m_precomps[0] = 0;
						ss.m_precomps[m_stepcount] = 1;
						m_precompdiv = 1 / (float)m_stepcount;
					}
					break;
					
				}
			}
			public override void Build()
			{
				int idx, count;
				BezierSplinePoint pp, sp, ep, np;
				//
				if(m_points.Count < 2)
				{
					m_segments = null;
					m_length = 0;
					return;
				}
				if(m_wrapmode == SplineWrapMode.Loop)
				{
					count = m_points.Count;
				}
				else
				{
					count = m_points.Count - 1;
				}
				//
				m_segments = new BezierSplineSegment[count];
				m_length = 0;
				idx = 0;
				if(m_wrapmode == SplineWrapMode.Loop)
				{
					while(idx < count)
					{
						pp = m_points[SplineUtil.WrapIndex(idx - 1, m_points.Count)];
						sp = m_points[SplineUtil.WrapIndex(idx, m_points.Count)];
						ep = m_points[SplineUtil.WrapIndex(idx + 1, m_points.Count)];
						np = m_points[SplineUtil.WrapIndex(idx + 2, m_points.Count)];
						
						m_segments[idx] = new BezierSplineSegment();
						BuildSegment(m_segments[idx], pp, sp, ep, np);
						++idx;
					}
				}
				else
				{
					while(idx < count)
					{
						pp = m_points[SplineUtil.ClampIndex(idx - 1, m_points.Count)];
						sp = m_points[SplineUtil.ClampIndex(idx, m_points.Count)];
						ep = m_points[SplineUtil.ClampIndex(idx + 1, m_points.Count)];
						np = m_points[SplineUtil.ClampIndex(idx + 2, m_points.Count)];
						
						m_segments[idx] = new BezierSplineSegment();
						BuildSegment(m_segments[idx], pp, sp, ep, np);
						++idx;
					}
				}
				
				++m_buildnum;

				if (OnSplineRebuild != null)
					OnSplineRebuild();

			}
Beispiel #18
0
        protected override Vector3 GetDrawPosition(int segidx, float t)
        {
            BezierSplineSegment ss = m_segments[segidx];

            return(GetPosition(ss, t));
        }