예제 #1
0
        // 5.2. - 5.6. recursively fitting a straight or quadratic line segment on this sequence of path nodes,
        // called from tracepath()
        // Returns a segment (a list of those doubles is a segment).
        public static IEnumerable <Segment> Fit(IReadOnlyList <InterpolationPoint> path, SequenceIndices sequence, Tracing tracing, SvgRendering rendering)
        {
            var pathLength = path.Count;

            // return if invalid sequence.End
            // TODO: When would this ever happen?
            if ((sequence.End > pathLength) || (sequence.End < 0))
            {
                yield break;
            }

            // TODO: This is actually the number of line segments in the sequence. Not the number of points in the sequence.
            var sequenceLength = sequence.End - sequence.Start;

            sequenceLength += sequenceLength < 0 ? pathLength : 0;

            int errorIndex;
            var lineResult = LineSegment.Fit(path, tracing.LTres, sequence, sequenceLength, out errorIndex, rendering);

            if (lineResult != null)
            {
                yield return(lineResult);

                yield break;
            }

            // 5.3. If the straight line fails (an error>ltreshold), find the point with the biggest error
            var fitIndex     = errorIndex;
            var splineResult = SplineSegment.Fit(path, tracing.QTres, sequence, sequenceLength, ref errorIndex, rendering);

            if (splineResult != null)
            {
                yield return(splineResult);

                yield break;
            }

            // 5.5. If the spline fails (an error>qtreshold), find the point with the biggest error,
            var splitIndex = (fitIndex + errorIndex) / 2;

            // 5.6. Split sequence and recursively apply 5.2. - 5.6. to startpoint-splitpoint and splitpoint-endpoint sequences
            foreach (var segmentPart in Fit(path, new SequenceIndices {
                Start = sequence.Start, End = splitIndex
            }, tracing, rendering))
            {
                yield return(segmentPart);
            }
            foreach (var segmentPart in Fit(path, new SequenceIndices {
                Start = splitIndex, End = sequence.End
            }, tracing, rendering))
            {
                yield return(segmentPart);
            }
        }
예제 #2
0
        private void GenerateSplinePlanes(float planeGive, SplineSegment mainSpline, out Plane startPlane, out Plane endPlane)
        {
            var startNodePos     = mainSpline.FirstControlPoint.Position;
            var startNodeControl = NodeConnection.ThisNode.GetNodeControl(NodeConnection.NextNode).Flatten().normalized;

            startPlane = new Plane(startNodeControl, startNodePos + startNodeControl * planeGive);
            var endNodePos     = mainSpline.SecondControlPoint.Position;
            var endNodeControl = NodeConnection.NextNode.GetNodeControl(NodeConnection.ThisNode).Flatten().normalized;

            endPlane = new Plane(endNodeControl, endNodePos + endNodeControl * planeGive);
        }
예제 #3
0
 public void EnterSplineSegment(int previousSplineExitPoint, SplineComputer spline, int entryPoint, Spline.Direction direction)
 {
     if (!isEngine)
     {
         return;
     }
     if (back != null)
     {
         segment.end  = previousSplineExitPoint;
         back.segment = segment;
     }
     segment = new SplineSegment(spline, entryPoint, direction);
 }
예제 #4
0
        public Vector3 GetTangent(int segidx, float segpos)
        {
            SplineSegment ss = mSegments[segidx];

            if (Reparam == ReparamType.None)
            {
                return(GetTangent(ss, segpos / ss.mLength));
            }
            else
            {
                return(GetTangent(ss, GetReparam(ss, segpos / ss.mLength)));
            }
        }
예제 #5
0
        private void OnSplineUpdate(SplineUpdateInfo inInfo)
        {
            Vector3 diff = inInfo.Point - transform.position;

            transform.position = inInfo.Point;

            float speed = diff.magnitude / Routine.DeltaTime;

            Debug.Log("Speed: " + speed.ToString());

            SplineSegment seg = inInfo.GetSegment();

            GetComponent <SpriteRenderer>().color =
                Color.Lerp((Color)inInfo.Spline.GetVertexUserData(seg.VertexA), (Color)inInfo.Spline.GetVertexUserData(seg.VertexB), seg.Interpolation);
        }
예제 #6
0
        public Vector3 GetPositionByT(int segidx, float t, out float offset)
        {
            SplineSegment ss = mSegments[segidx];

            offset = ss.mStartlen + ss.mLength * t;

            if (Reparam == ReparamType.None)
            {
                return(GetPosition(ss, t));
            }
            else
            {
                return(GetPosition(ss, GetReparam(ss, t)));
            }
        }
예제 #7
0
        void ApplyOffset()
        {
            if (isEngine)
            {
                ResetSegments();
                return;
            }
            float  totalMoved = 0f, moved = 0f;
            double start = front.tracer.UnclipPercent(front.tracer.result.percent);

            //Travel backwards along the front wagon's spline
            Spline.Direction inverseDirection = front.segment.direction;
            InvertDirection(ref inverseDirection);
            SplineComputer spline  = front.segment.spline;
            double         percent = front.segment.Travel(start, offset, inverseDirection, out moved, front.segment.spline.isClosed);

            totalMoved += moved;
            //Finalize if moved fully without reaching a spline end or a junction
            if (Mathf.Approximately(totalMoved, offset))
            {
                if (segment != front.segment)
                {
                    if (back != null)
                    {
                        back.segment = segment;
                    }
                }
                if (segment != front.segment)
                {
                    segment = front.segment;
                }
                ApplyTracer(spline, percent, front.tracer.direction);
                return;
            }

            //Otherwise, move along the current recorded spline segment
            if (segment != front.segment)
            {
                inverseDirection = segment.direction;
                InvertDirection(ref inverseDirection);
                spline      = segment.spline;
                percent     = segment.Travel(offset - totalMoved, inverseDirection, out moved, segment.spline.isClosed);
                totalMoved += moved;
            }
            ApplyTracer(spline, percent, segment.direction);
        }
