játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
(C++) DirectX programozás 6. - Matematika összefoglaló 1. 2005.09.16 16:31



DirectX programozás 6. - Matematika összefoglaló 1.


Három dimenzióban gondolkodni jóval nehezebb, mint síkban. Ugyanis a végtelen nehezen felfogható, és 3D-ben végtelen sok sík van. 2D-ben egy. És az egyes szám kedves szám. Nézzük, hogy mi is a célunk! Elsõ és legfontosabb cél, hogy lefényképezzük a 3 dimenziós teret 2 dimenzióssá! Második, hogy ezt a leggyorsabban tegyük. Harmadik, hogy ebben a térben a mozgást lehetõvé tegyük, és sajnos elvetve a liberalizmust, korlátozzuk a mozgást(ütközés). Szeretnénk interpolált mozgást, mint a látványos animáció alapját. Ezekhez pedig kemény matematika kell.

Gondolatok a 3D-rõl

Na, azt hiszem ez most egy picit hosszú lesz, és nehéz is, fõleg nekem, de azért belekezdünk. Természetesen még mindig azt tartom, hogy a 2D-t érdemesebb ûzni, mert könnyebb jó játékot írni benne, de a tapasztalat mutatja, hogy sokan szeretnének 3D-ben programozni. Elõrebocsájtom, hogy a 3D jóval nehezebb, mint a 2D, ugyanis ott csupán x,y koordináta van, illetve nem kell komolyabb vetítést alkalmazni, nincsen bonyolult clipping(azaz vágás), nem kell annyi matematika, csak jobb meglátás. Nem ismertes a lineáris algebra és a vektor számítás bonyolúlt lépései. Itt sajnos muszáj megismerni. Ráadásul annyira bebonyolított már a 3D, hogy aki komolyan akar vele foglalkozni, annak annyi. Szóval legyen nekünk is annyi, és kezdjünk bele!

Próbálom a matematikát úgy kezelni, mintha ezen lap olvasója középiskolai végzetséggel rendelkezne. Felsõfokú végzetséggel rendelkezõk akár ki is hagyhatják a matek részt. Nem szeretnék részletes lenni, nem fogok kiselõadást tartani a lineáris algebráról, sem a vektorterekrõl. Csak annyit, ami kell a 3D-hez(persze nem csak a grafikához!). Például ütközésvizsgálatot matek nélkül NEM lehet csinálni!

Természetesen vektorgrafikát fogunk használni, ugyanis például a ray-tracing(sugárkövetés) nagyon lassú, és mi gyors grafikát szeretnénk. Platformnak ajánlkozik az oldal címét adó DirectX, de lehet használni OpenGL-t is. Én mégis a DirectX-et választanám, mert abban tudok 3D-t programozni. Egyébként az OpenGL ugyan az, csak más parancsnevekkel. A DirectX elõnye, hogy objektum-orientált. Az OpenGL-é, hogy helyenként gyorsabb. Nem megyek bele semmilyen vitába, csak annyit mondok, hogy D3D-hez értek. Ugyanolyan jó az OpenGL is. Errõl ennyit.

Lássuk, hogy milyen módszerek vannak a 3D-s megjelenítésre! Két fõ megoldás kínálkozik, ebbõl az egyik sokkal jobb mínõségû, mint a másik, cserébe annyival lassabb is. Tehát az elsõ módszer a sugárkövetés, népszerû nevén a ray-tracing. Lényege, hogy egy sugarat indítunk a monitor minden pixelébõl a térbe, vizsgáljuk, hogy mivel ütközik, aztán ezekbõl az adatokból meghatározzuk a pixel színét. Tehát pont fordítva van, mint a valóság: ott a fényforrásból indulnak a sugarak a térbe, de mivel abból végtelen sok van, ezért az nem alkalmas számítógépes modellezéshez. Mivel minden fénysugár számítása, aztán a sugár törése után rekurzív újraszámolása sokig tart, ezért mi inkább az inkrementális képszintézist alkalmazzuk. Ennek a lényege, hogy az egyszer már kiszámított felületet ne számítsuk újra, azaz használjunk azonos adatokat újra. Ezért minden felület kizárólag sokszögekbõl állhat. Ez azért jó, mert csak a csúcspontjaival kell igazán foglalkozni, majd a csúcspontok kiszámított vetített koordinátáit össze kell kötni, és kész. Mint látni fogjuk, azért kellenek sokszögek, mert minden geometriai transzformációnk szakasztartó lesz, azaz szakasz képe szakasz lesz, de errõl majd késõbb.

