示例#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);
                    }
                }
            }
        }
示例#2
0
        public static void DrawSpline(Spline spline, Color color, double from = 0.0, double to = 1.0, bool drawThickness = false, bool thicknessAutoRotate = false)
        {
            double add = spline.moveStep;

            if (add < 0.0025)
            {
                add = 0.0025;
            }
            double percent   = from;
            Color  prevColor = Handles.color;

            Handles.color = color;
            if (drawThickness)
            {
                Camera       editorCamera = SceneView.currentDrawingSceneView.camera;
                SplineResult fromResult   = spline.Evaluate(percent);
                SplineResult toResult     = new SplineResult();
                Vector3      fromNormal   = fromResult.normal;
                if (thicknessAutoRotate)
                {
                    fromNormal = (editorCamera.transform.position - fromResult.position).normalized;
                }
                Vector3 fromRight = Vector3.Cross(fromResult.direction, fromNormal).normalized *fromResult.size * 0.5f;
                while (true)
                {
                    percent = DMath.Move(percent, to, add);
                    spline.Evaluate(toResult, percent);
                    Vector3 toNormal = toResult.normal;
                    if (thicknessAutoRotate)
                    {
                        toNormal = (editorCamera.transform.position - toResult.position).normalized;
                    }
                    Vector3 toRight = Vector3.Cross(toResult.direction, toNormal).normalized *toResult.size * 0.5f;

                    Handles.DrawLine(fromResult.position + fromRight, toResult.position + toRight);
                    Handles.DrawLine(fromResult.position - fromRight, toResult.position - toRight);
                    Handles.DrawLine(fromResult.position + fromRight, fromResult.position - fromRight);
                    if (percent == to)
                    {
                        break;
                    }
                    fromResult.CopyFrom(toResult);
                    fromNormal = toNormal;
                    fromRight  = toRight;
                }
            }
            else
            {
                Vector3 fromPoint = spline.EvaluatePosition(percent);
                Vector3 toPoint   = new Vector3();
                while (true)
                {
                    percent = DMath.Move(percent, to, add);
                    toPoint = spline.EvaluatePosition(percent);
                    Handles.DrawLine(fromPoint, toPoint);
                    if (percent == to)
                    {
                        break;
                    }
                    fromPoint = toPoint;
                }
            }
            Handles.color = prevColor;
        }
        public static void DrawSpline(Spline spline, Color color, double from = 0.0, double to = 1.0, bool drawThickness = false, bool thicknessAutoRotate = false)
        {
            double add = spline.moveStep;

            if (add < 0.0025)
            {
                add = 0.0025;
            }
            Color prevColor = Handles.color;

            Handles.color = color;
            int iterations = spline.iterations;

            if (drawThickness)
            {
                Transform editorCamera = SceneView.currentDrawingSceneView.camera.transform;
                if (positions.Length != iterations * 6)
                {
                    positions = new Vector3[iterations * 6];
                }
                SplineResult prevResult = spline.Evaluate(from);
                Vector3      prevNormal = prevResult.normal;
                if (thicknessAutoRotate)
                {
                    prevNormal = (editorCamera.position - prevResult.position).normalized;
                }
                Vector3 prevRight  = Vector3.Cross(prevResult.direction, prevNormal).normalized *prevResult.size * 0.5f;
                int     pointIndex = 0;
                for (int i = 1; i < iterations; i++)
                {
                    double       p         = DMath.Lerp(from, to, (double)i / (iterations - 1));
                    SplineResult newResult = spline.Evaluate(p);
                    Vector3      newNormal = newResult.normal;
                    if (thicknessAutoRotate)
                    {
                        newNormal = (editorCamera.position - newResult.position).normalized;
                    }
                    Vector3 newRight = Vector3.Cross(newResult.direction, newNormal).normalized *newResult.size * 0.5f;

                    positions[pointIndex] = prevResult.position + prevRight;
                    positions[pointIndex + iterations * 2] = prevResult.position - prevRight;
                    positions[pointIndex + iterations * 4] = newResult.position - newRight;
                    pointIndex++;
                    positions[pointIndex] = newResult.position + newRight;
                    positions[pointIndex + iterations * 2] = newResult.position - newRight;
                    positions[pointIndex + iterations * 4] = newResult.position + newRight;
                    pointIndex++;
                    prevResult = newResult;
                    prevRight  = newRight;
                    prevNormal = newNormal;
                }
                Handles.DrawLines(positions);
            }
            else
            {
                if (positions.Length != iterations * 2)
                {
                    positions = new Vector3[iterations * 2];
                }
                Vector3 prevPoint  = spline.EvaluatePosition(from);
                int     pointIndex = 0;
                for (int i = 1; i < iterations; i++)
                {
                    double p = DMath.Lerp(from, to, (double)i / (iterations - 1));
                    positions[pointIndex] = prevPoint;
                    pointIndex++;
                    positions[pointIndex] = spline.EvaluatePosition(p);
                    pointIndex++;
                    prevPoint = positions[pointIndex - 1];
                }
                Handles.DrawLines(positions);
            }
            Handles.color = prevColor;
        }
示例#4
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);
                }
            }
        }