예제 #8
0
        protected float GetLength(SplineSegment ss)
        {
            float   len = 0;
            Vector3 start, end;
            float   t = 0, dt = 1 / (float)StepCount;
            int     idx = 0;

            start = ss.mStartpos;
            while (idx < StepCount)
            {
                t    += dt;
                end   = GetPosition(ss, t);
                len  += (end - start).magnitude;
                start = end;
                ++idx;
            }
            return(len);
        }
예제 #9
0
 public SplineSegment GetSpline(bool recalculate = false, bool applyModifiers = true)
 {
     if (recalculate)
     {
         RecalculateSpline();
     }
     if (applyModifiers)
     {
         foreach (var connectionComponent in Components)
         {
             var splineMod = connectionComponent as ISplineModifier;
             if (splineMod != null)
             {
                 _spline = splineMod.ProcessSpline(_spline);
             }
         }
     }
     return(_spline);
 }
예제 #10
0
    private void Temp(Color c, SplineNode node, SplineSegment segment)
    {
        int depth = segment.Depth();

        if (depth == _depth | viewAllNodes)
        {
            if (segment.ChildCount <= 0)
            {
                Handles.color = c.Whitten(.3f);
                Handles.DrawDottedLine(node.PositionStart, segment.GlobalPosition(), 2f);
                Handles.color = c.Blacken(.3f);
                Handles.DrawLine(node.PositionEnd, segment.GlobalPosition());
            }
        }

        foreach (SplineSegment child in segment.Children)
        {
            Temp(c, node, child);
        }
    }
예제 #11
0
        protected float GetReparam(SplineSegment ss, float u)
        {
            if (u <= 0)
            {
                return(0);
            }
            else if (u >= 1)
            {
                return(1);
            }

            switch (Reparam)
            {
            case ReparamType.RungeKutta:
            {
                int   ridx = (int)(u * (float)StepCount);
                float uc   = (u - ss.mPrecomps[ridx]) / mPrecompdiv;
                return(Mathf.Lerp(ss.mParams[ridx], ss.mParams[ridx + 1], uc));
            }

            case ReparamType.Simple:
            {
                int ridx = 0;
                for (int i = 1; i < StepCount + 1; ++i)
                {
                    if (ss.mPrecomps[i] > u)
                    {
                        ridx = i - 1;
                        break;
                    }
                }
                float uc = (u - ss.mPrecomps[ridx]) / (ss.mPrecomps[ridx + 1] - ss.mPrecomps[ridx]);
                return(Mathf.Lerp(ss.mParams[ridx], ss.mParams[ridx + 1], uc));
            }

            default:
                return(0);
            }
        }
예제 #12
0
    private void RecursiveDrawSegment(SplineSegment segment)
    {
        foreach (SplineSegment child in segment.Children)
        {
            RecursiveDrawSegment(child);
        }

        int        depth     = segment.Depth();
        Vector3    gPosition = segment.GlobalPosition();
        Vector3    gScale    = segment.GlobalPosition();
        Quaternion gRotation = segment.GlobalRotation();


        if (depth == _depth | viewAllNodes)
        {
            Gizmos.color = Palette.ColorWheel(segment.Depth(), 6);
            UnityEditor.Handles.color = Gizmos.color;
            UnityEditor.Handles.DrawWireDisc(gPosition, gRotation * Vector3.forward, 7f - depth);
            UnityEditor.Handles.DrawLine(gPosition, gPosition + segment.GlobalRotation() * (Vector3.forward * (depth + 1) * 5f));

            //UnityEditor.Handles.Label(compareLocalGlobal ? segment.LocalPosition : segment.GlobalPosition(), segment.Depth().ToString());
            UnityEditor.Handles.Label(segment.GlobalPosition() + Vector3.down * segment.Depth() * 10, "L:" + segment.LocalScale.ToString() + " G:" + segment.GlobalScale());
        }
    }