Szóval körülbelül ennyit a 3D-rõl, aztán kezdjünk is bele, mondjuk egybõl a matematikába!


Matematikai áttekintés

Ezt mindenki olvassa el, ha nem tudja a matek alapokat! Ezt használjuk 2D-hez is! Ha viszont valaki hibát talál, vagy hasonlót, akkor köszönettel veszem a hozzászólását. Nem kell félni, az eleje tök elmélet, aztán gyakorlatiassabb lesz.


Matematikai összefoglaló a 3D programozásához

Mielõtt nekilátnék, szeretném leszögezni, hogy ez a leírás lehet, hogy néhány résznél pontatlan, rosszabb esetben hibás lesz. Ha valaki ilyet venne észre, az szóljon. Történhet mindez azért, mert nem vagyok matematikus, másrészt ember vagyok. Teljesen értelmetlen dolgokat azért próbálok nem írni, és azt is jól tudom, hogy nagyon sokan vannak, akik ezeket a dolgokat nálam jobban tudják! Így ez a leírás nem nekik szól, de a hibák felfedezéséért köszöneti illeti õket.

1. rész
Vektorok

Fordított sorrendben kezdeném, nem egybõl a lineáris algebrával, hanem a vektorokkal. Ennek az a magyarázata, hogy egyszerû õket megérteni, szemléletesek, mindenki ismeri õket bizonyos szintig, és jól szemléltethetõ velük késõbb a lineáris algebra. Lássuk akkor, mik is azok a vektorok!

A vektort kezdetben úgy fogjuk definiálni, hogy a vektor egy irányított szakasz. Mindez három dimenzióig el is képzelhetõ, onnan viszont már csak izomorfizmussal tudjuk õket szemléletesebben értelmezni. Ez azért jó nekünk, mert így szemléletesen tudjuk õket kezelni, mert egy irányított szakaszt könnyen el tudunk képzelni. Nézzük például az alábbi vektort:


Tehát egy vektort egyszerûen egy nyíllal jelölünk! Írásban teljesen szokásos betûvel jelölni õket, méghozzá általában kisbetûvel.

Jelölése: a vagy a

Nyomtatásban általában elég a vastag betûs jelölés, kézzel való írásmódban általában aláhúzzák, vagy egy nyilat tesznek felé.
Fontos hangsúlyozni, hogy a két- és háromdimenziós vektorok vektorteret alkotnak, ami most még nem mond sokat, de majd késõbb, a lineáris algebránál ez nagyon nagy jelentõséggel fog bírni. Így mi most az euklideszi térrel fogunk foglalkozni. Errõl is beszélünk majd a vektortereknél.
A vektoroknak van tartóegyenese, az az egyenes, amely átmegy rajta. A vektoroknak van iránya, ami a szakasz irányát jelzi. A vektor rendelkezik hosszal is:

  • a vektornak van hossza, melyet az |a| jelöléssel jelölünk. Értéke a szakasz hossza. Igaz rá a háromszög-egyenlõtlenség:
    • |a+b||a|+|b|, amit szemléletesen bizonyíthat az Olvasó(bár a vektorösszeadást még nem definiáltuk).
