/// <summary> /// Gets the interpolated position for a certain group TF using a linear approximation /// </summary> /// <remarks>TF (Total Fragment) relates to the total length of the group</remarks> /// <param name="tf">TF value reflecting position in the group (0..1)</param> /// <returns>the interpolated position</returns> public override Vector3 InterpolateFast(float tf) { float localTF; CurvySpline spl = TFToSpline(tf, out localTF); return(spl.InterpolateFast(localTF)); }
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); } } } }
public CurvyMeshSegmentInfo(SplinePathMeshBuilder mb, float tf, float distance, Vector3 scale) { Spline = mb.Spline; TF = tf; mDistance = distance; Vector3 p = (mb.FastInterpolation) ? Spline.InterpolateFast(TF) : Spline.Interpolate(TF); if (mb.UseWorldPosition) { Matrix = Matrix4x4.TRS(mb.Transform.InverseTransformPoint(p), Spline.GetOrientationFast(TF), scale); } else { Matrix = Matrix4x4.TRS(Spline.Transform.InverseTransformPoint(p), Spline.GetOrientationFast(TF), scale); } }
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); }
public CurvyMeshSegmentInfo(SplinePathMeshBuilder mb, float tf, float distance, Vector3 scale) { Spline = mb.Spline; TF = tf; mDistance = distance; Vector3 p = (mb.FastInterpolation) ? Spline.InterpolateFast(TF) : Spline.Interpolate(TF); if (mb.UseWorldPosition) Matrix = Matrix4x4.TRS(mb.Transform.InverseTransformPoint(p), Spline.GetOrientationFast(TF), scale); else Matrix = Matrix4x4.TRS(Spline.Transform.InverseTransformPoint(p), Spline.GetOrientationFast(TF), scale); }
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; } }