Example #1
0
        public static ObjectBounds GetApproximateXZObjectBounds(this SplineSegment s)
        {
            var rot =
                Quaternion.LookRotation(s.FirstControlPoint.Position.xz().x0z() -
                                        s.SecondControlPoint.Position.xz().x0z());
            var b = new ObjectBounds(s.Points[0].Position, Vector3.zero, rot);

            for (var i = 0; i < s.Points.Count; i++)
            {
                b.Encapsulate(s.Points[i].Position);
            }
            return(b);
        }
Example #2
0
        public static Vector3 GetDeltaOnSpline(this SplineSegment s, float naturalT)
        {
            var p0 = s.FirstControlPoint.Position;
            var p1 = s.FirstControlPoint.Position + s.FirstControlPoint.Control;
            var p2 = s.SecondControlPoint.Position + s.SecondControlPoint.Control;
            var p3 = s.SecondControlPoint.Position;

            var a = 3 * Mathf.Pow(1 - naturalT, 2) * (p1 - p0);
            var b = 6 * (1 - naturalT) * naturalT * (p2 - p1);
            var c = 3 * Mathf.Pow(naturalT, 2) * (p3 - p2);

            return(a + b + c);
        }
Example #3
0
        public static Vector3 GetNaturalPointOnSpline(this SplineSegment s, float naturalT)
        {
            var p0 = s.FirstControlPoint.Position;
            var p1 = s.FirstControlPoint.Position + s.FirstControlPoint.Control;
            var p2 = s.SecondControlPoint.Position + s.SecondControlPoint.Control;
            var p3 = s.SecondControlPoint.Position;

            var t2 = naturalT * naturalT;
            var t3 = naturalT * t2;

            var mt  = 1 - naturalT;
            var mt2 = mt * mt;
            var mt3 = mt * mt2;

            return(p0 * mt3 + 3 * p1 * mt2 * naturalT + 3 * p2 * mt * t2 + p3 * t3);
        }
Example #4
0
        public static float NaturalToUniformTime(this SplineSegment s, float naturalT)
        {
            for (var i = 1; i < s.Points.Count; i++)
            {
                var thisPoint = s.Points[i];
                var thisNT    = thisPoint.NaturalTime;

                if (naturalT > thisNT)
                {
                    continue;
                }

                var lastPoint = s.Points[i - 1];
                var lastNT    = lastPoint.NaturalTime;

                var frac = naturalT - lastNT;
                var lerp = frac / (thisNT - lastNT);

                return(Mathf.Lerp(lastPoint.AccumLength / s.Length, thisPoint.AccumLength / s.Length, lerp));
            }
            return(1);
        }
Example #5
0
        public static float UniformToNaturalTime(this SplineSegment s, float uniformT)
        {
            var length = s.Length;

            for (var i = 1; i < s.Points.Count; i++)
            {
                var thisPoint = s.Points[i];
                var thisUt    = thisPoint.AccumLength / length;

                if (uniformT > thisUt)
                {
                    continue;
                }

                var lastPoint = s.Points[i - 1];
                var lastUt    = lastPoint.AccumLength / length;

                var frac = uniformT - lastUt;
                var lerp = frac / (thisUt - lastUt);
                return(Mathf.Lerp(lastPoint.NaturalTime, thisPoint.NaturalTime, lerp));
            }
            return(1);
        }
Example #6
0
        public static float GetClosestUniformTimeOnSpline(this SplineSegment s, Vector3 worldPos, float threshold)
        {
            // Basically a binary search along a spline
            var rangeT = new Vector2(0, 1);

            while (true)
            {
                var midPointT = Mathf.Lerp(rangeT.x, rangeT.y, .5f);

                var minPos = s.GetUniformPointOnSpline(rangeT.x);
                var midPos = s.GetUniformPointOnSpline(midPointT);
                var maxPos = s.GetUniformPointOnSpline(rangeT.y);

                var firstDist  = (minPos - worldPos).magnitude;
                var midDist    = (midPos - worldPos).magnitude;
                var secondDist = (maxPos - worldPos).magnitude;

                var firstSegment  = firstDist + midDist;
                var secondSegment = midDist + secondDist;

                // The current candidate is good enough
                if (Mathf.Abs(firstDist - secondDist) < threshold)
                {
                    return(midPointT);
                }

                if (firstSegment < secondSegment)
                {
                    rangeT = new Vector2(rangeT.x, midPointT);
                }
                else
                {
                    rangeT = new Vector2(midPointT, rangeT.y);
                }
            }
        }
