XE5-Opengl 3d translate/rotate probléma

XE5-Opengl 3d translate/rotate probléma
2020-03-02T17:06:51+01:00
2020-03-05T20:16:53+01:00
2022-10-15T21:26:14+02:00
Stella_209
Írok egy Delphi XE5 grafikus tervezőprogramot, ami 2d alakzatok kivágását vezérli egy vágógépen.
Szeretném a kivágandó objektumokat 3d-ben megjeleníteni.
Ezt sikerült is opengl-ben. Egy listából még ki is tudok választani egy objektumot.
Csak hogy: a 3 tengely irányában (x,y,z) el is kell tudni mozgatni ill. saját középpontja körül forgatni.
Ez tenné lehetővé, hogy térben összeállíthassunk egy komplex 3d objektumot.

Valamit nem jó csinálok, mert eredeti helyén mennek a műveletek, de ha elmozgatom, akkor már az objektum nem a saját tengelye,
ha nem az eredeti helye körül forog.
Ugye vissza kellene vinni az origóba, elforgatni és vissza a mostani helyére.

LEEGYSZERŰSÍTVE: Adott n darab 3d objektum, amitből egy kiválasztottat szeretnék a világkoordináta-rendszer 3 tengelyével párhuzamosan eltolni
és saját középpontja körül forgatni.

Minden objektum egy eleme a compiled listának, azaz glCallList(index)-el kirajzoltatható.
Minden objektum transzformációit egy hozzá tartozó rekordban tárolom:

Type TPointRec3d = record X: TFloat; // az objektum középpont 3d koordinátái Y: TFloat; Z: TFloat; R: TFloat; RotAngle_X: TFloat; // Forgási szögek RotAngle_Y: TFloat; RotAngle_Z: TFloat; RotX,RotY,RotZ : TFloat; ScaleX,ScaleY,ScaleZ: TFloat; Selected: boolean; end; Trans3d = TPointRec3d; // Íme a renderelő rutin: procedure TMainForm.GPaint(Sender: TObject); Var j: integer; w,h: double; TR : TPointRec3d; Cent: TPoint2d; kp : TPoint2d; mArr : array[0..15] of GLfloat; // a tömb 0,4,8 eleme az x tengely, 1,5,9 az y 2,6,10 a z tengely, 11,12,13 elem az origo begin if not Sablon.Loading then begin // Papír középpontja w := Sablon.Paper.x/2; h := Sablon.Paper.y/2; G.setColor(clGray); g.Plane(-w,-h,0,w,-h,0,w,h,0,-w,h,0); glTranslatef(-w,-h,0); For j:=0 to Pred(Sablon.FCurveList.Count) do begin TR := Sablon.Curves[j].Trans3d; // Forgatás az objektum középpontja körül Cent := Sablon.Curves[j].Center; kp := Point2d( Cent.X, Cent.Y ); glPushMatrix; glGetFloatv(GL_MODELVIEW_MATRIX, @mArr); // Eltolás az origóba glTranslatef( (kp.x), (kp.y), 0); // Forgatás glRotatef( TR.RotAngle_X, 1, 0, 0); glRotatef( TR.RotAngle_Y, 0, 1, 0); glRotatef( TR.RotAngle_Z, 0, 0, 1); // Visszatolás az objektum eredeti helyére glTranslatef( -(kp.x-tr.x), -(kp.y-tr.y), TR.Z); if j=ObjectList.ItemIndex then gDrawObject(j,clRed) // Valós idejű vázrajz rutin pirossal else if g.WireFrame then gDrawObject(j,clBlue) else glCallList(j+10); glPopMatrix; end; end; end;
Hogyan módosítsam a képleteket? Ha a kiválasztott objektumot elforgatom, akkor a továbbiakban máris nem a világkoordináta-rendszer tengelyei mentén fog x,y,z irányokba elmozdulni, ha nem az objektum modelview koordinátta rendszerében.
Mutasd a teljes hozzászólást!
Csatolt állomány
Ha majd kiserletezel a matrixokkal, akkor mindig irasd ki szám szerint, hogy az agyad kicsit hozzaszokjon, hogy milyen transzformacio mit muvel a matrix-szal. Kesobb pedig a projection matrix is johet, meg a z-vel osztas, ott már akkor mind a 16 szam porogni fog.

Kozben guberaltam regi kodok kozott es talaltam egy kis segitseget:

Bounds3f bb = viewer->getSelectionBounds; V3f center = (bb.vMax+bb.vMin)*0.5f, bottom = center; bottom.coord(1) = bb.vMin.coord(1); M44f m = mTranslation(ui->seMoveX->value(), ui->seMoveY->value(), ui->seMoveZ->value()) *mTranslation(-center) *mRotationX(ui->seRotX->value()*(-PIf/180)) *mRotationY(ui->seRotY->value()*(-PIf/180)) *mRotationZ(ui->seRotZ->value()*(-PIf/180)) *mTranslation(center) *mTranslation(-bottom) *mScaling(ui->seScaleX->value()*0.01f, ui->seScaleY->value()*0.01, ui->seScaleZ->value()*0.01) *mTranslation(bottom); prj.multiplySelectedObjMatrices(m);

