Exemplo n.º 1
0
        /// <summary>
        /// Same as Spline.Evaluate but the result is transformed by the computer's transform
        /// </summary>
        /// <param name="result"></param>
        /// <param name="percent"></param>
        public void Evaluate(double percent, SplineSample result)
        {
            if (!hasSamples)
            {
                result = new SplineSample();
                return;
            }
            int    index;
            double lerp;

            GetSamplingValues(percent, out index, out lerp);
            if (lerp > 0.0)
            {
                SplineSample.Lerp(samples[index], samples[index + 1], lerp, result);
            }
            else
            {
                result.CopyFrom(samples[index]);
            }
        }
Exemplo n.º 2
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);
                    }
                }
            }
        }