예제 #13
0
    /**
     * This function updates the spline mesh. It is called automatically once in a while, if updateMode isn't set to DontUpdate.
     */
    public void UpdateMesh( )
    {
        Setup( );

        //Reset the generated meshes
        if (BentMesh)
        {
            BentMesh.Clear( );
        }

        if (baseMesh == null || spline == null || segmentCount <= 0)
        {
            return;
        }


        //Gather model data
        Vector3[] verticesBase = baseMesh.vertices;
        Vector3[] normalsBase  = baseMesh.normals;
        Vector4[] tangentsBase = baseMesh.tangents;
        Vector2[] uvBase       = baseMesh.uv;

        int[] trianglesBase = baseMesh.triangles;


        //Allocate some memory for new mesh data
        Vector3[] verticesNew = new Vector3[verticesBase.Length * segmentCount];
        Vector3[] normalsNew  = new Vector3[normalsBase.Length * segmentCount];
        Vector4[] tangentsNew = new Vector4[tangentsBase.Length * segmentCount];
        Vector2[] uvNew       = new Vector2[uvBase.Length * segmentCount];

        int[] trianglesNew = new int[trianglesBase.Length * segmentCount];


        //Group front/rear vertices together
        List <int> verticesFront = new List <int>( );
        List <int> verticesBack  = new List <int>( );

        Vector3 centerFront = Vector3.zero;
        Vector3 centerBack  = Vector3.zero;

        for (int i = 0; i < verticesBase.Length; i++)
        {
            if (verticesBase[i].z > 0f)
            {
                verticesFront.Add(i);
                centerFront += verticesBase[i];
            }
            else if (verticesBase[i].z < 0f)
            {
                verticesBack.Add(i);
                centerBack += verticesBase[i];
            }
        }

        centerFront /= verticesFront.Count;
        centerBack  /= verticesBack.Count;


        if (splineSegment >= 0 && splineSegment < spline.SegmentCount)
        {
            SplineSegment currentSegment = spline.SplineSegments[splineSegment];

            int vIndex = 0;

            for (int segment = 0; segment < segmentCount; segment++)
            {
                float param0 = (float)segment / segmentCount;
                float param1 = (float)(segment + 1) / segmentCount;

                if (param1 == 1f)
                {
                    param1 -= 0.00001f;
                }

                param0 = currentSegment.ConvertSegmentToSplineParamter(param0);
                param1 = currentSegment.ConvertSegmentToSplineParamter(param1);

                CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack, param0, param1,
                                  verticesBase, normalsBase, tangentsBase, uvBase, verticesNew, normalsNew, tangentsNew, uvNew);

                for (int i = 0; i < trianglesBase.Length; i++)
                {
                    trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment);
                }
            }

            BentMesh.vertices = verticesNew;
            BentMesh.uv       = uvNew;

            if (normalsBase.Length > 0)
            {
                BentMesh.normals = normalsNew;
            }

            if (tangentsBase.Length > 0)
            {
                BentMesh.tangents = tangentsNew;
            }

            BentMesh.triangles = trianglesNew;
        }
        else
        {
            int vIndex = 0;

            for (int segment = 0; segment < segmentCount; segment++)
            {
                float param0 = (float)segment / segmentCount;
                float param1 = (float)(segment + 1) / segmentCount;

                if (param1 == 1f)
                {
                    param1 -= 0.00001f;
                }

                CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack, param0, param1,
                                  verticesBase, normalsBase, tangentsBase, uvBase, verticesNew, normalsNew, tangentsNew, uvNew);

                for (int i = 0; i < trianglesBase.Length; i++)
                {
                    trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment);
                }
            }

            BentMesh.vertices = verticesNew;
            BentMesh.uv       = uvNew;

            if (normalsBase.Length > 0)
            {
                BentMesh.normals = normalsNew;
            }

            if (tangentsBase.Length > 0)
            {
                BentMesh.tangents = tangentsNew;
            }

            BentMesh.triangles = trianglesNew;
        }
    }
예제 #14
0
            public void Execute(ArchetypeChunk chunk, int index, int entityOffset)
            {
                var localToParentAcessor = chunk.GetNativeArray(localToParentType);
                var animationAcessor     = chunk.GetNativeArray(splineAnimationType);
                var justSpawnedAcessor   = default(NativeArray <JustSpawned>);

                if (chunk.Has(justSpawnedType))
                {
                    justSpawnedAcessor = chunk.GetNativeArray(justSpawnedType);
                }

                for (int i = 0; i < chunk.Count; i++)
                {
                    SplineAnimationSpeed anim = animationAcessor[i];
                    var elements = elementAcessor[anim.spline];
                    var segments = segmentAcessor[anim.spline];
                    if (anim.index >= elements.Length)
                    {
                        continue;
                    }

                    float move = anim.speed * deltaTime;
                    if (justSpawnedAcessor.IsCreated)
                    {
                        move = anim.speed * justSpawnedAcessor[i].deltaTime;
                    }
                    float         left;
                    SplineSegment segment = segments[anim.segIndex];
                    while (move >= (left = (segment.end - anim.t) / (segment.end - segment.start) * segment.length))
                    {
                        move -= left;
                        if (++anim.segIndex >= segments.Length || segments[anim.segIndex].start == 0)
                        {
                            if (anim.isLoop)
                            {
                                if (++anim.index >= elements.Length)
                                {
                                    anim.index    = 0;
                                    anim.segIndex = 0;
                                }
                            }
                            else
                            {
                                if (++anim.index >= elements.Length - 1)
                                {
                                    anim.index    = elements.Length;
                                    anim.segIndex = 0;
                                    anim.t        = 0;
                                    break;
                                }
                            }
                        }
                        segment = segments[anim.segIndex];
                        anim.t  = segment.start;
                    }

                    if (anim.index >= elements.Length)
                    {
                        SplineElement last = elements[elements.Length - 1];
                        localToParentAcessor[i] = new LocalToParent {
                            Value = math.float4x4(last.rotation, last.point)
                        };
                    }
                    else
                    {
                        anim.t += (move / segment.length) * (segment.end - segment.start);
                        SplineElement start    = elements[anim.index];
                        SplineElement end      = anim.index < elements.Length - 1 ? elements[anim.index + 1] : elements[0];
                        float3        position = Bezier.GetPoint(start.point, start.point + start.forward, end.point + end.backward, end.point, anim.t);
                        quaternion    rotation = math.nlerp(start.rotation, end.rotation, anim.t);
                        localToParentAcessor[i] = new LocalToParent {
                            Value = math.float4x4(rotation, position)
                        };
                    }
                    animationAcessor[i] = anim;
                }
            }
