public static void DrawPathHandle(ObiPath path, Matrix4x4 referenceFrame, float thicknessScale, int resolution, bool drawOrientation = true) { if (path == null || path.GetSpanCount() == 0) { return; } Matrix4x4 prevMatrix = Handles.matrix; Handles.matrix = referenceFrame; // Draw the curve: int curveSegments = path.GetSpanCount() * resolution; Vector3[] samples = new Vector3[curveSegments + 1]; Vector3[] leftSamples = new Vector3[curveSegments + 1]; Vector3[] rightSamples = new Vector3[curveSegments + 1]; Vector3[] upSamples = new Vector3[curveSegments + 1]; for (int i = 0; i <= curveSegments; ++i) { float mu = i / (float)curveSegments; samples[i] = path.points.GetPositionAtMu(path.Closed, mu); if (drawOrientation) { Vector3 tangent = path.points.GetTangentAtMu(path.Closed, mu); Vector3 right = Vector3.Cross(tangent, path.normals.GetAtMu(path.Closed, mu)).normalized; Vector3 up = Vector3.Cross(right, tangent).normalized; float thickness = path.thicknesses.GetAtMu(path.Closed, mu) * thicknessScale + 0.05f; leftSamples[i] = samples[i] - right * thickness; rightSamples[i] = samples[i] + right * thickness; upSamples[i] = samples[i] + up * thickness; if (i % 5 == 0) { Handles.DrawLine(leftSamples[i], rightSamples[i]); Handles.DrawLine(samples[i], samples[i] + up * thickness); } } } if (drawOrientation) { DrawControlPointArcs(path, thicknessScale); } DrawPathPolylines(samples, leftSamples, rightSamples, upSamples, drawOrientation); DrawPathPolylines(samples, leftSamples, rightSamples, upSamples, drawOrientation); Handles.matrix = prevMatrix; }
public static float ScreenPointToCurveMu(ObiPath path, Vector2 screenPoint, Matrix4x4 referenceFrame, int samples = 30) { if (path.ControlPointCount >= 2) { samples = Mathf.Max(1, samples); float step = 1 / (float)samples; float closestMu = 0; float minDistance = float.MaxValue; for (int k = 0; k < path.GetSpanCount(); ++k) { int nextCP = (k + 1) % path.ControlPointCount; var wp1 = path.points[k]; var wp2 = path.points[nextCP]; Vector3 _p = referenceFrame.MultiplyPoint3x4(wp1.position); Vector3 p = referenceFrame.MultiplyPoint3x4(wp1.outTangentEndpoint); Vector3 p_ = referenceFrame.MultiplyPoint3x4(wp2.inTangentEndpoint); Vector3 p__ = referenceFrame.MultiplyPoint3x4(wp2.position); Vector2 lastPoint = HandleUtility.WorldToGUIPoint(path.m_Points.Evaluate(_p, p, p_, p__, 0)); for (int i = 1; i <= samples; ++i) { Vector2 currentPoint = HandleUtility.WorldToGUIPoint(path.m_Points.Evaluate(_p, p, p_, p__, i * step)); float mu; float distance = Vector2.SqrMagnitude((Vector2)ObiUtils.ProjectPointLine(screenPoint, lastPoint, currentPoint, out mu) - screenPoint); if (distance < minDistance) { minDistance = distance; closestMu = (k + (i - 1) * step + mu / samples) / (float)path.GetSpanCount(); } lastPoint = currentPoint; } } return(closestMu); } else { Debug.LogWarning("Curve needs at least 2 control points to be defined."); } return(0); }