سلام.
پیدا کردم اشکال از کجاست.
وقتی مقدار X یا Y یا Z رو برای RotationAngle تغییر میدید یک متغیر داخلی در RotationAngle به اسم FSave هست که ابتدا مقدار زاویه ی فعلی رو (آخرین وضعیت دوران) ذخیره میکنه بعد مقداری رو که شما بهش دادید ذخیره میکنه. متغیر FSaveیک جور Offset به حساب میاد و کارش اینه که دوران جدید رو حول محور موضعی خود شی (با استفاده از آخرین وضعیت قبلی) اعمال کنه.
به همین خاطر در هر فریم که شی حول یکی از محور ها دوران داده میشه ، در واقع حول محور X یا Y یا Z خود شی دوران داده میشه (نسبت به آخرین وضعیت قبلی) نه حول محور های مختصات جهانی.
حالا برای این که اون رو گول بزنیم میشه قبل از تغییر زاویه ی جدید اول مقادیر x و Y و Z فعلی رو ذخیره کنیم بعد از تابع ResetRotationAngle استفاه کنیم (تا مقادیر زوایا و offset اونها به صفر تغییرکنه) بعد سه تا مقدار رو به دلخواه تغییر بدیم بعد اون ها رو به ترتیب آخرین محور به اولین محور ست کنیم (چون دوران قبلی روی کارمون تاثیر نگذاره).
نکته : اگر ترتیب دوران x بعد y بعد z رو بخوایم شبیه سازی کنیم اول باید زاویه ی z بعد y بعد x رو ست کنیم، دلیلش اینه که زاویه های موجود تو هر مرحله از ست کردن، روی کارمون تاثیر میگذاره پس ترتیب باید از آخر به اول باشه.
مثلا اگر بخوایم با استفاده از دو تا Trackbar دوران X و Y یک TLayer3D رو تغییر بدیم بر اساس دوران x بعد y بعد z ، کدی مشابه کد زیر می تونیم بنویسیم :
procedure TForm1.TrackBar1Change(Sender: TObject);
var
y, z : Single;
begin
// x = newVal
y := Layer3D1.RotationAngle.Y;
z := Layer3D1.RotationAngle.Z;
Layer3D1.ResetRotationAngle;
Layer3D1.RotationAngle.Z := z;
Layer3D1.RotationAngle.Y := y;
Layer3D1.RotationAngle.X := (Sender as TTrackBar).Value;
end;
procedure TForm1.TrackBar2Change(Sender: TObject);
var
x, z : Single;
begin
x := Layer3D1.RotationAngle.X;
// y = newVal
z := Layer3D1.RotationAngle.Z;
Layer3D1.ResetRotationAngle;
Layer3D1.RotationAngle.Z := z;
Layer3D1.RotationAngle.Y := (Sender as TTrackBar).Value;
Layer3D1.RotationAngle.X := x;
end;
برای FloatAnimation هم میتونید مثلا برای مقادیر Value این دو تا Trackbar انیمیشن رو انجام بدید تا OnChange اون ها انجام بشه.