-
TPoint = record x,y,z:single; //Позиция точки в пространстве time:integer; //Время end;
Есть список точек в 3D пространстве Points:array of TPoint отсортированных по time. текущее время CurrentTime:integer; инертность inert:single;
По сути набор точек задает траекторию движения объекта. Ключевые позиции. Нужно получить позицию объекта в текущий момент времени. Если время попадает на ключевую позицию, то просто значение позиции возвращается. А вот если нужно интерполировать, то проблема. inert - это коэфициент инертности. Если коэфициент 0 - то все просто, линейная интерполяция дает нужный результат. Если коэфициент 1 - нужен идеально гладкий сплайн.
Проблема в том, что я не умею сплайны в 3Д строить. и инет не очень то делится инфой. Математических знаний хватило на то, чтобы понять, что будет кривая третьего порядка, но как ее строить - х.з.
-
>нужен идеально гладкий сплайн. Если устроит гладкость первого порядка (согласование по первой производной), то легче всего использовать сплайны Кэтмулл-Рома (частный случай TCB-сплайнов). По четырем соседним точкам рассчитывается полином между второй и третьей точкой.
Гладкость второго порядка - согласование в узлах по производной (наклону) и по второй производной (кривизне) Кубичеси\кие интерполяционные сплайны достаточно широко освещены, иcходники найти нетрудно (например, alglib.sources.ru). Правда, в большинстве случаев рассматривается двумерный случай с параметризацией по X, тебе же лучше использовать параметрические сплайны, выбрав нужную параметризацию. Единого мнения о том, какая параметризация кошернее, нету. В простейшем случае - по номеру точки, если точки относительно равномерно расположены. Можно и по расстоянию между ними.
-
Да, еще обратил внимание на твой коэффициент 0-1. Если нужны и промежуточные значения, то TCB-сплайны (Kochanek-Bartels) - то, что доктор прописал - параметр T (tension) меняешь в нужных пределах, а С и B нулевые (или единичные, не помню), и получаешь нужные результаты
-
Нашел аглоритм построения сплайна Кэтмулл-Рома. Но пробелма в том, что он для 2Д случая. Как на 3Д переделать? Знаний не хватает. :( PROCEDURE Spline_Calc (Ap, Bp, Cp, Dp: Point3D; T, D: Real; Var X, Y: Real);
VAR T2, T3: Real;
BEGIN
T2 := T * T;
T3 := T2 * T;
X := ((Ap.X*T3) + (Bp.X*T2) + (Cp.X*T) + Dp.X)/D;
Y := ((Ap.Y*T3) + (Bp.Y*T2) + (Cp.Y*T) + Dp.Y)/D;
END;
PROCEDURE Catmull_Rom_ComputeCoeffs (N: Integer; Var Ap, Bp, Cp, Dp: Point3D);
BEGIN
Ap.X := -CtrlPt[N-1].X + 3*CtrlPt[N].X - 3*CtrlPt[N+1].X + CtrlPt[N+2].X;
Bp.X := 2*CtrlPt[N-1].X - 5*CtrlPt[N].X + 4*CtrlPt[N+1].X - CtrlPt[N+2].X;
Cp.X := -CtrlPt[N-1].X + CtrlPt[N+1].X;
Dp.X := 2*CtrlPt[N].X;
Ap.Y := -CtrlPt[N-1].Y + 3*CtrlPt[N].Y - 3*CtrlPt[N+1].Y + CtrlPt[N+2].Y;
Bp.Y := 2*CtrlPt[N-1].Y - 5*CtrlPt[N].Y + 4*CtrlPt[N+1].Y - CtrlPt[N+2].Y;
Cp.Y := -CtrlPt[N-1].Y + CtrlPt[N+1].Y;
Dp.Y := 2*CtrlPt[N].Y;
END;
-
Стоп. Или все просто и я туплю??
-
Координаты же вроде одинаково считаются... Для трех координат будет так: PROCEDURE Spline_Calc (Ap, Bp, Cp, Dp: Point3D; T, D: Real; Var X, Y, Z: Real);
VAR T2, T3: Real;
BEGIN
T2 := T * T;
T3 := T2 * T;
X := ((Ap.X*T3) + (Bp.X*T2) + (Cp.X*T) + Dp.X)/D;
Y := ((Ap.Y*T3) + (Bp.Y*T2) + (Cp.Y*T) + Dp.Y)/D;
Y := ((Ap.Z*T3) + (Bp.Z*T2) + (Cp.Z*T) + Dp.Z)/D;
END;
PROCEDURE BSpline_ComputeCoeffs (N: Integer; Var Ap, Bp, Cp, Dp: Point3D);
BEGIN
Ap.X := -CtrlPt[N-1].X + 3*CtrlPt[N].X - 3*CtrlPt[N+1].X + CtrlPt[N+2].X;
Bp.X := 3*CtrlPt[N-1].X - 6*CtrlPt[N].X + 3*CtrlPt[N+1].X;
Cp.X := -3*CtrlPt[N-1].X + 3*CtrlPt[N+1].X;
Dp.X := CtrlPt[N-1].X + 4*CtrlPt[N].X + CtrlPt[N+1].X;
Ap.Y := -CtrlPt[N-1].Y + 3*CtrlPt[N].Y - 3*CtrlPt[N+1].Y + CtrlPt[N+2].Y;
Bp.Y := 3*CtrlPt[N-1].Y - 6*CtrlPt[N].Y + 3*CtrlPt[N+1].Y;
Cp.Y := -3*CtrlPt[N-1].Y + 3*CtrlPt[N+1].Y;
Dp.Y := CtrlPt[N-1].Y + 4*CtrlPt[N].Y + CtrlPt[N+1].Y;
Ap.Z := -CtrlPt[N-1].Z + 3*CtrlPt[N].Z - 3*CtrlPt[N+1].Z + CtrlPt[N+2].Z;
Bp.Z := 3*CtrlPt[N-1].Z - 6*CtrlPt[N].Z + 3*CtrlPt[N+1].Z;
Cp.Z := -3*CtrlPt[N-1].Z + 3*CtrlPt[N+1].Z;
Dp.Z := CtrlPt[N-1].Z + 4*CtrlPt[N].Z + CtrlPt[N+1].Z;
END; ?
-
Упс. не тот код: PROCEDURE Spline_Calc (Ap, Bp, Cp, Dp: Point3D; T, D: Real; Var X, Y, Z: Real);
VAR T2, T3: Real;
BEGIN
T2 := T * T;
T3 := T2 * T;
X := ((Ap.X*T3) + (Bp.X*T2) + (Cp.X*T) + Dp.X)/D;
Y := ((Ap.Y*T3) + (Bp.Y*T2) + (Cp.Y*T) + Dp.Y)/D;
Y := ((Ap.Z*T3) + (Bp.Z*T2) + (Cp.Z*T) + Dp.Z)/D;
END;
PROCEDURE Catmull_Rom_ComputeCoeffs (N: Integer; Var Ap, Bp, Cp, Dp: Point3D);
BEGIN
Ap.X := -CtrlPt[N-1].X + 3*CtrlPt[N].X - 3*CtrlPt[N+1].X + CtrlPt[N+2].X;
Bp.X := 2*CtrlPt[N-1].X - 5*CtrlPt[N].X + 4*CtrlPt[N+1].X - CtrlPt[N+2].X;
Cp.X := -CtrlPt[N-1].X + CtrlPt[N+1].X;
Dp.X := 2*CtrlPt[N].X;
Ap.Y := -CtrlPt[N-1].Y + 3*CtrlPt[N].Y - 3*CtrlPt[N+1].Y + CtrlPt[N+2].Y;
Bp.Y := 2*CtrlPt[N-1].Y - 5*CtrlPt[N].Y + 4*CtrlPt[N+1].Y - CtrlPt[N+2].Y;
Cp.Y := -CtrlPt[N-1].Y + CtrlPt[N+1].Y;
Dp.Y := 2*CtrlPt[N].Y;
Ap.Z := -CtrlPt[N-1].Z + 3*CtrlPt[N].Z - 3*CtrlPt[N+1].Z + CtrlPt[N+2].Z;
Bp.Z := 2*CtrlPt[N-1].Z - 5*CtrlPt[N].Z + 4*CtrlPt[N+1].Z - CtrlPt[N+2].Z;
Cp.Z := -CtrlPt[N-1].Z + CtrlPt[N+1].Z;
Dp.Z := 2*CtrlPt[N].Z;
END;
-
Похоже что нет...
-
Вроде одинаково. У тебя опечатка в Spline_Calc, там Z = должно быть. Можно ещё B-сплайны использовать (искать TBSpline), хотя считать их сложнее, но кривая получается более плавная.
-
> У тебя опечатка в Spline_Calc, там Z = должно быть.
Исправил уже. Толку нету. > Можно ещё B-сплайны использовать (искать TBSpline), хотя > считать их сложнее, но кривая получается более плавная.
У меня как раз код, который сравнивает два варианта, БСплайны и Кэтмулл-Рома. Отсюда код: http://www.enlight.ru/demo/faq/smth.phtml?query=alg_curves_splinesНа 2Д отлично работает. А вот 3Д не хотит.
-
-
-
Все. у меня заработало. Спасибо всем!!!!!
> [11] Sapersky (01.11.08 19:43)
Уже заработало. :) Видимо я где-то косячил. Спасибо!
-
>Видимо я где-то косячил. пополам не делил
|