//Derivative at point t public float ExactDerivative(float t) { MyVector3 A = posA; MyVector3 B = handle; MyVector3 C = posB; //Layer 1 //(1-t)A + tB = A - At + Bt //(1-t)B + tC = B - Bt + Ct //Layer 2 //(1-t)(A - At + Bt) + t(B - Bt + Ct) //A - At + Bt - At + At^2 - Bt^2 + Bt - Bt^2 + Ct^2 //A - 2At + 2Bt + At^2 - 2Bt^2 + Ct^2 //A - t(2(A - B)) + t^2(A - 2B + C) //Derivative: -(2(A - B)) + t(2(A - 2B + C)) MyVector3 derivativeVector = t * (2f * (A - 2f * B + C)); derivativeVector += -2f * (A - B); float derivative = MyVector3.Magnitude(derivativeVector); return(derivative); }
// // Derivative // public override float GetDerivative(float t) { MyVector3 derivativeVec = GetDerivativeVec(posA, posB, handleA, handleB, t); float derivative = MyVector3.Magnitude(derivativeVec); return(derivative); }
// // Calculate the area of a triangle in 3d space // //https://math.stackexchange.com/questions/128991/how-to-calculate-the-area-of-a-3d-triangle public static float CalculateTriangleArea(MyVector3 p1, MyVector3 p2, MyVector3 p3) { MyVector3 normal = CalculateTriangleNormal(p1, p2, p3, shouldNormalize: false); float parallelogramArea = MyVector3.Magnitude(normal); float triangleArea = parallelogramArea * 0.5f; return(triangleArea); }
// // Derivative at point t // public override float GetDerivative(float t) { //Alternative 1. Estimated //float derivative = InterpolationHelpMethods.EstimateDerivative(this, t); //Alternative 2. Exact MyVector3 derivativeVec = GetDerivativeVec(posA, posB, handlePos, t); float derivative = MyVector3.Magnitude(derivativeVec); return(derivative); }
// // Alternative 3. Rotation Minimising Frame (also known as "Parallel Transport Frame" or "Bishop Frame") // //Gets its stability by incrementally rotating a coordinate system (= frame) as it is translate along the curve //Has to be computed for the entire curve because we need the previous frame (previousTransform) belonging to a point before this point //Is initalized by using "Fixed Up" or "Frenet Normal" public static MyQuaternion GetOrientation_RotationFrame(MyVector3 position, MyVector3 tangent, InterpolationTransform previousTransform) { /* * //This version is from https://pomax.github.io/bezierinfo/#pointvectors3d * //Reflect the known frame onto the next point, by treating the plane through the curve at the point exactly between the next and previous points as a "mirror" * MyVector3 v1 = position - previousTransform.position; * * float c1 = MyVector3.Dot(v1, v1); * * MyVector3 riL = previousTransform.Right - v1 * (2f / c1) * MyVector3.Dot(v1, previousTransform.Right); * * MyVector3 tiL = previousTransform.Forward - v1 * (2f / c1) * MyVector3.Dot(v1, previousTransform.Forward); * * //This gives the next point a tangent vector that's essentially pointing in the opposite direction of what it should be, and a normal that's slightly off-kilter * //reflect the vectors of our "mirrored frame" a second time, but this time using the plane through the "next point" itself as "mirror". * MyVector3 v2 = tangent - tiL; * * float c2 = MyVector3.Dot(v2, v2); * * //Now we can calculate the normal and right vector belonging to this orientation * MyVector3 right = riL - v2 * (2f / c2) * MyVector3.Dot(v2, riL); * * //The source has right x tangent, but then every second normal is flipped * MyVector3 normal = MyVector3.Cross(tangent, right); * * MyQuaternion orientation = new MyQuaternion(tangent, normal); */ //This version is from Game Programming Gems 2: The Parallel Transport Frame //They generate the same result and this one is easier to understand //The two tangents MyVector3 T1 = previousTransform.Forward; MyVector3 T2 = tangent; //You move T1 to the new position, so A is a vector going from the new position MyVector3 A = MyVector3.Cross(T1, T2); //This is the angle between T1 and T2 float alpha = Mathf.Acos(MyVector3.Dot(T1, T2) / (MyVector3.Magnitude(T1) * MyVector3.Magnitude(T2))); //Now rotate the previous frame around axis A with angle alpha MyQuaternion F1 = previousTransform.orientation; MyQuaternion F2 = MyQuaternion.RotateQuaternion(F1, alpha * Mathf.Rad2Deg, A); MyQuaternion orientation = F2; return(orientation); }
// // Estimate the derivative at point t // //https://www.youtube.com/watch?v=pHMzNW8Agq4 public static float EstimateDerivative(Curve curve, float t) { //We can estimate the derivative by taking a step in each direction of the point we are interested in //Should be around this number float derivativeStepSize = 0.0001f; MyVector3 valueMinus = curve.GetInterpolatedValue(t - derivativeStepSize); MyVector3 valuePlus = curve.GetInterpolatedValue(t + derivativeStepSize); //Have to multiply by two because we are taking a step in each direction MyVector3 derivativeVector = (valuePlus - valueMinus) * (1f / (derivativeStepSize * 2f)); float derivative = MyVector3.Magnitude(derivativeVector); return(derivative); }
// // Calculate the center of circle in 3d space given three coordinates // //From https://gamedev.stackexchange.com/questions/60630/how-do-i-find-the-circumcenter-of-a-triangle-in-3d public static MyVector3 CalculateCircleCenter(MyVector3 a, MyVector3 b, MyVector3 c) { MyVector3 ac = c - a; MyVector3 ab = b - a; MyVector3 abXac = MyVector3.Cross(ab, ac); //This is the vector from a to the circumsphere center MyVector3 toCircumsphereCenter = MyVector3.Cross(abXac, ab) * Mathf.Pow(MyVector3.Magnitude(ac), 2f); toCircumsphereCenter += MyVector3.Cross(ac, abXac) * Mathf.Pow(MyVector3.Magnitude(ab), 2f); toCircumsphereCenter *= (1f / (2f * Mathf.Pow(MyVector3.Magnitude(abXac), 2f))); float circumsphereRadius = MyVector3.Magnitude(toCircumsphereCenter); //The circumsphere center becomes MyVector3 ccs = a + toCircumsphereCenter; return(ccs); }
//Actual derivative at point t public float ExactDerivative(float t) { MyVector3 A = posA; MyVector3 B = handleA; MyVector3 C = handleB; MyVector3 D = posB; //Layer 1 //(1-t)A + tB = A - At + Bt //(1-t)B + tC = B - Bt + Ct //(1-t)C + tD = C - Ct + Dt //Layer 2 //(1-t)(A - At + Bt) + t(B - Bt + Ct) = A - At + Bt - At + At^2 - Bt^2 + Bt - Bt^2 + Ct^2 = A - 2At + 2Bt + At^2 - 2Bt^2 + Ct^2 //(1-t)(B - Bt + Ct) + t(C - Ct + Dt) = B - Bt + Ct - Bt + Bt^2 - Ct^2 + Ct - Ct^2 + Dt^2 = B - 2Bt + 2Ct + Bt^2 - 2Ct^2 + Dt^2 //Layer 3 //(1-t)(A - 2At + 2Bt + At^2 - 2Bt^2 + Ct^2) + t(B - 2Bt + 2Ct + Bt^2 - 2Ct^2 + Dt^2) //A - 2At + 2Bt + At^2 - 2Bt^2 + Ct^2 - At + 2At^2 - 2Bt^2 - At^3 + 2Bt^3 - Ct^3 + Bt - 2Bt^2 + 2Ct^2 + Bt^3 - 2Ct^3 + Dt^3 //A - 3At + 3Bt + 3At^2 - 6Bt^2 + 3Ct^2 - At^3 + 3Bt^3 - 3Ct^3 + Dt^3 //A - 3t(A - B) + t^2(3A - 6B + 3C) + t^3(-A + 3B - 3C + D) //A - 3t(A - B) + t^2(3(A - 2B + C)) + t^3(-(A - 3(B - C) - D) //The derivative: -3(A - B) + 2t(3(A - 2B + C)) + 3t^2(-(A - 3(B - C) - D) //-3(A - B) + t(6(A - 2B + C)) + t^2(-3(A - 3(B - C) - D) MyVector3 derivativeVector = t * t * (-3f * (A - 3f * (B - C) - D)); derivativeVector += t * (6f * (A - 2f * B + C)); derivativeVector += -3f * (A - B); float derivative = MyVector3.Magnitude(derivativeVector); return(derivative); }