Example #1
0
        /// <summary>
        /// Same as Spline.Project but the point is transformed by the computer's transform.
        /// </summary>
        /// <param name="position">Point in space</param>
        /// <param name="subdivide">Subdivisions default: 4</param>
        /// <param name="from">Sample from [0-1] default: 0f</param>
        /// <param name="to">Sample to [0-1] default: 1f</param>
        /// <param name="mode">Mode to use the method in. Cached uses the cached samples while Calculate is more accurate but heavier</param>
        /// <param name="subdivisions">Subdivisions for the Calculate mode. Don't assign if not using Calculated mode.</param>
        /// <returns></returns>
        public void Project(Vector3 position, int controlPointCount, SplineSample result, double from = 0.0, double to = 1.0)
        {
            if (!hasSamples)
            {
                return;
            }
            if (Count == 1)
            {
                if (result == null)
                {
                    result = new SplineSample(samples[0]);
                }
                else
                {
                    result.CopyFrom(samples[0]);
                }
                return;
            }
            Spline.FormatFromTo(ref from, ref to);
            //First make a very rough sample of the from-to region
            int steps = (controlPointCount - 1) * 6; //Sampling six points per segment is enough to find the closest point range
            int step  = Count / steps;

            if (step < 1)
            {
                step = 1;
            }
            float  minDist   = (position - samples[0].position).sqrMagnitude;
            int    fromIndex = 0;
            int    toIndex   = Count - 1;
            double lerp;

            if (from != 0.0)
            {
                GetSamplingValues(from, out fromIndex, out lerp);
            }
            if (to != 1.0)
            {
                GetSamplingValues(to, out toIndex, out lerp);
                if (lerp > 0.0 && toIndex < Count - 1)
                {
                    toIndex++;
                }
            }
            int checkFrom = fromIndex;
            int checkTo   = toIndex;

            //Find the closest point range which will be checked in detail later
            for (int i = fromIndex; i <= toIndex; i += step)
            {
                if (i > toIndex)
                {
                    i = toIndex;
                }
                float dist = (position - samples[i].position).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist   = dist;
                    checkFrom = Mathf.Max(i - step, 0);
                    checkTo   = Mathf.Min(i + step, Count - 1);
                }
                if (i == toIndex)
                {
                    break;
                }
            }
            minDist = (position - samples[checkFrom].position).sqrMagnitude;

            int index = checkFrom;

            //Find the closest result within the range
            for (int i = checkFrom + 1; i <= checkTo; i++)
            {
                float dist = (position - samples[i].position).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist = dist;
                    index   = i;
                }
            }
            //Project the point on the line between the two closest samples
            int backIndex = index - 1;

            if (backIndex < 0)
            {
                backIndex = 0;
            }
            int frontIndex = index + 1;

            if (frontIndex > Count - 1)
            {
                frontIndex = Count - 1;
            }
            Vector3 back             = LinearAlgebraUtility.ProjectOnLine(samples[backIndex].position, samples[index].position, position);
            Vector3 front            = LinearAlgebraUtility.ProjectOnLine(samples[index].position, samples[frontIndex].position, position);
            float   backLength       = (samples[index].position - samples[backIndex].position).magnitude;
            float   frontLength      = (samples[index].position - samples[frontIndex].position).magnitude;
            float   backProjectDist  = (back - samples[backIndex].position).magnitude;
            float   frontProjectDist = (front - samples[frontIndex].position).magnitude;

            if (backIndex < index && index < frontIndex)
            {
                if ((position - back).sqrMagnitude < (position - front).sqrMagnitude)
                {
                    SplineSample.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result);
                    if (sampleMode == SplineComputer.SampleMode.Uniform)
                    {
                        result.percent = DMath.Lerp(GetSamplePercent(backIndex), GetSamplePercent(index), backProjectDist / backLength);
                    }
                }
                else
                {
                    SplineSample.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result);
                    if (sampleMode == SplineComputer.SampleMode.Uniform)
                    {
                        result.percent = DMath.Lerp(GetSamplePercent(frontIndex), GetSamplePercent(index), frontProjectDist / frontLength);
                    }
                }
            }
            else if (backIndex < index)
            {
                SplineSample.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result);
                if (sampleMode == SplineComputer.SampleMode.Uniform)
                {
                    result.percent = DMath.Lerp(GetSamplePercent(backIndex), GetSamplePercent(index), backProjectDist / backLength);
                }
            }
            else
            {
                SplineSample.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result);
                if (sampleMode == SplineComputer.SampleMode.Uniform)
                {
                    result.percent = DMath.Lerp(GetSamplePercent(frontIndex), GetSamplePercent(index), frontProjectDist / frontLength);
                }
            }

            if (Count > 1 && from == 0.0 && to == 1.0 && result.percent < samples[1].percent) //Handle looped splines
            {
                Vector3 projected = LinearAlgebraUtility.ProjectOnLine(samples[Count - 1].position, samples[Count - 2].position, position);
                if ((position - projected).sqrMagnitude < (position - result.position).sqrMagnitude)
                {
                    double l = LinearAlgebraUtility.InverseLerp(samples[Count - 1].position, samples[Count - 2].position, projected);
                    SplineSample.Lerp(samples[Count - 1], samples[Count - 2], l, result);
                    if (sampleMode == SplineComputer.SampleMode.Uniform)
                    {
                        result.percent = DMath.Lerp(GetSamplePercent(Count - 1), GetSamplePercent(Count - 2), l);
                    }
                }
            }
        }
