/// <summary>
        /// Evaluate the splien at the given time and write the result to the "result" object
        /// </summary>
        /// <param name="result">The result output</param>
        /// <param name="percent">Percent of evaluation [0-1]</param>
        public void Evaluate(SplineResult result, double percent)
        {
            if (points.Length == 0)
            {
                result = new SplineResult();
                return;
            }
            percent = DMath.Clamp01(percent);
            if (closed && points.Length <= 2)
            {
                closed = false;
            }
            if (points.Length == 1)
            {
                result.position  = points[0].position;
                result.normal    = points[0].normal;
                result.direction = Vector3.forward;
                result.size      = points[0].size;
                result.color     = points[0].color;
                result.percent   = percent;
                return;
            }

            double  doubleIndex = (points.Length - 1) * percent;
            int     pointIndex  = Mathf.Clamp(DMath.FloorInt(doubleIndex), 0, points.Length - 2);
            double  getPercent  = doubleIndex - pointIndex;
            Vector3 point       = EvaluatePosition(percent);

            result.position = point;
            result.percent  = percent;
            if (pointIndex <= points.Length - 2)
            {
                SplinePoint nextPoint = points[pointIndex + 1];
                if (pointIndex == points.Length - 2 && closed)
                {
                    nextPoint = points[0];
                }
                float valueInterpolation = (float)getPercent;
                if (customValueInterpolation != null)
                {
                    if (customValueInterpolation.length > 0)
                    {
                        valueInterpolation = customValueInterpolation.Evaluate(valueInterpolation);
                    }
                }
                float normalInterpolation = (float)getPercent;
                if (customNormalInterpolation != null)
                {
                    if (customNormalInterpolation.length > 0)
                    {
                        normalInterpolation = customNormalInterpolation.Evaluate(normalInterpolation);
                    }
                }
                result.size   = Mathf.Lerp(points[pointIndex].size, nextPoint.size, valueInterpolation);
                result.color  = Color.Lerp(points[pointIndex].color, nextPoint.color, valueInterpolation);
                result.normal = Vector3.Slerp(points[pointIndex].normal, nextPoint.normal, normalInterpolation);
            }
            else
            {
                if (closed)
                {
                    result.size   = points[0].size;
                    result.color  = points[0].color;
                    result.normal = points[0].normal;
                }
                else
                {
                    result.size   = points[pointIndex].size;
                    result.color  = points[pointIndex].color;
                    result.normal = points[pointIndex].normal;
                }
            }
            if (type == Type.BSpline)
            {
                double step = (1.0 - precision) / points.Length;
                if (percent <= 1.0 - step && percent >= step)
                {
                    result.direction = EvaluatePosition(percent + step) - EvaluatePosition(percent - step);
                }
                else
                {
                    Vector3 back = Vector3.zero, front = Vector3.zero;
                    if (closed)
                    {
                        if (percent < step)
                        {
                            back = EvaluatePosition(1.0 - (step - percent));
                        }
                        else
                        {
                            back = EvaluatePosition(percent - step);
                        }
                        if (percent > 1.0 - step)
                        {
                            front = EvaluatePosition(step - (1.0 - percent));
                        }
                        else
                        {
                            front = EvaluatePosition(percent + step);
                        }
                        result.direction = front - back;
                    }
                    else
                    {
                        back             = result.position - EvaluatePosition(percent - step);
                        front            = EvaluatePosition(percent + step) - result.position;
                        result.direction = Vector3.Slerp(front, back, back.magnitude / front.magnitude);
                    }
                }
            }
            else
            {
                EvaluateTangent(ref result.direction, percent);
            }
            result.direction.Normalize();
        }
