/// <summary>Get the path position to native path units. /// If the distance cache is not valid, then calling this will /// trigger a potentially costly regeneration of the path distance cache</summary> /// <param name="pos">The value to convert from</param> /// <param name="units">The units in which pos is expressed</param> /// <returns>The path position, in native units</returns> public float ToNativePathUnits(float pos, PositionUnits units) { if (units == PositionUnits.PathUnits) { return(pos); } if (DistanceCacheSampleStepsPerSegment < 1 || PathLength < UnityVectorExtensions.Epsilon) { return(MinPos); } if (units == PositionUnits.Normalized) { pos *= PathLength; } pos = StandardizePathDistance(pos); float d = pos / m_cachedDistanceStepSize; int i = Mathf.FloorToInt(d); if (i >= m_DistanceToPos.Length - 1) { return(MaxPos); } float t = d - (float)i; return(MinPos + Mathf.Lerp(m_DistanceToPos[i], m_DistanceToPos[i + 1], t)); }
public float ConvertWorldPositionToPathPosition(Vector3 worldPosition, PositionUnits units) { float position = FindClosestPoint(worldPosition, 0, -1, 10); float currentUnits = FromPathNativeUnits(position, units); return(currentUnits); }
private Vector2 StandardOrigin(Vector2 position, PositionUnits positionUnits, Vector2 renderTargetSize, float dpi) { Vector2 origin = new Vector2(); if (positionUnits == PositionUnits.Pixels) { origin.X = (position.X / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - (position.Y / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.DIPs) { origin.X = ((position.X * dpi / 96.0f) / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - ((position.Y * dpi / 96.0f) / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.Normalized) { origin.X = position.X * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * 2.0f; } else if (positionUnits == PositionUnits.UniformWidth) { origin.X = position.X * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * (renderTargetSize.X / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.UniformHeight) { origin.X = position.X * (renderTargetSize.Y / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * 2.0f; } return(origin); }
/// <summary>Convert a path position from native path units to the desired units. /// If the distance cache is not valid, then calling this will /// trigger a potentially costly regeneration of the path distance cache</summary> /// <param name="pos">The value to convert from, in native units</param> /// <param name="units">The units to convert to</param> /// <returns>The path position, in the requested units</returns> public float FromPathNativeUnits(float pos, PositionUnits units) { if (units == PositionUnits.PathUnits) { return(pos); } float length = PathLength; if (DistanceCacheSampleStepsPerSegment < 1 || length < UnityVectorExtensions.Epsilon) { return(0); } pos = StandardizePos(pos); float d = pos / m_cachedPosStepSize; int i = Mathf.FloorToInt(d); if (i >= m_PosToDistance.Length - 1) { pos = m_PathLength; } else { float t = d - (float)i; pos = Mathf.Lerp(m_PosToDistance[i], m_PosToDistance[i + 1], t); } if (units == PositionUnits.Normalized) { pos /= length; } return(pos); }
/// <summary>Get the maximum value, for the given unit type</summary> /// <param name="units">The unit type</param> /// <returns>The maximum allowable value for this path</returns> public float MaxUnit(PositionUnits units) { if (units == PositionUnits.Normalized) { return(1); } return(units == PositionUnits.Distance ? PathLength : MaxPos); }
/// <summary>Get the orientation the curve at a point along the path.</summary> /// <param name="pos">Postion along the path. Need not be normalized.</param> /// <param name="units">The unit to use when interpreting the value of pos.</param> /// <returns>World-space orientation of the path</returns> public Quaternion EvaluateOrientationAtUnit(float pos, PositionUnits units) { if (units == PositionUnits.Distance) { pos = GetPathPositionFromDistance(pos); } return(EvaluateOrientation(pos)); }
/// <summary>Get the tangent of the curve at a point along the path.</summary> /// <param name="pos">Postion along the path. Need not be normalized.</param> /// <param name="units">The unit to use when interpreting the value of pos.</param> /// <returns>World-space direction of the path tangent. /// Length of the vector represents the tangent strength</returns> public Vector3 EvaluateTangentAtUnit(float pos, PositionUnits units) { if (units == PositionUnits.Distance) { pos = GetPathPositionFromDistance(pos); } return(EvaluateTangent(pos)); }
/// <summary>Get the minimum value, for the given unit type</summary> /// <param name="units">The unit type</param> /// <returns>The minimum allowable value for this path</returns> public float MinUnit(PositionUnits units) { if (units == PositionUnits.Normalized) { return(0); } return(units == PositionUnits.Distance ? 0 : MinPos); }
/// <summary>Normalize the unit, so that it lies between MinUmit and MaxUnit</summary> /// <param name="pos">The value to be normalized</param> /// <param name="units">The unit type</param> /// <returns>The normalized value of pos, between MinUnit and MaxUnit</returns> public virtual float NormalizeUnit(float pos, PositionUnits units) { if (units == PositionUnits.Distance) { return(NormalizePathDistance(pos)); } return(NormalizePos(pos)); }
public float ConvertPathUnit(float currentPosition, PositionUnits currentUnit, PositionUnits wantedUnit) { Vector3 position = EvaluatePositionAtUnit(currentPosition, currentUnit); float prevPos = ToNativePathUnits(currentPosition, currentUnit); float pathPosition = FindClosestPoint(position, Mathf.FloorToInt(prevPos), -1, 10); pathPosition = FromPathNativeUnits(pathPosition, wantedUnit); return(pathPosition); }
/// <summary>Standardize the unit, so that it lies between MinUmit and MaxUnit</summary> /// <param name="pos">The value to be standardized</param> /// <param name="units">The unit type</param> /// <returns>The standardized value of pos, between MinUnit and MaxUnit</returns> public virtual float StandardizeUnit(float pos, PositionUnits units) { if (units == PositionUnits.PathUnits) { return(StandardizePos(pos)); } if (units == PositionUnits.Distance) { return(StandardizePathDistance(pos)); } float len = PathLength; if (len < UnityVectorExtensions.Epsilon) { return(0); } return(StandardizePathDistance(pos * len) / len); }
/// <summary>Find the closest point on the path to a given worldspace target point.</summary> /// <remarks>Performance could be improved by checking the bounding polygon of each segment, /// and only entering the best segment(s)</remarks> /// <param name="p">Worldspace target that we want to approach</param> /// <param name="startSegment">In what segment of the path to start the search. /// A Segment is a section of path between 2 waypoints.</param> /// <param name="searchRadius">How many segments on either side of the startSegment /// to search. -1 means no limit, i.e. search the entire path</param> /// <param name="stepsPerSegment">We search a segment by dividing it into this many /// straight pieces. The higher the number, the more accurate the result, but performance /// is proportionally slower for higher numbers</param> /// <returns>The position along the path that is closest to the target point. /// The value is in Path Units, not Distance units.</returns> public virtual float FindClosestPoint( Vector3 p, int startSegment = 0, int searchRadius = -1, int stepsPerSegment = 10, PositionUnits units = PositionUnits.PathUnits) { float start = MinPos; float end = MaxPos; if (searchRadius >= 0) { int r = Mathf.FloorToInt(Mathf.Min(searchRadius, (end - start) / 2f)); start = startSegment - r; end = startSegment + r + 1; if (!Looped) { start = Mathf.Max(start, MinPos); end = Mathf.Max(end, MaxPos); } } stepsPerSegment = Mathf.RoundToInt(Mathf.Clamp(stepsPerSegment, 1f, 100f)); float stepSize = 1f / stepsPerSegment; float bestPos = startSegment; float bestDistance = float.MaxValue; int iterations = (stepsPerSegment == 1) ? 1 : 3; for (int i = 0; i < iterations; ++i) { Vector3 v0 = EvaluatePosition(start); for (float f = start + stepSize; f <= end; f += stepSize) { Vector3 v = EvaluatePosition(f); float t = p.ClosestPointOnSegment(v0, v); float d = Vector3.SqrMagnitude(p - Vector3.Lerp(v0, v, t)); if (d < bestDistance) { bestDistance = d; bestPos = f - (1 - t) * stepSize; } v0 = v; } start = bestPos - stepSize; end = bestPos + stepSize; stepSize /= stepsPerSegment; } if (units == PositionUnits.PathUnits) { return(bestPos); } return(ConvertPathUnit(bestPos, PositionUnits.PathUnits, units)); }
/// <summary>Get the maximum value, for the given unity type</summary> /// <param name="units">The uniot type</param> /// <returns>The maximum allowable value for this path</returns> public float MaxUnit(PositionUnits units) { return(units == PositionUnits.Distance ? PathLength : MaxPos); }
/// <summary>Get the minimum value, for the given unity type</summary> /// <param name="units">The uniot type</param> /// <returns>The minimum allowable value for this path</returns> public float MinUnit(PositionUnits units) { return(units == PositionUnits.Distance ? 0 : MinPos); }
public float FromUnitDistanceToReal3DDistance(float amount, PositionUnits units) { amount = ConvertPathUnit(amount, units, PositionUnits.Distance); return(amount); }
/// <summary>Get the orientation the curve at a point along the path.</summary> /// <param name="pos">Postion along the path. Need not be normalized.</param> /// <param name="units">The unit to use when interpreting the value of pos.</param> /// <returns>World-space orientation of the path</returns> public Quaternion EvaluateOrientationAtUnit(float pos, PositionUnits units) { return(EvaluateOrientation(ToNativePathUnits(pos, units))); }
/// <summary>Get the tangent of the curve at a point along the path.</summary> /// <param name="pos">Postion along the path. Need not be normalized.</param> /// <param name="units">The unit to use when interpreting the value of pos.</param> /// <returns>World-space direction of the path tangent. /// Length of the vector represents the tangent strength</returns> public Vector3 EvaluateTangentAtUnit(float pos, PositionUnits units) { return(EvaluateTangent(ToNativePathUnits(pos, units))); }
public virtual float FindClosestPointFromRay(Ray ray, int maxSteps = 30, float sizeSteps = 1, PositionUnits units = PositionUnits.PathUnits) { Vector3 closestPointOnRay = ray.origin; float closestPoint = FindClosestPoint(closestPointOnRay, 0, -1, 10); float closestDist = Vector3.Distance(closestPointOnRay, EvaluatePosition(closestPoint)); for (int i = 1; i < maxSteps; i++) { Vector3 pointOnRay = ray.origin + ray.direction * (i * sizeSteps); float pointOnSpline = FindClosestPoint(pointOnRay, 0, -1, 10); Vector3 vectorOnSpline = EvaluatePosition(pointOnSpline); float dist = Vector3.Distance(pointOnRay, vectorOnSpline); if (dist < closestDist) { closestPoint = pointOnSpline; closestDist = dist; } } if (units == PositionUnits.PathUnits) { return(closestPoint); } return(ConvertPathUnit(closestPoint, PositionUnits.PathUnits, units)); }
private Vector2 StandardOrigin(Vector2 position, PositionUnits positionUnits, Vector2 renderTargetSize, float dpi) { Vector2 origin = new Vector2(); if (positionUnits == PositionUnits.Pixels) { origin.X = (position.X / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - (position.Y / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.DIPs) { origin.X = ((position.X * dpi / 96.0f) / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - ((position.Y * dpi / 96.0f) / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.Normalized) { origin.X = position.X * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * 2.0f; } else if (positionUnits == PositionUnits.UniformWidth) { origin.X = position.X * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * (renderTargetSize.X / renderTargetSize.Y) * 2.0f; } else if (positionUnits == PositionUnits.UniformHeight) { origin.X = position.X * (renderTargetSize.Y / renderTargetSize.X) * 2.0f - 1.0f; origin.Y = 1.0f - position.Y * 2.0f; } return origin; }
//private struct SpriteRunInfo //{ // public ShaderResourceView textureView; // public BlendState1 blendState; // public int numSprites; //}; public Vector2 CalculatePointerPosition(Vector2 position, PositionUnits positionUnits) { return StandardOrigin(position, positionUnits, m_renderTargetSize, m_dpi); }
//private struct SpriteRunInfo //{ // public ShaderResourceView textureView; // public BlendState1 blendState; // public int numSprites; //}; public Vector2 CalculatePointerPosition(Vector2 position, PositionUnits positionUnits) { return(StandardOrigin(position, positionUnits, m_renderTargetSize, m_dpi)); }