Létezik egy ún. nullelem is, amit nullvektornak(0) hívunk. Az elõbbi értelmezésben a nullvektor hossza nulla. Iránya tetszõleges.
Egységelem egyértelmûen nem értelmezhetõ, mert kétféle szorzás is van(tehát a*1 nem egyértelmû, mire vonatkozik), viszont van egységvektor, melynek általános jele e, és |e|=1.

Nézzük, hogy a vektorokra milyen mûveletek vannak értelmezve!

  • Létezik a vektorok között összeadás, amit a + jellel jelölünk. Erre a mûveletre igazak az alábbiak(a,b vektorok):
    • Az összeadás kommutatív: a+b=b+a
    • Asszociatív: (a+b)+c=a+(b+c)
    • nullelemmel: a+0=a
    Az összeadás geometriai jelentése a következõ: az egyik vektor végpontjába felmérjük a másik vektort, és az elsõ vektor kezdõpontjából az utolsó vektor végpontjába fog mutatni az összeg:

  • Az összeadással tudjuk definiálni a kivonást az alábbi alakban:
    • b-a az a vektor, melyre (b-a)+a=b
      természetesen nem kommutativ és nem asszociatív
    Geometriai jelentése: a két vektort közös kezdõpontba toljuk, majd a kivonandó végpontjából a kisebbítendõ végpontjába mutató vektor a különbség:

  • A vektort szorozhatjuk skalárral: a(ahol ), aminek a tartóegyenese az a tartóegyenese, iránya megegyezik a-val, ha >0, és ellentétes a-val, ha <0. =0 esetén a nullvektor, egyéb esetben a hossza |||a|.
    • kommutativ: a=a
    • asszociatív: (a=()a, amit felírva a hosszakra egyértelmûen adódik
    • és disztributív a skalárra és a vektorra is: (a+b)=a+b és (+)a=a+a
Gondolom eddig nem bonyolult. Szükség van ezeknek a mûveleteknek az értelmezésére és mûveleti tulajdonságainak leírására, mert csak így számolhatunk velük. Szóval ha értelmeztük õket, akkor sokra még nem megyünk velük, mert számolni nem tudunk velük. Mivel tudjuk, hogy a térben végtelen sok vektor létezik, ezért illene találnunk egy vonatkoztatási rendszert. Ezt most intuitív módon vezetjük be, hiszen mindenki ismeri már a Descartes-féle derékszögû koordinátarendszert. Ezért nézzük mi is ez a koordinátarendszer!

Higgyük el egyelõre, hogy ha felveszünk három, egymásra merõleges i,j,k egységvektort, akkor ezek orthonormált rendszert alkotnak, és ez a három vektor bármilyen térbeli vektort elõ tud állítani a fenn értelmezett mûveletekkel(ezt hívják lineáris kombinációnak). Tehát bármely v vektorra:

v=xi+yj+zk

Ekkor i,j,k-t a Descartes-féle koordinátarendszer bázisainak hívjuk, x,y,z-t pedig, mint a lineáris kombináció skalár együtthatóit nevezhetjük a v koordinátáinak, így v megadható a v(x,y,z) alakban. Ebbõl azt a következtetést vonhatjuk le, hogy minden vektor kezdõpontját kijelölõ origót megadva, és arra felmérve három egymásra merõleges vektort egyértelmûen megadhatunk egy vektort x,y,z koordinátákkal, melyeket felhasználhatunk számolásra! Nézzük a mûveleteket a koordinátákra!
  • Az összeadás: legyen a(a1,a2,a3), b(b1,b2,b3)! Ekkor ha c=a+b, akkor c(a1+b1,a2+b2,a3+b3). Tehát az összeadást a koordinátákra elvégezve a vektorra is összeadást kapunk. Természetesen így ezek kielégítik az összeadásra kritériumait: a+b=b+a; (a+b)+c=a+(b+c); a+0=a;
  • A kivonás: a kivonást ugyancsak a koordinátákra kell elvégezni.
  • Skalárral szorzás: a skalárral szorzást is a koordinátákra kell elvégezni. =-1 esetén jól látható, hogy az additív inverzet kapjuk(-a).
Fontos, hogy minden vektor helyvektor, így az origóból a megadott koordinátájú pontba mutat. Egy pont szemléltetése vektorral jelképes, hiszen pontokat nem adhatunk össze! Mégis számoláshoz gyakran használjuk, hogy a pontokat vektorokkal adjuk meg. Így a pont távolsága az origótól a vektor hossza lesz:

ha a(a1,a2,a3), akkor |a|=(a12+a22+a32) (gyökvonás)

Ezzel meg is adtuk az alapmûveletet a vektorokra nézve, kivéve egyet: ez pedig a szorzás(mármint két vektor szorzata). Nézzük meg, hogy például az összeadás milyen mûvelet! Leírtuk ugye a mûveleti tulajdonságait, melyek lényegében az összeadás definíciói. Mivel minden térbeli vektor valamilyen rögzített koordinátarendszerben elképzelhetõ a valós számok köbének(3, ugyanis ez xx-et jelent(Descartes szorzat), ami, mint tudjuk középiskolából, rendezett számhármasokat jelent, a koordináták pedig ugyancsak rendezett számhármasok), ezért az összeadás 33 mûvelet. Azaz vektorból vektort csinál(ez például az f(a)=a+b mûveletre igaz, azaz az a vektorhoz a+b-t rendel). De szorzást kétféleképpen is megadhatunk: 33 vagy 3 , azaz vagy vektorból vektort képezõ szorzást, vagy vektorból valós számot képezõ szorzást. Az elõbbit vektoriális(cross vagy wedge product), az utóbbit skaláris szorzásnak(dot product) nevezzük. Grafikában mindkettõnek nagy jelentõsége van, a valódi szorzást viszont inkább a skaláris szorzás tükrözi. Nézzük ezeket a szorzatokat!

  • Skaláris szorzás: itt a skaláris arra utal, hogy számot kapunk(jele a pont(mint szorzás) vagy írásban semmi). A skaláris szorzás definiciója:
    a.b=|a||b|cos()
    itt az a két vektor bezárt szögét jelenti, a |a| és a |b| a vektorok hosszát.
    • Ennek a nagyon fontos következménye: két nem nullvektor akkor, és csak akkor merõleges egymásra, ha skaláris szorzatuk nulla. Tehát ha merõlegesek, akkor skaláris szorzatuk nulla, ha pedig a skaláris szorzatuk nulla, akkor merõlegesek(ezt jelenti az akkor és csak akkor).
    • Másik fontos tény: koordinátákra a skaláris szorzat, ha a(a1,a2,a3), b(b1,b2,b3): a1*b1+a2*b2+a3*b3. Azaz a megfelelõ koordináták szorzatának az összege.

  • Vektoriális szorzat: mivel az eredmény egy vektor, ezért meg kall adnunk az eredményvektor irányát és hosszát(jele a kereszt()).
    • A vektor iránya jobbkéz szabály szerint merõleges lesz a két vektor síkjára. Gondolom ez magyarázatra szorul: ha ab, akkor jobbkezünk hüvelykujja mutasson a irányába, mutatóujja b irányába, az eredmény a középsõ ujjunk iránya. Természetesen mindegyik ujjunk legyen merõleges a többire(mintha a 3-at mutatnánk, csak a középsõ ujjunk görbüljön derékszögig).
    • Hossza a vektorok által bezárt paralelogramma területe. Tehát |ab|=|a||b|sin()
    • Koordinátákra már lényegesen bonyolultabb, az alábbi determináns kifejtését igényli: legyen a(a1,a2,a3) és b(b1,b2,b3), akkor
      tehát az i,j,k együtthatói a koordináták(bázisvektorok együtthatói).
  • Szorzatok tulajdonságai:
    • Skaláris szorzás:
      • ab=ba
      • (ab)=(a)b=a(b), ahol
      • három vektorral vigyázni kell: (ab)ca(bc), mert az elsõ c-vel, a második a-val párhuzamos
      • (a+b)c=ac+bc
    • Vektoriális szorzás:
      • abba, hanem ab=-ba, tehát ellentétes irányúak
      • (ab)=ab=ab, ahol
      • (ab) ca (bc)
      • viszont disztributív: a(b+c)=ab+ac
Na, ennyit az elméletrõl, nézzünk példákat és gyakran elõforduló feladatokat! Hangsúlyozom, hogy grafika szempontjából fontos dolgokat emelnék ki, így fõleg a koordinátákkal foglalkozunk.


Vektor X tengellyel bezárt szöge(2D-s vektorok esetén)

Ez a legegyszerûbb, hiszen csupán alapvetõ matematikai észrevételt kell tennünk (ha a(a1,a2)):
. Ebbõl a szög számolható arctg-al. Pl.: a(1,2), akkor =63,43o.


Két vektor bezárt szöge

Ez is egyszerû, hiszen a skaláris szorzatot kétféleképpen is tudjuk számolni, így
a szokásos jelölésekkel(ezentúl mindig így fogom jelölni).


Vektor normalizálása

Egy vektor normalizálásán azt értjük, hogy a vektorból egységvektort csinálunk. Ezt egyszerûen úgy csináljuk, hogy elosztjuk a hosszával. Tehát ha b(b1,b2,b3), akkor . Mivel osztani nem tudunk, ezért a vektort a hosszának a reciprokával kell szorozni(persze csak elméletben, mivel a számmal való osztás a reciprokával való szorzásként definiált. Nyugodtan oszthatjuk a koordinátákat a hosszával). Az egységvektorral könnyen készíthetünk adott hosszúságú és irányú vektorokat, hiszen csak a hosszal meg kell szorozni az egységvektort(aminek az eredménye a szükséges vektor lesz).


Egy vektor merõleges vetülete egy másik vektorra

Ez is egy fontos dolog, és a skaláris szorzás másik legfontosabb alkalmazása. Legyen két vektorunk, az egyik a, a másik b. Ekkor a merõleges vetülete b-re az ábrán látható(vastagabb vonallal).


Ebbõl az látszik, hogy a vetület hossza |a|*cos(), ha a két vektor által bezárt szög. Ebbõl vetületet úgy nyerünk, ha készítünk egy |a|*cos() hosszúságú, b irányú vektort. Ehhez egy b irányú egységvektor kell, ami jelen esetben e=b/|b|. De mivel mi a két vektor koordinátáját ismerjük, ezért arra kell nekünk megoldás. Ez egyszerû, hiszen tudjuk, hogy |e|=1, így |a|*cos()=|a|*|e|*cos(). Ez pedig pont az a és a b egységvektorának, az e-nek a skalárszorzata. Ha ezzel még megszorozzuk az e-t, akkor már tényleg a vetületvektort kapjuk: (ae)e, ahol e=b/|b|.

Erre nézzünk egy példát! Legyen síkban két helyvektorunk: a(8,4) és b(15,0). Azért ezek, mert ezt ránézésbõl meg lehet mondani, hogy az a merõleges vetülete a b-re egy X tengely irányába mutató 8 hosszúságú vektor lesz. Nézzük ezt számokkal! e=b/|b|=(15/15,0/15)=(1,0)=i, ami az X irányú bázisvektorunk. Akkor nézzük: ae=8*1+0*4=8, és így (ae)e=(8*1,8*0)=(8,0). Tehát jó eredmény jött ki.


A sík

Ez egy nagyon fontos téma, így tessék figyelni. Egy síkot sokféleképpen megadhatunk egyértelmûen: megadhatjuk három nem egybeesõ és nem egy egyenesre esõ ponttal, de megadhatjuk egy irányvektorral és egy ponttal, mely nem az irányvektor egyenesére esik, de a leggyakoribb megadási módja az, hogy megadjuk egy pontját és a normálvektorát, mely merõleges a síkra. Nagyon fontos még a sík egyenlete. Egy síkidom vagy térbeli test egyenletén vagy egyenletrendszerén azt értjük, hogy az egyenletet(eket) kielégítik a test vagy a síkidom pontjai. Ez azért fontos, mert így tudunk velük számolni. Például egy pont egyenlete egyszerûen pl. x=8; y=9; z=3. Mert ezt az egyenletrendszert csak a pont koordinátái elégítik ki(a (8,9,3) pont).

Vezessük le akkor gyorsan a sík egyenletét! Legyen a sík egy pontja P(x0,y0,z0) és legyen a normálvektora n(A,B,C). Természetesen a P pontot most helyvektorként fogjuk kezelni. Egy sík egyenletének azt kell eldöntenie, hogy egy pont a síkon van-e, vagy nem? Ezt egyszerû eldönteni, hiszen a sík összes vektora merõleges a sík normálvektorára. Minden vektor, ami nem a síkon van, nem merõleges a normálvektorra. Ez elég is nekünk. De hogy csinálunk ilyen vektort? Egyszerû: legyen a vizsgálandó vektor a kérdéses pont és P pont közt. Ha ez a vektor merõleges a normálvektorra, akkor a kérdéses pont a síkon van. Tehát akkor legyen a tér egy pontja G(x,y,z). Kezeljük ezt is úgy mint egy vektort! Akkor a P-bõl a G-be mutató vektor (G-P). Ez egyszerûen a kivonás geometriai jelentésébõl következik. Tudjuk, hogy két vektor akkor, és csak akkor merõleges egymásra, ha skaláris szorzatuk nulla. Tehát alkalmazzuk ezt:

(G-P)n=0.

Ezt nevezzük a sík vektoros egyenletének. Itt P a sík egy pontja, n a normálvektora, G pedig a kérdéses pont. Ha G-re igaz ez az egyenlet, akkor a G pont a síkon van. Fejtsük ki koordinátákra ezt az egyenletet!

(x-x0)*A+(y-y0)*B+(z-z0)*C=0

amit átrendezve

A*x+B*y+C*z+D=0

egyenletet kapjuk, ahol D=-A*x0-B*y0-C*z0. D-t nevezzük a sík paraméterének. Fontos megjegyezni, hogy ha a normálvektor egységvektor, akkor –D=Pn a sík origótól való távolsága, hiszen így P n-re való merõleges vetületének a hossza az origótól való távolsága(ez pedig pontosan a P-nek és az n-nek a skaláris szorzata). Ugyancsak fontos, hogy egy pont távolságát a síktól ugyanígy tudjuk számolni. Csupán megszorozzuk a sík egység normálvektorát az a vektorral, ha a a sík egyik pontjából mutat a kérdéses pontba.

Másik fontos dolog a síkkal kapcsolatosan, hogy ha a síkot három ponttal adjuk meg, akkor ebbõl a három pontból két vektor csinálva, azok vektoriális szorzata adja a normálvektort.

Mivel a koszinusz 90 foknál vált elõjelet, ezért a skaláris szorzás jól használható síkkal való ütközésvizsgálatra. Ugyanis meg tudjuk mondani, hogy egy pont a sík melyik oldalán van. Ha a pont átkerült a másik oldalra, akkor ütközés történt. Ugyanis a sík elõbb felírt vektoros egyenlete nem nulla, ha a pont nem a síkon van, viszont a sík egyik oldalán pozitív (a normálvektor irányába), a másik oldalán negatív. De errõl majd máshol és máskor.

Ha van két vektorunk, mely a síkon fekszik(persze nem párhuzamosak), akkor azokat használhatjuk pontgenerálásra a síkon. Ekkor a sík egy pontjához kell hozzáadni a vektorok skalárszorosát:

P=P0+t1*v1+t2*v2

Ahol P egy generált pont, P0 a sík egy pontja, t1,t2 skalárok, v1,v2 pedig a sík egy-egy vektora.


Az egyenes

Egy egyenes felírása roppant fontos dolog, hiszen az egyik leggyakrabban használt geometriai fogalom. Egy egyenes megadható egy pontjával és irányvektorával. Az irányvektor tartóegyenese a kérdéses egyenes. Az egyenesnek általában a paraméteres alakját használjuk:

r=r0+t*v

Itt r az egyenes egy generált pontja, r0 az egyenes egy pontja, t skalár, v pedig az egyenes irányvektora. Természetesen itt is megadható egy egyenlet, amelynek a gyökei az egyenes pontjai, csupán ezt az egyenletet ritkán használjuk. Azért leírom ezt is! Legyen a kérdéses pontba mutató vektor r és az egyenes egy pontja r0. Legyen továbbá v az egyenes irányvektora! Ekkor ha az r pontra igaz, hogy

|(r-r0)v|=0

akkor az r pont rajta van az egyenesen. Ez logikus, hiszen párhuzamos vektorok vektoriális szorzata nulla.

Gondolom az egyenes egyenlete érthetõ, ezért inkább gyakorlati problémákkal foglalkozunk.


Egyenes és pont távolsága

A számítás már jól ismert módszer alapján történik. Legyen r0 vektor az egyenes egy pontja és r a kérdéses pontba mutató vektor és legyen v az egyenes egység irányvektora! Ekkor az egyenes egyenlete

r0+t*v
és
r-r0

vektor az egyenes egy pontjából a kérdéses pontba mutató vektor. Jól tudjuk, hogy ennek a skalárszorzata az egység irányvektorra az r-r0 vektor egyenesre vett merõleges vetületének a hossza. Ezért az

a=r0+((r-r0)v)*v

vektor a kérdéses pont egyenesre vett merõleges vetületére mutat. Ezért |a-r| a kérdéses pont és az egyenes távolsága. De nézzünk erre egy példát! Legyen egy egyenes például ilyen:


Látható, hogy ekkor az irányvektor például v(1,1), r0 mondjuk r0(0,1). De nekünk most egység irányvektor kell, ami v(1/|v|,1/|v|) és mivel , ezért v(2/2, 2/2). Ezért az egyenesünk egyenlete:

r=(0,1)+t*(2/2, 2/2)

Akkor nézzük mondjuk az r(2,0) pont távolságát az egyenesünktõl! Megkeressük a merõleges vetületét az egyenesre:

(0,1)+((2-0,0-1)( 2/2, 2/2))*( 2/2, 2/2)=(0,1)+( 2/2)*( 2/2, 2/2)=(1/2,3/2)

Tehát a (1/2,3/2) a (2,0) pont merõleges vetülete az egyenesre. Ezért a távolság:

|(1/2-2,3/2-0)|=|(-3/2,3/2)|=32/2

Egyszerû geometriai számításokkal ellenõrizhetõ a számítás helyessége.


Sík és egyenes metszéspontja

Ilyen esetben mindig venni kell az egyik egyenletét, és be kell helyettesíteni a másik összes pontját. Így megkaphatjuk a metszéspontot. Nézzük ezt az

r=r0+t*v

egyenesre(szokásos jelölés) és az

(r-P)n=0

síkra (r a kérdéses pont, P a sík egy pontja, n a normálvektora). Szándékosan írtam mindkettõbe r-et, hiszen r-et elõállíthatjuk, mint az egyenes összes pontját, és minden r pontról megállapítható, hogy rajta van-e a síkon. Ezért a dolgunk egyszerû behelyettesítés. Most látni fogjuk az elõnyét annak, hogy megnéztük a mûveleti azonosságokat a skaláris szorzásnál! Helyettesítsünk be, majd t-t kifejezve, majd kiszámolva és beírva az egyenes egyenletébe megkapjuk a metszéspontot. Ugyanis minden pont az egyenesen rendelkezik egy t paraméterrel, így mi a metszéspont t paraméterét kapjuk meg. Tehát:

(r0+t*v-P)n=0

Mivel (a+b)c=ac+bc a skaláris szorzásra, ezért ezt alakítva:

t*vn+(r0-P)n=0

Ebbõl, mivel (r0-P)n skalár lesz (azaz szám), ezért átvihetjük a túloldalra:

t*vn=-(r0-P)n

Természetesen vn-el leoszthatunk, mert az ugyancsak egy skalár lesz(számmal pedig oszthatunk). Mivel (ab)=(a)b=a(b), ezért a mínusz jelet bevihetjük a jobboldalon a zárójelbe:


Nyilván ezt visszaírva az eredeti egyenes egyenletbe, a metszéspontot kapjuk. Nem szükséges egységvektorokat használnunk.


Pont helyzetének vizsgálata

Ez egy nagyon egyszerû probléma, hiszen csupán az a kérdés(pillanatnyilag), hogy egy pont egy egyenes melyik oldalán van(fontos, hogy síkban legyen az egyenes és a sík, ami egy egyenes esetén mûködik is, de többnél feltétlenül egy síkban kell lenniük) . Ha több egyenes egy síkban van, és például egy háromszöget alkotnak, akkor ezzel a módszerrel meg tudjuk vizsgálni, hogy a pont a háromszögbe esik-e. A megoldás módja nagyon egyszerû(vízszintes sík esetén): ha a pontba az egyenesbõl egy vektort húzunk, akkor az egyenes irányvektorának és ennek a vektornak vektoriális szorzata az egyik oldalon lefele mutat, a másik oldalon felfele. Ha ezt a vektort szorozzuk a sík normálvektorával, akkor egy számot kapunk(skaláris szorzás). Ha ez nulla, akkor a pont az egyenesen van, ha negatív, akkor az egyik oldalán, ha nagyobb, mint nulla, akkor a másik oldalán. Például legyen egy vízszintes sík, felfelé mutató normálvektorral(n), és rajta egy befele mutató irányvektorú egyenes(v). A tõle balra lévõ pontokra számítva az elõbbi gondolatmenetet(ha az egyenesbõl a pontba mutató vektor r):

vr

lefele mutat, majd erre:

(vr)n<0

Az egyenestõl jobbra ez pozitív.


Ennyit a vektorokról, ezután lineáris algebrával foglalkozunk. Természetesen, ha eszembe jut valami még, akkor bõvítem ezt a dokumentumot!

Vektor-elmélet és gyakorlat: matek1.exe


Kapcsolódó linkek:
   Crusader DirectX programozás honlapja
   Itt található Crusader összes tutoriáljának eredetije.


A cikksorozat további részei:
DirectX programozás 1. - Bevezetés, Windows ablak létrehozása, Idõzítõ
DirectX programozás 2. - DirectDraw inicializálása, használata
DirectX programozás 3. - DirectDraw megjelenítés 1.
DirectX programozás 4. - DirectDraw megjelenítés 2.
DirectX programozás 5. - Izometrikus grafika
DirectX programozás 6. - Matematika összefoglaló 1.
DirectX programozás 7. - Matematika összefoglaló 2.: Lineáris algebra
DirectX programozás 8. - DirectInput
DirectX programozás 9. - DirectSound, Ogg Vorbis lejátszás
DirectX programozás 10. - Izometrikus grafika 2.
DirectX programozás 11. - Objektumorientált programozás

Értékelés: 0

Új hozzászólás
Nincs megjegyzés