Exemple #2
0
        public void Evaluate(SplineResult result, double percent)
        {
            if (points.Length == 0)
            {
                result = new SplineResult();
                return;
            }
            percent = DMath.Clamp01(percent);
            if (closed && points.Length <= 2)
            {
                closed = false;
            }
            if (points.Length == 1)
            {
                result.position  = points[0].position;
                result.normal    = points[0].normal;
                result.direction = Vector3.forward;
                result.size      = points[0].size;
                result.color     = points[0].color;
                result.percent   = percent;
                return;
            }

            double  doubleIndex = (points.Length - 1) * percent;
            int     pointIndex  = Mathf.Clamp(DMath.FloorInt(doubleIndex), 0, points.Length - 2);
            double  getPercent  = doubleIndex - pointIndex;
            Vector3 point       = EvaluatePosition(percent);

            result.position = point;
            result.percent  = percent;
            if (pointIndex <= points.Length - 2)
            {
                SplinePoint nextPoint = points[pointIndex + 1];
                if (pointIndex == points.Length - 2 && closed)
                {
                    nextPoint = points[0];
                }
                float valueInterpolation = (float)getPercent;
                if (customValueInterpolation != null)
                {
                    if (customValueInterpolation.keys.Length > 0f)
                    {
                        valueInterpolation = customValueInterpolation.Evaluate(valueInterpolation);
                    }
                }
                float normalInterpolation = (float)getPercent;
                if (customNormalInterpolation != null)
                {
                    if (customNormalInterpolation.keys.Length > 0)
                    {
                        normalInterpolation = customNormalInterpolation.Evaluate(normalInterpolation);
                    }
                }
                result.size   = Mathf.Lerp(points[pointIndex].size, nextPoint.size, valueInterpolation);
                result.color  = Color.Lerp(points[pointIndex].color, nextPoint.color, valueInterpolation);
                result.normal = Vector3.Slerp(points[pointIndex].normal, nextPoint.normal, normalInterpolation);
            }
            else
            {
                if (closed)
                {
                    result.size   = points[0].size;
                    result.color  = points[0].color;
                    result.normal = points[0].normal;
                }
                else
                {
                    result.size   = points[pointIndex].size;
                    result.color  = points[pointIndex].color;
                    result.normal = points[pointIndex].normal;
                }
            }
            double step = (1.0 - precision) / points.Length;

            if (percent < 1.0 - step)
            {
                result.direction = EvaluatePosition(percent + step) - result.position;
            }
            else
            {
                if (closed)
                {
                    result.direction  = EvaluatePosition(percent + step) - result.position;
                    result.direction += EvaluatePosition(percent + step - 1f) - EvaluatePosition(0f);
                }
                else
                {
                    result.direction = EvaluatePosition(DMath.Clamp01(percent + step)) - result.position;
                    if (Mathf.Max(result.direction.x, result.direction.y, result.direction.z) <= 0.009f) //If the direction vector is too small, calculate the direction backwards
                    {
                        double backPercent = DMath.Clamp01(percent - step);
                        result.direction = result.position - EvaluatePosition(backPercent);
                    }
                }
            }
            result.direction.Normalize();
        }
