コード例 #1
0
        /// <summary>
        /// Same as Spline.EvaluatePositions but the results are transformed by the computer's transform
        /// </summary>
        /// <param name="from">Start position [0-1]</param>
        /// <param name="to">Target position [from-1]</param>
        /// <returns></returns>
        public void EvaluatePositions(ref Vector3[] positions, double from = 0.0, double to = 1.0)
        {
            if (!hasSamples)
            {
                positions = new Vector3[0];
                return;
            }
            Spline.FormatFromTo(ref from, ref to);
            int    fromIndex, toIndex;
            double lerp;

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

            if (positions == null)
            {
                positions = new Vector3[clippedIterations];
            }
            else if (positions.Length != clippedIterations)
            {
                positions = new Vector3[clippedIterations];
            }
            positions[0] = EvaluatePosition(from);
            positions[positions.Length - 1] = EvaluatePosition(to);
            for (int i = 1; i < positions.Length - 1; i++)
            {
                positions[i] = samples[i + fromIndex].position;
            }
        }
コード例 #2
0
        /// <summary>
        /// Same as Spline.CalculateLength but this takes the computer's transform into account when calculating the length.
        /// </summary>
        /// <param name="from">Calculate from [0-1] default: 0f</param>
        /// <param name="to">Calculate to [0-1] default: 1f</param>
        /// <param name="resolution">Resolution [0-1] default: 1f</param>
        /// <param name="address">Node address of junctions</param>
        /// <returns></returns>
        public float CalculateLength(double from = 0.0, double to = 1.0)
        {
            if (!hasSamples)
            {
                return(0f);
            }
            Spline.FormatFromTo(ref from, ref to);
            float   length = 0f;
            Vector3 pos = EvaluatePosition(from);
            int     fromIndex, toIndex;
            double  lerp;

            GetSamplingValues(from, out fromIndex, out lerp);
            GetSamplingValues(to, out toIndex, out lerp);
            if (lerp > 0.0 && toIndex < Count - 1)
            {
                toIndex++;
            }
            for (int i = fromIndex + 1; i < toIndex; i++)
            {
                length += Vector3.Distance(samples[i].position, pos);
                pos     = samples[i].position;
            }
            length += Vector3.Distance(EvaluatePosition(to), pos);
            return(length);
        }
コード例 #3
0
        /// <summary>
        /// Same as Spline.Evaluate but the results are transformed by the computer's transform
        /// </summary>
        /// <param name="from">Start position [0-1]</param>
        /// <param name="to">Target position [from-1]</param>
        /// <returns></returns>
        public void Evaluate(ref SplineSample[] results, double from = 0.0, double to = 1.0)
        {
            if (!hasSamples)
            {
                results = new SplineSample[0];
                return;
            }
            Spline.FormatFromTo(ref from, ref to);
            int    fromIndex, toIndex;
            double lerp;

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

            if (results == null)
            {
                results = new SplineSample[clippedIterations];
            }
            else if (results.Length != clippedIterations)
            {
                results = new SplineSample[clippedIterations];
            }
            results[0] = Evaluate(from);
            results[results.Length - 1] = Evaluate(to);
            for (int i = 1; i < results.Length - 1; i++)
            {
                results[i] = samples[i + fromIndex];
            }
        }
コード例 #4
0
        /// <summary>
        /// Calculates the length between <paramref name="from"/> and <paramref name="to"/> with applied local offset to to the samples
        /// The offset is multiplied by the sample sizes
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        public float CalculateLengthWithOffset(Vector3 offset, double from = 0.0, double to = 1.0)
        {
            if (!hasSamples)
            {
                return(0f);
            }
            Spline.FormatFromTo(ref from, ref to);
            float length = 0f;

            Evaluate(from, _workSample);
            Vector3 pos = _workSample.position + _workSample.up * offset.y * _workSample.size + _workSample.right * offset.x * _workSample.size + _workSample.forward * offset.z * _workSample.size;
            int     fromIndex, toIndex;
            double  lerp;

            GetSamplingValues(from, out fromIndex, out lerp);
            GetSamplingValues(to, out toIndex, out lerp);

            if (lerp > 0.0 && toIndex < Count - 1)
            {
                toIndex++;
            }

            for (int i = fromIndex + 1; i < toIndex; i++)
            {
                Vector3 newPos = samples[i].position + samples[i].up * offset.y * samples[i].size + samples[i].right * offset.x * samples[i].size + samples[i].forward * offset.z * samples[i].size;
                length += Vector3.Distance(newPos, pos);
                pos     = newPos;
            }

            Evaluate(to, _workSample);
            _workSample.position += _workSample.up * offset.y * _workSample.size + _workSample.right * offset.x * _workSample.size + _workSample.forward * offset.z * _workSample.size;
            length += Vector3.Distance(_workSample.position, pos);
            return(length);
        }
コード例 #5
0
        protected void HandleJunctions(double from, double to)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                return;
            }
#endif
            if (onNode == null)
            {
                return;
            }
            if (from == to)
            {
                return;
            }
            UnclipPercent(ref from);
            UnclipPercent(ref to);
            Spline.FormatFromTo(ref from, ref to, true);
            int fromPoint, toPoint;
            fromPoint = spline.PercentToPointIndex(from, _direction);
            toPoint   = spline.PercentToPointIndex(to, _direction);
            if (fromPoint != toPoint)
            {
                List <NodeConnection> queue = new List <NodeConnection>();
                if (_direction == Spline.Direction.Forward)
                {
                    for (int i = fromPoint + 1; i <= toPoint; i++)
                    {
                        NodeConnection junction = GetJunction(i);
                        if (junction != null)
                        {
                            queue.Add(junction);
                        }
                    }
                }
                else
                {
                    for (int i = toPoint - 1; i >= fromPoint; i--)
                    {
                        NodeConnection junction = GetJunction(i);
                        if (junction != null)
                        {
                            queue.Add(junction);
                        }
                    }
                }
                if (queue.Count > 0)
                {
                    onNode(queue);
                }
            }
        }
コード例 #6
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);
                    }
                }
            }
        }
コード例 #7
0
        protected void CheckNodes(double from, double to)
        {
#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                return;
            }
#endif
            if (onNode == null)
            {
                return;
            }
            if (from == to)
            {
                return;
            }
            UnclipPercent(ref from);
            UnclipPercent(ref to);
            Spline.FormatFromTo(ref from, ref to, true);
            int fromPoint, toPoint;
            fromPoint = spline.PercentToPointIndex(from, _direction);
            toPoint   = spline.PercentToPointIndex(to, _direction);

            if (fromPoint != toPoint)
            {
                if (_direction == Spline.Direction.Forward)
                {
                    for (int i = fromPoint + 1; i <= toPoint; i++)
                    {
                        NodeConnection junction = GetJunction(i);
                        if (junction != null)
                        {
                            nodeConnectionQueue.Add(junction);
                        }
                    }
                }
                else
                {
                    for (int i = toPoint - 1; i >= fromPoint; i--)
                    {
                        NodeConnection junction = GetJunction(i);
                        if (junction != null)
                        {
                            nodeConnectionQueue.Add(junction);
                        }
                    }
                }
            }
            else if (from < MIN_DELTA && to > from)
            {
                NodeConnection junction = GetJunction(0);
                if (junction != null)
                {
                    nodeConnectionQueue.Add(junction);
                }
            }
            else if (to > 1.0 - MIN_DELTA && from < to)
            {
                NodeConnection junction = GetJunction(spline.pointCount - 1);
                if (junction != null)
                {
                    nodeConnectionQueue.Add(junction);
                }
            }
        }