Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Lazaroz
Založen: 06. 09. 2007 Příspěvky: 11
|
Zaslal: 6. září 2007, 15:25:03 Předmět: pohyb objektu a jeho natoceni po trajektorii |
|
|
zdravim chci se optat jak vyresit problem s natáčením objektu po určité trajektorii objekt natáčím pomocí translate v opengl .Jde mě oto,že objektu nastavím waypointy kam se má pohybovat ,to mě funguje,ale horší je to už s tím,jak objekt natočím pomocí translací ve směru waypointu .Každy waypoint má souřadnice a vektor takže jsem zkusil vypočítat úhel mezi dvěma vektory ale to je blbost protože nezjistím jestli je ten úhel kladný nebo záporný,takže se mi otáčí objekt sice o spravnou velikost uhlu ale ne už ve správném směru čili když se třebas objekt pohybuje dopředu tak má čumák dozadu atd jeslti mě chápete .díky za každou radu |
|
Návrat nahoru |
|
|
Lando
Založen: 29. 07. 2007 Příspěvky: 33 Bydliště: Cestice
|
Zaslal: 6. září 2007, 15:50:35 Předmět: |
|
|
Zkusil bych to asi tak, ze bych vzal vektor kterym se ten objekt pohybuje. Potom vytvoril pravy vektor operaci cross s nejakym docasnym up vektorem (0,1,0 nebo 0,0,1, podle toho "kde je nahore") Dalsi cross praveho vektoru a vektoru pohybu potom da posledni vektor. Tyto tri navzajem pravouhle vektory potom naskladane (po sloupcich?) do matice daji rotacni matici. |
|
Návrat nahoru |
|
|
Lazaroz
Založen: 06. 09. 2007 Příspěvky: 11
|
Zaslal: 6. září 2007, 16:15:56 Předmět: |
|
|
Lando napsal: |
Zkusil bych to asi tak, ze bych vzal vektor kterym se ten objekt pohybuje. Potom vytvoril pravy vektor operaci cross s nejakym docasnym up vektorem (0,1,0 nebo 0,0,1, podle toho "kde je nahore") Dalsi cross praveho vektoru a vektoru pohybu potom da posledni vektor. Tyto tri navzajem pravouhle vektory potom naskladane (po sloupcich?) do matice daji rotacni matici. |
asi to chapu cece dikec lando zkusim to a snad to pujde pokud nekdo ma jeste jiny zpusob tak sem snim cim vic jich bude tim lip |
|
Návrat nahoru |
|
|
ladik-BigBoss
Založen: 28. 07. 2007 Příspěvky: 162
|
Zaslal: 8. září 2007, 00:53:22 Předmět: |
|
|
ja bych ty uhly mezi sebou linearne interpoloval;
asi nejlepsi by bylo uzit quaterniony, ale tem nerozumim |
|
Návrat nahoru |
|
|
pcmaster
Založen: 28. 07. 2007 Příspěvky: 1824
|
Zaslal: 8. září 2007, 01:13:59 Předmět: |
|
|
ak to chces kvaternionmi, musis si nastudovat nieco o nich a potom o SLERP (Spherical Linear intERPolation). A mozno aj nie
Slerp funguje tak, ze do nej narves kvaternion1 (rotaciu1) a kvaternion2 (rotaciu2) a parameter t z intervalu <0,1>. A vypluje to na teba vysledny kvaternion.
V skratke: kvaternion je normalny 4D vektor (v nasom pripade jednotkovy). Reprezentuje rotaciu. Vsetky taketo jednotkove kvaterniony tvoria povrch jednotkovej hyper-gule (dokonca 2x, ale to je nepodstatne). SLERP robi to, ze vyberie bod na obluku na tejto 4D guli, na obluku, ktory zacina v bode kvaternion1 (parameter t=0) a konci v bode kvaternion2 (t=1). Viz literatura. V podstate to pri rovnomernej zmene t od 0 do 1 a naslednej aplikacii vysledneho kvaternionu napr. na nejaky vektore, tento vektor otaca pekne rovnomerne po najkratsej krivke.
Pre teba je dolezite vyrobit kvaternion1 a kvaternion2. Pozri do literatury, ale v skratke:
Kvaternion je stvorica (w,x,y,z), pripadne dvojica (w, V). Potom:
citace: |
Kvaternion(os3D, uhol) = (cos(uhol/2), os3D*sin(uhol/2)) |
Tiez ho mozes vyrobit z rotacnej matice alebo z eulerovych uhlov.
Viac sa mi vysvetlovat nechce, po statniciach tu zverejnim moju bakalarsku pracu, kde uvadzam mimo ineho dost odkazov na literaturu a tieto velmi zname postupy aj strucne polopaticky opisujem (aby som mal dost stran ).
(Odpuste mnohe matematicke nezrovnalosti, mam plnu hlavu superskalarnych architektur a inych kokotin na statnice a myslim, ze to na informacnej hodnote neuskodi.) _________________ Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est. |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 8. září 2007, 09:54:50 Předmět: |
|
|
Jestli to dobře chápu, tak jediné co potřebuješ je, aby se model "díval" směrem kterým jede. Imho to řešit nějakýmy kvaterniony je trochu moc drsný. Já jsem to v jedné své hře vyřešil jednoduše:
Protože pohyb se koná víceméně po rovine, počítal jsem si vždy jen úhly na rovine XZ - prostě z dvou bodu (modelX,modelY) a (cilX,cilY) jsem vypocital vektor, ze ktereho mi vyplynul uhel (napriklad pokud je cil primo pred modelem tak je uhel 0, pokud je za nim tak 180 atd). Z toho jsem mel cilovy uhel natoceni modelu. Aktualni uhel modelu na rovine XZ je "uhelH" (jako "horizontalni uhel", pak ma jeste uhelV, tedy vertikalni uhel). Nasledne staci proste menit uhelH v kazdem framu dokud nebude roven "cilovemu uhlu" - vsimneme si ze pokud model jede, cilovy uhel se porad meni, ale to je osetreno tim ze se cilovy uhel neustale prepocitava.
Kód pro výpočet jakým směrem se má koukat model:
(uhel)
kód: |
double Enemy::GetDirToTarget(double pX, double pZ, double tX, double tZ)
{
double result, protilehla, prepona;
if ((pX - tX) > 0 && (pZ - tZ) > 0)
{
// 1. kvadrant, + 0, X protilehla
protilehla = pX - tX;
prepona = sqrt((pX - tX)*(pX - tX) + (pZ - tZ)*(pZ - tZ));
result = asin(protilehla / prepona) * (180/PI);
}
else if ((pX - tX) > 0 && (pZ - tZ) < 0)
{
// 2. kvadrant, + 90, Z protilehla
protilehla = tZ - pZ;
prepona = sqrt((pX - tX)*(pX - tX) + (pZ - tZ)*(pZ - tZ));
result = asin(protilehla / prepona) * (180/PI) + 90;
}
else if ((pX - tX) < 0 && (pZ - tZ) < 0)
{
// 3. kvadrant, + 180, X protilehla
protilehla = tX - pX;
prepona = sqrt((pX - tX)*(pX - tX) + (pZ - tZ)*(pZ - tZ));
result = asin(protilehla / prepona) * (180/PI) + 180;
}
else
{
// 4. kvadrant, + 270, Z protilehla
protilehla = pZ - tZ;
prepona = sqrt((pX - tX)*(pX - tX) + (pZ - tZ)*(pZ - tZ));
result = asin(protilehla / prepona) * (180/PI) + 270;
}
//result = result % 360;
return result;
return 0.0;
}
|
uhel k cili a jeho zmena:
kód: |
bool Enemy::RotateToTarget(int who, double targetX, double targetZ)
{
double uhelCil = GetDirToTarget(targetX, targetZ, enemInfo[who].x, enemInfo[who].z);
if (abs(uhelCil - enemInfo[who].angleH) > 3)
{
if (uhelCil > enemInfo[who].angleH)
{
if (abs(uhelCil - enemInfo[who].angleH) > 180)
{
enemInfo[who].angleH -= 40 * Hra->delay;
}
else
{
enemInfo[who].angleH += 40 * Hra->delay;
}
}
else
{
if (abs(uhelCil - enemInfo[who].angleH) > 180)
{
enemInfo[who].angleH += 40 * Hra->delay;
}
else
{
enemInfo[who].angleH -= 40 * Hra->delay;
}
}
if (enemInfo[who].angleH > 360)
enemInfo[who].angleH -= 360;
if (enemInfo[who].angleH < 0)
enemInfo[who].angleH += 360;
}
if (abs(uhelCil - enemInfo[who].angleH) < 25)
return true;
else
return false;
}
|
A samotné vykreslení:
kód: |
void Enemy::Draw(int who)
{
int k;
k = enemInfo[who].modelType;
glPushMatrix();
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.1f);
glBindTexture(GL_TEXTURE_2D, enemTex[k].texID);
glTranslated(enemInfo[who].x, enemInfo[who].y + enemInfo[who].elevation, enemInfo[who].z);
glRotated(enemInfo[who].angleH, 0.0, 1.0, 0.0);
glmDraw(enemUniq[k], GLM_FLAT | GLM_TEXTURE);
glDisable(GL_ALPHA_TEST);
glPopMatrix();
}
|
Snad to trochu pomůže a snad je to aspoň k tématu.
To že je kód prasárna vím a je mi to jedno [/code] _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
pcmaster
Založen: 28. 07. 2007 Příspěvky: 1824
|
Zaslal: 8. září 2007, 13:33:56 Předmět: |
|
|
Ale hej, preco by to tak nemohlo fungovat Ja som len reagoval na ladika.
S kvaternionmi to vobec nie je zlozite. Ak mas predpripravene struktury pre kvaterniony a hotovu funkciu SLERP (3rd-party), tak peknu kameru a podobne mas implementovanu za 10 minut a nemusis sa srat so sinusmi a kosinusmi _________________ Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est. |
|
Návrat nahoru |
|
|
Marek
Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 8. září 2007, 14:28:05 Předmět: |
|
|
Quaterniony jsou tady asi nejvhodnejsi. Ono kdyz si z toho odstranite ten SLERP, tak to ma stejne vlastnosti jako 3x3 matice bez scale + je tu vyhoda, ze nasobek quaternionu nemeni rotaci (takze nemusi byt jednotkovy). Ten SLERP je na animace fakt nejlepsi, protoze pri interpolaci eulerovych uhlu tam mate gimbal lock (prvni uhel orotuje hlavni osy pred aplikaci druheho uhlu). Implementaci quaternionu se na netu vali hafo, takze neni problem jednu vzit a pouzit. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
|
Peta
Založen: 28. 07. 2007 Příspěvky: 154 Bydliště: V prvnim patre hned vedle koupelny.
|
Zaslal: 8. září 2007, 15:49:10 Předmět: |
|
|
To jo no - kazdopadne ja jsem prezentoval reseni vhodne pro trochu specialni pripad, tj pohyb vicemene po rovine, jestli to potrebuje pro obecnejsi pripad (tj uplny pohyb v prostoru) tak asi bude lepsi pouzit ty quaterniony. _________________ Když je Ti smutno, otoč se tváří ke slunci a všechny stíny padnou za Tebe. |
|
Návrat nahoru |
|
|
Lazaroz
Založen: 06. 09. 2007 Příspěvky: 11
|
Zaslal: 8. září 2007, 22:23:44 Předmět: |
|
|
quateriony nebo co to je jsem zatim nak nestudoval pac me to prijde slozity na cloveka co nema vysku ale zkusil jsem tu prvni radu a poskladal jsem tu rotační matici ale pracuje to nak divne mrknete jestli sem to udelal spravne
kód: |
RotateMatrix.m[0]=directionV.vx;
RotateMatrix.m[4]=directionV.vy;
RotateMatrix.m[8]=directionV.vz;
C_VECTOR UP;
C_VECTOR result;
C_VECTOR result2;
UP.Set(0,1,0);
result=UP*directionV;
RotateMatrix.m[1]=result.vx;
RotateMatrix.m[5]=result.vy;
RotateMatrix.m[9]=result.vz;
result2=result*directionV;
RotateMatrix.m[2]=result2.vx;
RotateMatrix.m[6]=result2.vy;
RotateMatrix.m[10]=result2.vz; |
|
|
Návrat nahoru |
|
|
Lazaroz
Založen: 06. 09. 2007 Příspěvky: 11
|
Zaslal: 17. září 2007, 12:55:26 Předmět: |
|
|
tak metoda s naskladanim cross uhlu a nasledne sestaveni matice me nefunguje resp objekt se otáčí ale ne tak jak má asi jsem to blbě poskládal ,byl bych moc rad,kdyby tu někdo uveřejnil kus kodu třeba jak to udělat pomocí toho Quaternionu nebo jen pomocí matic díky moc |
|
Návrat nahoru |
|
|
Lazaroz
Založen: 06. 09. 2007 Příspěvky: 11
|
Zaslal: 18. září 2007, 08:53:02 Předmět: |
|
|
tak jsem konečně našel funkční kod ktery jsem si ttrošku upravil ale funguje!
kód: |
C_VECTOR x_dir(0.0,0.0,1.0),y_dir;
C_VECTOR dir=directionV;
__int64 d=dir.vz;
if(d>-0.999999999 && d<0.999999999){ // to avoid problems with normalize in special cases
x_dir=x_dir-dir*d;
x_dir.Normalize();
y_dir=dir.Cross(x_dir);
}else{
x_dir=C_VECTOR(dir.vz,0,-dir.vx);
y_dir=C_VECTOR(0,1,0);
};
// x_dir and y_dir is orthogonal to dir and to eachother.
// so, you can make matrix from x_dir, y_dir, and dir in whatever way you prefer.
// What to do depends to what API you use and where arrow model is pointing.
// this is matrix i use which may give starting point.
// this is for arrow that points in z direction (for arrow that points in x direction you may try swapping dir and x_dir)
RotateMatrix.m[0]=x_dir.vx;
RotateMatrix.m[1]=x_dir.vy;
RotateMatrix.m[2]=x_dir.vz;
RotateMatrix.m[3]=0.0;
RotateMatrix.m[4]=y_dir.vx;
RotateMatrix.m[5]=y_dir.vy;
RotateMatrix.m[6]=y_dir.vz;
RotateMatrix.m[7]=0.0;
RotateMatrix.m[8]=dir.vx;
RotateMatrix.m[9]=dir.vy;
RotateMatrix.m[10]=dir.vz;
RotateMatrix.m[11]=0.0;
RotateMatrix.m[12]=0;
RotateMatrix.m[13]=0;
RotateMatrix.m[14]=0;
RotateMatrix.m[15]=1.0;
|
|
|
Návrat nahoru |
|
|
|