protected CGData GetSplineData(CurvySpline spline, bool fullPath, CGDataRequestRasterization raster, CGDataRequestMetaCGOptions options) { if (spline == null || spline.Count == 0) { return(null); } List <ControlPointOption> optionsSegs = new List <ControlPointOption>(); int materialID = 0; float maxStep = float.MaxValue; var data = (fullPath) ? new CGPath() : new CGShape(); // calc start & end point (distance) float startDist; float endDist; getRange(spline, raster, out startDist, out endDist); float stepDist = (endDist - startDist) / (raster.Resolution - 1); data.Length = endDist - startDist; // initialize with start TF float tf = spline.DistanceToTF(startDist); float startTF = tf; float endTF = (endDist > spline.Length && spline.Closed) ? spline.DistanceToTF(endDist - spline.Length) + 1 : spline.DistanceToTF(endDist); // Set properties data.SourceIsManaged = IsManagedResource(spline); data.Closed = spline.Closed; data.Seamless = spline.Closed && raster.Length == 1; if (data.Length == 0) { return(data); } // Scan input spline and fetch a list of control points that provide special options (Hard Edge, MaterialID etc...) if (options) { optionsSegs = CGUtility.GetControlPointsWithOptions(options, spline, startDist, endDist, raster.Mode == CGDataRequestRasterization.ModeEnum.Optimized, out materialID, out maxStep); } // Setup vars List <SamplePointUData> extendedUVData = new List <SamplePointUData>(); List <Vector3> pos = new List <Vector3>(); List <float> relF = new List <float>(); List <float> sourceF = new List <float>(); List <Vector3> tan = new List <Vector3>(); List <Vector3> up = new List <Vector3>(); float curDist = startDist; Vector3 curPos; float curF; Vector3 curTan = Vector3.zero; Vector3 curUp = Vector3.zero; List <int> softEdges = new List <int>(); int dead = 100000; raster.Resolution = Mathf.Max(raster.Resolution, 2); switch (raster.Mode) { case CGDataRequestRasterization.ModeEnum.Even: #region --- Even --- // we advance the spline using a fixed distance bool dupe = false; // we have at least one Material Group SamplePointsMaterialGroup grp = new SamplePointsMaterialGroup(materialID); // and at least one patch within that group SamplePointsPatch patch = new SamplePointsPatch(0); var clampMode = (data.Closed) ? CurvyClamping.Loop : CurvyClamping.Clamp; while (curDist <= endDist && --dead > 0) { tf = spline.DistanceToTF(spline.ClampDistance(curDist, clampMode)); curPos = (UseCache) ? spline.InterpolateFast(tf) : spline.Interpolate(tf); curF = (curDist - startDist) / data.Length;//curDist / endDist; if (Mathf.Approximately(1, curF)) { curF = 1; } pos.Add(curPos); relF.Add(curF); sourceF.Add(curDist / spline.Length); if (fullPath) // add path values { curTan = (UseCache) ? spline.GetTangentFast(tf) : spline.GetTangent(tf, curPos); curUp = spline.GetOrientationUpFast(tf); tan.Add(curTan); up.Add(curUp); } if (dupe) // HardEdge, IncludeCP, MaterialID changes etc. need an extra vertex { pos.Add(curPos); relF.Add(curF); sourceF.Add(curDist / spline.Length); if (fullPath) { tan.Add(curTan); up.Add(curUp); } dupe = false; } // Advance curDist += stepDist; // Check next Sample Point's options. If the next point would be past a CP with options if (optionsSegs.Count > 0 && curDist >= optionsSegs[0].Distance) { if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) { extendedUVData.Add(new SamplePointUData(pos.Count, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } // clamp point at CP and maybe duplicate the next sample point curDist = optionsSegs[0].Distance; dupe = optionsSegs[0].HardEdge || optionsSegs[0].MaterialID != grp.MaterialID || (options.CheckExtendedUV && optionsSegs[0].UVEdge); // end the current patch... if (dupe) { patch.End = pos.Count; grp.Patches.Add(patch); // if MaterialID changes, we start a new MaterialGroup if (grp.MaterialID != optionsSegs[0].MaterialID) { data.MaterialGroups.Add(grp); grp = new SamplePointsMaterialGroup(optionsSegs[0].MaterialID); } // in any case we start a new patch patch = new SamplePointsPatch(pos.Count + 1); if (!optionsSegs[0].HardEdge) { softEdges.Add(pos.Count + 1); } // Extended UV if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) { extendedUVData.Add(new SamplePointUData(pos.Count + 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } } // and remove the CP from the options optionsSegs.RemoveAt(0); } // Ensure last sample point position is at the desired end distance if (curDist > endDist && curF < 1) // next loop curF will be 1 { curDist = endDist; } } if (dead <= 0) { Debug.LogError("[Curvy] He's dead, Jim! Deadloop in SplineInputModuleBase.GetSplineData (Even)! Please send a bug report!"); } // store the last open patch patch.End = pos.Count - 1; grp.Patches.Add(patch); // ExplicitU on last Vertex? //if (optionsSegs.Count > 0 && optionsSegs[0].UVShift) // extendedUVData.Add(new SamplePointUData(pos.Count - 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); // if path is closed and no hard edges involved, we need to smooth first normal if (data.Closed && !spline[0].GetMetadata <MetaCGOptions>(true).HardEdge) { softEdges.Add(0); } data.MaterialGroups.Add(grp); // fill data data.SourceF = sourceF.ToArray(); data.F = relF.ToArray(); data.Position = pos.ToArray(); if (fullPath) { ((CGPath)data).Direction = tan.ToArray(); data.Normal = up.ToArray(); } #endregion break; case CGDataRequestRasterization.ModeEnum.Optimized: #region --- Optimized --- dupe = false; // we have at least one Material Group grp = new SamplePointsMaterialGroup(materialID); // and at least one patch within that group patch = new SamplePointsPatch(0); float stepSizeTF = stepDist / spline.Length; float maxAngle = raster.AngleThreshold; float stopAt; bool atStopPoint; curPos = spline.Interpolate(tf); curTan = spline.GetTangent(tf, curPos); var addPoint = new System.Action <float>((float f) => { sourceF.Add(curDist / spline.Length); pos.Add(curPos); relF.Add((curDist - startDist) / data.Length); if (fullPath) { tan.Add(curTan); up.Add(spline.GetOrientationUpFast(f)); } }); while (tf < endTF && dead-- > 0) { addPoint(tf % 1); // Advance stopAt = (optionsSegs.Count > 0) ? optionsSegs[0].TF : endTF; atStopPoint = spline.MoveByAngleExtINTERNAL(ref tf, Generator.MinDistance, maxStep, maxAngle, out curPos, out curTan, out stepDist, stopAt, data.Closed, stepSizeTF); curDist += stepDist; if (Mathf.Approximately(tf, endTF) || tf > endTF) { curDist = endDist; endTF = (data.Closed) ? DTMath.Repeat(endTF, 1) : Mathf.Clamp01(endTF); curPos = spline.Interpolate(endTF); if (fullPath) { curTan = spline.GetTangent(endTF, curPos); } addPoint(endTF); break; } if (atStopPoint) { if (optionsSegs.Count > 0) { if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) { extendedUVData.Add(new SamplePointUData(pos.Count, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } // clamp point at CP and maybe duplicate the next sample point curDist = optionsSegs[0].Distance; maxStep = (optionsSegs[0].MaxStepDistance); dupe = optionsSegs[0].HardEdge || optionsSegs[0].MaterialID != grp.MaterialID || (options.CheckExtendedUV && optionsSegs[0].UVEdge); if (dupe) { // end the current patch... patch.End = pos.Count; grp.Patches.Add(patch); // if MaterialID changes, we start a new MaterialGroup if (grp.MaterialID != optionsSegs[0].MaterialID) { data.MaterialGroups.Add(grp); grp = new SamplePointsMaterialGroup(optionsSegs[0].MaterialID); } // in any case we start a new patch patch = new SamplePointsPatch(pos.Count + 1); if (!optionsSegs[0].HardEdge) { softEdges.Add(pos.Count + 1); } // Extended UV if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) { extendedUVData.Add(new SamplePointUData(pos.Count + 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } addPoint(tf); } // and remove the CP from the options optionsSegs.RemoveAt(0); } else { addPoint(tf); break; } } } if (dead <= 0) { Debug.LogError("[Curvy] He's dead, Jim! Deadloop in SplineInputModuleBase.GetSplineData (Optimized)! Please send a bug report!"); } // store the last open patch patch.End = pos.Count - 1; grp.Patches.Add(patch); // ExplicitU on last Vertex? if (optionsSegs.Count > 0 && optionsSegs[0].UVShift) { extendedUVData.Add(new SamplePointUData(pos.Count - 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } // if path is closed and no hard edges involved, we need to smooth first normal if (data.Closed && !spline[0].GetMetadata <MetaCGOptions>(true).HardEdge) { softEdges.Add(0); } data.MaterialGroups.Add(grp); // fill data data.SourceF = sourceF.ToArray(); data.F = relF.ToArray(); data.Position = pos.ToArray(); data.Bounds = spline.Bounds; if (fullPath) { ((CGPath)data).Direction = tan.ToArray(); data.Normal = up.ToArray(); } #endregion break; } data.Map = (float[])data.F.Clone(); if (!fullPath) { data.RecalculateNormals(softEdges); if (options && options.CheckExtendedUV) { CalculateExtendedUV(spline, startTF, endTF, extendedUVData, data); } } return(data); }
protected CGData GetSplineData(CurvySpline spline, bool fullPath, CGDataRequestRasterization raster, CGDataRequestMetaCGOptions options) { if (spline == null || spline.Count == 0) return null; List<ControlPointOption> optionsSegs = new List<ControlPointOption>(); int materialID = 0; float maxStep = float.MaxValue; var data = (fullPath) ? new CGPath() : new CGShape(); // calc start & end point (distance) float startDist; float endDist; getRange(spline, raster, out startDist, out endDist); float stepDist = (endDist - startDist) / (raster.Resolution - 1); data.Length = endDist - startDist; // initialize with start TF float tf = spline.DistanceToTF(startDist); float startTF = tf; float endTF = (endDist > spline.Length && spline.Closed) ? spline.DistanceToTF(endDist - spline.Length) + 1 : spline.DistanceToTF(endDist); // Set properties data.SourceIsManaged = IsManagedResource(spline); data.Closed = spline.Closed; data.Seamless = spline.Closed && raster.Length == 1; if (data.Length == 0) return data; // Scan input spline and fetch a list of control points that provide special options (Hard Edge, MaterialID etc...) if (options) optionsSegs = CGUtility.GetControlPointsWithOptions(options, spline, startDist, endDist, raster.Mode == CGDataRequestRasterization.ModeEnum.Optimized, out materialID, out maxStep); // Setup vars List<SamplePointUData> extendedUVData = new List<SamplePointUData>(); List<Vector3> pos = new List<Vector3>(); List<float> relF = new List<float>(); List<float> sourceF = new List<float>(); List<Vector3> tan = new List<Vector3>(); List<Vector3> up = new List<Vector3>(); float curDist = startDist; Vector3 curPos; float curF; Vector3 curTan = Vector3.zero; Vector3 curUp = Vector3.zero; List<int> softEdges = new List<int>(); int dead = 100000; raster.Resolution = Mathf.Max(raster.Resolution, 2); switch (raster.Mode) { case CGDataRequestRasterization.ModeEnum.Even: #region --- Even --- // we advance the spline using a fixed distance bool dupe = false; // we have at least one Material Group SamplePointsMaterialGroup grp = new SamplePointsMaterialGroup(materialID); // and at least one patch within that group SamplePointsPatch patch = new SamplePointsPatch(0); var clampMode=(data.Closed) ? CurvyClamping.Loop : CurvyClamping.Clamp; while (curDist <= endDist && --dead>0) { tf = spline.DistanceToTF(spline.ClampDistance(curDist, clampMode)); curPos = spline.Interpolate(tf); curF = (curDist-startDist) / data.Length;//curDist / endDist; if (Mathf.Approximately(1, curF)) curF = 1; pos.Add(curPos); relF.Add(curF); sourceF.Add(curDist / spline.Length); if (fullPath) // add path values { curTan = spline.GetTangent(tf,curPos); curUp = spline.GetOrientationUpFast(tf); tan.Add(curTan); up.Add(curUp); } if (dupe) // HardEdge, IncludeCP, MaterialID changes etc. need an extra vertex { pos.Add(curPos); relF.Add(curF); sourceF.Add(curDist / spline.Length); if (fullPath) { tan.Add(curTan); up.Add(curUp); } dupe = false; } // Advance curDist += stepDist; // Check next Sample Point's options. If the next point would be past a CP with options if (optionsSegs.Count > 0 && curDist >= optionsSegs[0].Distance) { if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) extendedUVData.Add(new SamplePointUData(pos.Count, optionsSegs[0].UVEdge,optionsSegs[0].FirstU, optionsSegs[0].SecondU)); // clamp point at CP and maybe duplicate the next sample point curDist = optionsSegs[0].Distance; dupe = optionsSegs[0].HardEdge || optionsSegs[0].MaterialID != grp.MaterialID || (options.CheckExtendedUV && optionsSegs[0].UVEdge); // end the current patch... if (dupe) { patch.End = pos.Count; grp.Patches.Add(patch); // if MaterialID changes, we start a new MaterialGroup if (grp.MaterialID != optionsSegs[0].MaterialID) { data.MaterialGroups.Add(grp); grp = new SamplePointsMaterialGroup(optionsSegs[0].MaterialID); } // in any case we start a new patch patch = new SamplePointsPatch(pos.Count + 1); if (!optionsSegs[0].HardEdge) softEdges.Add(pos.Count + 1); // Extended UV if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) extendedUVData.Add(new SamplePointUData(pos.Count + 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); } // and remove the CP from the options optionsSegs.RemoveAt(0); } // Ensure last sample point position is at the desired end distance if (curDist > endDist && curF < 1) // next loop curF will be 1 curDist = endDist; } if (dead<= 0) Debug.LogError("[Curvy] He's dead, Jim! Deadloop in SplineInputModuleBase.GetSplineData (Even)! Please send a bug report!"); // store the last open patch patch.End = pos.Count - 1; grp.Patches.Add(patch); // ExplicitU on last Vertex? //if (optionsSegs.Count > 0 && optionsSegs[0].UVShift) // extendedUVData.Add(new SamplePointUData(pos.Count - 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); // if path is closed and no hard edges involved, we need to smooth first normal if (data.Closed && !spline[0].GetMetadata<MetaCGOptions>(true).HardEdge) softEdges.Add(0); data.MaterialGroups.Add(grp); // fill data data.SourceF = sourceF.ToArray(); data.F = relF.ToArray(); data.Position = pos.ToArray(); if (fullPath) { ((CGPath)data).Direction = tan.ToArray(); data.Normal = up.ToArray(); } #endregion break; case CGDataRequestRasterization.ModeEnum.Optimized: #region --- Optimized --- dupe = false; // we have at least one Material Group grp = new SamplePointsMaterialGroup(materialID); // and at least one patch within that group patch = new SamplePointsPatch(0); float stepSizeTF = stepDist / spline.Length; float maxAngle = raster.AngleThreshold; float stopAt; bool atStopPoint; curPos = spline.Interpolate(tf); curTan = spline.GetTangent(tf, curPos); var addPoint = new System.Action<float>((float f) => { sourceF.Add(curDist/spline.Length); pos.Add(curPos); relF.Add((curDist -startDist) / data.Length); if (fullPath) { tan.Add(curTan); up.Add(spline.GetOrientationUpFast(f)); } }); while (tf < endTF && dead-- > 0) { addPoint(tf%1); // Advance stopAt = (optionsSegs.Count > 0) ? optionsSegs[0].TF : endTF; atStopPoint = spline.MoveByAngleExtINTERNAL(ref tf, Generator.MinDistance, maxStep, maxAngle, out curPos, out curTan, out stepDist, stopAt, data.Closed,stepSizeTF); curDist += stepDist; if (Mathf.Approximately(tf, endTF) || tf > endTF) { curDist = endDist; endTF = (data.Closed) ? DTMath.Repeat(endTF,1) : Mathf.Clamp01(endTF); curPos = spline.Interpolate(endTF); if (fullPath) curTan = spline.GetTangent(endTF, curPos); addPoint(endTF); break; } if (atStopPoint) { if (optionsSegs.Count > 0) { if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) extendedUVData.Add(new SamplePointUData(pos.Count, optionsSegs[0].UVEdge,optionsSegs[0].FirstU, optionsSegs[0].SecondU)); // clamp point at CP and maybe duplicate the next sample point curDist = optionsSegs[0].Distance; maxStep = (optionsSegs[0].MaxStepDistance); dupe = optionsSegs[0].HardEdge || optionsSegs[0].MaterialID != grp.MaterialID || (options.CheckExtendedUV && optionsSegs[0].UVEdge); if (dupe) { // end the current patch... patch.End = pos.Count; grp.Patches.Add(patch); // if MaterialID changes, we start a new MaterialGroup if (grp.MaterialID != optionsSegs[0].MaterialID) { data.MaterialGroups.Add(grp); grp = new SamplePointsMaterialGroup(optionsSegs[0].MaterialID); } // in any case we start a new patch patch = new SamplePointsPatch(pos.Count + 1); if (!optionsSegs[0].HardEdge) softEdges.Add(pos.Count + 1); // Extended UV if (optionsSegs[0].UVEdge || optionsSegs[0].UVShift) extendedUVData.Add(new SamplePointUData(pos.Count+1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); addPoint(tf); } // and remove the CP from the options optionsSegs.RemoveAt(0); } else { addPoint(tf); break; } } } if (dead <= 0) Debug.LogError("[Curvy] He's dead, Jim! Deadloop in SplineInputModuleBase.GetSplineData (Optimized)! Please send a bug report!"); // store the last open patch patch.End = pos.Count - 1; grp.Patches.Add(patch); // ExplicitU on last Vertex? if (optionsSegs.Count > 0 && optionsSegs[0].UVShift) extendedUVData.Add(new SamplePointUData(pos.Count - 1, optionsSegs[0].UVEdge, optionsSegs[0].FirstU, optionsSegs[0].SecondU)); // if path is closed and no hard edges involved, we need to smooth first normal if (data.Closed && !spline[0].GetMetadata<MetaCGOptions>(true).HardEdge) softEdges.Add(0); data.MaterialGroups.Add(grp); // fill data data.SourceF = sourceF.ToArray(); data.F = relF.ToArray(); data.Position = pos.ToArray(); data.Bounds = spline.Bounds; if (fullPath) { ((CGPath)data).Direction = tan.ToArray(); data.Normal = up.ToArray(); } #endregion break; } data.Map = (float[])data.F.Clone(); if (!fullPath) { data.RecalculateNormals(softEdges); if (options && options.CheckExtendedUV) CalculateExtendedUV(spline,startTF,endTF,extendedUVData, data); } return data; }