//Display curve with high resolution, which is useful if we want to compare the actual curve with a curve split into steps //Unity has built-in Handles.DrawBezier but doesn't exist for other curve types public static void DisplayCurve(_Curve curve, Color color) { int steps = 200; List <MyVector3> positionsOnCurve = InterpolationHelpMethods.SplitCurve(curve, steps, tEnd: 1f); List <Vector3> positionsOnCurveStandardized = positionsOnCurve.ConvertAll(x => x.ToVector3()); DisplayCurve(positionsOnCurveStandardized, false, color, false); }
private void BezierCubicEqualSteps(MyVector3 posA, MyVector3 posB, MyVector3 handleA, MyVector3 handleB) { //Store the interpolated values so we later can display them List <Vector3> actualPositions = new List <Vector3>(); //Create a curve which is the data structure used in the following calculations BezierCubic bezierCubic = new BezierCubic(posA, posB, handleA, handleB); //Step 1. Calculate the length of the entire curve //This is needed to so we know how long we should walk each step float lengthNaive = InterpolationHelpMethods.GetLength_Naive(bezierCubic, steps: 20, tEnd: 1f); float lengthExact = InterpolationHelpMethods.GetLength_SimpsonsRule(bezierCubic, tStart: 0f, tEnd: 1f); Debug.Log("Naive length: " + lengthNaive + " Exact length: " + lengthExact); int steps = 5; //Important not to confuse this with the step size we use to iterate t //This step size is distance in m float length = lengthNaive; float lengthStepSize = length / (float)steps; float stepSize = 1f / (float)steps; float t = 0f; float distanceTravelled = 0f; for (int i = 0; i < steps + 1; i++) { //MyVector3 inaccuratePos = bezierCubic.GetInterpolatedValue(t); //Calculate t to get to this distance //Method 1 //float actualT = InterpolationHelpMethods.Find_t_FromDistance_Iterative(bezierCubic, distanceTravelled, length); //Method 2 float actualT = InterpolationHelpMethods.Find_t_FromDistance_Lookup(bezierCubic, distanceTravelled, accumulatedDistances: null); MyVector3 actualPos = bezierCubic.GetInterpolatedValue(actualT); actualPositions.Add(actualPos.ToVector3()); //Test that the derivative calculations are working float dEst = InterpolationHelpMethods.EstimateDerivative(bezierCubic, t); float dAct = bezierCubic.ExactDerivative(t); Debug.Log("Estimated derivative: " + dEst + " Actual derivative: " + dAct); //Debug.Log("Distance " + distanceTravelled); //Move on to next iteration distanceTravelled += lengthStepSize; t += stepSize; } //List<MyVector3> positionsOnCurve = InterpolationHelpMethods.SplitCurve(bezierCubic, 20, tEnd: 1f); //foreach (MyVector3 p in positionsOnCurve) //{ // Gizmos.DrawWireSphere(p.ToVector3(), 0.1f); //} DisplayInterpolatedValues(actualPositions, useRandomColor: true); //Display the start and end values and the handle points DisplayHandle(handleA.ToVector3(), posA.ToVector3()); DisplayHandle(handleB.ToVector3(), posB.ToVector3()); //Display the actual Bezier cubic for reference Handles.DrawBezier(posA.ToVector3(), posB.ToVector3(), handleA.ToVector3(), handleB.ToVector3(), Color.blue, EditorGUIUtility.whiteTexture, 1f); }
private void BezierCubicTest_EqualSteps(MyVector3 posA, MyVector3 posB, MyVector3 handleA, MyVector3 handleB) { //Create a curve which is the data structure used in the following calculations BezierCubic bezierCubic = new BezierCubic(posA, posB, handleA, handleB); //Step 1. Calculate the length of the entire curve //This is needed so we know for how long we should walk each step float lengthNaive = InterpolationHelpMethods.GetLength_Naive(bezierCubic, steps: 20, tEnd: 1f); float lengthExact = InterpolationHelpMethods.GetLength_SimpsonsRule(bezierCubic, tStart: 0f, tEnd: 1f); //Debug.Log("Naive length: " + lengthNaive + " Exact length: " + lengthExact); //Step 2. Convert the t's to be percentage along the curve //Save the accurate t at each position on the curve List <float> accurateTs = new List <float>(); //The number of sections we want to divide the curve into int steps = 20; //Important not to confuse this with the step size we use to iterate t //This step size is distance in m float curveLength = lengthNaive; float curveLength_stepSize = curveLength / (float)steps; float t_stepSize = 1f / (float)steps; float t = 0f; float distanceTravelled = 0f; for (int i = 0; i < steps + 1; i++) { //MyVector3 inaccuratePos = bezierCubic.GetPosition(t); //Calculate the t needed to get to this distance along the curve //Method 1 //float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Iterative(bezierCubic, distanceTravelled, length); //Method 2 float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Lookup(bezierCubic, distanceTravelled, accumulatedDistances: null); accurateTs.Add(accurateT); //Debug.Log(accurateT); //Test that the derivative calculations are working //float dEst = InterpolationHelpMethods.EstimateDerivative(bezierCubic, t); //float dAct = bezierCubic.ExactDerivative(t); //Debug.Log("Estimated derivative: " + dEst + " Actual derivative: " + dAct); //Debug.Log("Distance " + distanceTravelled); //Move on to next iteration distanceTravelled += curveLength_stepSize; t += t_stepSize; } //Step3. Use the new t's to get information from the curve //The interpolated positions List <Vector3> actualPositions = new List <Vector3>(); //Save the tangent at each position on the curve List <Vector3> tangents = new List <Vector3>(); //Save the orientation, which includes the tangent //List<InterpolationTransform> orientations = new List<InterpolationTransform>(); for (int i = 0; i < accurateTs.Count; i++) { float accurateT = accurateTs[i]; //Position on the curve MyVector3 actualPos = bezierCubic.GetPosition(accurateT); actualPositions.Add(actualPos.ToVector3()); //Tangent at each position MyVector3 tangentDir = BezierCubic.GetTangent(posA, posB, handleA, handleB, accurateT); tangents.Add(tangentDir.ToVector3()); //Orientation, which includes both position and tangent //InterpolationTransform orientation = InterpolationTransform.GetTransform(bezierCubic, accurateT); //orientations.Add(orientation); } //The orientation at each t position MyVector3 startUpRef = MyVector3.Up; List <InterpolationTransform> orientationsFrames = InterpolationTransform.GetTransforms_RotationMinimisingFrame(bezierCubic, accurateTs, startUpRef); //Display stuff //The curve which is split into steps //DisplayInterpolation.DisplayCurve(actualPositions, useRandomColor: true); DisplayInterpolation.DisplayCurve(actualPositions, Color.gray); //The start and end values and the handle points DisplayInterpolation.DisplayHandle(handleA.ToVector3(), posA.ToVector3()); DisplayInterpolation.DisplayHandle(handleB.ToVector3(), posB.ToVector3()); //The actual Bezier cubic for reference DisplayInterpolation.DisplayCurve(bezierCubic, Color.black); //Handles.DrawBezier(posA.ToVector3(), posB.ToVector3(), handleA.ToVector3(), handleB.ToVector3(), Color.black, EditorGUIUtility.whiteTexture, 1f); //The tangents //DisplayInterpolation.DisplayDirections(actualPositions, tangents, 1f, Color.red); //The orientation //DisplayInterpolation.DisplayOrientations(orientations, 1f); DisplayInterpolation.DisplayOrientations(orientationsFrames, 1f); //Extrude mesh along the curve //InterpolationTransform testTrans = orientationsFrames[1]; //MyVector3 pos = testTrans.LocalToWorld(MyVector3.Up * 2f); //MyVector3 pos = testTrans.LocalToWorld(MyVector3.Right * 2f); //Gizmos.DrawSphere(pos.ToVector3(), 0.1f); //DisplayInterpolation.DisplayExtrudedMesh(orientationsFrames, meshProfile); }
private void BezierQuadraticTest_EqualSteps(MyVector3 posA, MyVector3 posB, MyVector3 handle) { //Create a curve which is the data structure used in the following calculations BezierQuadratic bezierQuadratic = new BezierQuadratic(posA, posB, handle); //Step 1. Calculate the length of the entire curve //This is needed to so we know how long we should walk each step float lengthNaive = InterpolationHelpMethods.GetLength_Naive(bezierQuadratic, steps: 20, tEnd: 1f); float lengthExact = InterpolationHelpMethods.GetLength_SimpsonsRule(bezierQuadratic, tStart: 0f, tEnd: 1f); //Debug.Log("Naive length: " + lengthNaive + " Exact length: " + lengthExact); //Step 2. Convert the t's to be percentage along the curve //Save the accurate t at each position on the curve List <float> accurateTs = new List <float>(); int steps = 5; //Important not to confuse this with the step size we use to iterate t //This step size is distance in m float length = lengthNaive; float lengthStepSize = length / (float)steps; float stepSize = 1f / (float)steps; float t = 0f; float distanceTravelled = 0f; for (int i = 0; i < steps + 1; i++) { //MyVector3 inaccuratePos = bezierCubic.GetInterpolatedValue(t); //Calculate t to get to this distance //Method 1 //float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Iterative(bezierQuadratic, distanceTravelled, length); //Method 2 float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Lookup(bezierQuadratic, distanceTravelled, accumulatedDistances: null); accurateTs.Add(accurateT); //Test that the derivative calculations are working //float dEst = InterpolationHelpMethods.EstimateDerivative(bezierQuadratic, t); //float dAct = bezierQuadratic.GetDerivative(t); //Debug.Log("Estimated derivative: " + dEst + " Actual derivative: " + dAct); //Debug.Log("Distance " + distanceTravelled); //Move on to next iteration distanceTravelled += lengthStepSize; t += stepSize; } //Get the data we want from the curve //Store the interpolated values so we later can display them List <Vector3> actualPositions = new List <Vector3>(); // List <Vector3> tangents = new List <Vector3>(); //Orientation, which includes the tangent and position List <InterpolationTransform> orientations = new List <InterpolationTransform>(); for (int i = 0; i < accurateTs.Count; i++) { float accurateT = accurateTs[i]; MyVector3 actualPos = bezierQuadratic.GetPosition(accurateT); actualPositions.Add(actualPos.ToVector3()); MyVector3 tangent = bezierQuadratic.GetTangent(accurateT); tangents.Add(tangent.ToVector3()); //Orientation, which includes both position and tangent InterpolationTransform orientation = InterpolationTransform.GetTransform_UpRef(bezierQuadratic, accurateT, MyVector3.Up); orientations.Add(orientation); } //Display //Unity doesnt have a built-in method to display an accurate Qudratic bezier, so we have to create our own //DisplayInterpolation.DisplayBezierQuadratic(bezierQuadratic, Color.black); DisplayInterpolation.DisplayCurve(bezierQuadratic, Color.black); //DisplayInterpolation.DisplayCurve(actualPositions, useRandomColor: true); DisplayInterpolation.DisplayCurve(actualPositions, Color.gray); //Display the start and end values and the handle points DisplayInterpolation.DisplayHandle(handle.ToVector3(), posA.ToVector3()); DisplayInterpolation.DisplayHandle(handle.ToVector3(), posB.ToVector3()); //Stuff on the curve //DisplayInterpolation.DisplayDirections(actualPositions, tangents, 1f, Color.red); DisplayInterpolation.DisplayOrientations(orientations, 1f); }