public Vector2 GetEdgeWindowPosition(int edgeIndex) { int nextIndex = SplineUtility.NextIndex(edgeIndex, m_Points.Count); Vector2 start = m_Points[edgeIndex].m_Position; Vector2 startTangent = (Vector2)m_Points[edgeIndex].m_RightTangent + start; Vector2 end = m_Points[nextIndex].m_Position; Vector2 endTangent = (Vector2)m_Points[nextIndex].m_LeftTangent + end; return(BezierUtility.BezierPoint(start, startTangent, endTangent, end, 0.5f) + Vector3.up * kWindowHeaderHeight); }
private void LayoutEdges() { if (currentEvent.type != EventType.Layout) { return; } PrepareEdgePoints(); int pointCount = GetPointCount(); int edgeCount = OpenEnded() ? pointCount - 1 : pointCount; float minDistance = float.MaxValue; for (int index = 0; index < edgeCount; ++index) { int id = GUIUtility.GetControlID("Edge".GetHashCode(), FocusType.Passive); if (currentEvent.type == EventType.Layout) { int nextIndex = SplineUtility.NextIndex(index, pointCount); Vector3 position0 = GetPosition(index); Vector3 position1 = GetPosition(nextIndex); Vector3 tangent0 = GetRightTangent(index) + position0; Vector3 tangent1 = GetLeftTangent(nextIndex) + position1; float t; Vector3 closestPoint = BezierUtility.ClosestPointOnCurve(ScreenToWorld(currentEvent.mousePosition), position0, position1, tangent0, tangent1, out t); Vector2 guiPosition = HandleUtility.WorldToGUIPoint(closestPoint); float distance = (currentEvent.mousePosition - guiPosition).magnitude; if (m_HoveredPointIndex == -1) { HandleUtility.AddControl(id, distance); if (HandleUtility.nearestControl == id) { m_HoveredEdgeIndex = index; m_HoveredPointIndex = -1; m_HoveredTangentPoint = -1; } } if (distance < minDistance) { m_ClosestPoint = closestPoint; m_ClosestPointT = t; minDistance = distance; } } } }
/// <summary> /// 按要求将网格,得到新的网格 /// </summary> /// <param name="meshData"></param> /// <param name=""></param> /// <returns></returns> public static void CurveMeshStruct(HandleData handle, MeshStruct meshDataTemp, ref MeshStruct meshData) { for (int i = 0; i < meshData.vertices.Length; i++) { Vector3 item = meshData.vertices[i]; //区域内部 if (item.x > handle.LeftCenterPoint.x && item.x < handle.RightCenterPoint.x) { Vector3 newCenterPos = BezierUtility.CalculateBezierPoint((item.x - handle.LeftCenterPoint.x) / (handle.RightCenterPoint.x - handle.LeftCenterPoint.x), handle.LeftCenterPoint, handle.HandPoint1, handle.HandPoint2, handle.RightCenterPoint); meshData.vertices[i].y = meshDataTemp.vertices[i].y + newCenterPos.y; } } }
// returns the tangent at the point on the curve between startIdx and startIdx + 1 public float3 TangentAt(ref DynamicBuffer <PathPoint> points, int startIdx, float t, int loopIndex) { if (BezierUtility.HasLoop(loopIndex, points.Length) && startIdx == points.Length - 1) { return(BezierUtility.EvalTangent(points[startIdx].position, points[startIdx].outTangent, points[loopIndex].inTangent, points[loopIndex].position, t)); } return(BezierUtility.EvalTangent(points[startIdx].position, points[startIdx].outTangent, points[startIdx + 1].inTangent, points[startIdx + 1].position, t)); }
static void SampleCurve(float colliderDetail, Vector3 startPoint, Vector3 startTangent, Vector3 endPoint, Vector3 endTangent, ref List <IntPoint> path) { if (startTangent.sqrMagnitude > 0f || endTangent.sqrMagnitude > 0f) { for (int j = 0; j <= colliderDetail; ++j) { float t = j / (float)colliderDetail; Vector3 newPoint = BezierUtility.BezierPoint(startPoint, startTangent + startPoint, endTangent + endPoint, endPoint, t) * s_ClipperScale; path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y)); } } else { Vector3 newPoint = startPoint * s_ClipperScale; path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y)); newPoint = endPoint * s_ClipperScale; path.Add(new IntPoint((System.Int64)newPoint.x, (System.Int64)newPoint.y)); } }
public float AngleAt(int startIdx, float t) { if (!HasLoop && startIdx >= NumPoints - 1) { Debug.LogError("Invalid startIdx: " + startIdx + " in AngleAt"); } else if (HasLoop && startIdx >= NumPoints) { Debug.LogError("Invalid startIdx: " + startIdx + " in AngleAt"); } if (HasLoop && startIdx == NumPoints - 1) { return(BezierUtility.EvalAngle(points[startIdx].position, points[startIdx].outTangent, points[loopIndex].inTangent, points[loopIndex].position, t)); } return(BezierUtility.EvalAngle(points[startIdx].position, points[startIdx].outTangent, points[startIdx + 1].inTangent, points[startIdx + 1].position, t)); }
private float3 EvalConstantSpeed(ref DynamicBuffer <PathPoint> points, ref float curScale, float speed, int loopIndex) { bool hasLoop = BezierUtility.HasLoop(loopIndex, points.Length); // approx ideal about to move on scale float travelDist = speed * dt; int numSubsteps = 50; int leftIdx = (int)math.floor(curScale); for (int i = 0; i < numSubsteps && BezierUtility.IsInBound(curScale, loopIndex, points.Length); ++i) { float localT = curScale - leftIdx; curScale += travelDist / numSubsteps / math.length( TangentAt(ref points, leftIdx, localT, loopIndex)); leftIdx = (int)math.floor(curScale); } // outside curve, return position of last point if (!hasLoop && curScale >= points.Length - 1) { return(points[points.Length - 1].position); } // looping and beyond loop point, reset as if at loop point else if (hasLoop && curScale >= points.Length) { curScale -= points.Length; curScale += loopIndex; leftIdx = (int)math.floor(curScale); return(EvalAt(ref points, leftIdx, curScale - leftIdx, loopIndex)); } // still inside curve else { return(EvalAt(ref points, leftIdx, curScale - leftIdx, loopIndex)); } }
private void HandleInsertPointToEdge() { EventType eventType = currentEvent.GetTypeForControl(m_DragPointControlId); if (m_HoveredPointIndex == -1 && m_HoveredEdgeIndex != -1 && GUIUtility.hotControl == 0 && eventType == EventType.MouseDown && currentEvent.button == 0 && !currentEvent.shift) { RecordUndo(); ClearSelection(); int nextIndex = SplineUtility.NextIndex(m_HoveredEdgeIndex, GetPointCount()); TangentMode leftTangentMode = GetTangentMode(m_HoveredEdgeIndex); TangentMode rightTangentMode = GetTangentMode(nextIndex); Vector3 leftStartPosition; Vector3 leftEndPosition; Vector3 leftStartTangent; Vector3 leftEndTangent; Vector3 rightStartPosition; Vector3 rightEndPosition; Vector3 rightStartTangent; Vector3 rightEndTangent; Vector3 position0 = GetPosition(m_HoveredEdgeIndex); Vector3 position1 = GetPosition(nextIndex); Vector3 tangent0 = GetRightTangent(m_HoveredEdgeIndex) + position0; Vector3 tangent1 = GetLeftTangent(nextIndex) + position1; BezierUtility.SplitBezier(m_ClosestPointT, position0, position1, tangent0, tangent1, out leftStartPosition, out leftEndPosition, out leftStartTangent, out leftEndTangent, out rightStartPosition, out rightEndPosition, out rightStartTangent, out rightEndTangent); if (leftTangentMode != TangentMode.Linear) { SetTangentMode(m_HoveredEdgeIndex, TangentMode.Broken); SetRightTangent(m_HoveredEdgeIndex, leftStartTangent - leftStartPosition); } if (rightTangentMode != TangentMode.Linear) { SetTangentMode(nextIndex, TangentMode.Broken); SetLeftTangent(nextIndex, rightEndTangent - rightEndPosition); } InsertPointAt(nextIndex, m_ClosestPoint); if (leftTangentMode != TangentMode.Linear || rightTangentMode != TangentMode.Linear) { SetTangentMode(nextIndex, TangentMode.Broken); if (m_ClosestPointT == 0.5f) { SetTangentMode(nextIndex, TangentMode.Continuous); } SetLeftTangent(nextIndex, leftEndTangent - leftEndPosition); SetRightTangent(nextIndex, rightStartTangent - rightStartPosition); } m_HoveredPointIndex = nextIndex; m_HoveredEdgeIndex = -1; HandleUtility.nearestControl = m_DragPointControlId; } }
public Vector2 GetPointAlongCurve(float progress) { var s = curve.spline; return(curve.transform.TransformPoint(BezierUtility.BezierPoint(s.GetPosition(0), s.GetPosition(0) + s.GetRightTangent(0), s.GetPosition(1) + s.GetLeftTangent(1), s.GetPosition(1), progress))); }