예제 #15
0
    /// <summary>
    /// Computes keyframe times to ensure a constant speed along the given spline.
    /// </summary>
    /// <remarks>
    /// If the speed is 0 or omitted, it will be auto-computed so the animation completes in 1s.
    /// </remarks>
    public static float[] ComputeSplineTimes(Vector3[] positions, float speed = 0f)
    {
        bool isUnitLength = (speed == 0f);
          if (isUnitLength)
        speed = 1f;

          int frameCount = positions.Length;
          float[] times = new float[frameCount];
          times[0] = 0f;

          if (frameCount < 4)
          {
          for (int i = 1; i < frameCount; ++i)
              times[i] = times[i - 1] + (positions[i] - positions[i - 1]).magnitude / speed;
          }
          else
          {
          times[1] = (positions[1] - positions[0]).magnitude / speed;

          int samplesPerSegment = 16;
          Vector3 oldPosition = positions[1];
          for (int j = 2; j < frameCount - 1; ++j)
          {
              SplineSegment segment = new SplineSegment(positions[j-2], positions[j-1], positions[j], positions[j+1]);
              float segmentLength = 0f;
              for (int i = 0; i < samplesPerSegment; ++i)
              {
                  float t = (float)i / (float)(samplesPerSegment - 1);
                  Vector3 position = segment.GetPosition(t);

                  segmentLength += (position - oldPosition).magnitude;

                  oldPosition = position;
              }

              times[j] = times[j-1] + segmentLength / speed;
          }

          float endDistance = (positions[frameCount - 1] - positions[frameCount - 2]).magnitude;
          times[frameCount - 1] = times[frameCount - 2] + endDistance / speed;
          }

          if (isUnitLength)
          {
        float totalTime = 0f;
        foreach (float time in times)
            totalTime += time;

        for (int i = 0; i < times.Length; ++i)
            times[i] /= totalTime;
          }

          return times;
    }
예제 #16
0
    private void UpdateMesh(Mesh dstMesh, int splineSegment, ref List <Vector3> lightProbePositions)
    {
        Vector2 probeExtents = new Vector2(baseMesh.bounds.extents.x + lightProbeExtrude.x, lightProbeExtrude.y);

        Vector3[] segmentProbePositions =
        {
            new Vector3(0,               probeExtents.y + lightProbeHeight * 0.5f, 0),
            new Vector3(probeExtents.x,  probeExtents.y,                           0),
            new Vector3(probeExtents.x,  probeExtents.y + lightProbeHeight,        0),
            new Vector3(-probeExtents.x, probeExtents.y,                           0),
            new Vector3(-probeExtents.x, probeExtents.y + lightProbeHeight, 0)
        };

        //Gather model data
        Vector3[] verticesBase = baseMesh.vertices;
        Vector3[] normalsBase  = baseMesh.normals;
        Vector4[] tangentsBase = baseMesh.tangents;
        Vector2[] uvBase       = baseMesh.uv;
        Vector2[] uvLightmap   = baseMesh.uv2;

        ArrayList allTrianglesBase = new ArrayList();

        for (int q = 0; q < baseMesh.subMeshCount; ++q)
        {
            allTrianglesBase.Add(baseMesh.GetTriangles(q));
        }

        var localSegmentCount = segmentCount / splineSegmentCount;

        //Allocate some memory for new mesh data
        Vector3[] verticesNew   = new Vector3[verticesBase.Length * localSegmentCount];
        Vector3[] normalsNew    = new Vector3[normalsBase.Length * localSegmentCount];
        Vector4[] tangentsNew   = new Vector4[tangentsBase.Length * localSegmentCount];
        Vector2[] uvNew         = new Vector2[uvBase.Length * localSegmentCount];
        Vector2[] lightmapUvNew = new Vector2[uvBase.Length * localSegmentCount];

        ArrayList allTrianglesNew = new ArrayList();

        for (int q = 0; q < baseMesh.subMeshCount; ++q)
        {
            allTrianglesNew.Add(new int[baseMesh.GetTriangles(q).Length *localSegmentCount]);
        }

        //Group front/rear vertices together
        List <int> verticesFront = new List <int>( );
        List <int> verticesBack  = new List <int>( );

        Vector3 centerFront = Vector3.zero;
        Vector3 centerBack  = Vector3.zero;
        Vector3 minCorner   = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);

        for (int i = 0; i < verticesBase.Length; i++)
        {
            if (verticesBase[i].z > 0f)
            {
                verticesFront.Add(i);
                centerFront += verticesBase[i];
            }
            else if (verticesBase[i].z < 0f)
            {
                verticesBack.Add(i);
                centerBack += verticesBase[i];
            }

            minCorner = Vector3.Min(minCorner, verticesBase[i]);

            verticesBase[i].x = verticesBase[i].x + xyOffset.x;
            verticesBase[i].y = verticesBase[i].y + xyOffset.y;
        }

        centerFront /= verticesFront.Count;
        centerBack  /= verticesBack.Count;


