private List <OrientedPoint> GetPath() { var path = new List <OrientedPoint>(); for (float t = 0; t < spline.nodes.Count - 1; t += 1 / 10.0f) { var point = spline.GetLocationAlongSpline(t); var rotation = CubicBezierCurve.GetRotationFromTangent(spline.GetTangentAlongSpline(t)); path.Add(new OrientedPoint(point, rotation)); } return(path); }
public void TestPathDeform() { IMesh geom = new TextMesh("Hello World"); var curve = new CubicBezierCurve(new Vec3(0, 0, 1), new Vec3(2, 0, 0), new Vec3(9, 0, 0), new Vec3(11, 0, 1)); geom = new Geometry.Modifiers.PathDeform(Vec3.I, curve, geom); MeshGroup group = new MeshGroup(); group.Add(geom); SaveGeometry("pathdeform.modifier", group); }
/// <summary> /// Adds a node at the end of the spline. /// </summary> /// <param name="node"></param> public void AddNode(SplineNode node) { nodes.Add(node); if (nodes.Count != 1) { SplineNode previousNode = nodes[nodes.IndexOf(node) - 1]; CubicBezierCurve curve = new CubicBezierCurve(previousNode, node); curve.Changed.AddListener(() => UpdateAfterCurveChanged()); curves.Add(curve); } RaiseNodeCountChanged(); UpdateAfterCurveChanged(); }
/// <summary> /// Set the cubic Bézier curve to use to bend the source mesh, and begin to listen to curve control points for changes. /// </summary> /// <param name="curve"></param> /// <param name="update">If let to true, update the resulting mesh immediatly.</param> public void SetCurve(CubicBezierCurve curve, bool update = true) { if (this.curve != null) { this.curve.Changed.RemoveListener(() => Compute()); } this.curve = curve; curve.Changed.AddListener(() => Compute()); if (update) { Compute(); } }
public static void Animate(double duration, nfloat delay, CubicBezierCurve curve, Action changes, Action completion = null) { var propertyAnimator = new UIViewPropertyAnimator(duration, curve.ToCubicTimingParameters()); propertyAnimator.AddAnimations(changes, delay); if (completion != null) { propertyAnimator.AddCompletion(_ => completion()); } propertyAnimator.StartAnimation(); }
//Высчитывает приблизительную длину кубической кривой Безье public float ApproximateLineLength(CubicBezierCurve curve) { float length = 0f; Vector3 point1 = curve.p0; Vector3 point2; for (float i = 0.05f; i < 1f; i += 0.05f) { point2 = CalculateBezierPoint(i, curve); length += Vector3.Distance(point1, point2); point1 = point2; } return(length); }
//Возвращает следующий сегмент кубической кривой Безье, //Зависящий от предыдущего public CubicBezierCurve NextDots(CubicBezierCurve oldSettings, Vector3 nextPosition, EnemyBoundaries boundaries) { CubicBezierCurve cubicCurve = new CubicBezierCurve(); cubicCurve.p0 = oldSettings.p3; cubicCurve.p1 = oldSettings.p2; cubicCurve.p3 = nextPosition; cubicCurve.p2 = GenerationMath.RandomPositionInCylinder( cubicCurve.p3, Vector3.Distance(cubicCurve.p0, nextPosition), boundaries); return(cubicCurve); }
private void OnEnable() { curves.Clear(); for (int i = 0; i < nodes.Count - 1; i++) { SplineNode n = nodes[i]; SplineNode next = nodes[i + 1]; CubicBezierCurve curve = new CubicBezierCurve(n, next); curve.Changed.AddListener(() => UpdateAfterCurveChanged()); curves.Add(curve); } RaiseNodeCountChanged(); UpdateAfterCurveChanged(); }
/// <summary> /// Initialize the default values. /// </summary> private void Awake() { if (m_ControlPoints == null || m_ControlPoints.Length <= 1) { return; } m_Curve = new CubicBezierCurve[(m_ControlPoints.Length / 3)]; for (int i = 0; i < m_Curve.Length; ++i) { var startIndex = i * 3; m_Curve[i] = new CubicBezierCurve(transform.TransformPoint(m_ControlPoints[startIndex]), transform.TransformPoint(m_ControlPoints[startIndex + 1]), transform.TransformPoint(m_ControlPoints[startIndex + 2]), transform.TransformPoint(m_ControlPoints[startIndex + 3])); } }
private void InitializeAnimator() { _animator = new Animator(); CubicBezierCurve c = new CubicBezierCurve(new PointF(0, 0), new PointF(0.5f, 0f), new PointF(.5f, 1f), new PointF(1, 1)); _animator.PointFromDistanceFunction = c.GetPointOnCurve; _animator.Duration = 200; // 750; _animator.FrameRate = 30; _animator.SpeedFunction = Animator.SpeedFunctions.SinSpeed; _animator.Animate += OnAnimator_Animate; _animator.Finished += OnAnimator_Finished; }
//Возвращает четыре точки, нужные для построения кубической кривой Безье public CubicBezierCurve CreateCubicLineDots(Vector3 startPosition, Vector3 finishPosition, EnemyBoundaries boundaries) { CubicBezierCurve cubicCurve = new CubicBezierCurve(); cubicCurve.p0 = startPosition; cubicCurve.p1 = GenerationMath.RandomPositionInCylinder( startPosition, Vector3.Distance(startPosition, finishPosition), boundaries); cubicCurve.p3 = finishPosition; cubicCurve.p2 = GenerationMath.RandomPositionInCylinder( finishPosition, Vector3.Distance(startPosition, finishPosition), boundaries); return(cubicCurve); }
// Similar to GetPoint but returns the tangent at the specified point on the path. The tangent is not normalized. // The longer the tangent the 'more influence' it has pulling the path in that direction. public Vector3 GetTangent(float t) { // Only closed paths accept t values out of range. if (type == Type.Closed) { while (t < 0.0f) { t += (float)numCurveSegments; } while (t > (float)numCurveSegments) { t -= (float)numCurveSegments; } } else { t = Mathf.Clamp(t, 0.0f, (float)numCurveSegments); } Assert.IsTrue((t >= 0) && (t <= (float)numCurveSegments)); // Segment 0 is for t E [0, 1). The last segment is for t E [NumCurveSegments-1, NumCurveSegments]. // The following 'if' statement deals with the final inclusive bracket on the last segment. The cast must truncate. int segment = (int)t; if (segment >= numCurveSegments) { segment = numCurveSegments - 1; } Vector3[] curveCVs = new Vector3[4]; curveCVs[0] = controlVerts[3 * segment + 0]; curveCVs[1] = controlVerts[3 * segment + 1]; curveCVs[2] = controlVerts[3 * segment + 2]; curveCVs[3] = controlVerts[3 * segment + 3]; CubicBezierCurve bc = new CubicBezierCurve(curveCVs); return(bc.GetTangent(t - (float)segment)); }
/// <summary> /// Insert the given node in the spline at index. Index must be greater than 0 and less than node count. /// </summary> /// <param name="index"></param> /// <param name="node"></param> public void InsertNode(int index, SplineNode node) { if (index == 0) { throw new Exception("Can't insert a node at index 0"); } SplineNode previousNode = nodes[index - 1]; SplineNode nextNode = nodes[index]; nodes.Insert(index, node); curves[index - 1].ConnectEnd(node); CubicBezierCurve curve = new CubicBezierCurve(node, nextNode); curve.Changed.AddListener(() => UpdateAfterCurveChanged()); curves.Insert(index, curve); RaiseNodeCountChanged(); UpdateAfterCurveChanged(); }
// This function returns a single closest point. There may be more than one point on the path at the same distance. // Use ComputeApproxParamPerUnitLength to determine a good paramThreshold. eg. Say you want a 15cm threshold, // use: paramThreshold = ComputeApproxParamPerUnitLength() * 0.15f. public float ComputeClosestParam(Vector3 pos, float paramThreshold) { var minDistSq = float.MaxValue; var closestParam = 0.0f; for (var startIndex = 0; startIndex < controlVerts.Length - 1; startIndex += 3) { var curve = new CubicBezierCurve(controlVerts[startIndex + 0], controlVerts[startIndex + 1], controlVerts[startIndex + 2], controlVerts[startIndex + 3]); var curveClosestParam = curve.GetClosestParam(pos, paramThreshold); var curvePos = curve.GetPoint(curveClosestParam); var distSq = (curvePos - pos).sqrMagnitude; if (distSq < minDistSq) { minDistSq = distSq; var startParam = ((float)startIndex) / 3.0f; closestParam = startParam + curveClosestParam; } } return(closestParam); }
internal static void DoCurveField(Rect position, CubicBezierCurve curve, Color color, SerializedProperty property) { int id = GUIUtility.GetControlID(EditorGUIUtility.native, position); Event current = Event.current; position.width = Mathf.Max(position.width, 2f); position.height = Mathf.Max(position.height, 2f); //TODO - update open curve editor window EventType typeForControl = current.GetTypeForControl(id); switch (typeForControl) { case EventType.KeyDown: break; case EventType.Repaint: Rect position1 = position; ++position1.y; --position1.height; SPEditorGUI.DrawCurveSwatch(position1, curve, color, Color.gray); //EditorStyles.colorPickerBox.Draw(position1, GUIContent.none, id, false); break; case EventType.mouseDown: if (position.Contains(current.mousePosition)) { //TODO - show CubicBezierCurveEditorWindow current.Use(); GUIUtility.ExitGUI(); } break; } }
/// <summary> /// Remove the given node from the spline. The given node must exist and the spline must have more than 2 nodes. /// </summary> /// <param name="node"></param> public void RemoveNode(SplineNode node) { int index = nodes.IndexOf(node); if (nodes.Count <= 2) { throw new Exception("Can't remove the node because a spline needs at least 2 nodes."); } CubicBezierCurve toRemove = index == nodes.Count - 1? curves[index - 1] : curves[index]; if (index != 0 && index != nodes.Count - 1) { SplineNode nextNode = nodes[index + 1]; curves[index - 1].ConnectEnd(nextNode); } nodes.RemoveAt(index); toRemove.Changed.RemoveListener(() => UpdateAfterCurveChanged()); curves.Remove(toRemove); RaiseNodeCountChanged(); UpdateAfterCurveChanged(); }
private void Create() { RemoveThumbs(); // Create Move (M) command if this is the first token if (!CurrentFigure.Tokens.Any()) { CurrentFigure.Tokens.Add( new Move( Cache.MouseDownPoint.X - 50.0, Cache.MouseDownPoint.Y + 50.0)); } if (StartWithMove && !(CurrentFigure.Tokens.Last() is Move)) { CurrentFigure.Tokens.Add( new Move( Cache.MouseDownPoint.X - 50.0, Cache.MouseDownPoint.Y + 50.0)); } // Token which will be created Token token = null; // Depending on command create corresponding token if (CreateCommand == VDCanvasCommand.CreateLine) { token = new Line(Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y - 50.0); } else if (CreateCommand == VDCanvasCommand.CreateCubicCurve) { token = new CubicBezierCurve( Cache.MouseDownPoint.X - 50.0, Cache.MouseDownPoint.Y, Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y, Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y - 50.0); } else if (CreateCommand == VDCanvasCommand.CreateQuadraticCurve) { token = new QuadraticBezierCurve( Cache.MouseDownPoint.X, Cache.MouseDownPoint.Y, Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y - 50.0); } else if (CreateCommand == VDCanvasCommand.CreateSmoothCubicCurve) { token = new SmoothCubicBezierCurve( Cache.MouseDownPoint.X, Cache.MouseDownPoint.Y, Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y - 50.0); } else if (CreateCommand == VDCanvasCommand.CreateSmoothQuadraticCurve) { token = new SmoothQuadraticBezierCurve( Cache.MouseDownPoint.X, Cache.MouseDownPoint.Y, Cache.MouseDownPoint.X + 50.0, Cache.MouseDownPoint.Y - 50.0); } else if (CreateCommand == VDCanvasCommand.CreateClose) { token = new Close(); } // Add just created token to the figure CurrentFigure.Tokens.Add(token); // Depending on Shift key status continue to create elements if (Keyboard.GetKeyStates(Key.LeftShift) != KeyStates.Down) { Edit(token); } else { GoToCreateMode(); } InvalidateMeasure(); }
public static void Animate(double duration, CubicBezierCurve curve, Action changes, Action completion = null, CancellationToken?cancellationToken = null) => Animate(duration, 0.0f, curve, changes, completion, cancellationToken);
public static UICubicTimingParameters ToCubicTimingParameters(this CubicBezierCurve self) => new UICubicTimingParameters( new CGPoint(self.P0, self.P1), new CGPoint(self.P2, self.P3) );
public static CAMediaTimingFunction ToMediaTimingFunction(this CubicBezierCurve self) => new CAMediaTimingFunction(self.P0, self.P1, self.P2, self.P3);
public Vector3 GetPoint(float t) { return(transform.TransformPoint(CubicBezierCurve.GetPoint(controlPoints[0], controlPoints[1], controlPoints[2], controlPoints[3], t))); }
private void Compute() { if (source == null) { return; } int nbVert = source.vertices.Length; // find the bounds along x float minX = float.MaxValue; float maxX = float.MinValue; foreach (Vertex vert in vertices) { Vector3 p = vert.v; if (sourceRotation != Quaternion.identity) { p = sourceRotation * p; } if (sourceTranslation != Vector3.zero) { p += sourceTranslation; } maxX = Math.Max(maxX, p.x); minX = Math.Min(minX, p.x); } float length = Math.Abs(maxX - minX); List <Vector3> deformedVerts = new List <Vector3>(nbVert); List <Vector3> deformedNormals = new List <Vector3>(nbVert); // for each mesh vertex, we found its projection on the curve foreach (Vertex vert in vertices) { Vector3 p = vert.v; Vector3 n = vert.n; // application of rotation if (sourceRotation != Quaternion.identity) { p = sourceRotation * p; n = sourceRotation * n; } if (sourceTranslation != Vector3.zero) { p += sourceTranslation; } float distanceRate = Math.Abs(p.x - minX) / length; Vector3 curvePoint = curve.GetLocationAtDistance(curve.Length * distanceRate); Vector3 curveTangent = curve.GetTangentAtDistance(curve.Length * distanceRate); Quaternion q = CubicBezierCurve.GetRotationFromTangent(curveTangent) * Quaternion.Euler(0, -90, 0); // application of scale float scaleAtDistance = startScale + (endScale - startScale) * distanceRate; p *= scaleAtDistance; // application of roll float rollAtDistance = startRoll + (endRoll - startRoll) * distanceRate; p = Quaternion.AngleAxis(rollAtDistance, Vector3.right) * p; n = Quaternion.AngleAxis(rollAtDistance, Vector3.right) * n; // reset X value of p p = new Vector3(0, p.y, p.z); deformedVerts.Add(q * p + curvePoint); deformedNormals.Add(q * n); } result.vertices = deformedVerts.ToArray(); result.normals = deformedNormals.ToArray(); result.uv = source.uv; result.triangles = source.triangles; GetComponent <MeshFilter>().mesh = result; }
void OnSceneGUI() { Event e = Event.current; if (e.type == EventType.MouseDown) { Undo.RegisterCompleteObjectUndo(se, "change extruded shape"); // if control key pressed, we will have to create a new vertex if position is changed if (e.alt) { mustCreateNewNode = true; } } if (e.type == EventType.MouseUp) { mustCreateNewNode = false; } Vector3 splineStartTangent = se.spline.GetTangentAlongSpline(0); Vector3 splineStart = se.spline.GetLocationAlongSpline(0); Quaternion q = CubicBezierCurve.GetRotationFromTangent(splineStartTangent); foreach (SplineExtrusion.Vertex v in se.ShapeVertices) { // we create point and normal relative to the spline start where the shape is drawn Vector3 point = se.transform.TransformPoint(q * v.point + splineStart); Vector3 normal = se.transform.TransformPoint(q * (v.point + v.normal) + splineStart); if (v == selection) { // draw the handles for selected vertex position and normal float size = HandleUtility.GetHandleSize(point) * 0.3f; float snap = 0.1f; // create a handle for the vertex position Vector3 movedPoint = Handles.Slider2D(0, point, splineStartTangent, Vector3.right, Vector3.up, size, Handles.CircleHandleCap, new Vector2(snap, snap)); if (movedPoint != point) { // position has been moved Vector2 newVertexPoint = Quaternion.Inverse(q) * (se.transform.InverseTransformPoint(movedPoint) - splineStart); if (mustCreateNewNode) { // We must create a new node mustCreateNewNode = false; SplineExtrusion.Vertex newVertex = new SplineExtrusion.Vertex(newVertexPoint, v.normal, v.uCoord); int i = se.ShapeVertices.IndexOf(v); if (i == se.ShapeVertices.Count - 1) { se.ShapeVertices.Add(newVertex); } else { se.ShapeVertices.Insert(i + 1, newVertex); } selection = newVertex; } else { v.point = newVertexPoint; // normal must be updated if point has been moved normal = se.transform.TransformPoint(q * (v.point + v.normal) + splineStart); } se.GenerateMesh(); } else { // vertex position handle hasn't been moved // create a handle for normal Vector3 movedNormal = Handles.Slider2D(normal, splineStartTangent, Vector3.right, Vector3.up, size, Handles.CircleHandleCap, snap); if (movedNormal != normal) { // normal has been moved v.normal = (Vector2)(Quaternion.Inverse(q) * (se.transform.InverseTransformPoint(movedNormal) - splineStart)) - v.point; se.GenerateMesh(); } } Handles.BeginGUI(); DrawQuad(HandleUtility.WorldToGUIPoint(point), CURVE_COLOR); DrawQuad(HandleUtility.WorldToGUIPoint(normal), Color.red); Handles.EndGUI(); } else { // we draw a button to allow selection of the vertex Handles.BeginGUI(); Vector2 p = HandleUtility.WorldToGUIPoint(point); if (GUI.Button(new Rect(p - new Vector2(QUAD_SIZE / 2, QUAD_SIZE / 2), new Vector2(QUAD_SIZE, QUAD_SIZE)), GUIContent.none)) { selection = v; } Handles.EndGUI(); } // draw an arrow from the vertex location to the normal Handles.color = Color.red; Handles.DrawLine(point, normal); // draw a line between that vertex and the next one int index = se.ShapeVertices.IndexOf(v); int nextIndex = index == se.ShapeVertices.Count - 1 ? 0 : index + 1; SplineExtrusion.Vertex next = se.ShapeVertices[nextIndex]; Handles.color = CURVE_COLOR; Vector3 vAtSplineEnd = se.transform.TransformPoint(q * next.point + splineStart); Handles.DrawLine(point, vAtSplineEnd); } }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { EditorGUI.BeginProperty(position, label, property); FieldInfo controllerFieldInfo = fieldInfo.DeclaringType.GetField(fieldInfo.Name + "Controller", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool bIsDirty = false; int indentLevel = EditorGUI.indentLevel; CubicBezierCurve obj = (CubicBezierCurve)fieldInfo.GetValue(property.serializedObject.targetObject); CubicBezierCurveController objController = null; if (controllerFieldInfo != null) { objController = (CubicBezierCurveController)controllerFieldInfo.GetValue(property.serializedObject.targetObject); objController.c = obj; } Rect contentPosition = EditorGUI.PrefixLabel(position, label); contentPosition.width *= .25f; EditorGUIUtility.labelWidth = 40f; EditorGUI.BeginChangeCheck(); bool newLoop = EditorGUI.Toggle(contentPosition, "Loop:", obj.loop); if (EditorGUI.EndChangeCheck()) { bIsDirty = true; Undo.RecordObject(property.serializedObject.targetObject, "Curve Loop Flag Changed"); obj.loop = newLoop; } contentPosition.x += contentPosition.width; EditorGUIUtility.labelWidth = 14f; EditorGUI.SelectableLabel(contentPosition, "l: " + obj.numberOfNodes.ToString()); contentPosition.y += contentPosition.height; EditorGUILayout.BeginVertical(); pointsFoldoutState = EditorGUILayout.Foldout(pointsFoldoutState, "Curve Points:"); if (pointsFoldoutState) { EditorGUI.indentLevel++; int buttonPanelWidth = 40 + (objController != null ? 40 : 0); for (int i = 0; i < obj.p.Length; i++) { Rect dataRect = GUILayoutUtility.GetRect(0, float.MaxValue, EditorGUIUtility.singleLineHeight, EditorGUIUtility.singleLineHeight); Rect leftRect = dataRect; Rect rightRect = dataRect; leftRect.xMax = leftRect.xMin + 48f; dataRect.xMin += 48f; dataRect.xMax -= buttonPanelWidth; rightRect.xMin = rightRect.xMax - buttonPanelWidth; if (i % (obj.chunkSize - 1) == 0) { GUIStyle s = EditorStyles.label; EditorGUI.LabelField(leftRect, "Node"); } vec3 p = MathExGUI.vec3Field(dataRect, null, obj.p[i], false); if (obj.p[i] != p) { if (!bIsDirty) { Undo.RecordObject(property.serializedObject.targetObject, "Curve Point Modified"); } obj.p[i] = p; bIsDirty = true; } Rect addRect = rightRect; Rect removeRect = rightRect; addRect.xMax = addRect.xMax - 20; addRect.xMin = addRect.xMax - 20; removeRect.xMin = removeRect.xMax - 20; if (i % (obj.chunkSize - 1) == 0) { if (objController != null) { Rect modeRect = rightRect; modeRect.xMax = modeRect.xMin + 40; modeRect.xMin -= 10; int currentMode = (int)objController.modes[i / (obj.chunkSize - 1)]; int newMode = EditorGUI.Popup(modeRect, currentMode, modeOptions); if (newMode != currentMode) { bIsDirty = true; Undo.RecordObject(property.serializedObject.targetObject, "Curve Point Mode Changed"); objController.modes[i / (obj.chunkSize - 1)] = (CubicBezierCurveController.CurveMode)newMode; } } if (GUI.Button(addRect, "+")) { bIsDirty = true; Undo.RecordObject(property.serializedObject.targetObject, "Curve Point Added"); int nni = obj.getIndexNode(i); float nnit = obj.getNodeTime(nni); vec3 nni0v = obj.velocity(nnit); int ni = nni - 1; float nit = ni < 0 ? 0 : obj.getNodeTime(ni); vec3 ni1v = obj.velocity(nit); float init = (nit + nnit) / 2f; float dt = (nnit - nit) / 2f; vec3 inv = obj.value(init); vec3 in0v = inv - obj.velocity(init) * dt; vec3 in1v = inv + obj.velocity(init) * dt; obj.p[obj.getNodeIndex(ni) + 1] = obj.value(nit) + ni1v * dt; obj.p[obj.getNodeIndex(nni) - 1] = obj.value(nnit) - nni0v * dt; if (objController != null) { objController.insert(nni, in0v, inv, in1v); } else { obj.insert(nni, in0v, inv, in1v); } } if (GUI.Button(removeRect, "-")) { bIsDirty = true; Undo.RecordObject(property.serializedObject.targetObject, "Curve Point Removed"); if (objController != null) { objController.remove(i / (obj.chunkSize - 1)); } else { obj.remove(i / (obj.chunkSize - 1)); } } } } EditorGUI.indentLevel--; } EditorGUILayout.EndVertical(); EditorGUI.indentLevel = indentLevel; if (bIsDirty) { fieldInfo.SetValue(property.serializedObject.targetObject, obj); property.serializedObject.ApplyModifiedProperties(); } EditorGUI.EndProperty(); }
protected void calculateMovementParameters(CubicBezierCurve curve) { uniformMotion.Distance = bezierLines.ApproximateLineLength(curve); uniformMotion.Speed = thisEnemy.Speed; uniformMotion.GetTime(); }
/// <summary> /// Smesh goes brrr /// </summary> /// <param name="uv"></param> private void GenerateMesh(Vector2 uv) { // On vide nos listes Mesh.Clear(); vertices.Clear(); triangles.Clear(); normals.Clear(); uv0.Clear(); uv1.Clear(); CubicBezierCurve bezier = GetBezierRepresentation(Space.Self); float curveArcLegth = bezier.GetArcLength(); float tiling = GetTextureAspectRatio(); int edgeCount = Mathf.Max(2, Mathf.RoundToInt(curveArcLegth * RoadChain.trianglesPerSegment)); // 2 triangles minimum sinon kaboom // Generation vertices normales & map texture for (int i = 0; i < edgeCount; ++i) { float t = i / (edgeCount - 1f); OrientedPoint op = bezier.GetOrientedPoint(t); float uv0V = t * tiling; float uv1U = Mathf.Lerp(uv.x, uv.y, t); for (int j = 0; j < RoadChain.mesh2D.VertexCount; ++j) { vertices.Add(op.LocalToWorldPos(RoadChain.mesh2D.vertices[j].point)); normals.Add(op.LocalToWorldVec(RoadChain.mesh2D.vertices[j].normal)); uv0.Add(new Vector2(RoadChain.mesh2D.vertices[j].u, uv0V)); uv1.Add(new Vector2(uv1U, 0)); } } // Generation des triangles for (int i = 0; i < edgeCount - 1; ++i) { int ifv = i * RoadChain.mesh2D.VertexCount; int ipofv = (i + 1) * RoadChain.mesh2D.VertexCount; for (int j = 0; j < RoadChain.mesh2D.LineCount; j += 2) { int t = RoadChain.mesh2D.triangles[j]; int tpo = RoadChain.mesh2D.triangles[j + 1]; triangles.Add(ifv + t); triangles.Add(ipofv + t); triangles.Add(ipofv + tpo); triangles.Add(ifv + t); triangles.Add(ipofv + tpo); triangles.Add(ifv + tpo); } } Mesh.SetVertices(vertices); Mesh.SetTriangles(triangles, 0); Mesh.SetNormals(normals); Mesh.SetUVs(0, uv0); Mesh.SetUVs(1, uv1); Mesh.RecalculateBounds(); MeshCollider collider = GetComponent <MeshCollider>(); collider.sharedMesh = Mesh; }
/// <summary> /// Changes the type of the selected line. /// </summary> /// <param name="value">The value.</param> private void ChangeLineType(object value) { Type type = value as Type; if (type == null) { throw new ArgumentException(); } SelectedLine selectedLine = _selectedLine; if (selectedLine == null) { return; } ILine currLine = selectedLine.Line; Type currLineType = currLine.GetType(); if (type == currLineType) { return; } ILine newLine; if (type == typeof(Line)) { newLine = new Line(currLine.Start, currLine.End); } else if (type == typeof(QuadraticBezierCurve)) { if (currLineType == typeof(Line)) { newLine = new QuadraticBezierCurve( currLine.Start, new LineVector((currLine.Start.Vector + currLine.End.Vector) / 2), currLine.End); } else if (currLineType == typeof(CubicBezierCurve)) { CubicBezierCurve cubic = (CubicBezierCurve)currLine; Vector2 vec = currLine.Start.Vector + (currLine.End.Vector - currLine.Start.Vector) / 2; newLine = new QuadraticBezierCurve( cubic.Start, new LineVector(vec), cubic.End); } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } } else if (type == typeof(CubicBezierCurve)) { if (currLineType == typeof(Line)) { Vector2 vec = (currLine.End.Vector - currLine.Start.Vector) / 3; newLine = new CubicBezierCurve( currLine.Start, new LineVector(currLine.Start.Vector + vec), new LineVector(currLine.Start.Vector + vec + vec), currLine.End); } else if (currLineType == typeof(QuadraticBezierCurve)) { QuadraticBezierCurve quad = (QuadraticBezierCurve)currLine; Vector2 start = quad.Start.Vector; Vector2 end = quad.End.Vector; Vector2 control = quad.ControlPoint.Vector; newLine = new CubicBezierCurve( quad.Start, new LineVector(start + (2f / 3f * (control - start))), new LineVector(end + (2f / 3f * (control - end))), quad.End); } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } Debug.Assert(newLine.GetType() == type, "newLine.GetType() == type"); selectedLine.EdgePart.Lines.Replace(currLine, newLine); _selectedLine = new SelectedLine( selectedLine.Tile, selectedLine.EdgePart, newLine, selectedLine.LineTransform); }
/// <summary> /// Get local point from center curve of pipe at time. /// </summary> /// <param name="time">Time of pipe center curve.</param> /// <returns>Local point on pipe curve at time.</returns> protected override Vector3 GetLocalPoint(float time) { return(CubicBezierCurve.GetPoint(anchor, time)); }
/// <summary> /// Changes the type of the selected line. /// </summary> /// <param name="value">The value.</param> private void ChangeLineType(object value) { Type type = value as Type; if (type == null) throw new ArgumentException(); SelectedLine selectedLine = _selectedLine; if (selectedLine == null) return; ILine currLine = selectedLine.Line; Type currLineType = currLine.GetType(); if (type == currLineType) return; ILine newLine; if (type == typeof(Line)) newLine = new Line(currLine.Start, currLine.End); else if (type == typeof(QuadraticBezierCurve)) { if (currLineType == typeof(Line)) { newLine = new QuadraticBezierCurve( currLine.Start, new LineVector((currLine.Start.Vector + currLine.End.Vector) / 2), currLine.End); } else if (currLineType == typeof(CubicBezierCurve)) { CubicBezierCurve cubic = (CubicBezierCurve) currLine; Vector2 vec = currLine.Start.Vector + (currLine.End.Vector - currLine.Start.Vector) / 2; newLine = new QuadraticBezierCurve( cubic.Start, new LineVector(vec), cubic.End); } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } } else if (type == typeof(CubicBezierCurve)) { if (currLineType == typeof(Line)) { Vector2 vec = (currLine.End.Vector - currLine.Start.Vector) / 3; newLine = new CubicBezierCurve( currLine.Start, new LineVector(currLine.Start.Vector + vec), new LineVector(currLine.Start.Vector + vec + vec), currLine.End); } else if (currLineType == typeof(QuadraticBezierCurve)) { QuadraticBezierCurve quad = (QuadraticBezierCurve) currLine; Vector2 start = quad.Start.Vector; Vector2 end = quad.End.Vector; Vector2 control = quad.ControlPoint.Vector; newLine = new CubicBezierCurve( quad.Start, new LineVector(start + (2f / 3f * (control - start))), new LineVector(end + (2f / 3f * (control - end))), quad.End); } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } } else { throw new NotSupportedException( $"Cannot change a line of type '{currLineType.FullName}' to a line of type '{type.FullName}'."); } Debug.Assert(newLine.GetType() == type, "newLine.GetType() == type"); selectedLine.EdgePart.Lines.Replace(currLine, newLine); _selectedLine = new SelectedLine( selectedLine.Tile, selectedLine.EdgePart, newLine, selectedLine.LineTransform); }
public Vector3 GetCurveVelocity(float t) { return(transform.TransformPoint(CubicBezierCurve.GetCurveRateOfChange(controlPoints[0], controlPoints[1], controlPoints[2], controlPoints[3], t)) - transform.position); }
/// <summary> /// Get point on path curve at time. /// </summary> /// <param name="time">Time of curve.</param> /// <returns>The point on path curve at time.</returns> public override Vector3 GetPoint(float time) { return(transform.TransformPoint(CubicBezierCurve.GetPoint(anchor, time))); }