Example #7
0
 public static Vector3 GetUpVector(this SplineSegment s, float naturalT)
 {
     return(Vector3.Lerp(s.FirstControlPoint.UpVector, s.SecondControlPoint.UpVector, naturalT));
 }
Example #8
0
 public static Quaternion GetRotation(this SplineSegment s, float naturalT)
 {
     return(Quaternion.Euler(Vector3.Lerp(s.FirstControlPoint.Rotation, s.SecondControlPoint.Rotation, naturalT)));
 }
Example #9
0
        // Distorts a mesh along a spline
        public static Mesh DistortAlongSpline(this Mesh sourceMesh, SplineSegment spline, Matrix4x4 meshTransform,
                                              float splineStartTime = 0, float splineEndTime = 1, float snapDistance = 0,
                                              SplineSegment.ESplineInterpolation splineInterpolation = SplineSegment.ESplineInterpolation.Natural)
        {
            var result = new Mesh();
            var verts  = new List <Vector3>(sourceMesh.vertices);

            var meshBounds = new Bounds();

            for (var i = 0; i < verts.Count; i++)
            {
                verts[i] = meshTransform.MultiplyPoint3x4(verts[i]);
                if (i == 0)
                {
                    meshBounds.center = verts[i];
                }
                else
                {
                    meshBounds.Encapsulate(verts[i]);
                }
            }
            //DebugHelper.DrawCube(meshBounds.center, meshBounds.extents, Quaternion.identity, Color.white, 20);

            var splineLength = spline.Length;
            var colors       = new Color[verts.Count];

            // Transform vert from mesh space to spline-axis space
            for (var i = verts.Count - 1; i >= 0; i--)
            {
                var vert = verts[i];

                // First is finding the vert on the spline axis
                var normalizedVert = vert - meshBounds.min;
                // Normalized vert tells us where it falls on the splines 't' axis
                normalizedVert = new Vector3(
                    normalizedVert.x / Mathf.Max(float.Epsilon, meshBounds.size.x),
                    normalizedVert.y / Mathf.Max(float.Epsilon, meshBounds.size.y),
                    normalizedVert.z / Mathf.Max(float.Epsilon, meshBounds.size.z));
                var t = Mathf.Lerp(splineStartTime, splineEndTime, normalizedVert.x);

                var dist = t * splineLength;
                if (dist < snapDistance)
                {
                    t = 0;
                }

                var distRemaining = splineLength - dist;
                if (distRemaining < snapDistance)
                {
                    t = 1;
                }

                t = Mathf.Clamp01(t);

                var natT = t;
                if (splineInterpolation == SplineSegment.ESplineInterpolation.Uniform)
                {
                    natT = spline.UniformToNaturalTime(t);
                }

                //var rotation = spline.GetRotation(natT);
                var tangent       = spline.GetTangent(natT);
                var splineForward = Quaternion.LookRotation(tangent, spline.GetUpVector(natT));
                //var axisRotation = GetAxisRotation(axis);

                //var uniformT = spline.NaturalToUniformTime(t);
                var pointAlongSpline = /*transform.worldToLocalMatrix**/ spline.GetUniformPointOnSpline(t);

                //var vectorFromAxis = GetVectorFromAxis(vert, axis);
                //var splineAdjustedVert = vert - vectorFromAxis;

                verts[i]  = pointAlongSpline + splineForward * new Vector3(0, vert.y, vert.z);
                colors[i] = Color.Lerp(Color.black, Color.white, t);
            }

            result.SetVertices(verts);
            result.colors = colors;
            result.SetTriangles(sourceMesh.GetTriangles(0), 0);
            result.SetUVs(0, new List <Vector2>(sourceMesh.uv));
            return(result);
        }