//		float meshAspect = (xyScale.x * baseMesh.bounds.size.x) / baseMesh.bounds.size.z;
//		Vector2 lightmapScale = new Vector2(
//			(baseMesh.bounds.size.x * xyScale.x),
//			spline.Length/(float)splineSegmentCount);
        //;;Debug.Log ("lightmapScale " + lightmapScale.x + "," + lightmapScale.y + " " + splineSegmentCount + " " + localSegmentCount + " " + baseMesh.bounds.size);


        int vIndex = 0;

        int boxDimension = (int)Mathf.Round(Mathf.Sqrt(localSegmentCount) + 0.5f);

        //;;Debug.Log ("boxDimension " + boxDimension);

        for (int segment = 0; segment < localSegmentCount; segment++)
        {
            float localParam0 = (float)segment / localSegmentCount;
            float localParam1 = (float)(segment + 1) / localSegmentCount;

            if (localParam1 == 1f)
            {
                localParam1 -= 0.00001f;
            }

            float splineParam0 = localParam0;
            float splineParam1 = localParam1;

            if (splitMesh && splineSegment < spline.SegmentCount)
            {
                SplineSegment currentSegment = spline.SplineSegments[splineSegment];

                splineParam0 = currentSegment.ConvertSegmentToSplineParamter(localParam0);
                splineParam1 = currentSegment.ConvertSegmentToSplineParamter(localParam1);
            }

            int onX = segment / boxDimension;
            //int onY = segment % boxDimension;
            //;;Debug.Log(onX + " " + onY);

            var columnStartingSegment = onX * boxDimension;
            var lightmapOffset        = new Vector2(
                onX,
                -Mathf.Max(0f, (float)columnStartingSegment / (float)localSegmentCount));

            CalculateBentMesh(ref vIndex, verticesFront, verticesBack, ref centerFront, ref centerBack,
                              splineParam0, splineParam1, localParam0, localParam1, new Vector2(1.0f / ((float)boxDimension), (float)(boxDimension - 1)), lightmapOffset,
                              verticesBase, normalsBase, tangentsBase, uvBase, uvLightmap,
                              verticesNew, normalsNew, tangentsNew, uvNew, lightmapUvNew);

            for (int q = 0; q < allTrianglesNew.Count; ++q)
            {
                int[] trianglesNew  = allTrianglesNew[q] as int[];
                int[] trianglesBase = allTrianglesBase[q] as int[];
                for (int i = 0; i < trianglesBase.Length; i++)
                {
                    trianglesNew[i + (segment * trianglesBase.Length)] = trianglesBase[i] + (verticesBase.Length * segment);
                }
            }
        }

        var localLightProbeSegmentCount = lightProbeSegmentCount / splineSegmentCount;

        for (int segment = 0; segment < localLightProbeSegmentCount + 1; segment++)
        {
            float param0 = (float)segment / localLightProbeSegmentCount;
            float paramC = ((float)segment + 0.5f) / localLightProbeSegmentCount;
            if (splitMesh && splineSegment < spline.SegmentCount)
            {
                SplineSegment currentSegment = spline.SplineSegments[splineSegment];
                param0 = currentSegment.ConvertSegmentToSplineParamter(param0);
                paramC = currentSegment.ConvertSegmentToSplineParamter(paramC);
            }

            Vector3    pos0 = spline.transform.InverseTransformPoint(spline.GetPositionOnSpline(param0));
            Quaternion rot0 = spline.GetOrientationOnSpline(param0) * Quaternion.Inverse(spline.transform.localRotation);
            Vector3    posC = spline.transform.InverseTransformPoint(spline.GetPositionOnSpline(paramC));
            Quaternion rotC = spline.GetOrientationOnSpline(paramC) * Quaternion.Inverse(spline.transform.localRotation);

            foreach (var probePos in segmentProbePositions)
            {
                lightProbePositions.Add(pos0 + rot0 * probePos);
            }
            if (segment != localLightProbeSegmentCount)
            {
                lightProbePositions.Add(posC + rotC * segmentProbePositions[0]);
            }
        }

        dstMesh.vertices = verticesNew;
        dstMesh.uv       = uvNew;
        dstMesh.uv2      = lightmapUvNew;

        if (normalsBase.Length > 0)
        {
            dstMesh.normals = normalsNew;
        }

        if (tangentsBase.Length > 0)
        {
            dstMesh.tangents = tangentsNew;
        }

        dstMesh.subMeshCount = allTrianglesNew.Count;
        for (int q = 0; q < allTrianglesNew.Count; ++q)
        {
            int[] trianglesNew = allTrianglesNew[q] as int[];
            dstMesh.SetTriangles(trianglesNew, q);
        }
    }
예제 #17
0
 /// <summary> Creates the mesh given the 4 control points </summary>
 public void SetupSegment(Vector3 P0, Vector3 P1, Vector3 P2, Vector3 P3)
 {
     _segment = new SplineSegment(P0, P1, P2, P3);
     SetupMesh();
 }
예제 #18
0
        public Vector3 GetNormalByT(int segidx, float t)
        {
            SplineSegment ss = mSegments[segidx];

            return(GetNormal(ss, t));
        }
