'How to scale a Bezier Curves t value while keeping its initial and final derivatives the same?
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.
Solution 1:[1]
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);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | local idiot |