Ez tobb kijelolt objectet:
- eltol a world axisain
- forgat a boundingBox kozepe korul, world axisok menten, EulerXYZ szerint
- Skáláz a boundingBox alja-kozepe korul.

Ezt a transzformaciot belerakja m-be, es az osszes objectet megszorozza vele. Az objectek matrixai a world-re vonatkoznak, nem hierarchikusak.
Mutasd a teljes hozzászólást!

  • A 3 axis, amelyek korul forgatsz, az a modelview-nek megfelelo x, y, z most.

    Ha a world space korul akarsz transzformalni, akkor a world space axisait meg kell szoroznod a modelview inverzével.

    Ez egyebkent az en IQ-mat is elegge meghaladja, 3 evente szivok vele, aztan osszeall a kep, csak kell egy kicsit tanulni: Tutorial 3 : Matrices

    Sokat nem tudok segiteni, de én ezen igy kerekednek felul:

    Kell egy matrix/vector math framework, ami ezeket tudja:
    - pont, matrix szorzata
    - matrix inverze
    - matrix, matrix szorzat (sorrend szamit!!!)

    Ezekkel mindenre kepes lehetsze. Az opengl beepitett cuccait meg a fentiek alapjan vagy pontosan megérted, vagy eleg csak a glMultMatrix meg a push/pop. Szerintem a legfontosabb, hogy a matrixokat te kezeld.

    Az euler rotation, amit te hasznalsz pont erre a feladatra nem jo a gimbal lock miatt.
    Minden objectnel nyilvan kene tartanod azoknak a matrix-szát és azt a matrixot transzformálnod, attol fuggoen, hogy eppen melyik gombot nyomja a user. (Kesobb el lehet jutni a quaternionokig is, de ehhez a feladathoz az nem szukseges, az EulerXYZ viszont kifejezetten nem jo :D)

    Osszegezve: Ez az Eulerrel csak is az elso elforgatuasig fog korrektul menni. Nyilvan kell tartanod minden objektumra a homogen transzformacios matrixokat es mivel a classic OpenGL ebben nem segít, neked (valami 3rd party cuccnak) kell azt megoldani.
    Mutasd a teljes hozzászólást!
  • Sejtettem - és ezt Real_het meg is erősítette -, hogy előbb-utóbb mátrixos megoldása lesz a dolognak. Csak eddig óckodtam tőle. Most viszont nincs mese: meg kell tanulnom és főleg értenem. Szerencsére van egy mátrix műveletekre kiélezett unit-om. Ill. része ez a GLScene komponensnek is.
    Nem akartam túlbonyolítani a dolgot ezért a nyers OpenGL elégnek tünt. De, tényleg csak elemi rutinokat tartalmaz. Az ínyencségeket (térbeli transzformációk, objektum kiválasztás és interaktív bevatkozások) kidolgozását már a programozóra bízza, avagy külső komponensekkel megvalósítható.
    Most már belátom, hogy a mátrix-algebrát nem lehet kikerülni vagy elhagyni!
    Mutasd a teljes hozzászólást!
  • Ha majd kiserletezel a matrixokkal, akkor mindig irasd ki szám szerint, hogy az agyad kicsit hozzaszokjon, hogy milyen transzformacio mit muvel a matrix-szal. Kesobb pedig a projection matrix is johet, meg a z-vel osztas, ott már akkor mind a 16 szam porogni fog.

    Kozben guberaltam regi kodok kozott es talaltam egy kis segitseget:

    Bounds3f bb = viewer->getSelectionBounds; V3f center = (bb.vMax+bb.vMin)*0.5f, bottom = center; bottom.coord(1) = bb.vMin.coord(1); M44f m = mTranslation(ui->seMoveX->value(), ui->seMoveY->value(), ui->seMoveZ->value()) *mTranslation(-center) *mRotationX(ui->seRotX->value()*(-PIf/180)) *mRotationY(ui->seRotY->value()*(-PIf/180)) *mRotationZ(ui->seRotZ->value()*(-PIf/180)) *mTranslation(center) *mTranslation(-bottom) *mScaling(ui->seScaleX->value()*0.01f, ui->seScaleY->value()*0.01, ui->seScaleZ->value()*0.01) *mTranslation(bottom); prj.multiplySelectedObjMatrices(m);

    Ez tobb kijelolt objectet:
    - eltol a world axisain
    - forgat a boundingBox kozepe korul, world axisok menten, EulerXYZ szerint
    - Skáláz a boundingBox alja-kozepe korul.

    Ezt a transzformaciot belerakja m-be, es az osszes objectet megszorozza vele. Az objectek matrixai a world-re vonatkoznak, nem hierarchikusak.
    Mutasd a teljes hozzászólást!
  • Bocsáss meg, de ugye ez nem Delphi kód? Sajnos a meghívott eljárásokat is ismernem kellene a megértéshez.
    Mutasd a teljes hozzászólást!
  • Ez csak egy muveleti sorrend, iranymutatas gyanant. Glsceneben is megvannak ezek a dolgok.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd