» »

DirectX - težavica

DirectX - težavica

Mezetix ::

Imam dva problema z mojim programčičem, k mu ljubkovalno pravim 3dEngine :)
Uspesno furam mesh okoli po prostoru in več ali manj uboga kar mu pravi logika. Problem je pri rotiranju okoli svojih osi.
Se pravi moja ladica lepo plove, kakor bi mogla, vendar je obrnjena v napačno smer. (leti ritensko ali bočno naprej bol malo)
Pozicijo uspešno spreminjam z:

D3DXMatrixTranslation(&World,p.x,p.y,p.z);

Rotacijo pa bi moral spreminjati z

D3DXMatrixRotationX(&RotX,a);
D3DXMatrixRotationY(&RotY,b);
D3DXMatrixRotationZ(&RotZ,g);

Problem je v kotih a,b,g, ker ne vem kako jih izračunati.
Moja ladica ima pozicijo, Heding , Side in Up vektor. Laico bi rad obrnil v smer Heding.
Ker je heading normaliziran bi morala biti rec preprosta
angleX= cos X (u radianih)
Sem probal več varijant pa mi nikakor ne uspe dobiti pravih rezultatov. Kako pravilno usmeriti objekt, če potrebuješ kot iz vektorja?

Drugi problem imam pa pri transformiranju. v World space mi ni problem. Problem je nazaj. Se pravi moram narediti matrico, iz lokalnih koordinat. Iz Pozicija, Heading, Side in Up. Pa se mi spet nekje zatakne. Če ma kdo kakšen priročen link bi bil zelo srečen, ker najdem samo za World transformacije.

Senitel ::

Kaj tu pravzaprav spreminjaš vsak frame in kaj vsak frame sestaviš iz 0? Kako množiš vse skup?

Mezetix ::

Ja normalno postavitev.
begin scene
for each vehicle
{
zračunaj matrice rotacijo in položaj (&World)
SetTransform(D3DTS_WORLD, &World);
nariši objekt
}
end scene

Zdej razmislam, da bi mogu rotirat z D3DXMatrixRotationAxis okol lokalnih osi objekta.

Mezetix ::

Vem da je to bolj matematičen problem, samo po moji logiki...
mamo lokalne vektorje vozilca; Pos, Head, Side, Up. Vsak ma x,y,z;

Postaviti objekt na Pos in rotirati za določen kot je u directx simpl z zgoraj omenjenimi ukazi.

objekt bi moral najprej zarotirati u željeno smer, ki je doložena z Head,Sid,Up, kateri so pravokotni med sabo in so normalizirani (dolžina 1).
Se pravi da moram izračunat kot med vektorjema : world x(1,0,0) in Head (x,y,z) - ampak samo x rotacijo oz Pitch oz koliko se ladja zavrti gor-dol.
Potem isto za y, koliko se zavrti levo desno - yaw.
In potem še rol za Z, ampak ta niti ni tako pomemben.

Senitel ::

Ok, od začetka...
Če imaš izračunane vektorje za pozicijo, heading, side in up potem imaš že bazo prostora in te vektorje samo še spakiraš v matriko.
Če imaš 3 rotacije po oseh (pitch, yaw, roll) in neko pozicijo, potem poračunaš vse 4 matrike kot imaš v prvem postu napisano in jih zmnožiš skup v "world" (ali pa sestaviš matriko direkt tako, da izračunaš osi).
Dosti bolj enostavno bi bilo, da pač ladijco postaviš nekam (matrika) in če se premakne naprej za 10 množiš to matriko s translacijo za 10 po z, če se obrne za 10 stopinj levo množiš matriko z rotacijo 10 stopinj levo.

Ni mi pa jasno kaj sploh misliš s tistim "kako izračunat a, b in g"?

Mezetix ::

Sej problem je glih v računanju rotacije po osi.

D3DXMatrixRotationX(&RotX,a);

nardi matrico za rotacijo okol x osi za kot a. Kako dobim ta a iz vektorjev Hed,Side in Up.

Nekje sem zasledil, da je
angle = acos(v1ov2)
Se pravi kot je acos(vec heding dot vec Xaksa)
sam to mi ne deluje prov.

Zgodovina sprememb…

  • spremenil: Mezetix ()

Senitel ::

Come on... Ta tvoj heading in a sta eno in isto (xaxis = (1, 0, 0) => heading dot xaxis = heading.x => acos(heading.x) = kar kol si že pač v osnovi dal not).
Lahko pokažeš teh nekaj vrstic kode, da bo sploh jasno kaj poskušaš naredit?

Mezetix ::

Mi je ratalu.
Sm prebral tvoj zadn post pa sm se mal zamislu, k se že sam mal zamislu, zakaj rabm kote računat, če mam pa tri vektorje za lokalni koordinatni sistem. Sm mal brskal po netu in prebral tole stran:
http://www.fastgraph.com/makegames/3dro...
In mi je vse jasno... več al mejn. Toplo priporočam branje za vse k majo težave z rotiranjem.

Uglavnem sem unesu sledeče podatke u matrico:
m_World._11=side.x; m_World._12=side.y; m_World._13=side.z; // Side vector in row 1
m_World._21=up.x; m_World._22=up.y; m_World._23=up.z; // Up vector in row 2
m_World._31=hed.x; m_World._32=hed.y; m_World._33=hed.z; //heading vector in row 3

Jo pomnožu z pozicijo in zdej se moji avijoncki prov lepo vozjo in se obračajo v pravo smer. 8-)
(OK, se vozijo z repom naprej ampak tu bomo že obrnli okol )

Zdej se morm samo še lotit da lahko kerokol točko/vektor premaknem u ta lokalno pozicijo. Rabm za računat trke. Mislem, da gre pa po istem sistemu.

Hvala še enkrt za trud :)

Senitel ::

No fajn. :) Lahko pa dodaš še naslednje:
m_World._41 = pos.x; m_World._42 = pos.y; m_World._43 = pos.z; m_World._44 = 1.0f;
In se znebiš matričnega množenja, da spraviš pozicijo not.
Pa m_World._14 = m_World._24 = m_World._34 = 0.0f;

Iz world v local space pa vektor spraviš tako, da ga množiš z inverzom tega m_World.

Mezetix ::

Sem probaval tud s pozicijo, pa mi ni lavfalo, ker sem jo tlačil v 14,24,34 točke matrice in ne 41,42,43.
Ker na uni strani, ki sm jo napisal, je pisalo, da je tako prav.

Še eno hitro vprašanje. Nardit moram dve funkcije, u bistvu štiri.
PointToWorld, PointToLocal in
VecorToWorld, VectorToLocal

Kot si že reku, za u World uporabm tko narjeno matrico, nazaj u local pa uporabm inverse.
Glede točke ali vektorja pa samo spremenim uno enko na poz. 44 u nulo. Če sm prov zastopu.
Vector oz. mesh mora bit tm 1.0f, da se računa kot vektor (smer in dolžina) z 0.0f pa kot točka (samo pozicija).

Senitel ::

DirectX (fixed function pipeline, pri shaderjih je itak vse odvisno od tega kako naprogramiraš sam shader) iz nekega razloga uporablja "row major" matrike, ves ostali svet (OpenGL, vsa matematika,...) uporablja "column major" matrike. Rezultat tega je, da so bazni vektorji pakirani v vrstice (kot si že sam ugotovil, glede na to kako polniš m_World) in ne v stolpce. V bistvu moraš vse matrike, ki jih prebereš na oni strani transponirat.

Matrike pusti pri miru. Ni treba nič spremnijat _44 elementa. Vzameš pač samo tiste skalarne produke, ki jih rabiš: 3 za "point" in 4 za "vektor".

Sicer ti pa sploh ni treba pisat onih štirih funkcij. Ima D3DX že vse kar rabiš: D3DXVec3Transform in D3DXVec4Transform.
BTW: Zakaj bi ločeval med local in world? Saj daš matriko za parameter pa je.

Mezetix ::

Glede preračunavanja iz World u local. Rabm zarad računanja trkov. Ladica ma naprimer kvadr projeciran po svoji z osi pred sabo in sega cca. 10 dolzin ladje naprej(kolkr prevozi u sekundi). Zdej lahko za vsako ladico kvadr spremenim u world, pa u worldu testiram če se kej prekriva z ovirami. in če se, potli zračunam vektor stran od objekta glede na smer ladice in pol ta vektor spremenim nazaj u lokal in ga seštejem z hedingom da zavije stran od ovire.

Je pa mejn računanja, če vržem oviro u lokal in mam pol use u lokal. (še prej zavržeš use ovire k so predaleč, da jih ni preveč). Isto mam pol lažji za vse izstrelke al karkoli bom že skreirou.

Bi te pa vprašal še neki, k vidm da se spoznaš na directX. Rad bi narisal črto oz puščico. Se pravi brez senčenja sam črto, k bi jo uporabljal da vidim sile na ladji (iz mesha vn bi štrlele, za heding in podobne stvari). Zdej gledam da bi naredu z

