Fizikai szimuláció és ütközésdetektálás Önálló laboratórium
Készítette: Rózsa Tamás
2008. május 15.
Budapesti Műszaki és Gazdaságtudományi Egyetem Villamosmérnöki és Informatikai Kar
Tartalomjegyzék
1. Bevezetés ............................................................................................................... 2 2. Specifikáció............................................................................................................. 3 3. Fizikai alapok .......................................................................................................... 4 4. Implementáció...................................................................................................... 12 5. Fejlesztési, bővítési lehetőségek............................................................................ 15 6. Irodalomjegyzék ................................................................................................... 16
–1–
1. Bevezetés A számítógépes grafika jelentőségét nem is kell említeni – napjainkban rengeteg alkalmazás működik valamilyen képfeldolgozáson és/vagy megjelenítésen alapuló módszerekkel, elég csak például az orvosi alkalmazásokra gondolni. A számítógépek fejlődésének egyik nagy hajtóereje a játékok. Ezeknél ugyanis minél élethűbb képet, sőt mozgásokat, animációkat szeretnénk megjeleníteni, ami rengeteg, több milliós nagyságrendű műveletvégzéssel járhat másodpercenként. Ezért fontos, hogy a megjelenítés ne csak szép és valóságos legyen, hanem mindez gyorsan is történjen. Jelen dokumentumban egy fizikai szimulációs program működésének alapjait mutatom be, amely egy ház összeomlását szimulálja.
–2–
2. Specifikáció 2.1. A kitőzött feladat A feladat épület összeomlásának vizsgálata. Az épület kezdetben egyszerű, szabályos téglatest alakú téglákból áll, és – egyelőre – nem tartalmaz ajtót, ablakot, gerendát, stb., de a program moduláris felépítésének köszönhetően ezek figyelembevétele nincs kizárva, így egy későbbi feladatban esetlegesen beépíthetők. Az összeomlás akkor a legszemléletesebb, ha a ház magas, toronyszerű. Egy egységes, felépített ház önmagától nyilvánvalóan nem omlik össze, tehát valamilyen fizikai hatást kell keltenünk a szimulációhoz. Ez többféleképpen történhet: az egyik lehetséges eset, hogy egérkattintással kijelölünk téglákat, amiket aztán „kiveszünk” a házból. Ha emiatt a stabilitás megszűnik, nyomonkövethetjük az összedőlést. (Ez a szimulációs forma a jelenlegi változatban nincs implementálva.) Egy másik lehetséges esetben egy nagy tömegű tárgyat nekiütköztetünk a ház falának, és ha az ütközés elég nagy erejű, megindíthatja az összeomlást. Ennek valóságalapja lehet az az eset, amikor egy kamion belerohan az épületbe. A feladat megoldásában egy nagy tömegű tárgyat ejtünk a magasból a ház falára. További funkciók: annak érdekében, hogy a szimuláció különböző nézetekből nyomonkövethető legyen, a nézet a program futása közben bármikor változtatható a billentyűzet segítségével (a kamera pozíciója, a nézeti irány, közelítés/távolodás, stb.). A szimuláció továbbá bármikor megállítható, majd folytatható.
2.2. A megvalósításhoz választott eszközök A megvalósítás C++ programozási nyelvvel történt. Ennek egyik – legfontosabb – oka, hogy lehetővé teszi a grafikus elemek OpenGL-lel (1.3-as változat) való megjelenítését, továbbá támogatja az objektum-orientált szemléletet. Ez utóbbi azért fontos, mert így a program könnyen bővíthetővé, kiterjeszthetővé vált, aminek köszönhetően további esetek, különböző feladatok implementálhatók, vagy egyes részek könnyen átemelhetők más szimulációs programokba is. Az ablakozás GLUT segítségével történik, ezzel függetlenítve azt az operációs rendszer típusától. Fejlesztőeszköznek a Microsoft Visual Studio 2008-as változatát választottam, mert rengeteg felhasználóbarát funkcióval rendelkezik (például IntelliSense), ami nagy mértékben megkönnyíti a fejlesztést.
–3–
3. Fizikai alapok 3.1. Bevezetés A megvalósítandó program magas szinten a következő három dolgot végzi el a szimuláció során: ütközések detektálása ütközés esetén az ütközésválasz számítása objektumok állapotának frissítése az előzők és egyéb hatások (gravitáció) figyelembevételével A következőkben ezen hatások vizsgálatával folytatjuk.
3.2. A test állapotvektora A programban minden objektum rendelkezik saját állapotvektorral, amelyet az aktuális térbeli helyzetének ill. a mozgásállapotának leírására használunk. Az állapotvektor megválasztása több módon is történhet, azonban legkézenfekvőbbnek, vagy legkönnyebben kezelhetőnek talán az a változat tűnik, amely a következő elemeket tartalmazza: r 1. a test tömegközéppontjának koordinátái ( c ) 2. a test orientációs mátrixa ( A ) r 3. a test impulzusvektora ( I ) r 4. a test impulzusmomentum-vektora ( J ) Az 1. és 3. jellemző az egyenes vonalú, míg a 2. és 4. jellemző a forgómozgásból származik. Más csoportosítás szerint az 1. és 2. jellemző a test térbeli elhelyezkedését írja le, a 3. és 4. pedig a mozgásállapotát. Megjegyzés (1): Tekintsünk egy szabadon eső testet, ami a gravitáció hatására gyorsul, és csak függőleges irányú sebességkomponense van. A kirajzoltatáshoz ebben az egyszerű esetben is el kell tárolni a pozíció mellett az impulzust is, mivel a programműködés alapja az, hogy adott időközönként – amikor az operációs rendszer meghívja a rajzoltató függvényt – egyenletes mozgással közelítjük a gyorsuló mozgást is. A következő iterációban a legutóbb kiszámolt sebességhez, mint kezdősebességhez fog hozzáadódni az aktuális – rövid ideig tartó változásból származó – sebességváltozás. Megjegyzés (2): A testekhez egy-egy lokális koordináta-rendszert rendelünk, melynek origója a test tömegközéppontja. Így a testre vonatkozó vektorok és fizikai törvények sok esetben sokkal könnyebben írhatók fel, és nagy mértékben megkönnyítik a számítást. Az orientációs mátrix ezen koordináta-rendszer bázisvektorainak világkoordináta-rendszerben felírt változatait tartalmazza (a bázisvektorok háromelemű sorvektorok, ebből három kerül egymás alá).
3.3. Ütközésdetektálás A mozgás következtében ütközés jöhet létre a színtérben szereplő objektumok között. A program jelenlegi változatában két típusú objektum van: a talaj és a téglák. Az egyszerűség kedvéért a talajt egy végtelen tömegű és tehetetlenségi nyomatékú, végtelen oldalhosszúságú és
–4–
végtelen kis magasságú téglatestnek tekintjük, így a számítások rá is hasonlóan végezhetők, mint a téglára. Ütközésdetektálásra a szituációtól függően számos algoritmus létezik. Az alapvető módszer, ami a programban szerepel, az objektumok éleit veti össze a többi objektum lapjaival, vagyis (korlátozott) síklapok és egyenesek (szakaszok) metszéspontját számítja ki, amennyiben az létezik – ellenkező esetben nem jelent ütközést. A következő (3.3.1.) fejezetben tehát a poliéder-poliéder ütközésvizsgálattal foglalkozunk.
3.3.1. Poliéder-poliéder ütközésvizsgálat Ahogy az már korábban említésre került, ez az algoritmus minden objektumra megvizsgálja, hogy az összes többi objektummal történt-e ütközés, vagyis az első objektum összes élét össze kell vetni a másik objektum összes lapjával. Az algoritmus egyszerűsített pszeudo-kódja a következő lehet: ütközésvizsgálat o1 és o2 objektumok között { o1 éleinek lekérdezése; o2 lapjainak lekérdezése; o1 minden élére { o2 minden lapjára { lap normálvektorának lekérdezése; ha az él két végpontja a lap különböző oldalán van { sík és egyenes metszéspontjának számítása; ha a metszéspont a lapon belül és az élen (mint szakasz) helyezkedik el { ütközés jelentése; } } } } } Annak eldöntése, hogy az él két végpontja a lap különböző oldalán helyezkedik el, az alábbiak szerint történhet: Ha f a sík egy pontjába mutató helyvektor, e1 és e2 az él két végpontjába mutató vektorok, akkor r r r r r r amennyiben az n ⋅ e1 − f és az n ⋅ e2 − f skalárok előjele ellentétes, vagyis hányadosuk 0-nál kisebb, akkor a pontok ellentétes oldalon helyezkednek el, különben nem. Ezután vizsgálandó az egyenes és sík metszéspontja, amely elemi geometriai módszerek alapján a következőképpen történhet: r r r A metszéspontba mutató vektor: e2 + a ⋅ (e1 − e2 ) Amennyiben az a valós paraméter 0 és 1 közötti, úgy a metszéspont a szakaszon belülre esik. Ebben az esetben azt kell még eldönteni, hogy nemcsak a síkon, hanem a lapon (korlátos síkon) belül vagyunk-e. Ez eldönthető például úgy, hogy ellenőrizzük, a metszéspontból a lap éleinek látószögei
(
)
(
)
–5–
kiadják-e összességében a 360°-ot. Másik módszer: az e1, e2 pontokon áthaladó él és egy r r r r tetszőleges p pont esetén az (e2 − e1 ) × ( p − e1 ) vektor az egyik esetben a lap normálvektorával megegyező, míg a másik esetben azzal ellenkező irányba fog mutatni. Ezt kifejezést a normálvektorral szorozva tehát egyik esetben pozitív, másik esetben negatív eredményt kapunk. Amennyiben mind a négy élre ez a kifejezés nemnegatívnak adódik, úgy a négyszögön (lapon) belül van a metszéspont.
3.3.2. Az ütközésvizsgálat pontatlanságából eredő problémák és azok megoldásai Az egyik nagyon fontos probléma a pontatlanságból ered. Mivel a rendszer diszkréten működik, vagyis a rajzoló függvényt bizonyos időnként az operációs rendszer hívja, csak diszkrét időpillanatban tekinthetünk a rendszerre, ami azt jelenti, hogy nagy valószínűséggel az ütközésdetektálásnál észlelt ütközési pont nem a tényleges ütközési pont.
3.1. ábra A 3.1. ábrán látható, hogy amennyiben a tégla (az ábrán előlnézetben ábrázolt téglatest látható) fentről érkezett, és ott még nem ütközött semmilyen más tárggyal, előfordulhat, hogy a következő pillanatban, amikor lehetőségünk lesz a rendszerre pillantani, az objektum már túlhaladt a tényleges ütközési ponton. Szerencsés esetben ez csak a pontatlanságot növeli kisebb-nagyobb mértékben, azonban előfordulhat akár olyan eset is, hogy két objektum áthaladt egymáson, és az ütközést elmulasztottuk (gondoljunk például arra, hogy egy nagyon kis test nagyon nagy sebességgel esik lefelé). A problémán segíthet az ún. folytonos ütközésvizsgálat használat, mely során nem csak diszkrét időpillanatokban figyelnünk, hanem a fizika folytonos egyenleteit felhasználva végig nyomon követjük az objektum pályáját. Ezzel akár az ütközés pontos pillanata is meghatározható. Mivel azonban a végső programba ez az algoritmus nem került bele, a további részletek ismertetésére itt most nem kerül sor. A pontatlanság felvet egy újabb problémát is, nevezetesen azt, hogy olyan is előfordulhat, hogy az egyik iterációban a fentről érkező és talajjal ütköző tégla a 3.1. ábrán látható pozícióból indul el felfelé. Ez akkor probléma, ha a következő iterációban a tégla feljebb, de még mindig a sík lapja alá kerül, hiszen ekkor egy újabb ütközést detektálunk, holott fizikailag nem jött létre új kölcsönhatás. A probléma megoldható, ha minden objektumról tudjuk, hogy mely más objektumokkal ütköztek az előző iterációban, és ha kétszer egymás után ugyanazon objektumok ütközését detektáljuk, akkor abból kiindulva, hogy ez bizonyára egyetlen ütközés eredménye, nem számítunk
–6–
újabb ütközésválaszt. Ez a módszer így azonban még nem teljes: gondoljunk egy, a csúcsára érkező téglára. Ekkor azt várhatjuk, hogy a leérkezett csúcs a talajon (talajban) marad, és addig fordul a tégla, míg az alsó lap egy másik csúcsa el nem éri a síkot. Ha azonban az első csúcs nem emelkedik a talaj síkja felé, akkor – mivel a „tiltólista” alapján nem számítunk ütközést – ahelyett, hogy megállna (vagy akár egy kicsit visszapattanna – ez az ütközés rugalmasságától függ), a tégla bele fog fordulni a síkba! Ne csak azt tároljuk el az objektumokról, hogy mely másikakkal ütközött, hanem azt is, hogy mi volt az ütközési pont. Ha az előző példánál maradunk, akkor eltároljuk, hogy a tégla pl. elülső lapján lévő bal alsó sarka ütközött a talajjal, így lehetővé tesszük, hogy a jobb oldali sarok ütközését viszont már detektálhassuk. Megjegyzés: kezdetben az objektum ütközési listája üres. Ha detektálunk egy ütközést, az felkerül az adott objektum listájára, és kiszámítjuk az ütközésválaszt. Ha a következő iterációban is ugyanazt az ütközést detektáljuk, akkor nem végzünk újabb műveleteket, ha viszont már nem detektálunk ütközést, akkor az előzőt el kell távolítani a listáról. Ezzel tesszük lehetővé például, hogy egy pattogó labda többször is visszapattanhasson. Szintén a pontatlanság okozza a következő problémát: ha egy tégla a „talajjal párhuzamosan” érkezik, és kis mértékben belesüllyed, akkor 4 ponton detektálunk ütközést, amire az egyszerű algoritmus 4 ütközésválaszt számol (egy másik teljesen hasonló esetben, ötszög alapú hasábnál viszont már 5 ütközésválaszt számítana). Ha a tégla csúcsára érkezik (3.2. ábra), akkor 3 él metszi a síkot, amire pedig 3 ütközésválaszt számolna a program. Ez így nyilván nem működik (az objektum a többszörös számítás miatt olyan nagy impulzust kapna, hogy magasra elszállna).
3.2. ábra Egy egyszerű közelítést alkalmazva azonban a probléma orvosolható: az ütközési pontokba mutató vektorokat átlagoljuk, vagyis a vektorokat összegezzük, majd ezt elosztjuk az ütközések számával, és erre a pontra számítunk egyetlen ütközést. Lapjára érkező téglatest esetén a lap középpontjára (súlypontjára), csúcsára érkező tégla esetén a sík és a tégla metszetében lévő háromszög súlypontjára fogjuk az ütközést számítani (3.2. ábra). Ez utóbbi esetben minél korábban detektáljuk az ütközést, annál inkább a csúcsba mutató vektort fogunk kapni. A tégla háromféleképpen érkezhet: csúcsára, élére vagy lapjára. A fenti közelítés minden esetben helyes eredményt ad. (Ha ennél is pontosabb eredményre lenne szükségünk, az algoritmus
–7–
kiegészíthető oly módon, hogy felismerje, éppen melyik csúcspontról, élközépről vagy lapközépről van szó.)
3.3.3. Az ütközésvizsgálat számításigénye és a szimuláció gyorsítása A 3.3.1. fejezetben leírt algoritmus másik jelentős gondja a számításigény. Gondoljunk bele, hogy minden egyes iterációban minden objektumot össze kell vetni az összes többivel, és megvizsgálni, hogy az egyik objektum összes éle közül valamelyik (akár több is) metszi-e a másik objektum összes lapjának valamelyikét (akár többet is). Csupán tájékoztató jelleggel: egy 2.8 GHzes Pentium processzoron egy tégla és talaj esetén még nem tapasztalható lassúság, azonban egy 100 darab téglából álló épület esetén körülbelül 2-3 másodperc telik el, míg a program egy gombnyomásra reagál. Mindenképpen szükséges tehát valamilyen gyorsítás eszközölése, hiszen például egy játék esetén ekkora késleltetés semmiképpsem engedhető meg, ráadásul akár több objektumból is felépülhet a színtér. Az egyik nagyon egyszerű és könnyen implementálható módszer az ún. befoglaló gömbök (bounding spheres) alkalmazása (3.3. ábra). Az algoritmus lényege, hogy a test középpontjából megkeressük a legtávolabbi csúcsot, majd a középpontból ennek a távolságnak megfelelő sugarú gömböt képzelünk az objektum köré, és ezzel az ütközésvizsgálat annyiból áll, hogy ellenőrizzük, a távolság nagyobb-e a sugárnál, vagy nem. (Sík esetén a „távolság” a síklap, valamint a gömbközéppont sugárral csökkentett távolsága, két befoglaló gömb esetén a gömbközéppontokba mutató helyvektorok különbségének hossza, a két sugárral csökkentve.)
3.3. ábra Egy másik, szintén egyszerű és gyors algoritmus a – tengelyekkel párhuzamos oldalélű – befoglaló dobozok (axis aligned bounding boxes – AABB) algoritmus (3.4. ábra).
3.4. ábra Egy AABB-t hat skalárral írhatunk le: a befoglalandó objektum pontjai közül minimális és maximális értékű koordinátákkal (téglatest esetén elég a csúcsok koordinátáinak minimumát ill.
–8–
[
]
[
]
2 2 2 2 2 2 maximumát vizsgálni). Az x1min , y 1min , z 1min , x 1max , y 1max , z 1max és x min , y min , z min , x max , y max , z max AABB-k
akkor metszik egymást, ha valamennyi alábbi egyenlőtlenség fennáll: 2 2 2 2 2 2 x1min ≤ x max , x1max ≥ x min , y 1min ≤ y max , y 1max ≥ y min , z 1min ≤ z max , z 1max ≥ z min
Megjegyzés: Téglatest esetén triviálisnak tűnhet, hogy ezt a módszert célszerű alkalmazni (téglát téglával veszünk körül), azonban fontos, hogy a befoglaló alakzat élei a világkoordinátarendszerrel párhuzamosak, így ferde helyzetű tégla esetén akár nagyobb térfogatot is kaphatunk, mint a befoglaló gömbök esetén. Azért is szükséges további ütközésvizsgálat (például a 3.3.1. fejezetben leírt), mert ez a módszer csak az ütközés tényét jelenti, például metszéspontot nem tudunk ilyen módszerrel számítani. Mindkét módszerre elmondható általánosságban, hogy ütközés esetén háromszor kell (célszerű) számolni: először a befoglaló alakzatokat vizsgáljuk, ha ezek ütköznek, akkor az egyik testet a másik befoglaló alakzatával vetjük össze, majd ha ekkor is van metszés, csak akkor végezzük el a tényleges alakzat-alakzat ütközésvizsgálatot. Így még mindig rengeteg számítást spórolhatunk meg. Hogy mikor melyik gyorsító eljárást célszerű alkalmazni, az a felhasznált alakzatoktól függ. A talajnak például borzasztó nagy a befoglaló gömbje, míg az AABB-je tökéletesen használható. Mégis, összehasonlításképpen: a gyorsítás nélküli házösszeomlásnál tapasztalt 2-3 másodperces késleltetés befoglaló gömböket alkalmazó algoritmussal kb. fél másodpercre redukálódott.
3.4. Ütközésválasz Ha objektumok ütközését detektáltuk, ki kell számítani, hogy az ütközés hogyan változtatta meg a testek állapotvektorát. A mozgást felírhatunk egy egyenes vonalú és egy forgómozgás összegeként. Így egy p pont r r r r sebessége v P = V P + ω P × rP , ahol VP az egyenes vonalú mozgásból származó sebesség, ωP a forgómozgásból származó szögsebesség, rP pedig a test tömegközéppontjából a P pontba mutató vektor. Ha az ütközés alatt átlagosan F erő ébredt, akkor a hatás-ellenhatás törvény (III. Newtonr r törvény) értelmében az egyik testre F ⋅ n , a másik testre − F ⋅ n erő hat, ahol n jelöli az ütközési normálist (él-lap metszés esetén, ami a program jelenlegi változatában előfordulhat, a lap normálvektora lesz az ütközési normális). A testre azonban forgatónyomaték is hathat, így az el is r r r r fordulhat. Az egyik testre rA × (F ⋅ n ) , a másik testre − rB × (F ⋅ n ) forgatónyomaték hat, annak a fontos észrevételnek a figyelembevételével, hogy olyan „egyszerű” rendszer esetén, mint amilyennel a ház összeomlását szimuláljuk, a forgás középpontja a test tömegközéppontja lesz. (Első megközelítésben talán azt hihetnék, hogy az ütközési pont körül fog fordulni a téglánk, de ez csak abban az esetben lenne így, ha ez valamilyen kényszerből következne. A mi esetünkben nincs rögzítés, és más kényszer sem áll fenn, a téglatest forgása a három, tömegközépponton átmenő főtengelyek körüli forgás szuperpozíciójaként fog előállni – 3.5. ábra.) A fizika törvényei alapján ismerjük az alábbi összefüggéseket: r r r ∆I = F∆t ⋅ n = m ⋅ ∆V (impulzusvektor változása) r r r r ∆J = F∆t ⋅ r × n = Θ(t ) ⋅ ∆ω (impulzusmomentum-vektor változása)
–9–
amiből az ütközés utáni sebességek és szögsebességek írhatók fel. Az impulzusmomentum képletében szereplő Θ mátrix a test tehetetlenségi mátrixa. Korábban már megállapítottuk, hogy a tégla csak a három főtengelye körül fordulhat el, így ennek tehetetlenségi mátrixában csak a főátlóban lesznek elemek, mégpedig:
Θ téglatest
m(b 2 + c 2 ) / 12 0 0 = 0 0 m(a 2 + c 2 ) / 12 2 2 0 0 ( + ) / 12 m a b
Fontos észrevétel továbbá, hogy a tehetetlenségi mátrix orientációfüggő. A téglatest létrehozásánál megadjuk a fenti mátrixot, majd az orientáció változásakor a Θ’=AT·Θ·A képlet szerint dolgozhatunk.
3.5. ábra
r r r Ha a testek ütközés előtti relatív sebessége v= n ⋅ (v A − v B ) volt, akkor – ütközés után r r r egymástól távolodva – a relatív sebesség − b ⋅ n ⋅ v A' − v B' lesz, ahol b a 0 és 1 közötti rugalmassági tényező, vagyis itt van lehetőségünk az energiaelnyelődést figyelembe venni. A két kifejezést r r r r r r egyenlővé téve, némi átrendezést követően az n ⋅ v A' − v B' − n ⋅ (v A − v B ) = −(1 + b)v egyenletre jutunk. Ebbe behelyettesítve, valamint felhasználva a korábbi fizikai összefüggéseket, átrendezéseket követően az alábbi egyenletre jutunk:
(
)
(
F∆t=
1 mA
)
− (1 + b ) r r r r r r −1 + n ⋅ Θ A (t )rA × n × rA + m1B + n ⋅ Θ −B1 (t )rB × n × rB
(
)
(
)
amiből fel tudjuk írni az impulzusvektor és az impulzusmomentum-vektor változását, amiből pedig meghatározhatjuk a testek új sebességeit, szögsebességeit, vagyis elvégezhetjük az állapotvektorok aktualizálását, mégpedig a következő módon: r r ω = Θ −1 (t ) ⋅ J r r I (t ) c+ = ∆t m r T A + = A ⋅ [ω ×] ⋅ ∆t r r I ± = F∆t ⋅ n r r r J ± = F∆ t ⋅ r × n ahol a ± jel jelentése, hogy az egyik testhez tartozó vektor esetében hozzáadódik, a másikéban levonódik a számított mennyiség. – 10 –
Megjegyzés: a számítási pontatlanságok miatt az orientációs mátrixot minden lépésben normalizálni kell, vagyis ügyelni kell rá, hogy a sorvektorai egységnyi hosszúak, illetve egymásra merőlegesek legyenek. Pontosabb eredmény érhető el, ha nem orientációs mátrixszal, hanem kvaterniókkal számolunk.
– 11 –
4. Implementáció Ebben a fejezetben az előző fejezetekben összefoglaltak alapján tömören bemutatásra kerül az elkészített program. A program egy nagyon leegyszerűsített osztálydiagramja:
World
Main
Camera
Object
Brick
Plane 4.1. ábra
Fontosabb függvények és osztálytagok rövid ismertetése Main int main(int argc, char * argv[])
a program belépési pontja World void startstop()
a szimuláció szüneteltetése Enter lenyomására a következő Enterig void buildHouse(int a, int b, int h)
a paramétereknek megfelelő számú téglából álló házat épít void actualize(Object* obj, float dt)
az adott objektum állapotvektorát frissíti void collisionResponse(Object* obj1, Object* obj2, Vector cp, Vector n)
kiszámolja a két objektum megadott pontban megadott ütközési normálissal létrejövő ütközésválaszt int collisionDetection(Object* obj1, Object* obj2)
a két objektum között számolt ütközések számával tér vissza (0 is lehet) bool collisionDetectionWithBSs(Object* obj1, Object* obj2)
megadja, hogy a két objektum befoglaló gömbjeivel történt-e ütközés void animate(float dt)
az animációs függvény, amely az operációs rendszer hívásakor lefut void render()
az objektumok rajzolófüggvényeit hívja meg – 12 –
Camera void zoom(float amount)
nagyít (a paraméterérték előjele határozza meg a nagyítást/kicsinyítést) void movevertical(float amount)
kamera mozgatása függőlegesen void movehorizontal(float amount)
kamera mozgatása vízszintesen void pitch(float degree=1)
kamera döntése y-tengely körül void yaw(float degree=1)
kamera döntése x-tengely körül Object float m
tömeg Matrix theta
tehetetlenségi mátrix (időben változik) bool gravity
az adott objektumra hat-e a gravitáció (így küszöbölheti ki pl. a talaj leesése) Vector r
tömegközéppontba mutató vektor Frame frame
lokális koordináta-rendszer bázisvektorait tartalmazza (orientációs mátrix) Vector I
aktuális lendületvektor Vector J
aktuális impulzusmomentum-vektor virtual Face* getFaces()
objektum lapjait adja vissza virtual Edge* getEdges()
objektum éleit adja vissza virtual Vector* getVertices()
objektum csúcspontjaiba mutató vektorokat adja vissza virtual float getBSradius()
befoglaló gömb sugarát adja meg virtual void renderModel()
objektum kirajzolásáért felelős
– 13 –
Képek a program működéséről
4.2. ábra – Felépült ház
4.3. ábra – Ház összeomlás közben (a nagy tégla ráesett)
– 14 –
5. Fejlesztési, bővítési lehetőségek A megvalósított program számos bővítési, fejlesztési lehetőséggel rendelkezik, amely – többek között – az objektum-orientált szemléletnek köszönhetően remélhetőleg könnyen kivitelezhető. Ilyen lehetőségek például: Közelítő megoldások pontosítása, ha szükséges (például az ütközési pont meghatározása jelenleg közelítően, átlagolással történik) „Szépítés” – fényforrások elhelyezhetők ill. a téglák és a talaj is textúrázható OpenGL segítségével Gyorsítás Minden felesleges számítást mellőzni kell Gyorsító algoritmusok – például az AABB módszer fejlesztése oly módon, hogy ne feltétlenül csak tengelyekkel párhuzamos befoglaló doboz létezhessen, hanem más orientációjúra is működjön hatékonyan Hardveres gyorsítás támogatása – programozás GPU-ra Súrlódás, légellenállás és egyéb fizikai hatások figyelembevétele Konkáv poliéderek vagy szabálytalan alakú testek vizsgálata
– 15 –
6. Irodalomjegyzék [1] Háromdimenziós grafika, animáció és játékfejlesztés SZIRMAY-KALOS LÁSZLÓ, ANTAL GYÖRGY, CSONKA FERENC Computerbooks, 2006 [2] Ageia PhysX internetes leírás http://developer.nvidia.com/object/physx.htm http://www.iit.bme.hu/~szecsi/PhysXlab.html [3] Programozzunk C nyelven! BENKŐ TIBORNÉ, BENKŐ LÁSZLÓ, TÓTH BERTALAN Computerbooks, 2004 [4] Programozzunk C++ nyelven! TÓTH BERTALAN, LAPTEVA NATALIA Computerbooks, 2006 [5] http://www.techonthenet.com/
– 16 –