// Update is called once per frame void Update() { if (!Spline || !Spline.IsInitialized) { return; } // Runtime processing if (Application.isPlaying) { // get the TF of the current distance. // Note: It's recommended to use the TF based methods in consecutive calls, as the distance based // methods need to convert distance to TF internally each time! float tf = Spline.DistanceToTF(mDistance); // Move using cached values(slightly faster) or interpolate position now (more exact) // Note that we pass mTF and mDir by reference. These values will be changed by the Move methods mTransform.position = (FastInterpolation) ? Spline.MoveByFast(ref tf, ref mDir, Speed * Time.deltaTime, Clamping) : Spline.MoveBy(ref tf, ref mDir, Speed * Time.deltaTime, Clamping); mDistance = Spline.TFToDistance(tf); // Rotate the transform to match the spline's orientation if (SetOrientation) { transform.rotation = Spline.GetOrientationFast(tf); } } else // Editor processing: continuously place the transform to reflect property changes in the editor { InitPosAndRot(); } }
/// <summary> /// Converts a distance to a TF value /// </summary> /// <param name="distance">distance in the range 0..Length</param> /// <returns>a TF value in the range 0..1</returns> public override float DistanceToTF(float distance) { float localDistance; CurvySpline spl = DistanceToSpline(distance, out localDistance); return(SplineToTF(spl, spl.DistanceToTF(localDistance))); }
// Use this for initialization IEnumerator Start() { if (Spline && Cube) { while (!Spline.IsInitialized) { yield return(null); } cubes = new Transform[Amount]; tf = new float[Amount]; dir = new int[Amount]; cubes[0] = Cube; tf[0] = 0; dir[0] = (Speed >= 0) ? 1 : -1; // Scale Cube depending on Spline length and number of cubes float sc = Spline.Length / Amount; Cube.localScale = new Vector3(sc * 0.7f, sc * 0.7f, sc * 0.7f); // Create and position cubes Cube.position = Spline.InterpolateByDistance(0); for (int i = 1; i < Amount; i++) { { tf[i] = Spline.DistanceToTF(i * sc); cubes[i] = getCube(); cubes[i].position = Spline.Interpolate(tf[i]); cubes[i].rotation = Spline.GetOrientationFast(tf[i]); dir[i] = (Speed >= 0) ? 1 : -1; } } Speed = Mathf.Abs(Speed); } }
/// <summary> /// Converts a distance to a TF value /// </summary> /// <param name="distance">distance in the range 0..Length</param> /// <param name="clamping">Clamping to use</param> /// <returns>a TF value in the range 0..1</returns> public override float DistanceToTF(float distance, CurvyClamping clamping) { float localDistance; CurvySpline spl = DistanceToSpline(distance, out localDistance, clamping); return((spl) ? SplineToTF(spl, spl.DistanceToTF(localDistance)) : 0); }
void Update() { if (!Spline || !Spline.IsInitialized) { return; } if (Application.isPlaying && mDistance < 2) { float tf = Spline.DistanceToTF(mDistance); mTransform.position = (FastInterpolation) ? Spline.MoveByFast(ref tf, ref mDir, Speed * Time.deltaTime, Clamping) : Spline.MoveBy(ref tf, ref mDir, Speed * Time.deltaTime, Clamping); mDistance = Spline.TFToDistance(tf); if (SetOrientation) { transform.rotation = Spline.GetOrientationFast(tf); } } }
void Calculate() { if (selcount == 0) { return; } pos = new UnityEngine.Vector3[selcount]; up = new UnityEngine.Vector3[selcount]; tan = new UnityEngine.Vector3[selcount]; for (int i = 0; i < selcount; i++) { pos[i] = (UseWorldUnits) ? Spline.InterpolateByDistance(StartOffset + Step * i) : Spline.Interpolate(StartOffset + Step * i); up[i] = (UseWorldUnits) ? Spline.GetOrientationUpFast(Spline.DistanceToTF(StartOffset + Step * i)) : Spline.GetOrientationUpFast(StartOffset + Step * i); tan[i] = (UseWorldUnits) ? Spline.GetTangentByDistance(StartOffset + Step * i) : Spline.GetTangent(StartOffset + Step * i); } }
void Set() { float tf; // First get the TF if needed if (UseWorldUnits) { if (Distance >= Spline.Length) { Distance -= Spline.Length; } else if (Distance < 0) { Distance += Spline.Length; } tf = Spline.DistanceToTF(Distance); } else { if (Distance >= 1) { Distance -= 1; } else if (Distance < 0) { Distance += 1; } tf = Distance; } // Set the position transform.position = Spline.Interpolate(tf); // Set the rotation if (SetOrientation) { transform.rotation = Spline.GetOrientationFast(tf); } }
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; }
void DoInterpolate() { if (!mSpline.IsInitialized) { return; } GameObject go = Fsm.GetOwnerDefaultTarget(GameObject); if (go) { float tf = (PositionMode == CurvyPositionMode.Relative) ? CurvyUtility.ClampTF(Position.Value, Clamping) : mSpline.DistanceToTF(Position.Value, Clamping); Vector3 p = (UseCache.Value) ? mSpline.InterpolateFast(tf) : mSpline.Interpolate(tf); if (Space == Space.Self) { go.transform.localPosition = p; if (SetOrientation) { go.transform.localRotation = mSpline.GetOrientationFast(tf); } } else { go.transform.position = mSpline.transform.TransformPoint(p); if (SetOrientation) { go.transform.rotation = mSpline.transform.rotation * mSpline.GetOrientationFast(tf); } } } }
void DoInterpolate() { if (!mSpline.IsInitialized) { return; } System.Type metaDataType; { if (String.IsNullOrEmpty(MetaDataType.Value)) { metaDataType = null; } else { #if NETFX_CORE Type[] knownTypes = this.GetType().GetAllTypes(); #else Type[] knownTypes = TypeExt.GetLoadedTypes(); #endif metaDataType = knownTypes.FirstOrDefault(t => t.FullName == MetaDataType.Value); } } bool calc = !Input.IsNone; if (calc) { float f = (UseWorldUnits.Value) ? mSpline.DistanceToTF(Input.Value) : Input.Value; if (StorePosition.IsNone == false) { StorePosition.Value = (UseCache.Value) ? mSpline.InterpolateFast(f) : mSpline.Interpolate(f); } if (StoreTangent.IsNone == false) { StoreTangent.Value = mSpline.GetTangent(f); } if (StoreUpVector.IsNone == false) { StoreUpVector.Value = mSpline.GetOrientationUpFast(f); } if (StoreRotation.IsNone == false) { StoreRotation.Value = (StoreUpVector.IsNone) ? mSpline.GetOrientationFast(f) : Quaternion.LookRotation(mSpline.GetTangent(f), StoreUpVector.Value); } if (StoreScale.IsNone == false) { float localF; CurvySplineSegment segment = mSpline.TFToSegment(f, out localF); CurvySplineSegment nextControlPoint = segment.Spline.GetNextControlPoint(segment); if (ReferenceEquals(segment, null) == false) { StoreScale.Value = nextControlPoint ? Vector3.Lerp(segment.transform.lossyScale, nextControlPoint.transform.lossyScale, localF) : segment.transform.lossyScale; } else { StoreScale.Value = Vector3.zero; } } if (StoreTF.IsNone == false) { StoreTF.Value = f; } if (StoreDistance.IsNone == false) { StoreDistance.Value = (UseWorldUnits.Value) ? Input.Value : mSpline.TFToDistance(f); } if (metaDataType != null) { if (metaDataType.IsSubclassOf(typeof(CurvyMetadataBase)) == false) { //this if statement's branch does not exclude classes inheriting from CurvyMetadataBase but not from CurvyInterpolatableMetadataBase, but that's ok, those classes are handled below Debug.LogError("Meta data type " + metaDataType.FullName + " should be a subclass of CurvyInterpolatableMetadataBase<T>"); } else { if (StoreMetadata.IsNone == false) { MethodInfo genericMethodInfo = mSpline.GetType().GetMethod("GetMetadata").MakeGenericMethod(metaDataType); StoreMetadata.Value = (Object)genericMethodInfo.Invoke(mSpline, new System.Object[] { f }); } if (StoreInterpolatedMetadata.IsNone == false) { Type argumentType = GetInterpolatableMetadataGenericType(metaDataType); if (argumentType == null) { Debug.LogError("Meta data type " + metaDataType.FullName + " should be a subclass of CurvyInterpolatableMetadataBase<T>"); } else { MethodInfo genericMethodInfo = mSpline.GetType().GetMethod("GetInterpolatedMetadata").MakeGenericMethod(metaDataType, argumentType); StoreInterpolatedMetadata.SetValue(genericMethodInfo.Invoke(mSpline, new System.Object[] { f })); } } } } CurvySplineSegment seg = null; float segF = 0; if (StoreSegment.IsNone == false) { seg = getSegment(f, out segF); StoreSegment.Value = seg.gameObject; } if (StoreSegmentF.IsNone == false) { if (!seg) { seg = getSegment(f, out segF); } StoreSegmentF.Value = segF; } if (StoreSegmentDistance.IsNone == false) { if (!seg) { seg = getSegment(f, out segF); } StoreSegmentDistance.Value = seg.LocalFToDistance(segF); } } // General if (StoreLength.IsNone == false) { StoreLength.Value = mSpline.Length; } if (StoreCount.IsNone == false) { StoreCount.Value = mSpline.Count; } }
void Prepare() { #if UNITY_EDITOR mPerfWatch.Reset(); mPerfWatch.Start(); #endif if (Spline && StartMesh && ExtrusionParameter > 0) { StartMeshInfo = new MeshInfo(StartMesh, true, false); if (EndMesh) { EndMeshInfo = new MeshInfo(EndMesh, false, true); } else { EndMeshInfo = new MeshInfo(StartMesh, false, true); } // Calculate Steps float tf = FromTF; mSegmentInfo.Clear(); FromTF = Mathf.Clamp01(FromTF); ToTF = Mathf.Max(FromTF, Mathf.Clamp01(ToTF)); Vector3 scale; if (FromTF != ToTF) { switch (Extrusion) { case MeshExtrusion.FixedF: while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); tf += ExtrusionParameter; } break; case MeshExtrusion.FixedDistance: float d = Spline.TFToDistance(FromTF); tf = Spline.DistanceToTF(d); while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, d, scale)); d += ExtrusionParameter; tf = Spline.DistanceToTF(d); } break; case MeshExtrusion.Adaptive: while (tf < ToTF) { scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); int dir = 1; Spline.MoveByAngle(ref tf, ref dir, ExtrusionParameter, CurvyClamping.Clamp, 0.001f); } break; } if (!Mathf.Approximately(tf, ToTF)) { tf = ToTF; } scale = getScale(tf); mSegmentInfo.Add(new CurvyMeshSegmentInfo(this, tf, scale)); } } #if UNITY_EDITOR mPerfWatch.Stop(); DebugPerfPrepare = mPerfWatch.ElapsedTicks / (double)System.TimeSpan.TicksPerMillisecond; mPerfWatch.Reset(); #endif }