->DrawPrimitive( D3DPT_LINELIST, 0, 3 );

Sam pol bi spet moral zadevo premetavat skuz matrice. Rad bi pa naredu funkcijo, k bi vzela za parameter vektor 1 in 2 in bi zadeva narisala črto od prvega do druzga vektorja. Sam to verjetno ne bo šlo...

Senitel ::

Mislil sem izključno zakaj imet ekstra funkcije?
D3DXVec3Transform(&out, &vektor, &toWorldTransform);
D3DXVec3Transform(&out, &vektor, &toLocalTransform);
To je vse kar rabiš.

Glede črt. Sklepam da sedaj uporabljaš striktno D3DXMesh objekte (ki ti prikladno skrije vertex in index bufferje)?
Če se sprijazniš samo s črtami, oziroma "flat" puščicami je zadevo čisto enostavno izpeljat. Matrika je itak ista kot si jo uporabil za ladijco renderirat (edino kar bi lahko naredil je, da jo po potrebi malo skaliraš).
Narediš strukturo:
struct LVertex{
    D3DXVECTOR3 pos;
    D3DCOLOR color;
};

Potem narediš array:
LVertex pBuffer[] =
{
    {D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DCOLOR_ARGB(0, 255, 0, 0)},
    {D3DXVECTOR3(0.0f, 0.0f, 1.0f), D3DCOLOR_ARGB(0, 255, 0, 0)},
    {D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DCOLOR_ARGB(0, 0, 255, 0)},
    {D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DCOLOR_ARGB(0, 0, 255, 0)},
    {D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DCOLOR_ARGB(0, 0, 0, 255)},
    {D3DXVECTOR3(1.0f, 0.0f, 0.0f), D3DCOLOR_ARGB(0, 0, 0, 255)}
};

Nastaviš skalirano world matriko (po potrebi), nastaviš vertex format, izklopiš zbuffer (po potrebi, da ti ladijca tega ne skrije), za vsak slučaj izklopiš lučke (ker sem že pozabil kako se FF pipe obnaša) in zrenderiraš:
pDevice->SetTransform(D3DTS_WORLD, &m_World);
pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
pDevice->SetRenderState(D3DRS_ZENABLE, false);
pDevice->SetRenderState(D3DRS_LIGHTING, false);
pDevice->DrawPrimitiveUP(D3DPT_LINELIST, 3, pBuffer, sizeof(LVertex));
pDevice->SetRenderState(D3DRS_ZENABLE, true);
pDevice->SetRenderState(D3DRS_LIGHTING, true);

Ker je ta array statičen, se ti ga kasneje splača spakirat v vertex buffer in ga tam pustit (sicer ti DrawPrimitiveUP to naredi vsakič znova).

Mezetix ::

Ja tko sm mislu u osnovi narest. Mam pa spet neki tezav. Ce pustim use tku kot si napisal, mi riše črte samo na ladicah - se pravi zbufer ugasnejn mi nariše črto samo na vseh objektih (če leti mimo druga ladica, je na njej vidna črta) na ozadju je pa ni. To bo verjetno zato, k rišem črte u for zanki skupi z ladicami, naknadno pa še ozadje pa druge objekte. Pustim Z pa je uredu.

Poblem dva pa je... Neskončnost črt. Se pravi od točke v vsako smer je črta neskončna (do konca viewstruma kamere) pa ni pomembno če kej scalam al ne. Sm probal scalat na od 10.0f do 0.000001f pa je rezultat prou isti, kar mi je čudno. Če ga dam pa u - se pa pravilno obrne u drugo smer, tku da scaling deluje.

Menda bo lazji, če nardim nov mesh puščice. Simpl vrjanto pa jo rišem u wireframe. Bi mogl bit z dimenzijam use uredu.

Senitel ::

Najlažje bo, če črte narišeš čisto posebej po koncu vsega ostalega renderiranja (in zakaj za boga renderiraš ozadje nazadnje? >:D).

Če gredo črte v neskončnost, potem si nekaj zakvačkal z matrikami. Konkretno tisti _44 element v m_World si postavil na 0.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Matlab problem

Oddelek: Pomoč in nasveti
281428 (852) bluefish
»

Statični IP problem !

Oddelek: Pomoč in nasveti
241950 (1717) Invictus
»

C++ programirane v Open GL oz. Direct x

Oddelek: Programiranje
242964 (2235) Vesoljc
»

OpenGL problem

Oddelek: Programiranje
212475 (2041) Gundolf

Več podobnih tem