View Frustum oldalainak normál vektora

View Frustum oldalainak normál vektora
2016-09-19T17:43:30+02:00
2016-09-25T18:05:16+02:00
2022-08-10T08:20:32+02:00
KovacsA
Üdv!

3D-ben és játékkészítésben jártas személyek segítségét szeretném kérni bonyolult matekos elméleti dolgokhoz. :D

Elkeztem írni egy 3D játékot, ahol ugyebár sokat lehet optimalizálni, ha egyáltalán nem számolunk azzal, ami a kamera (vektor) látóterén kívül esik. Ennek az oldalai nálam síkokként kezelődnek, amikhez a programnak szüksége van a normál vektorokra.

Kell valami képlet vagy segítség, hogy ezeket hogyan tudom meghatározni, nem találtam semmit ami segítene az interneten. A felső-alsó már megvan, inkább az oldalsók kellenek.

Ha ez segít, van még valami, de nem m:

Van egy sajátos koordinátarendszerem, amiben yaw,pitch szögekkel bármilyen irányt megadhatok valahogy így: (csatolva) Az EAngle alakítja át ezeket koordinátákká


yaw az egy elfordulás mindig a függőleges (z) tengely körül, a pitch mindig ehhez képest a fel-le irány a z tengely felé. (Ahogy egyébként minden játék működik)
A kamerának tudjuk az irányát, mindenét, de konkrét helyekre nincs szükség most


Kód, hogy hol tartok most: (Java)

Plane[] sides = new Plane[4]; // represent the 4 sides of the frustum Plane znear; // the z-near plane EAngle left, top, right, bottom; public void update(){ float angle_verticalt = (float) (Math.atan2(Main.height/2+Main.Frame.getY(),Game.zoom)); float angle_verticalb = (float) (Math.atan2(Main.height/2-2*Main.Frame.getY(),Game.zoom)); float verRott = (float) (Math.toDegrees(angle_verticalt))-90.0f; float verRotb = (float) (Math.toDegrees(angle_verticalb))-90.0f; // left sides[0].normal = ??????????????? sides[0].distance = sides[0].normal.DotProduct(Game.ViewFrom[0], Game.ViewFrom[1], Game.ViewFrom[2]); // right sides[1].normal = ??????????? sides[1].distance = sides[1].normal.DotProduct(Game.ViewFrom[0], Game.ViewFrom[1], Game.ViewFrom[2]);*/ // top top.yaw = Game.ViewAngle.yaw; top.pitch=Game.ViewAngle.pitch+verRott; sides[2].normal = top.toVector(); sides[2].distance = sides[2].normal.DotProduct(Game.ViewFrom[0], Game.ViewFrom[1], Game.ViewFrom[2]); // bottom bottom.yaw = Game.ViewAngle.yaw; bottom.pitch=Game.ViewAngle.pitch-verRotb; sides[3].normal = bottom.toVector(); sides[3].distance = sides[3].normal.DotProduct(Game.ViewFrom[0], Game.ViewFrom[1], Game.ViewFrom[2]); // z-near clipping plane znear.normal = Game.ViewVector; znear.distance = znear.normal.DotProduct(Game.ViewFrom[0]*1.01f, Game.ViewFrom[1]*1.01f, Game.ViewFrom[2]*1.01f); }
verticalt, verticalb a felső-alsó látószög. Azért ilyen macerás, mert bele kell venni, hogyha nem teljes képernyőn fut, meg utána 90 fokkal forgatni, hogy merőleges legyen. ViewAngle a kamera iránya, ViewFrom a kamera helye

Köszönöm mindenkinek aki tud valamennyit segíteni!
Mutasd a teljes hozzászólást!
Csatolt állomány
Mit használsz a megjelenítéshez? Ezt a vágást jellemzően a render engine szokta megoldani, nem kell kézzel.

Viewing frustum - Wikipedia, the free encyclopedia
A near és far lapokat gondolom meg tudod határozni (a kamera lookat-je írányában a fov alapján egy mátrixszorzással adódik).
Ha megvan a lap, akkor megkeresheted a projektív síkon egy pontba eső sarkokat a near és far lapokon, azok között egy kivonással be tudod húzni az irányvektort, arra meg az up vektor irányába húzol egy merőlegest a felső laphoz, ellentétes irányba az alsó laphoz, a right vektor irányába a jobb laphoz és ellentétesen a bal laphoz és megvannak a normálvektorok.

