Пример #1
0
 public SplineFragmentEnumerator(zzOldISpline spline, float minStepProduct)
 {
     interpolator = new SplineInterpolatorEnumerator(spline, minStepProduct);
     started      = false;
     curPos       = Vector3.zero;
     lastPos      = Vector3.zero;
 }
Пример #2
0
 public SplineInterpolatorEnumerator(zzOldISpline spline, float minStepProduct)
 {
     started             = false;
     this.spline         = spline;
     this.minStepProduct = Mathf.Max(minStepProduct, -0.5F, Mathf.Min(minStepProduct, 0.98F));
     curControlAIdx      = -1;
     curControlBIdx      = -1;
     curPos         = Vector3.zero;
     curProgress    = 0F;
     hasLastStepPos = false;
     lastStepPos    = Vector3.zero;
     lastStep       = 0.33F;
 }
Пример #3
0
 /// <summary>
 /// Returns an enumerator that returns segments along an ISpline. For smoother splines, choose a
 /// minIntersegmentDotProduct that is closer to 1 (maximum 0.98F). For rougher splines, choose a
 /// minIntersegmentDotProduct that is closer to -1 (minimum -0.5F). A choise of 0 would allow angles
 /// up to but no larger than 90 degrees between adjacent spline segments.
 /// </summary>
 /// <remarks>
 /// SplineSegmentEnumerator is a small wrapper around SplineInterpolatorEnumerator that remembers
 /// the last position traversed to two points at a time.
 /// </remarks>
 public static SplineFragmentEnumerator TraverseFragments(this zzOldISpline spline, float minIntersegmentDotProduct = 0.9F)
 {
     return(new SplineFragmentEnumerator(spline, minIntersegmentDotProduct));
 }
Пример #4
0
 /// <summary>
 /// Returns an enumerator that will return points along an ISpline. For smoother splines, choose a
 /// minInterstepDotProduct that is closer to 1 (maximum 0.98F). For rougher splines, choose a
 /// minInterstepDotProduct that is closer to -1 (minimum -0.5F). A choice of 0 would allow angles
 /// up to but no larger than 90 degrees between adjacent spline segments.
 /// </summary>
 /// <remarks>
 /// The segment formed by each step returned and the previous step returned will have a dot product
 /// no smaller than minInterstepDotProduct with the segment formed by the previous step returned and
 /// the step before that. This enforces a maximum on cos(theta) where theta is the angle between any
 /// two adjacent segments in the spline. Specifically, the maximum angle could be calculated as
 /// arccos(minInterstepDotProduct).
 /// </remarks>
 public static SplineInterpolatorEnumerator Traverse(this zzOldISpline spline, float minInterstepDotProduct = 0.9F)
 {
     return(new SplineInterpolatorEnumerator(spline, minInterstepDotProduct));
 }
Пример #5
0
            /// <summary>
            /// Generates a quad-based spline mesh based on the input spline and provided spline thickness.
            /// The spline will be oriented so that its first segment faces towards initNormalFacingReference.
            /// Subsequent segments will rotate their normal/binormal directions based on the FromToRotation
            /// from one segment to the next.
            /// </summary>
            public static void GenerateQuadSplineMesh(ref List <Vector3> verts, ref List <int> indices,
                                                      zzOldISpline spline, float splineThickness, Vector3 initNormalFacingReference,
                                                      float minSplineSegmentDotProduct = 0.9F)
            {
                s_meshPoints.Clear();
                s_threePositionsBuffer.Clear();
                s_twoPointsBuffer.Clear();

                float halfThickness = splineThickness * 0.5F;

                // Traverse the spline, constructing SplineMeshPoints with precalculated normals and binormals
                // to make mesh construction more straight-forward. SplineMeshPoints will be converted into
                // connected quads for the spline mesh in the next step.
                Vector3 normal          = Vector3.zero;
                Vector3 binormal        = Vector3.zero;
                bool    firstPointAdded = false;
                int     count           = 0;

                foreach (Vector3 pointOnSpline in spline.Traverse(minSplineSegmentDotProduct))
                {
                    // Add a placeholder SplineMeshPoint, to be fixed later using information from neighboring points.
                    s_threePositionsBuffer.Add(pointOnSpline);
                    count++;

                    // With a buffer of three positions, we have enough information for the center point.
                    if (s_threePositionsBuffer.IsFull)
                    {
                        var p0 = s_threePositionsBuffer.Get(0);
                        var p1 = s_threePositionsBuffer.Get(1);
                        var p2 = s_threePositionsBuffer.Get(2);

                        // (Special case for the first position in the spline.)
                        if (!firstPointAdded)
                        {
                            normal = (initNormalFacingReference - p0).normalized;
                            Vector3 tangent = (p1 - p0).normalized;
                            binormal = (Vector3.Cross(tangent, normal)).normalized;
                            normal   = (Vector3.Cross(binormal, tangent)).normalized; // Ensure basis directions are orthogonal.

                            // Add the first spline mesh point, with a good normal (using the direction towards the camera
                            // as a reasonable basis).
                            s_meshPoints.Add(new SplineMeshPoint()
                            {
                                position = p0, normal = normal, binormal = binormal
                            });

                            firstPointAdded = true;
                        }

                        // Use neighbor information to fill in information for the center point in the buffer.
                        Vector3    p0Normal        = s_meshPoints[s_meshPoints.Count - 1].normal;
                        Vector3    p0Binormal      = s_meshPoints[s_meshPoints.Count - 1].binormal;
                        Quaternion segmentRotation = Quaternion.FromToRotation((p1 - p0), (p2 - p1));
                        normal   = segmentRotation * p0Normal;
                        binormal = segmentRotation * p0Binormal;
                        s_meshPoints.Add(new SplineMeshPoint()
                        {
                            position = p1, normal = normal, binormal = binormal
                        });
                    }
                }
                // (Finally, add the last spline mesh point.)
                s_meshPoints.Add(new SplineMeshPoint()
                {
                    position = s_threePositionsBuffer.Get(2), normal = normal, binormal = binormal
                });

                // Return early if there aren't enough spline mesh points.
                if (s_meshPoints.Count < 2)
                {
                    return;
                }

                // Using a prepared list of SplineMeshPoints, construct the mesh by building connected quads.
                firstPointAdded = false;
                foreach (SplineMeshPoint meshPoint in s_meshPoints)
                {
                    s_twoPointsBuffer.Add(meshPoint);

                    if (s_twoPointsBuffer.IsFull)
                    {
                        SplineMeshPoint p0 = s_twoPointsBuffer.Get(0);
                        SplineMeshPoint p1 = s_twoPointsBuffer.Get(1);

                        // (Special case for the first position in the spline.)
                        if (!firstPointAdded)
                        {
                            binormal = p0.binormal;

                            verts.Add(p0.position + binormal * halfThickness);
                            verts.Add(p0.position - binormal * halfThickness);

                            firstPointAdded = true;
                        }

                        binormal = (p0.binormal + p1.binormal).normalized;
                        addIncrementalQuad(verts, indices,
                                           p1.position + binormal * halfThickness,
                                           p1.position - binormal * halfThickness);
                    }
                }
                // (Finally, add the last quad.)
                addIncrementalQuad(verts, indices,
                                   s_meshPoints[s_meshPoints.Count - 1].position + binormal * halfThickness,
                                   s_meshPoints[s_meshPoints.Count - 1].position - binormal * halfThickness);
            }