예제 #19
0
        private void DoLodLevel(GameObject rootTarget, Config.LodLevel config, int lodLevelIndex)
        {
            // Get a version of the spline in local space
            var spline = new SplineSegment(NodeConnection.GetSpline());

            spline.ApplyMatrix(rootTarget.transform.worldToLocalMatrix);

            if (config.SourceMesh == null)
            {
                Debug.LogError("No mesh defined for CreateRenderMesh component!");
                return;
            }

            List <CombineInstance> workingMeshes = new List <CombineInstance>(); // All the meshes that will be combined at the end
            var totalSplineLength = spline.Length;
            var scale             = config.SourceMesh.bounds.size;

            scale.Scale(config.Scale);
            var sourceMeshAxisLength = MeshTools.GetScalarFromAxis(scale, config.Axis);

            var perMeshLength     = Math.Min(totalSplineLength, sourceMeshAxisLength);
            var perMeshPercentage = perMeshLength / totalSplineLength;

            var snapDistance = config.SnapDistance;

            var matrix = Matrix4x4.TRS(
                config.Offset,
                Quaternion.Euler(config.Rotation),
                config.Scale);
            var mirrorMatrix = Matrix4x4.TRS(
                new Vector3(config.Offset.x, config.Offset.y, -config.Offset.z),
                Quaternion.Euler(config.Rotation),
                new Vector3(config.Scale.x, config.Scale.y, -config.Scale.z));
            var meshCombineMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one);

            int chunkCount    = 0;
            var currentResult = CreateNewBakeResult(config, rootTarget, lodLevelIndex, chunkCount);

            chunkCount++;
            float distanceAccumulator = 0;

            for (var i = SplineRange.x; i < 1; i += perMeshPercentage)
            {
                var startTime = i;
                var endTime   = Mathf.Clamp01(i + perMeshPercentage);

                if (Math.Abs(startTime - endTime) < .001f)
                {
                    break;
                }

                if (config.SplineInterpolation == SplineSegment.ESplineInterpolation.Uniform)
                {
                    startTime = spline.NaturalToUniformTime(startTime);
                    endTime   = spline.NaturalToUniformTime(endTime);
                }

                var distanceLeft = totalSplineLength - (endTime * totalSplineLength);
                if (endTime < 1 && distanceLeft <= snapDistance)
                {
                    endTime = 1;
                    i       = 1;
                }

                if (currentResult == null)
                {
                    var newChunkObject = new GameObject("Chunk" + chunkCount);
                    newChunkObject.transform.SetParent(rootTarget.transform);
                    newChunkObject.transform.localPosition = Vector3.zero;
                    newChunkObject.transform.localRotation = Quaternion.identity;
                    newChunkObject.transform.localScale    = Vector3.one;
                    currentResult = CreateNewBakeResult(config, newChunkObject, lodLevelIndex, chunkCount);
                    chunkCount++;
                }

                workingMeshes.Add(new CombineInstance()
                {
                    mesh      = config.SourceMesh.DistortAlongSpline(spline, matrix, startTime, endTime, snapDistance, config.SplineInterpolation),
                    transform = meshCombineMatrix,
                });

                if (config.Mirror)
                {
                    workingMeshes.Add(new CombineInstance()
                    {
                        mesh = config.SourceMesh.DistortAlongSpline(spline, mirrorMatrix, startTime, endTime, snapDistance, config.SplineInterpolation)
                               .FlipWindingOrder(),
                        transform = Matrix4x4.identity,
                    });
                }

                distanceAccumulator += perMeshPercentage * totalSplineLength;
                if ((distanceAccumulator > config.BreakDistance && totalSplineLength - distanceAccumulator > config.BreakDistance) || Mathf.Approximately(endTime, 1))
                {
                    distanceAccumulator = 0;
                    if (workingMeshes.Count > 0)
                    {
                        CombineInstance[] combineInstances = workingMeshes
                                                             .Where((instance => instance.mesh != null && instance.mesh.bounds.size.magnitude > 0)).ToArray();
                        currentResult.Mesh.CombineMeshes(combineInstances);
                    }
                    for (int j = 0; j < workingMeshes.Count; j++)
                    {
                        DestroyImmediate(workingMeshes[j].mesh);
                    }

                    if (config.OverrideNormal)
                    {
                        var n = new List <Vector3>();
                        n.Fill(Vector3.up, currentResult.Mesh.vertexCount);
                        currentResult.Mesh.SetNormals(n);
                    }
                    else
                    {
                        currentResult.Mesh.RecalculateNormals();
                    }

                    if (Mathf.Approximately(currentResult.Mesh.bounds.size.x, 0) ||
                        Mathf.Approximately(currentResult.Mesh.bounds.size.y, 0) ||
                        Mathf.Approximately(currentResult.Mesh.bounds.size.z, 0))
                    {
                        continue;
                    }

                    currentResult.Mesh.RecalculateTangents();
                    currentResult.Mesh.RecalculateBounds();
                    if (config.CopyToCollider)
                    {
                        currentResult.MeshCollider.enabled    = true;
                        currentResult.MeshCollider.sharedMesh = currentResult.Mesh;
                    }

                    currentResult.Renderer.shadowCastingMode = config.ShadowCastingMode;
                    currentResult.Filter.sharedMesh          = currentResult.Mesh;
                    currentResult.Renderer.sharedMaterials   = config.Materials.ToArray();
                    Results.Add(currentResult);
                    currentResult = null;
                }
            }
        }
