Sagen wir, ich habe eine Bezier curveB(u)
, wenn ich u
Parameter mit einer konstanten Rate erhöht Ich habe keinen costant Geschwindigkeit Bewegung entlang der Kurve erhalten, da die Beziehung zwischen u
Parameter und dem Punkt Die Auswertung der Kurve ist nicht linear.Bezier Cubic Kurven: mit gleichmäßiger Beschleunigung bewegen
Ich habe gelesen und implementiert ein David Eberly article. Es erklärt, wie man sich mit konstanter Geschwindigkeit entlang einer parametrischen Kurve bewegt.
glaube, ich habe eine Funktion F(t)
, die einen Zeitwert t
als Eingabe nimmt und eine Geschwindigkeitsfunktion sigma
, die den Drehzahlwert zum Zeitpunkt kehrt t
, I eine costant Geschwindigkeitsbewegung entlang der Kurve erhalten, t Parameter mit einer konstanten Rate unterschiedlichen : B(F(t))
der Kern des Artikels ist verwende ich die folgende Funktion:
float umin, umax; // The curve parameter interval [umin,umax].
Point Y (float u); // The position Y(u), umin <= u <= umax.
Point DY (float u); // The derivative dY(u)/du, umin <= u <= umax.
float LengthDY (float u) { return Length(DY(u)); }
float ArcLength (float t) { return Integral(umin,u,LengthDY()); }
float L = ArcLength(umax); // The total length of the curve.
float tmin, tmax; // The user-specified time interval [tmin,tmax]
float Sigma (float t); // The user-specified speed at time t.
float GetU (float t) // tmin <= t <= tmax
{
float h = (t - tmin)/n; // step size, `n' is application-specified
float u = umin; // initial condition
t = tmin; // initial condition
for (int i = 1; i <= n; i++)
{
// The divisions here might be a problem if the divisors are
// nearly zero.
float k1 = h*Sigma(t)/LengthDY(u);
float k2 = h*Sigma(t + h/2)/LengthDY(u + k1/2);
float k3 = h*Sigma(t + h/2)/LengthDY(u + k2/2);
float k4 = h*Sigma(t + h)/LengthDY(u + k3);
t += h;
u += (k1 + 2*(k2 + k3) + k4)/6;
}
return u;
}
Es erlaubt mir, die Kurvenparameter u
berechnet zu bekommen die mitgelieferte Zeit mit t
und Sigma-Funktion. Jetzt funktioniert die Funktion, wenn die Geschwindigkeit sigma ist costant. Wenn Sigma eine gleichförmige Beschleunigung darstellt, erhalte ich falsche Werte.
Hier ist ein Beispiel einer geraden Bezier-Kurve, wobei P0 und P1 die Kontrollpunkte sind, T0 T1 die Tangente. Die Kurve ist definiert:
[x,y,z]= B(u) =(1–u)3P0 + 3(1–u)2uT0 + 3(1–u)u2T1 + u3P2
Lassen Sie uns sagen, dass ich die Position entlang der Kurve zum Zeitpunkt t = 3
wissen wollen. Wenn ich eine konstante Geschwindigkeit:
float sigma(float t)
{
return 1f;
}
und die folgenden Daten:
V0 = 1;
V1 = 1;
t0 = 0;
L = 10;
ich die Position analytisch berechnen kann:
px = v0 * t = 1 * 3 = 3
Wenn ich lösen die gleiche Gleichung mit meinem Bezierspline und der obige Algorithmus mit n =5
erhalte ich:
px = 3.002595;
Betrachtet man die numerische Approximation, ist der Wert ziemlich genau (ich habe eine Menge Tests durchgeführt). Ich lasse Details weg, aber Bézier meine Kurven Implementierung ist in Ordnung und die Länge der Kurve selbst wird ziemlich genau mit Gaussian Quadrature berechnet).
Wenn ich jetzt versuche, Sigma als eine einheitliche Beschleunigungsfunktion zu definieren, bekomme ich schlechte Ergebnisse. Betrachten Sie die folgenden Daten:
V0 = 1;
V1 = 2;
t0 = 0;
L = 10;
ich die Zeit ein Teilchen das P1 unter Verwendung eines linearen Bewegungsgleichungen erreicht berechnen kann:
L = 0.5 * (V0 + V1) * t1 =>
t1 = 2 * L/(V1 + V0) = 2 * 10/3 = 6.6666666
Mit t
I Beschleunigung berechnen:
a = (V1 - V0)/(t1 - t0) = (2 - 1)/6.6666666 = 0.15
Ich habe alle Daten, um meine Sigma-Funktion zu definieren:
float sigma (float t)
{
float speed = V0 + a * t;
}
Wenn ich analytisch dieses Problem lösen würde ich die folgende Geschwindigkeit eines Teilchens nach der Zeit erwarten t =3
:
Vx = V0 + a * t = 1 + 0.15 * 3 = 1.45
und die Position wird:
px = 0.5 * (V0 + Vx) * t = 0.5 * (1 + 1.45) * 3 = 3.675
Aber wenn ich berechnen sie mit der Alorithmus oben, die Position Ergebnisse:
px = 4.358587
das ist ziemlich anders fr om was ich erwarte.
Sorry für die lange Post, wenn jemand genug Geduld hat, um es zu lesen, würde ich mich freuen.
Haben Sie einen Vorschlag? Was vermisse ich? Jeder kann mir sagen, was ich falsch mache?
EDIT: ich mit 3D-Bezier-Kurve bin versucht. Definiert auf diese Weise:
public Vector3 Bezier(float t)
{
float a = 1f - t;
float a_2 = a * a;
float a_3 = a_2 *a;
float t_2 = t * t;
Vector3 point = (P0 * a_3) + (3f * a_2 * t * T0) + (3f * a * t_2 * T1) + t_2 * t * P1 ;
return point;
}
und die Ableitung:
public Vector3 Derivative(float t)
{
float a = 1f - t;
float a_2 = a * a;
float t_2 = t * t;
float t6 = 6f*t;
Vector3 der = -3f * a_2 * P0 + 3f * a_2 * T0 - t6 * a * T0 - 3f* t_2 * T1 + t6 * a * T1 + 3f * t_2 * P1;
return der;
}
und was gibt der Algorithmus für t = 6.6666 ...? Ist es der Wert 10, d. H. L, oder ein anderer? – lmsteffan