Amúgy nem szokás kiszámolni a frustrum alkotóinak az egyenleteit, elég szokott lenni távolság- és iránybecslésekkel (befoglaló gömb alapján) vágni, NDC-ben.
Mutasd a teljes hozzászólást!

  • Igen, azt nem említettem, hogy nem használok semmilyen engine-t 

    Az a baj, hogy nincs meg a left,right vektor még
    Mutasd a teljes hozzászólást!
  • Akkor azokat számold ki. (Ha az up megvan, akkor a left/right is megvan...)
    Nem jó ötlet a frustumra vágni, túl sok műveletet igényel és lehet, hogy eldob olyan dolgokat is, amelyekkel számolni kellene.

    Amúgy ha saját motort írsz, miért nem választottál valami alkalmas eszközt a célra? Java, komolyan? 
    Mutasd a teljes hozzászólást!
  • Ha elképzeled a vízszintes FOV-ot felülnézetből egy darab papíron, akkor ugye jobbra-balra FOV/2 szögben indul a képernyő két széle, és nyilván FOV/2+90 lesz a normálvektor iránya a nézeti irányhoz képest. Ha közben föl-le nézel, az ahhoz kapcsolódó forgatást még rá lehet ereszteni.
    Ha nincs explicit FOV-od, akkor is visszaszámolhatod a perspektivikus transzformációból.

    De gondolkodás nélkül is lehet: a képernyőn az x,y=-1...1 négyzet látszik, erre alkalmazva az egész transzformációs sorod inverzét kijönnek a határoló síkok. Ha a perspektivikus transzformáció el is szórja a z-t, az inverz (egy inverz) képzéséhez használhatod az önkényesen választott közeli-távoli vágósíkot. Itt most arra gondolok, ha GPU-t használsz (a beszélgetés egy része alapján az is lehet, hogy szoftveres renderelést akarsz).

    Amúgy ugye az eredeti koordináta rendszerben a nézet egy téglalap-alapú csonkagúla - nem vagyok benne biztos, hogy olyan nagy élmény vele számolni. Végignézni, hogy a 6 síkon belül vagy kívül van-e egy pont valószínűleg több művelet, mint az egy mátrixba összevont transzformáció-sort ráereszteni (még úgy is, hogy a végén van benne 2 vagy 3 osztás). Ráadásul ha van egy pont a kép baloldalától balra, egy másik meg a kép jobboldalától jobbra, de össze vannak kötve, akkor mégsem olyan jó ötlet eldobni őket - szóval Cohen–Sutherland algorithm - Wikipedia, the free encyclopedia -szerűséget kéne csinálni 3D-ben.
    Mutasd a teljes hozzászólást!
  • Ez minden világos, de egy lépést mindig kihagytok, ami a legjobban kellene nekem, hogy helyileg hol van a képernyő bal-jobb széle. Ha a horizont fele nézünk akkor vízszintesen kell forgatni FOV/2-vel, ha fel-le akkor függőlegesen (ráadásul nem akárhogy). Ezt megpróbáltam interpolálni, de nem jól működött a végpontok között (0;90;-90)

    A megjelenítés polygonokból áll, amiket egyszerű levágni 5 sík mentén. Emiatt sajnos külön kamera koordinátarendszer, perspektivikus transzformáció és mátrixok sincsenek egyáltalán, és a kamera sem a z tengely fele néz az origóból, hanem adott helyen, adott irányban van elhelyezve egy vektor formájában.
    Mutasd a teljes hozzászólást!
  • Elvileg csatoltam egy képet.

    A kép teteje felülnézet, a vízszintes fekete csík a nézeti irány, a képernyő közepe. A +-FOV/2 a horizont két végiránya, a képernyő szélei fel-le nézés nélkül. A kék csík lehet maga a képernyő, mondjuk.

    Az kép alsó része mindez oldalnézetből: levetítettem a nézőpontot, meg a képernyő síkját. És utána elnéztem felfele, ezt jelképezi a piros nyíl. Az eredmény meg a piros átló, ami persze ugyanolyan hosszú, mint a vízszintes szakasz volt, csak ez az ábra nem lett olyan szép. Az viszont látszik, hogy a képsík most már nem függőleges, hanem valamilyen irányú (szürke vonal, de azért az a "valamilyen irány" erősen összefügg a piros forgatás szögével), illetve hogy a horizont két végiránya is térben forog: "széltében" nem változik (zöld nyilak), de "hosszában" rövidebb lesz (zöld csík "közelebb" jött), mert bejön a "magasság" komponense (ez ugyanaz a piros vonal az oldalnézeti ábrában, szóval ugye nem jött az közelebb, csak a felülnézeti vetülete). És a forgatás síkja az a képernyő középvonala (függőleges).

    Mivel tetszőleges síkban macerás forgatni (bár a Wikipedia-ból persze könnyű kiszedni), ha érteni szeretnéd a történéseket, akkor jobban jársz azzal, ha előbb csinálod a magassági forgatást (egy szimpatikus síkban, pl. y-z), és utána a jobbra-balrát (aminek a síkja továbbra is x-z marad).
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Köszönöm a válaszokat mindenkinek, de most találtam meg végre egy pofátlanul egyszerű megoldást, ami igazából matt383 válasza leegyszerűsítve, úgyhogy az lesz jó

    Geometric Approach – Extracting the Planes

    nc = p + d * nearDist fc = p + d * farDist Wnear/2 = tan(ALPHA/2)*nd; // tan – is sin/cos a = (nc + right * Wnear / 2) - p a.normalize(); normalRight = up * a

    Mutasd a teljes hozzászólást!
abcd