/// <summary> /// 求曲线上与给定点最近的点 /// </summary> public float GetClosestLocation(Vector3 point, int segments) { Vector3 last = _f0; Vector3 current; float closest01; float sqrMagnitude; float bestSqrMagnitude = float.MaxValue; float bestT = 0f; for (int i = 1; i <= segments; i++) { current = GetPoint((float)i / segments); closest01 = MathKit.ClosestPointOnSegmentFactor(point, last, current); sqrMagnitude = (last + (current - last) * closest01 - point).sqrMagnitude; if (sqrMagnitude < bestSqrMagnitude) { bestSqrMagnitude = sqrMagnitude; bestT = (i - 1f + closest01) / segments; } last = current; } return bestT; }
protected override void OnMoveToolSceneGUI(T path) { if (_showTension) { for (int i = 0; i < path.segmentCount; i++) { float tension = path.GetSegmentTension(i); var point1 = path.GetNodePosition(i); var point2 = path.GetNodePosition((i + 1) % path.nodeCount); point1 = point1 * 0.75f + point2 * 0.25f; point2 = point1 / 3f + point2 * (2f / 3f); var point = (point2 - point1) * tension + point1; Handles.color = new Color(1f, 1f, 1f, 0.5f); HandlesKit.DrawAALine(point1, point2, 4); float capSize = HandleUtility.GetHandleSize(point) * FloatingWindow.capSize; using (var scope = new ChangeCheckScope(path)) { Handles.color = capNormalColor; point = Handles.FreeMoveHandle(point, Quaternion.identity, capSize, snap, Handles.CircleHandleCap); tension = MathKit.ClosestPointOnSegmentFactor(point, point1, point2); //tension = (float)Math.Round(tension, 2); //using (new HandlesGUIScope(0)) //{ // var pos2D = HandleUtility.WorldToGUIPoint(point); // var rect = new Rect(pos2D.x + 12, pos2D.y - 9, 32, 18); // EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.5f)); // using (new GUIContentColorScope(Color.white)) // { // EditorGUI.LabelField(rect, tension.ToString(), EditorStyles.whiteLabel); // } //} if (scope.changed) { path.SetSegmentTension(i, tension); } } } } int count = path.nodeCount; for (int i = 0; i < count; i++) { var position = path.GetNodePosition(i); float capSize = HandleUtility.GetHandleSize(position) * FloatingWindow.capSize; if (selectedNode == i) { using (var scope = new ChangeCheckScope(path)) { Handles.color = capSelectedColor; if (selectedTool == 0) { position = Handles.FreeMoveHandle(position, Quaternion.identity, capSize * 2, snap, Handles.RectangleHandleCap); } else { position = Handles.PositionHandle(position, path.transform.rotation); } if (scope.changed) { path.SetNodePosition(i, position); } } } else { Handles.color = capNormalColor; if (Handles.Button(position, Quaternion.identity, capSize, capSize, Handles.DotHandleCap)) { selectedNode = i; } } } }