Example #2
0
        public virtual void Project(SplineResult result, Vector3 point, double from = 0.0, double to = 1.0)
        {
            if (samples.Length == 0)
            {
                return;
            }
            if (samples.Length == 1)
            {
                if (result == null)
                {
                    result = new SplineResult(samples[0]);
                }
                else
                {
                    result.CopyFrom(samples[0]);
                }
                return;
            }
            if (computer == null)
            {
                result = new SplineResult();
                return;
            }
            //First make a very rough sample of the from-to region
            int steps = (computer.pointCount - 1) * 6; //Sampling six points per segment is enough to find the closest point range
            int step  = samples.Length / steps;

            if (step < 1)
            {
                step = 1;
            }
            float minDist   = (point - samples[0].position).sqrMagnitude;
            int   fromIndex = 0;
            int   toIndex   = samples.Length - 1;

            if (from != 0.0)
            {
                fromIndex = GetSampleIndex(from);
            }
            if (to != 1.0)
            {
                toIndex = Mathf.CeilToInt((float)to * (samples.Length - 1));
            }
            int checkFrom = fromIndex;
            int checkTo   = toIndex;

            //Find the closest point range which will be checked in detail later
            for (int i = fromIndex; i <= toIndex; i += step)
            {
                if (i > toIndex)
                {
                    i = toIndex;
                }
                float dist = (point - samples[i].position).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist   = dist;
                    checkFrom = Mathf.Max(i - step, 0);
                    checkTo   = Mathf.Min(i + step, samples.Length - 1);
                }
                if (i == toIndex)
                {
                    break;
                }
            }
            minDist = (point - samples[checkFrom].position).sqrMagnitude;

            int index = checkFrom;

            //Find the closest result within the range
            for (int i = checkFrom + 1; i <= checkTo; i++)
            {
                float dist = (point - samples[i].position).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist = dist;
                    index   = i;
                }
            }
            //Project the point on the line between the two closest samples
            int backIndex = index - 1;

            if (backIndex < 0)
            {
                backIndex = 0;
            }
            int frontIndex = index + 1;

            if (frontIndex > samples.Length - 1)
            {
                frontIndex = samples.Length - 1;
            }
            Vector3 back             = LinearAlgebraUtility.ProjectOnLine(samples[backIndex].position, samples[index].position, point);
            Vector3 front            = LinearAlgebraUtility.ProjectOnLine(samples[index].position, samples[frontIndex].position, point);
            float   backLength       = (samples[index].position - samples[backIndex].position).magnitude;
            float   frontLength      = (samples[index].position - samples[frontIndex].position).magnitude;
            float   backProjectDist  = (back - samples[backIndex].position).magnitude;
            float   frontProjectDist = (front - samples[frontIndex].position).magnitude;

            if (backIndex < index && index < frontIndex)
            {
                if ((point - back).sqrMagnitude < (point - front).sqrMagnitude)
                {
                    SplineResult.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result);
                }
                else
                {
                    SplineResult.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result);
                }
            }
            else if (backIndex < index)
            {
                SplineResult.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result);
            }
            else
            {
                SplineResult.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result);
            }
            if (from == 0.0 && to == 1.0 && result.percent < _address.moveStep / _resolution) //Handle looped splines
            {
                Vector3 projected = LinearAlgebraUtility.ProjectOnLine(samples[samples.Length - 1].position, samples[samples.Length - 2].position, point);
                if ((point - projected).sqrMagnitude < (point - result.position).sqrMagnitude)
                {
                    SplineResult.Lerp(samples[samples.Length - 1], samples[samples.Length - 2], LinearAlgebraUtility.InverseLerp(samples[samples.Length - 1].position, samples[samples.Length - 2].position, projected), result);
                }
            }
        }