예제 #20
0
    /// <summary>
    /// This function adds an offset to a BranchingSplineParameter while automatically switching splines when a juction is passed.
    /// </summary>
    /// <param name='bParam'>
    /// A BranchingSplineParameter.
    /// </param>
    /// <param name='distanceOffset'>
    /// An offset that shall be added to the BranchingSplineParameter (in game units).
    /// </param>
    /// <param name='bController'>
    /// A BranchingController-delegate that decides which path to follow if a junction is passed.
    /// </param>
    /// <returns>
    /// True if the spline used as reference path has been changed; False if not.
    /// </returns>
    public bool Advance(BranchingSplineParameter bParam, float distanceOffset, BranchingController bController)
    {
        bool splineChange = false;

        if (!SplinesAvailable)
        {
            return(false);
        }

        if (++recoursionCounter > 12)
        {
            recoursionCounter = 0;
            return(false);
        }

        CheckParameter(bParam);

        Spline     currentSpline = bParam.spline;
        SplineNode currentNode   = IsOnSplineNode(bParam.parameter, currentSpline);

        //Parameter on node?
        if (currentNode != null)
        {
            BranchingSplinePath nextPath = ChoseSpline(currentNode, bParam, bController, distanceOffset > 0);

            bParam.spline    = nextPath.spline;
            bParam.direction = nextPath.direction;
            bParam.parameter = currentNode.Parameters[bParam.spline].PosInSpline;

            SplineNode[] adjacentNodes = GetAdjacentSegmentNodes(nextPath.spline, currentNode);
            SplineNode   nextNode      = adjacentNodes[ForwardOnSpline(nextPath.direction, distanceOffset) ? 1 : 0];

            if (nextNode != null)
            {
                bParam.parameter += (nextNode.Parameters[bParam.spline].PosInSpline - currentNode.Parameters[bParam.spline].PosInSpline) * 0.001f;
                Advance(bParam, distanceOffset, bController);

                splineChange = false;
            }
            else
            {
                splineChange = false;
            }
        }
        else
        {
            SplineSegment currentSegment = currentSpline.GetSplineSegment(bParam.parameter);

            float signedSplineLength  = currentSpline.Length * (bParam.Forward ? 1 : -1);
            float normalizedOffsetDir = distanceOffset / signedSplineLength;

            float newParameter = bParam.parameter + normalizedOffsetDir;

            float clampedParameter = currentSegment.ClampParameterToSegment(newParameter);
            float offsetDifference = newParameter - clampedParameter;

            bParam.parameter = clampedParameter;

            if (Mathf.Approximately(offsetDifference, 0))
            {
                splineChange = false;
            }
            else
            {
                splineChange = Advance(bParam, offsetDifference * signedSplineLength, bController);
            }
        }

        recoursionCounter = 0;

        return(splineChange);
    }
예제 #21
0
        public void Build()
        {
            int         idx, count;
            SplinePoint p1, p2, p3, p4;


            if (mPoints.Count < 2)
            {
                mSegments = null;
                Length    = 0;
                return;
            }
            if (WrapType == WrapMode.Loop)
            {
                count = mPoints.Count;
            }
            else
            {
                count = mPoints.Count - 1;
            }

            mSegments = new SplineSegment[count];
            Length    = 0;
            idx       = 0;

            if (WrapType == WrapMode.Loop)
            {
                while (idx < count)
                {
                    p1 = mPoints[XSplineUtil.WrapIndex(idx - 1, mPoints.Count)];
                    p2 = mPoints[XSplineUtil.WrapIndex(idx, mPoints.Count)];
                    p3 = mPoints[XSplineUtil.WrapIndex(idx + 1, mPoints.Count)];
                    p4 = mPoints[XSplineUtil.WrapIndex(idx + 2, mPoints.Count)];

                    mSegments[idx] = new SplineSegment(InterpolateType);
                    if (InterpolateType == SplineType.Linear || InterpolateType == SplineType.Bezier)
                    {
                        BuildSegment(mSegments[idx], p1, p2, p3, p4);
                    }
                    else
                    {
                        BuildSegment(mSegments[idx], p2, p1, p4, p3);
                    }
                    ++idx;
                }
            }
            else
            {
                while (idx < count)
                {
                    p1 = mPoints[XSplineUtil.ClampIndex(idx - 1, mPoints.Count)];
                    p2 = mPoints[XSplineUtil.ClampIndex(idx, mPoints.Count)];
                    p3 = mPoints[XSplineUtil.ClampIndex(idx + 1, mPoints.Count)];
                    p4 = mPoints[XSplineUtil.ClampIndex(idx + 2, mPoints.Count)];

                    mSegments[idx] = new SplineSegment(InterpolateType);
                    if (InterpolateType == SplineType.Linear || InterpolateType == SplineType.Bezier)
                    {
                        BuildSegment(mSegments[idx], p1, p2, p3, p4);
                    }
                    else
                    {
                        BuildSegment(mSegments[idx], p2, p1, p4, p3);
                    }
                    ++idx;
                }
            }
            ++mBuildnum;
        }