Exemple #3
0
 internal Connection(SplineComputer comp, int index, SplinePoint inputPoint)
 {
     _pointIndex = index;
     _computer   = comp;
     point       = inputPoint;
 }
        public void BendObject(BendProperty p)
        {
            if (!p.enabled)
            {
                return;
            }


            GetevalResult(p.positionPercent);

            p.transform.position = evalResult.position;
            if (p.applyRotation)
            {
                //p.transform.rotation = evalResult.rotation * axisRotation * p.originalRotation;
                p.transform.rotation = bendRotation * (Quaternion.Inverse(p.parentRotation) * p.originalRotation);
            }
            else
            {
                p.transform.rotation = p.originalRotation;
            }
            if (p.applyScale)
            {
                p.transform.scale = p.originalScale * evalResult.size;
            }

            Matrix4x4 toLocalMatrix = Matrix4x4.TRS(p.transform.position, p.transform.rotation, p.transform.scale).inverse;

            if (p.editMesh != null)
            {
                BendMesh(p.vertexPercents, p.normals, p.editMesh, toLocalMatrix);
                p.editMesh.hasUpdate = true;
            }

            if (p._editColliderMesh != null)
            {
                BendMesh(p.colliderVertexPercents, p.colliderNormals, p.editColliderMesh, toLocalMatrix);
                p.editColliderMesh.hasUpdate = true;
            }

            if (p.originalSpline != null)
            {
                for (int n = 0; n < p.splinePointPercents.Length; n++)
                {
                    SplinePoint point = p.originalSpline.points[n];
                    GetevalResult(p.splinePointPercents[n]);
                    point.position = evalResult.position;
                    GetevalResult(p.primaryTangentPercents[n]);
                    point.tangent = evalResult.position;
                    GetevalResult(p.secondaryTangentPercents[n]);
                    point.tangent2 = evalResult.position;
                    switch (axis)
                    {
                    case Axis.X: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;

                    case Axis.Y: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;

                    case Axis.Z: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * point.normal; break;
                    }
                    p.destinationSpline.points[n] = point;
                }
            }
        }
        public override bool SceneEdit(ref SplinePoint[] points, ref List <int> selected)
        {
            bool change = false;

            if (originalPoints.Length == 0)
            {
                originalPoints = points;
                center         = computer.transform.position;
            }
            center = Handles.PositionHandle(center, computer.transform.rotation);
            DrawMirror();
            if (lastCenter != center || lastAxis != axis || lastFlip || mirrored.Length != originalPoints.Length * 2)
            {
                List <int> half   = GetHalf(ref originalPoints);
                int        welded = -1;
                if (half.Count > 0)
                {
                    if (flip)
                    {
                        if (IsWeldable(originalPoints[half[0]]))
                        {
                            welded = half[0];
                            half.RemoveAt(0);
                        }
                    }
                    else
                    {
                        if (IsWeldable(originalPoints[half[half.Count - 1]]))
                        {
                            welded = half[half.Count - 1];
                            half.RemoveAt(half.Count - 1);
                        }
                    }

                    int offset         = welded >= 0 ? 1 : 0;
                    int additionalSlot = computer.isClosed && half.Count > 0 ? 1 : 0;
                    if (additionalSlot > 0)
                    {
                        if (flip)
                        {
                            if (IsWeldable(originalPoints[half[half.Count - 1]]))
                            {
                                additionalSlot = 0;
                            }
                        }
                        else
                        {
                            if (IsWeldable(originalPoints[half[0]]))
                            {
                                additionalSlot = 0;
                            }
                        }
                    }
                    mirrored = new SplinePoint[half.Count * 2 + offset + additionalSlot];
                    for (int i = 0; i < half.Count; i++)
                    {
                        if (flip)
                        {
                            mirrored[i] = new SplinePoint(originalPoints[half[(half.Count - 1) - i]]);
                            mirrored[i + half.Count + offset] = GetMirrored(originalPoints[half[i]]);
                            SwapTangents(ref mirrored[i]);
                            SwapTangents(ref mirrored[i + half.Count + offset]);
                        }
                        else
                        {
                            mirrored[i] = new SplinePoint(originalPoints[half[i]]);
                            mirrored[i + half.Count + offset] = GetMirrored(originalPoints[half[(half.Count - 1) - i]]);
                        }
                    }
                    if (welded >= 0)
                    {
                        mirrored[half.Count] = new SplinePoint(originalPoints[welded]);
                        if (flip)
                        {
                            SwapTangents(ref mirrored[half.Count]);
                        }
                        MakeMiddlePoint(ref mirrored[half.Count]);
                    }

                    if (computer.isClosed && mirrored.Length > 0)
                    {
                        if (additionalSlot == 0)
                        {
                            MakeMiddlePoint(ref mirrored[0]);
                        }
                        mirrored[mirrored.Length - 1] = new SplinePoint(mirrored[0]);
                    }
                }
                else
                {
                    mirrored = new SplinePoint[0];
                }

                lastCenter = center;
                lastAxis   = axis;
                change     = true;
            }
            points = mirrored;
            selected.Clear();
            return(change);
        }
        void MakeMiddlePoint(ref SplinePoint point)
        {
            point.type     = SplinePoint.Type.Broken;
            point.position = computer.transform.InverseTransformPoint(point.position);
            point.tangent  = computer.transform.InverseTransformPoint(point.tangent);
            point.tangent2 = computer.transform.InverseTransformPoint(point.tangent2);
            Vector3 newPos      = point.position;
            Vector3 localCenter = computer.transform.InverseTransformPoint(center);

            switch (axis)
            {
            case Axis.X:

                newPos.x = localCenter.x;
                point.SetPosition(newPos);
                if ((point.tangent.x >= localCenter.x && flip) || (point.tangent.x <= localCenter.x && !flip))
                {
                    point.tangent2   = point.tangent;
                    point.tangent2.x = point.position.x + (point.position.x - point.tangent.x);
                }
                else
                {
                    point.tangent   = point.tangent2;
                    point.tangent.x = point.position.x + (point.position.x - point.tangent2.x);
                }
                break;

            case Axis.Y:
                newPos.y = localCenter.y;
                point.SetPosition(newPos);
                if ((point.tangent.y >= localCenter.y && flip) || (point.tangent.y <= localCenter.y && !flip))
                {
                    point.tangent2   = point.tangent;
                    point.tangent2.y = point.position.y + (point.position.y - point.tangent.y);
                }
                else
                {
                    point.tangent   = point.tangent2;
                    point.tangent.y = point.position.y + (point.position.y - point.tangent2.y);
                }
                break;

            case Axis.Z:
                newPos.z = localCenter.z;
                point.SetPosition(newPos);
                if ((point.tangent.z >= localCenter.z && flip) || (point.tangent.z <= localCenter.z && !flip))
                {
                    point.tangent2   = point.tangent;
                    point.tangent2.z = point.position.z + (point.position.z - point.tangent.z);
                }
                else
                {
                    point.tangent   = point.tangent2;
                    point.tangent.z = point.position.z + (point.position.z - point.tangent2.z);
                }
                break;
            }
            point.position = computer.transform.TransformPoint(point.position);
            point.tangent  = computer.transform.TransformPoint(point.tangent);
            point.tangent2 = computer.transform.TransformPoint(point.tangent2);
        }
