Home > OS >  How to scale a Bezier Curves t value while keeping its initial and final derivatives the same?
How to scale a Bezier Curves t value while keeping its initial and final derivatives the same?

Time:05-13

there are a lot of answers for scaling a bezier curve's position, but i want to scale its t value. I have found a solution for this, but the problem is once i scale my t value my velocity changes.

By scaling t value i mean scaling the range of t from 0,1 to 0,n The way im doing this currently is dividing whatever increment i use by the maximum t value i need, and converting it into a t with the range of 0,1 curT = deltaTime t = curT/maxT

this leads to my derivatives being incorrect. So they must be corrected by dividing them by MaxT to the power of whatever order derivative

D1 = d1 / MaxT ^ 1
D2 = d2 / MaxT^2

This is due to the formula for velocity and acceleration. Velocity = d/t acceleration = d/t^2

I have derived the formula for initial velocity to be

Vi = 2P1 - 2P2

and because i have initial velocity with some algebra i can derive P2

P2 = Vi/2 - p1

my problem is, this seems to scale incorrectly. If i change my maxT then my initial velocity will change aswell. how do i maintain a initial velocity while changing my scaling factor?

Relevant Code:

public partial struct AccelSimple : IJobEntity
{
    public float delta;
    void Execute(ref PhysicsVelocity velocity, ref BezierCurvePoints curve, ref Rotation rotation)
    {
        float t = curve.curTime / curve.timeScale;

        //calculate velocity at any point on curve
        velocity.Linear =
            (curve.p1 * (-2   2 * t)  
            curve.p2 * (2 - 4 * t)  
            curve.p4 * (2 * t)) / curve.timeScale;

        curve.curTime  = delta;
    }
}
 var handle = Entities.WithAll<FinishedMovementTag>().WithoutBurst().ForEach((Entity e,
         ref BezierCurvePoints curve, ref PatrolIndex index, in DynamicBuffer<PatrolPoints> points,
          in Translation translation, in PhysicsVelocity velocity, in AccelerationSpeed acceleration) =>
        {
            Debug.Log(curve.p4 - translation.Value);

            if (index.value >= points.Length - 1) index.value = 0;
            else index.value  ;

            //due to floating point and physics simulation errors cannot precalculate Curve
            //Starting Point of Curve
            curve.p1 = translation.Value;

            //Velocity of t=0
            curve.p2 = (curve.p1   (velocity.Linear / 2));

            //end position of curve
            curve.p4 = points[index.value].Position;
            
            //rough approximation of length of curve //was hoping this would allow math hacks to get velocity scaling factor
            float mag = Vector3.Magnitude(curve.p1 - curve.p4);

            //Time it should take to get to end of curve
            curve.timeScale = mag / acceleration.value;
            curve.curTime = 0;

            ecb.RemoveComponent(e, typeof(FinishedMovementTag));
            ecb.AddComponent(e, typeof(SimpleAccelTag));
        }).Schedule(this.Dependency);

this is with a second order bezier curve, i could use a third order but i dont really care about the velocity on exit so it seems like an unneccesary constraint.

Im using bezier curves because they model a curve being effected by derivatives of position, which seemed ideal for a physics path, as it has velocity acceleration jerk ect. built in. however to use the physical properties of the curve, i need to scale t up or down by a given degree.

My formula for the most part does exactly what i want it to do, it only fails around connecting 2 curves, and slowing down when a curve extends to far which is likely due to an incorrect formula on my account.

CodePudding user response:

This isn't a general answer, because i believe my use case is quite unique. long story short, it was a math mistake/ factor I didn't consider. I do properly scale my velocity according to time, but while doing that i scale down my velocity significantly. the solution to that is multiply my initial velocity calculation by the amount I scale it down by.

Time = Vector3.mag(p4-p1);

p2 = p1 (initial-velocity * .5f * time);

  • Related