Example #3
0
        public virtual void Project(SplineResult result, Vector3 point, double from = 0.0, double to = 1.0)
        {
            if (samples.Length == 0)
            {
                return;
            }
            if (samples.Length == 1)
            {
                if (result == null)
                {
                    result = new SplineResult(samples[0]);
                }
                else
                {
                    result.CopyFrom(samples[0]);
                }
                return;
            }
            if (computer == null)
            {
                result = new SplineResult();
                return;
            }
            int num  = (computer.pointCount - 1) * 6;
            int num2 = samples.Length / num;

            if (num2 < 1)
            {
                num2 = 1;
            }
            float num3 = (point - samples[0].position).sqrMagnitude;
            int   num4 = 0;
            int   num5 = samples.Length - 1;

            if (from != 0.0)
            {
                num4 = GetSampleIndex(from);
            }
            if (to != 1.0)
            {
                num5 = Mathf.CeilToInt((float)to * (float)(samples.Length - 1));
            }
            int num6 = num4;
            int num7 = num5;

            for (int i = num4; i <= num5; i += num2)
            {
                if (i > num5)
                {
                    i = num5;
                }
                float sqrMagnitude = (point - samples[i].position).sqrMagnitude;
                if (sqrMagnitude < num3)
                {
                    num3 = sqrMagnitude;
                    num6 = Mathf.Max(i - num2, 0);
                    num7 = Mathf.Min(i + num2, samples.Length - 1);
                }
                if (i == num5)
                {
                    break;
                }
            }
            num3 = (point - samples[num6].position).sqrMagnitude;
            int num8 = num6;

            for (int j = num6 + 1; j <= num7; j++)
            {
                float sqrMagnitude2 = (point - samples[j].position).sqrMagnitude;
                if (sqrMagnitude2 < num3)
                {
                    num3 = sqrMagnitude2;
                    num8 = j;
                }
            }
            int num9 = num8 - 1;

            if (num9 < 0)
            {
                num9 = 0;
            }
            int num10 = num8 + 1;

            if (num10 > samples.Length - 1)
            {
                num10 = samples.Length - 1;
            }
            Vector3 vector     = LinearAlgebraUtility.ProjectOnLine(samples[num9].position, samples[num8].position, point);
            Vector3 vector2    = LinearAlgebraUtility.ProjectOnLine(samples[num8].position, samples[num10].position, point);
            float   magnitude  = (samples[num8].position - samples[num9].position).magnitude;
            float   magnitude2 = (samples[num8].position - samples[num10].position).magnitude;
            float   magnitude3 = (vector - samples[num9].position).magnitude;
            float   magnitude4 = (vector2 - samples[num10].position).magnitude;

            if (num9 < num8 && num8 < num10)
            {
                if ((point - vector).sqrMagnitude < (point - vector2).sqrMagnitude)
                {
                    SplineResult.Lerp(samples[num9], samples[num8], magnitude3 / magnitude, result);
                }
                else
                {
                    SplineResult.Lerp(samples[num10], samples[num8], magnitude4 / magnitude2, result);
                }
            }
            else if (num9 < num8)
            {
                SplineResult.Lerp(samples[num9], samples[num8], magnitude3 / magnitude, result);
            }
            else
            {
                SplineResult.Lerp(samples[num10], samples[num8], magnitude4 / magnitude2, result);
            }
            if (from == 0.0 && to == 1.0 && result.percent < _address.moveStep / _resolution)
            {
                Vector3 vector3 = LinearAlgebraUtility.ProjectOnLine(samples[samples.Length - 1].position, samples[samples.Length - 2].position, point);
                if ((point - vector3).sqrMagnitude < (point - result.position).sqrMagnitude)
                {
                    SplineResult.Lerp(samples[samples.Length - 1], samples[samples.Length - 2], LinearAlgebraUtility.InverseLerp(samples[samples.Length - 1].position, samples[samples.Length - 2].position, vector3), result);
                }
            }
        }