Exemple #7
0
        public void BendObject(BendProperty p)
        {
            if (!p.enabled)
            {
                return;
            }
            Quaternion axisRotation = Quaternion.identity;

            switch (axis)
            {
            case Axis.X: axisRotation = Quaternion.AngleAxis(-90f, Vector3.up); break;

            case Axis.Y: axisRotation = Quaternion.AngleAxis(90f, Vector3.right); break;
            }
            GetBendResult(p.positionPercent);
            if (this.transform == computer.transform && p.transform.transform == this.transform)
            {
            }
            else
            {
                p.transform.position = bendResult.position;
                if (p.applyRotation)
                {
                    p.transform.rotation = bendResult.rotation * axisRotation * p.originalRotation;
                }
                else
                {
                    p.transform.rotation = p.originalRotation;
                }
                if (p.applyScale)
                {
                    p.transform.scale = p.originalScale * bendResult.size;
                }
            }
            if (p.editMesh != null)
            {
                for (int n = 0; n < p.vertexPercents.Length; n++)
                {
                    GetBendResult(p.vertexPercents[n]);
                    p.editMesh.vertices[n] = bendResult.position;
                    switch (axis)
                    {
                    case Axis.X: p.editMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * p.normals[n]; break;

                    case Axis.Y: p.editMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * p.normals[n]; break;

                    case Axis.Z: p.editMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * p.normals[n];
                        break;
                    }
                }
                p.editMesh.hasUpdate = true;
            }

            if (p.editColliderMesh != null)
            {
                for (int n = 0; n < p.colliderVertexPercents.Length; n++)
                {
                    GetBendResult(p.colliderVertexPercents[n]);
                    p.editColliderMesh.vertices[n] = bendResult.position;
                    switch (axis)
                    {
                    case Axis.X: p.editColliderMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * p.colliderNormals[n]; break;

                    case Axis.Y: p.editColliderMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * p.colliderNormals[n]; break;

                    case Axis.Z: p.editColliderMesh.normals[n] = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * p.colliderNormals[n]; break;
                    }
                }
                p.editColliderMesh.hasUpdate = true;
            }

            if (p.originalSpline != null)
            {
                for (int n = 0; n < p.splinePointPercents.Length; n++)
                {
                    SplinePoint point = p.originalSpline.points[n];
                    GetBendResult(p.splinePointPercents[n]);
                    point.position = bendResult.position;
                    GetBendResult(p.primaryTangentPercents[n]);
                    point.tangent = bendResult.position;
                    GetBendResult(p.secondaryTangentPercents[n]);
                    point.tangent2 = bendResult.position;
                    switch (axis)
                    {
                    case Axis.X: point.normal = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * point.normal; break;

                    case Axis.Y: point.normal = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * axisRotation * Quaternion.FromToRotation(Vector3.up, bendResult.normal) * point.normal; break;

                    case Axis.Z: point.normal = Quaternion.LookRotation(bendResult.direction, bendResult.normal) * point.normal; break;
                    }
                    p.destinationSpline.points[n] = point;
                }
            }
        }
        void Merge(int index, MergeSide currentSide, MergeSide otherSide, ref SplinePoint[] points)
        {
            SplinePoint[] mergedPoints = availableMergeComputers[index].GetPoints();
            SplinePoint[] original     = new SplinePoint[points.Length];
            points.CopyTo(original, 0);
            List <SplinePoint> pointsList = new List <SplinePoint>();

            if (!mergeEndpoints)
            {
                points = new SplinePoint[mergedPoints.Length + original.Length];
            }
            else
            {
                points = new SplinePoint[mergedPoints.Length + original.Length - 1];
            }

            if (currentSide == MergeSide.End)
            {
                if (otherSide == MergeSide.Start)
                {
                    for (int i = 0; i < original.Length; i++)
                    {
                        pointsList.Add(original[i]);
                    }
                    for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++)
                    {
                        pointsList.Add(mergedPoints[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < original.Length; i++)
                    {
                        pointsList.Add(original[i]);
                    }
                    for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++)
                    {
                        pointsList.Add(mergedPoints[(mergedPoints.Length - 1) - i]);
                    }
                }
            }
            else
            {
                if (otherSide == MergeSide.Start)
                {
                    for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++)
                    {
                        pointsList.Add(mergedPoints[i]);
                    }
                    for (int i = 0; i < original.Length; i++)
                    {
                        pointsList.Add(original[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++)
                    {
                        pointsList.Add(mergedPoints[(mergedPoints.Length - 1) - i]);
                    }
                    for (int i = 0; i < original.Length; i++)
                    {
                        pointsList.Add(original[i]);
                    }
                }
            }
            points = pointsList.ToArray();
            double mergedPercent = (double)(mergedPoints.Length - 1) / (points.Length - 1);
            double from          = 0.0;
            double to            = 1.0;

            if (currentSide == MergeSide.End)
            {
                from = 1.0 - mergedPercent;
                to   = 1.0;
            }
            else
            {
                from = 0.0;
                to   = mergedPercent;
            }
            MergeComputer(availableMergeComputers[index], from, to);
            Init();
        }