예제 #22
0
    /// <summary>
    /// This function updates the spline mesh. It is called automatically once in a while, if updateMode isn't set to DontUpdate.
    /// </summary>
    public void UpdateMesh( )
    {
        SetupMesh( );

        bentMesh.Clear( );

        if (baseMesh == null || spline == null || segmentCount <= 0)
        {
            return;
        }

        SetupMeshBuffers( );

        float startParam;
        float endParam;

        float deltaParam;

        switch (splitMode)
        {
        case SplitMode.BySplineSegment:
            SplineSegment[] splineSegments = spline.SplineSegments;

            splineSegment = Mathf.Clamp(splineSegment, 0, splineSegments.Length - 1);

            SplineSegment segment = splineSegments[splineSegment];

            startParam = (float)segment.StartNode.Parameters[spline].position;
            endParam   = startParam + (float)segment.NormalizedLength;

            break;

        case SplitMode.BySplineParameter:
            startParam = segmentStart;
            endParam   = segmentEnd;

            break;

        case SplitMode.DontSplit:
        default:
            startParam = 0;
            endParam   = 1;

            break;
        }

        deltaParam = endParam - startParam;

        float param0 = 0f;
        float param1 = 0f;

        SplineMeshModifier[] splineMeshModifiers = GetComponentsInChildren <SplineMeshModifier>( );

        for (int segmentIdx = 0; segmentIdx < segmentCount; segmentIdx++)
        {
            MeshData currentBaseMesh;

            if (segmentIdx == 0 && startBaseMesh != null)
            {
                currentBaseMesh = meshDataStart;
            }
            else if (segmentIdx == segmentCount - 1 && endBaseMesh != null)
            {
                currentBaseMesh = meshDataEnd;
            }
            else
            {
                currentBaseMesh = meshDataBase;
            }

            param0 = startParam + deltaParam * (float)(segmentIdx) / segmentCount;
            param1 = startParam + deltaParam * (float)(segmentIdx + 1) / segmentCount;

            BendMesh(param0, param1, currentBaseMesh, meshDataNew, splineMeshModifiers);
        }

        meshDataNew.AssignToMesh(bentMesh);
    }
예제 #23
0
        protected void BuildSegment(SplineSegment ss, SplinePoint p1, SplinePoint p2, SplinePoint p3, SplinePoint p4)
        {
            if (InterpolateType == SplineType.Linear)
            {
                PreparePoint(p1, p2, p3);
                PreparePoint(p2, p3, p4);

                ss.mStartpos  = p2.mPoint;
                ss.mEndpos    = p3.mPoint;
                ss.mStartctrl = ss.mStartpos + p2.mNextctrl;
                ss.mEndctrl   = ss.mEndpos + p3.mPrevctrl;
            }
            if (InterpolateType == SplineType.Bezier)
            {
                PreparePoint(p1, p2, p3);
                PreparePoint(p2, p3, p4);

                ss.mStartpos  = p2.mPoint;
                ss.mEndpos    = p3.mPoint;
                ss.mStartctrl = ss.mStartpos + p2.mNextctrl;
                ss.mEndctrl   = ss.mEndpos + p3.mPrevctrl;
            }
            else if (InterpolateType == SplineType.CatmullRom)
            {
                ss.mStartpos = p1.mPoint;
                ss.mEndpos   = p4.mPoint;

                ss.mStartctrl = p2.mPoint;
                ss.mEndctrl   = p3.mPoint;
            }



            ss.mStartlen = Length;
            float seglen = GetLength(ss);

            Length    += seglen;
            ss.mLength = seglen;
            ss.mEndlen = Length;

            switch (Reparam)
            {
            case ReparamType.None:
                ss.mParams   = null;
                ss.mPrecomps = null;
                break;

            case ReparamType.Simple:
            {
                mPrecompdiv = 1 / (float)StepCount;
                float param = 0, length = 0;

                Vector3 prev, next;

                ss.mParams   = new float[StepCount + 1];
                ss.mPrecomps = new float[StepCount + 1];
                for (int i = 1; i < StepCount + 1; ++i)
                {
                    prev            = GetPosition(ss, param);
                    param          += mPrecompdiv;
                    next            = GetPosition(ss, param);
                    length         += (next - prev).magnitude;
                    ss.mPrecomps[i] = length / seglen;
                    ss.mParams[i]   = param;
                }
                ss.mParams[0]           = 0;
                ss.mParams[StepCount]   = 1;
                ss.mPrecomps[0]         = 0;
                ss.mPrecomps[StepCount] = 1;
                mPrecompdiv             = 1 / (float)StepCount;
            }
            break;

            case ReparamType.RungeKutta:
                float dlen = seglen / (float)StepCount, lparam = 0;

                ss.mParams   = new float[StepCount + 1];
                ss.mPrecomps = new float[StepCount + 1];
                for (int i = 0; i < StepCount + 1; ++i)
                {
                    ss.mParams[i]   = GetReparamRungeKutta(ss, lparam);
                    ss.mPrecomps[i] = lparam / seglen;
                    lparam         += dlen;
                }
                ss.mParams[0]           = 0;
                ss.mParams[StepCount]   = 1;
                ss.mPrecomps[0]         = 0;
                ss.mPrecomps[StepCount] = 1;
                mPrecompdiv             = 1 / (float)StepCount;
                break;
            }
        }